# Comprehensive Improvement Plan for Elevator Project

## Executive Summary

This document outlines a comprehensive plan to refactor and improve the Elevator project to follow Laravel best practices, improve code quality, maintainability, and prepare for future Laravel version upgrades.

---

## 1. CRITICAL ISSUES (Priority: High)

### 1.1 Laravel Version Mismatch

**Issue**: Project is on Laravel 8, but user rules reference Laravel 11+ features.

**Actions**:

-   [ ] **Option A (Recommended)**: Upgrade to Laravel 11

    -   Update `composer.json` dependencies
    -   Follow Laravel upgrade guide (8 → 9 → 10 → 11)
    -   Update deprecated code patterns
    -   Migrate from `app/Http/Kernel.php` to `bootstrap/app.php` middleware configuration
    -   Move scheduled commands from `app/Console/Kernel.php` to `routes/console.php`
    -   Update service provider registration

-   [ ] **Option B**: Align user rules with Laravel 8 practices (if upgrade is not feasible immediately)

**Files Affected**:

-   `composer.json`
-   `app/Http/Kernel.php` → Remove (Laravel 11)
-   `bootstrap/app.php` → Update middleware registration
-   `routes/console.php` → Move scheduled commands here
-   All service providers

---

### 1.2 Fat Controller: UsersController (1777 lines, 58 methods)

**Issue**: Massive controller violating Single Responsibility Principle.

**Actions**:

-   [ ] **Extract Service Classes**:

    -   `UserService` - Core user operations (CRUD, status management)
    -   `UserTagService` - Tag-related operations (turn on/off, refresh)
    -   `UserPhoneService` - Phone-related operations
    -   `UserAccountService` - Account management
    -   `UserBillingService` - Billing and balance calculations
    -   `UserExportService` - Export functionality

-   [ ] **Extract Action Classes** (for complex operations):

    -   `RefreshUserTagsAction`
    -   `UpdateUserStatusAction`
    -   `GenerateUserCodeAction`
    -   `AttachUserToBarrierAction`

-   [ ] **Create Form Request Classes** (missing validations):

    -   `RefreshUserTagsRequest`
    -   `SendSmsRequest`
    -   `GenerateCodeRequest`
    -   `AttachToBarrierRequest`
    -   `ExportUsersRequest`
    -   `FilterUsersRequest`

-   [ ] **Split Controller**:

    -   Keep `UsersController` for basic CRUD
    -   Create `UserTagsController` for tag operations
    -   Create `UserAccountsController` (already exists, but consolidate)
    -   Create `UserPhonesController` for phone operations

**Target**: Each controller should have < 300 lines, < 10 methods

**Files to Create**:

```
app/Services/User/
  - UserService.php
  - UserTagService.php
  - UserPhoneService.php
  - UserAccountService.php
  - UserBillingService.php
  - UserExportService.php

app/Actions/User/
  - RefreshUserTagsAction.php
  - UpdateUserStatusAction.php
  - GenerateUserCodeAction.php
  - AttachUserToBarrierAction.php

app/Http/Requests/User/
  - RefreshUserTagsRequest.php
  - SendSmsRequest.php
  - GenerateCodeRequest.php
  - AttachToBarrierRequest.php
  - ExportUsersRequest.php
  - FilterUsersRequest.php
```

---

### 1.3 Routes File Issues

**Issue**: Closures with business logic, typos, poor organization.

**Actions**:

-   [ ] **Move Closures to Controllers**:

    -   `getPins/{id}` → `TagController@syncPins`
    -   `checkDev/{block}` → `DeviceController@check`
    -   `queueSize` → `QueueController@size` (or remove if not needed)

-   [ ] **Organize Routes**:

    -   Group by resource/feature
    -   Use route model binding consistently
    -   Extract API routes to separate files if needed
    -   Use named routes consistently

-   [ ] **Remove Hardcoded Logic**:

    -   Extract all business logic from route closures
    -   Use proper controllers and services

**Files Affected**:

-   `routes/web.php` - Major refactoring
-   Create new controller methods for closures

---

## 2. ARCHITECTURE & CODE QUALITY (Priority: High)

### 2.1 Service Layer Improvements

**Issue**: Services exist but inconsistently used, some return redirects.

**Actions**:

-   [ ] **Refactor TagService**:

    -   Remove `redirect()` calls (services should return data/status)
    -   Return DTOs or arrays instead
    -   Let controllers handle HTTP responses

-   [ ] **Create Consistent Service Interface**:

    -   All services should return data, not HTTP responses
    -   Use exceptions for errors
    -   Implement proper return types

-   [ ] **Extract More Services**:

    -   `BlockService` - Block operations
    -   `TransactionService` - Transaction operations
    -   `UtilityBillService` - Utility bill calculations
    -   `MessageService` - SMS/message sending
    -   `ExportService` - Generic export functionality

**Example Refactor**:

```php
// Before (TagService.php)
public function statusOn() {
    // ... logic ...
    return redirect()->route('users.edit', $this->tag->user_id)
        ->with('success', 'ჩიპი გააქტიურდა წარმატებით!');
}

// After
public function activateTag(): bool {
    // ... logic ...
    return true; // or throw exception on failure
}
```

---

### 2.2 Model Improvements

**Issue**: Inconsistent relationships, missing return types, methods returning wrong types.

**Actions**:

-   [ ] **Fix User Model**:

    -   `block()` method returns `first()` - should be a relationship
    -   `service()` returns string - should be a relationship
    -   Add return types to all methods
    -   Move business logic to services

-   [ ] **Add Model Scopes**:

    -   Extract common query patterns from controllers
    -   Create reusable scopes (e.g., `withBalance()`, `active()`, `withTags()`)

-   [ ] **Add Accessors/Mutators**:

    -   Move `getStatus()` helper to User model accessor
    -   Add proper type casting
    -   Use attribute accessors for computed properties

-   [ ] **Fix Relationships**:

    -   Ensure all relationships return relationship instances, not results
    -   Use proper relationship types (hasOne, belongsTo, etc.)

**Example**:

```php
// Before
public function block() {
    return $this->hasOneThrough(...)->first();
}

// After
public function block(): BelongsToMany {
    return $this->belongsToMany(Block::class, 'block_user');
}

// Usage in controller
$user->block()->first(); // or $user->block
```

---

### 2.3 Helper Functions Refactoring

**Issue**: Global helper functions that should be model methods or service methods.

**Actions**:

-   [ ] **Move to Model Accessors**:

    -   `getStatus()` → `User::getStatusAttribute()` or `User::statusBadge()`
    -   `utility()` → `Block::calculateUtility()` or service method

-   [ ] **Move to Service Classes**:

    -   `checkModel()` → `DeviceService::checkModel()`
    -   `reverseByTwoCharacters()` → `TagService::reverseTagId()`

-   [ ] **Keep as Helpers** (if truly generic):

    -   `getMonthName()` - OK as helper
    -   `pad_number()` - OK as helper
    -   `is_valid_georgian_phone()` - OK as helper

**Files Affected**:

-   `app/Helpers/Helper.php` - Reduce to minimal helpers
-   Move logic to appropriate models/services

---

### 2.4 Dependency Injection

**Issue**: Direct facade usage instead of dependency injection.

**Actions**:

-   [ ] **Inject Dependencies**:

    -   Replace `DB::` with injected `Connection` or repositories
    -   Replace `Mail::` with injected `Mailer`
    -   Replace `Storage::` with injected `Filesystem`
    -   Replace `Log::` with injected `Logger` (or use `Log` facade sparingly)

-   [ ] **Use Constructor Injection**:

    -   Inject services in controllers
    -   Use method injection for single-use services (per user rules)

**Example**:

```php
// Before
public function store(Request $request) {
    Mail::to($user)->send(...);
    DB::table('users')->insert(...);
}

// After
public function store(
    Request $request,
    Mailer $mailer,
    UserService $userService
) {
    $mailer->to($user)->send(...);
    $userService->create($request->validated());
}
```

---

## 3. VALIDATION & REQUEST HANDLING (Priority: Medium-High)

### 3.1 Form Request Coverage

**Issue**: Not all endpoints use Form Requests.

**Actions**:

-   [ ] **Create Missing Form Requests**:

    -   All controller methods should use Form Requests
    -   Extract validation from controllers
    -   Add proper authorization logic

-   [ ] **Fix Existing Form Requests**:

    -   Fix typo in `ServiceRequest`: `'requited'` → `'required'`
    -   Add proper return types
    -   Improve validation messages

-   [ ] **Use Form Request Methods**:

    -   `authorize()` - Add permission checks
    -   `rules()` - Validation rules
    -   `messages()` - Custom messages
    -   `prepareForValidation()` - Data preparation if needed

**Files to Create/Update**:

-   All controllers need corresponding Form Requests
-   Fix `app/Http/Requests/ServiceRequest.php`

---

### 3.2 Validation Rules

**Issue**: Inconsistent validation, some rules in controllers.

**Actions**:

-   [ ] **Create Custom Validation Rules**:

    -   `GeorgianPhoneRule` - For phone validation
    -   `AccountNumberRule` - For account number validation
    -   `TagIdRule` - For tag ID validation

-   [ ] **Use Rule Objects**:

    -   Replace string-based rules with Rule objects where appropriate
    -   Use `Rule::unique()` instead of string syntax

**Example**:

```php
// app/Rules/GeorgianPhoneRule.php
class GeorgianPhoneRule implements Rule {
    public function passes($attribute, $value) {
        return preg_match('/^5\d{8}$/', $value);
    }
}
```

---

## 4. CODE ORGANIZATION (Priority: Medium)

### 4.1 Directory Structure

**Issue**: Some organization issues, could be better structured.

**Actions**:

-   [ ] **Organize by Feature** (Optional, but recommended):

    ```
    app/
      Users/
        Controllers/
        Services/
        Requests/
        Actions/
        Models/ (if feature-specific)
      Blocks/
        Controllers/
        Services/
        Requests/
      Tags/
        Controllers/
        Services/
        Requests/
    ```

-   [ ] **Or Keep Current Structure** but improve:

    -   Group related services in subdirectories
    -   Group related requests in subdirectories
    -   Use consistent naming

---

### 4.2 Constants & Configuration

**Issue**: Magic numbers and hardcoded strings.

**Actions**:

-   [ ] **Create Constants**:

    -   `UserStatus` enum or constants class
    -   `TagStatus` enum
    -   `DeviceModel` enum
    -   `BillingType` enum

-   [ ] **Move to Config**:

    -   SMS templates → `config/messages.php`
    -   Device settings → `config/devices.php`
    -   Billing rules → `config/billing.php`

**Example**:

```php
// app/Enums/UserStatus.php
enum UserStatus: int {
    case ACTIVE = 1;
    case INACTIVE = 0;
}

// Usage
if ($user->status === UserStatus::ACTIVE) { ... }
```

---

### 4.3 Jobs Organization

**Issue**: Jobs exist but could be better organized.

**Actions**:

-   [ ] **Organize Jobs by Feature**:

    ```
    app/Jobs/
      User/
        TurnOnTagJob.php
        TurnOffTagJob.php
        RefreshUserTagsJob.php
      Phone/
        SendSmsJob.php
        SendTurnOnSmsJob.php
      Billing/
        ProcessBillingJob.php
    ```

-   [ ] **Improve Job Structure**:

    -   Add proper return types
    -   Add error handling
    -   Use job batching where appropriate (already done in some places)

---

## 5. DATABASE & QUERIES (Priority: Medium)

### 5.1 Query Optimization

**Issue**: N+1 queries, inefficient queries, direct DB queries.

**Actions**:

-   [ ] **Fix N+1 Queries**:

    -   Use `with()` for eager loading
    -   Review all controller methods
    -   Use `loadMissing()` when needed

-   [ ] **Use Query Builder Properly**:

    -   Replace direct `DB::` queries with Eloquent where possible
    -   Use query scopes
    -   Use `when()` for conditional queries

-   [ ] **Add Database Indexes**:

    -   Review migration files
    -   Add indexes for frequently queried columns
    -   Add composite indexes where needed

**Example**:

```php
// Before
$users = User::get();
foreach ($users as $user) {
    $block = $user->block(); // N+1 query
}

// After
$users = User::with('blocks')->get();
foreach ($users as $user) {
    $block = $user->blocks->first();
}
```

---

### 5.2 Repository Pattern (Optional)

**Issue**: Direct model usage in controllers.

**Actions**:

-   [ ] **Consider Repository Pattern**:
    -   Only if it adds value (not always necessary)
    -   Use for complex queries
    -   Keep simple queries in services

**Note**: Laravel's Eloquent is already a repository pattern, so only add if you have complex query logic that needs abstraction.

---

## 6. TESTING (Priority: Medium)

### 6.1 Test Coverage

**Issue**: Very few tests exist.

**Actions**:

-   [ ] **Set Up Testing**:

    -   Ensure Pest is properly configured
    -   Create test factories for all models
    -   Set up test database

-   [ ] **Write Tests**:

    -   Unit tests for services
    -   Feature tests for controllers
    -   Test critical business logic (billing, tag operations)

-   [ ] **Test Structure** (per user rules):

    -   Arrange-Act-Assert pattern
    -   Use meaningful factory data
    -   Test HTTP status, data structure, DB changes

**Example**:

```php
test('user can be created', function () {
    // Arrange
    $adminUser = User::factory()->create(['email' => 'admin@admin.com']);
    $this->actingAs($adminUser);

    // Act
    $response = $this->post(route('users.store'), [
        'name' => 'Test User',
        'account_number' => '12345',
        // ...
    ]);

    // Assert
    $response->assertStatus(302);
    $response->assertSessionHas('success');
    $this->assertDatabaseHas('users', [
        'account_number' => '12345',
    ]);
});
```

---

## 7. DOCUMENTATION & CODE STYLE (Priority: Low-Medium)

### 7.1 PHPDoc Comments

**Issue**: Missing or incomplete documentation.

**Actions**:

-   [ ] **Add PHPDoc**:

    -   All public methods
    -   Complex private methods
    -   Class properties where needed
    -   Use proper `@param`, `@return`, `@throws`

-   [ ] **Follow PSR-12**:

    -   Already using Laravel Pint (good!)
    -   Ensure consistent formatting

---

### 7.2 Return Types

**Issue**: Missing return types in many methods.

**Actions**:

-   [ ] **Add Return Types**:
    -   All controller methods
    -   All service methods
    -   All model methods
    -   Use union types where appropriate (PHP 8+)

**Example**:

```php
// Before
public function store($request) { ... }

// After
public function store(StoreUserRequest $request): RedirectResponse { ... }
```

---

## 8. SECURITY & PERFORMANCE (Priority: Medium)

### 8.1 Security Improvements

**Issue**: Some security concerns.

**Actions**:

-   [ ] **Authorization**:

    -   Ensure all routes have proper authorization
    -   Use Policies for resource authorization
    -   Check permissions in Form Requests

-   [ ] **Input Validation**:

    -   Sanitize all inputs
    -   Use proper validation rules
    -   Prevent SQL injection (use Eloquent/Query Builder)

-   [ ] **CSRF Protection**:

    -   Ensure all forms have CSRF tokens
    -   Verify API routes are properly protected

---

### 8.2 Performance

**Issue**: Potential performance issues.

**Actions**:

-   [ ] **Caching**:

    -   Cache frequently accessed data (blocks, services)
    -   Use cache tags where appropriate
    -   Implement cache invalidation

-   [ ] **Queue Optimization**:

    -   Review queue configuration
    -   Use appropriate queue connections
    -   Monitor queue performance

-   [ ] **Database Optimization**:

    -   Add indexes
    -   Optimize queries
    -   Consider database query logging in development

---

## 9. LARAVEL 11 SPECIFIC (If Upgrading)

### 9.1 Middleware Registration

**Actions**:

-   [ ] **Move to bootstrap/app.php**:
    ```php
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->web(append: [
            \App\Http\Middleware\PermissionMiddleware::class,
        ]);
    })
    ```

### 9.2 Service Providers

**Actions**:

-   [ ] **Register in bootstrap/providers.php**:
    -   Move provider registration from `config/app.php`
    -   Use Laravel 11 auto-discovery where possible

### 9.3 Scheduled Commands

**Actions**:

-   [ ] **Move to routes/console.php**:
    -   Move all scheduled commands from `app/Console/Kernel.php`
    -   Use `Schedule` facade

---

## 10. IMPLEMENTATION PRIORITY

### Phase 1 (Critical - Do First):

1. Fix routes file (closures, typos)
2. Extract UsersController into services
3. Fix model relationships
4. Add missing Form Requests
5. Fix validation issues

### Phase 2 (High Priority):

1. Refactor services (remove redirects, proper return types)
2. Move helper functions to appropriate classes
3. Add dependency injection
4. Fix N+1 queries
5. Add return types

### Phase 3 (Medium Priority):

1. Organize code structure
2. Add constants/enums
3. Improve job organization
4. Add tests
5. Add documentation

### Phase 4 (Nice to Have):

1. Consider Laravel 11 upgrade
2. Add caching
3. Performance optimization
4. Repository pattern (if needed)

---

## 11. ESTIMATED EFFORT

-   **Phase 1**: 2-3 weeks
-   **Phase 2**: 2-3 weeks
-   **Phase 3**: 2-3 weeks
-   **Phase 4**: 1-2 weeks (if upgrading to Laravel 11)

**Total**: 7-11 weeks for complete refactoring

---

## 12. RISKS & MITIGATION

### Risks:

1. **Breaking Changes**: Refactoring may introduce bugs

    - **Mitigation**: Write tests first, refactor incrementally

2. **Downtime**: Large refactoring may require downtime

    - **Mitigation**: Do in phases, test thoroughly

3. **Team Learning Curve**: New patterns may confuse team

    - **Mitigation**: Document changes, code reviews

---

## 13. SUCCESS METRICS

-   [ ] All controllers < 300 lines
-   [ ] All methods have return types
-   [ ] 80%+ test coverage for critical paths
-   [ ] No N+1 queries in main flows
-   [ ] All routes use Form Requests
-   [ ] Zero direct DB queries in controllers
-   [ ] All services return data, not HTTP responses
-   [ ] Code follows PSR-12 and Laravel conventions

---

## Notes

-   This plan should be implemented incrementally
-   Each phase should be tested before moving to the next
-   Consider feature flags for risky changes
-   Maintain backward compatibility where possible
-   Document all major changes

---

**Last Updated**: [Current Date]
**Version**: 1.0
