# Dev Notes

Practical recipes for working on this codebase. Read [ARCHITECTURE.md](ARCHITECTURE.md) first.

## Environment

- **DB:** MySQL (shared with VMS server). `.env`:
  ```
  DB_CONNECTION=mysql
  DB_HOST=127.0.0.1
  DB_DATABASE=amar_auto
  DB_USERNAME=rootuser
  DB_PASSWORD=Password@123
  ```
- **Superadmin:** `admin@amarauto.test` / `password` (`SuperAdminSeeder`).
- **Run:** `php artisan serve` → http://127.0.0.1:8000/login
- **Theme assets** live in `public/theme/assets` (184 MB, committed). Asset paths use
  `/theme/assets/...`.

## ⭐ Recipe: add a schema change (NO migrations)

We use the self-updater, not `php artisan make:migration`.

1. Add an idempotent function to `app/Services/UpdateHelper.php`:
   ```php
   public static function updateOneThreeZero(): bool
   {
       if (! Schema::hasTable('deliveries')) {
           Schema::create('deliveries', function (Blueprint $t) {
               $t->id();
               $t->unsignedBigInteger('company_id')->index();
               // ...
               $t->timestamps();
           });
       }
       return true;   // must return true on success
   }
   ```
2. Register it in `app/Helpers/update.json` (use a higher semver than current):
   ```json
   "1.3.0": { "date": "YYYY-MM-DD", "info": ["[NEW] Delivery logging"], "function": "updateOneThreeZero" }
   ```
3. Apply: `php artisan app:update` (or the `/admin/system/update` page).

Rules: every update fn must be **idempotent** (guard with `Schema::hasTable/hasColumn`)
and **return true**. On a fresh deploy, `app:update` runs every version in order.

## ⭐ Recipe: add a tenant module

1. **Registry** — add to `config/modules.php`:
   ```php
   'delivery_module' => ['title' => 'Deliveries', 'icon' => 'bi-truck',
       'default' => 'yes', 'permission' => 'logistics.view', 'route' => 'deliveries.index'],
   ```
2. **Permissions** — add keys to `config/permissions.php`.
3. **Translations** — add the title + labels to `resources/language/en.php` & `bn.php`.
4. **Model** — `use BelongsToCompany;` (auto tenant-scope + auto `company_id`).
5. **Routes** — tenant group in `routes/web.php`:
   ```php
   Route::middleware(['auth','company','module:delivery_module'])->group(function () {
       Route::get('deliveries', [DeliveryController::class,'index'])
           ->middleware('permission:logistics.view')->name('deliveries.index');
   });
   ```
6. **Controller + views** — never add `where('company_id', ...)` manually; the trait does it.
7. Sidebar picks it up automatically from the registry (gated by module + permission).

## Recipe: add a translatable label

1. Wrap in `_lang('My Label')` in the Blade view.
2. Add `'My Label' => 'My Label'` to `resources/language/en.php`.
3. Add `'My Label' => '<bangla>'` to `resources/language/bn.php`.
   Missing key → falls back to the key itself (English).

## Recipe: gate something by permission

- Route: `->middleware('permission:customers.manage')`
- Blade: `@if (user_can('customers.manage')) ... @endif`
- `admin` (superadmin) and `user` (company owner) bypass all permission checks.

## Conventions

- **Tenant scope is automatic** — trust `BelongsToCompany`; don't filter `company_id` by hand.
- **Money** = `decimal(12,2)`. **GPS** = `decimal(10,7)`. **Status** = small int / string enum.
- **Soft-delete** tenant master tables (`softDeletes()`), not transactional rows.
- **Mobile-first** for delivery/driver panels — they're the field-staff UI.
- Keep new Blade consistent with existing theme classes (`card custom-card`,
  `page-header-breadcrumb`, `btn btn-primary`, `bi bi-*` icons).

## Roles & permissions data

- System role templates: `config/roles.php` (Manager, Accountant, Delivery). Cloned into
  a company's `roles` table on company creation (`CompanyController::seedCompanyRoles`).
- A role's `permissions` column is a JSON array of keys from `config/permissions.php`
  (`['*']` = all).

## Gotchas

- `company_id()` returns `''` when not authenticated → tenant-scoped queries return all
  rows. Always run tenant pages behind `auth` + `company` middleware.
- The updater bootstraps `settings` + `update_audit_runs` itself — don't migrate them.
- After editing `composer.json` autoload `files`, run `composer dump-autoload`.
- After Blade/route/config edits in prod: `php artisan optimize:clear`.

## Reference: the VMS project

Live sibling system at `/Volumes/Files/VMS` (Laravel 10). Our tenancy, module-gating,
`_lang`, permission, and self-update patterns are modeled on it. When unsure how to build
something "the VMS way", grep that codebase:
- self-update: `app/Helpers/UpdateHelper.php`, `app/Helpers/update.json`
- helpers: `app/Helpers/general.php` (`company_id`, `get_company_option`, `has_permission`, `_lang`)
- middleware: `app/Http/Middleware/Company.php`, `EnsureCompanyMenuModuleEnabled.php`
