# ECFM – Database (Laravel migrations + models)

Imejengwa kwa Laravel 11+ (PHP 8.2+). Nakili folda `app/` na `database/` kwenye project yako, kisha:

    php artisan migrate
    php artisan db:seed            # settings, aina ya kuku, bidhaa, categories
    php artisan db:seed --class=DemoBatchSeeder   # (hiari) batch ya 50 na 180

## Wazo kuu

| Dhana | Jedwali | Maelezo |
|---|---|---|
| Aina ya mnyama / breed + life span default | `animal_types`, `animal_breeds` | Kuku wa mayai sasa; wanyama wengine baadaye bila kubadilisha schema |
| **Kundi (batch)** | `batches` | Kila kundi lina arrival/hatch date, `lifespan_days`, `planned_end_date`, idadi, banda, supplier |
| Idadi ya kuku (ledger) | `batch_movements` | intake, death, cull, sold, transfer, adjustment. `batches.current_count` = SUM(delta) |
| Rekodi ya siku | `daily_records` | vifo, cull, maji, chakula (ripoti), wagonjwa; unique(date,batch) |
| Utagaji | `egg_collections` | trei + loose, cracked/dirty/rejected, good_eggs; `eggs_per_tray` ni setting |
| Stock ya mayai | `egg_stock_movements` | collection (+), sale/breakage/writeoff (−) |
| Chakula/dawa/trei | `inventory_items`, `goods_receipts(+items)`, `inventory_movements` | Ledger; `batch_id` kwenye OUT = chakula kilichotumika na kundi |
| Afya | `health_events`, `treatments`, `vaccination_schedules` | withdrawal_ends_on huzuia mauzo ya mayai |
| Mauzo | `products`, `customers`, `sales_orders(+items)`, `deliveries`, `invoices`, `payments`, `payment_allocations` | Mayai, kuku wazee, mbolea |
| Gharama | `expense_categories`, `expenses` | `batch_id` hiari → gharama kwa kundi |
| Mengineyo | `settings`, `weight_samples`, `sheds`, `suppliers`, `audit_logs` | |

## Matumizi

```php
$a = Batch::create(['animal_type_id'=>1,'breed_id'=>1,'shed_id'=>1,'arrival_date'=>'2026-11-01','initial_count'=>50]);
$b = Batch::create(['animal_type_id'=>1,'breed_id'=>1,'shed_id'=>1,'arrival_date'=>'2027-01-10','initial_count'=>180]);

$a->record(BatchMovementType::Death, 2, ['reason'=>'Ugonjwa']);   // current_count 50 -> 48
$a->age_days; $a->life_stage; $a->remaining_life_days; $a->lifespan_used_pct;
$a->henDayPercent('2026-12-01','2026-12-31');
$a->feedPerBirdPerDay('2026-12-01','2026-12-31');   // gramu/kuku/siku
Batch::nearingEnd(30)->get();                       // makundi yanayokaribia cull

InventoryMovement::create(['inventory_item_id'=>3,'batch_id'=>$a->id,'type'=>'out','quantity'=>25,'movement_date'=>today()]);
EggStockMovement::availableTrays();
```

## Maamuzi ya muundo
- **Idadi na stock hazihaririwi moja kwa moja**: kila badiliko ni movement (ledger); `current_count`/`current_stock` ni cache. Negative haziruhusiwi.
- Life span ya kila batch inanakiliwa kutoka breed wakati wa kuunda; inaweza kuhaririwa kwa batch hiyo pekee.
- `daily_records` zikiidhinishwa, vifo/cull huingia kwenye ledger mara moja tu (`posted_at`). Mayai huingia stock baada ya idhini.
- Thamani za life span kwenye `AnimalSeeder` (siku 126 / 540) ni za kuanzia; **zithibitishwe na vet/breeder guide**. Withdrawal days hazibuniwi na mfumo.

## Bado haijafanywa (Phase baadaye)
Mkopo (`loan_accounts`), bajeti (`budget_lines`), tasks/notifications, RBAC kamili (tumia `spatie/laravel-permission`), mauzo-to-egg-stock posting wakati wa dispatch, policies.

> Haijaendeshwa kwenye Laravel halisi (mazingira haya hayana PHP): endesha `php artisan migrate:fresh --seed` na ujaribu kabla ya kutumia.

---

# API (JSON) – `/api/v1`

## Usanidi (project hii tayari imeunganishwa: Laravel 12 + Sanctum)
```bash
composer install
cp .env.example .env && php artisan key:generate   # weka DB kwenye .env (MySQL/PostgreSQL au sqlite)
php artisan migrate:fresh --seed                   # inaunda owner@ecfm.test / ChangeMe#2026 (BADILI)
php artisan route:list --path=api
php artisan serve
```
`bootstrap/app.php`:
```php
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias(['role' => \App\Http\Middleware\EnsureRole::class]);
})
->withExceptions(fn (Exceptions $e) => \App\Support\ApiExceptions::register($e))
```
Tuma header `Accept: application/json` na `Authorization: Bearer <token>`.

## Muundo
- **UUID**: kila jedwali la biashara lina `uuid` (trait `HasUuid`); API haionyeshi `id` wala `*_id`/`*_by` za ndani. Foreign keys hutumwa kama uuid (mf. `"batch_id": "<uuid ya batch>"`).
- **Audit**: trait `Auditable` + `AuditLogService` huandika create/update/delete/restore; `approved`, `returned`, `cancelled`, `login`, `report_generated` ni vitendo maalum. `audit_logs` haihaririwi wala kufutwa. Tazama: `GET /audit-logs?entity=Batch&entity_uuid=...`.
- Jibu: `{ "success": true, "message": "...", "data": ..., "meta": {...} }`; makosa: `{ "success": false, "message": "...", "errors": {...} }`.
- Roles (`users.staff_role`): owner (anaruhusiwa kila kitu), manager, attendant, storekeeper, driver, sales, finance, vet, auditor, admin.

## Endpoints kuu
| Eneo | Endpoints |
|---|---|
| Auth | `POST auth/login`, `GET auth/me`, `POST auth/logout` |
| Dashboard | `GET dashboard` (inachujwa kwa role) |
| Master data | `animal-types`, `breeds`, `sheds`, `products`, `suppliers`, `customers`, `expense-categories`, `inventory-items` (+ `inventory-items/low-stock`) – CRUD |
| Makundi | `GET/POST/PATCH batches`, `GET batches/{uuid}/summary`, `GET/POST batches/{uuid}/movements`, `POST batches/{uuid}/close` |
| Rekodi za siku | `daily-records` (+ `/{uuid}/approve`, `/{uuid}/return`) |
| Mayai | `egg-collections` (+ `/approve`), `GET egg-stock`, `GET egg-stock/movements`, `POST egg-stock/adjustments` |
| Ghala | `goods-receipts`, `inventory-movements` |
| Afya | `health-events` (+ `/treatments`, `/close`), `vaccination-schedules` (+ `/complete`) |
| Mauzo | `sales-orders` (+ `/approve`, `/dispatch`, `/deliver`, `/invoice`, `/cancel`), `invoices`, `invoices/debtors`, `payments` |
| Fedha | `expenses` (+ `/approve`, `/reject`, `/pay`) |
| Ripoti | `reports/production`, `reports/inventory` |
| Admin | `users`, `audit-logs` |

## Mfano
```bash
# Batch mpya ya kuku 180 (batch ya pili)
POST /api/v1/batches
{ "animal_type_id":"<uuid>", "breed_id":"<uuid>", "shed_id":"<uuid>", "arrival_date":"2027-01-10", "initial_count":180 }

# Rekodi ya siku (mhudumu), kisha meneja anaidhinisha
POST /api/v1/daily-records
{ "batch_id":"<uuid>", "record_date":"2027-01-20", "deaths":1, "feed_kg":21.5, "water_litres":40 }
POST /api/v1/daily-records/<uuid>/approve

# Utagaji
POST /api/v1/egg-collections
{ "batch_id":"<uuid>", "collection_date":"2027-01-20", "trays":3, "loose_eggs":12, "cracked":2 }
```

## Sheria zilizowekwa kwenye server
Aliyeingiza hawezi kuidhinisha rekodi yake (daily records, egg collections, orders, expenses) · vifo/cull huingia ledger baada ya idhini tu · stock haiwi negative (chakula na mayai) · mayai ya kundi lililo kwenye withdrawal hayauzwi (dispatch inatumia FIFO bila makundi yaliyozuiwa) · oda inazuiwa ikizidi mayai yanayopatikana · malipo hayazidi deni la ankara · matumizi juu ya kikomo cha category yanahitaji owner · mabadiliko ya role/password/status yanafuta token za mtumiaji.

## Mapungufu yanayojulikana
Hakuna tests wala FormRequest (validation iko ndani ya controllers); hakuna endpoint ya kupakua risiti/POD (zimehifadhiwa disk `local` binafsi); ankara kuwa `overdue` kunahitaji scheduled command; kuuza kuku hai na mayai ni mtiririko wa msingi; dashboard haina "variance vs target" kwa sababu target haijahifadhiwa kwenye DB. **Hakuna code iliyoendeshwa** (mazingira haya hayana PHP/Composer): endesha `php artisan route:list` na migrate kwenye project halisi kabla ya kuitegemea.
