## Car Repairs Shop — AI agent working notes

This repo is a Laravel 12 app with Livewire (Volt + Flux UI), Tailwind, and Vite. The UI is primarily Livewire pages; a few classic controllers exist for resource routes. Tests use in-memory SQLite.

### Architecture map
- **Workflow-driven design**: The app implements an 11-step automotive repair workflow from vehicle reception to delivery with status tracking, inspections, estimates, and customer notifications.
- Core domains live in `app/Livewire/**` and `app/Models/**` (Customers, Vehicles, Inventory, JobCards, Estimates, Diagnosis, WorkOrders, Timesheets, Users, Reports, CustomerPortal).
- **WorkflowService** (`app/Services/WorkflowService.php`) orchestrates the complete repair process with methods for each workflow step.
- **InspectionChecklistService** (`app/Services/InspectionChecklistService.php`) manages standardized vehicle inspections and comparison logic.
- Routes are in `routes/web.php`:
  - Root decides destination based on `auth()->user()->isCustomer()` → customers go to `/customer-portal`, admins/staff to `/dashboard`, guests to `/login`.
  - Admin/staff area uses `admin.only` + `permission:*` middleware. Customer portal uses `auth` only.
  - Volt pages registered via `Volt::route('settings/...', 'settings.something')`.
- Middleware aliases are registered in `bootstrap/app.php`:
  - `admin.only`, `role`, `permission` point to custom classes in `app/Http/Middleware`. Route `permission:` strings are the canonical auth gates in this app.
- Settings use Spatie Laravel Settings (`app/Settings/**`, `config/settings.php`), e.g., `app(\App\Settings\GeneralSettings::class)` for shop phone/email in views.
- Blade components: anonymous components live under `resources/views/components/**`. Example: `<x-layouts.customer-portal />` is backed by `resources/views/components/layouts/customer-portal.blade.php`.

### 11-Step Workflow Implementation
The system follows a structured automotive repair workflow:
1. **Vehicle Reception** → `JobCard::STATUS_RECEIVED` - Basic data capture, unique sequence numbers by branch (`ACC/00212`, `KSI/00212`)
2. **Initial Inspection** → `JobCard::STATUS_INSPECTED` - Standardized checklist via `InspectionChecklistService`
3. **Service Assignment** → `JobCard::STATUS_ASSIGNED_FOR_DIAGNOSIS` - Assign to Service Coordinator
4. **Diagnosis** → `JobCard::STATUS_IN_DIAGNOSIS` - Full diagnostic with timesheet tracking
5. **Estimate** → `JobCard::STATUS_ESTIMATE_SENT` - Detailed estimate with email/SMS notifications
6. **Approval** → `JobCard::STATUS_APPROVED` - Customer approval triggers team notifications
7. **Parts Procurement** → `JobCard::STATUS_PARTS_PROCUREMENT` - Inventory management and sourcing
8. **Repairs** → `JobCard::STATUS_IN_PROGRESS` - Work execution with timesheet tracking
9. **Final Inspection** → `JobCard::STATUS_COMPLETED` - Outgoing inspection with discrepancy detection
10. **Delivery** → `JobCard::STATUS_DELIVERED` - Customer pickup and satisfaction tracking
11. **Archival** - Document archiving and job closure

### Conventions and patterns
- **Status-driven workflow**: Use `JobCard::getStatusOptions()` for consistent status handling. Each status corresponds to a workflow step.
- **Role hierarchy**: Service Supervisor → Service Coordinator → Technician. Use role helper methods like `$user->isServiceCoordinator()`.
- Livewire pages reside under `app/Livewire/{Area}/{Page}.php` with views under `resources/views/{area}/{page}.blade.php` (Volt routes may point directly to views).
- Authorization:
  - Use `admin.only` to gate admin/staff routes.
  - Use `permission:domain.action` strings on routes (e.g., `permission:customers.view`, `inventory.create`). Keep naming consistent with existing routes.
- **Branch-specific operations**: All job cards have `branch_code`. Use `JobCard::byBranch($code)` scope for filtering.
- Customer Portal layout requires a `jobCard` prop. When using `<x-layouts.customer-portal>`, pass it explicitly:
  - Example: `<x-layouts.customer-portal :job-card="$jobCard"> ... </x-layouts.customer-portal>`
- **Inspection system**: Use `InspectionChecklistService` for standardized checklists. Incoming vs outgoing inspections are compared automatically.

### Developer workflows
- Install & run (common):
  - PHP deps: `composer install`
  - Node deps: `npm install`
  - Generate key & migrate: `php artisan key:generate && php artisan migrate --seed`
  - Dev loop (servers + queue + logs + Vite): `composer dev` (runs: serve, queue:listen, pail, vite)
  - Asset build: `npm run build`
- Testing:
  - Run tests: `./vendor/bin/phpunit` (uses in-memory SQLite per `phpunit.xml`)
  - Alternative: `composer test` (clears config and runs `artisan test`)
- Debugging:
  - Logs via Laravel Pail are included in `composer dev`. Otherwise: `php artisan pail`.

### Routing and modules (examples)

### Data Flow and State Management
- **Status-Driven Design**: Each workflow step corresponds to a specific JobCard status. Always use status constants from the model.
- **Service Dependencies**: WorkflowService orchestrates the complete flow, InspectionChecklistService handles standardized vehicle inspections.
- **Customer Communication**: Auto-notifications at each step keep customers informed of progress.
- **Quality Control**: Built-in inspection comparisons and quality alerts ensure consistent service delivery.
- Admin resources (with permissions):
  - `Route::resource('customers', CustomerController::class)->middleware('permission:customers.view');`
- Inventory area pages are Livewire classes under `app/Livewire/Inventory/**` and grouped under `Route::prefix('inventory')` with `permission:inventory.*`.
- Customer portal routes:
  - `Route::prefix('customer-portal')->middleware(['auth'])->group(function () { Route::get('/status/{jobCard}', \\App\\Livewire\\CustomerPortal\\JobStatus::class)->name('customer-portal.status'); });`

### Testing notes (project-specific)
- Tests use in-memory SQLite; avoid relying on factories that don’t exist. Prefer lightweight stubs or create the minimal model records needed.
- For Blade/Livewire views using a layout slot, render the page view (not the layout)
  and pass required data. Example: `View::make('livewire.customer-portal.job-status', ['jobCard' => $jobCard])->render();`

### Guardrails for agents
- When adding new admin routes, wire `admin.only` and appropriate `permission:*` middleware, and register Volt pages via `Volt::route` when applicable.
- Keep anonymous Blade components under `resources/views/components/**` and pass required props explicitly.
- Use `app(\App\Settings\GeneralSettings::class)` for shop metadata instead of hardcoding.
- Follow existing permission key patterns (`domain.action`).

If anything above is unclear or you need deeper details (e.g., settings schema, specific Livewire page conventions), propose a short diff or ask for a quick pointer to the relevant file.
