diff --git a/CLAUDE.md b/CLAUDE.md index 6ddb35b..4ad4c55 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -266,7 +266,47 @@ bind `FakeSmsService` via `$this->app->instance(SmsService::class, ...)` in `GET /admin/reports/compliance.csv?from=&to=` streams a DENR-style dumpsite-release export, `POST /admin/reports/rebuild` triggers aggregation on demand. -- All 164 feature tests passing +- [x] Module 13b: Notifications — complete + - `notification_preferences` table + `notifications` (Laravel inbox). + - `App\Notifications\Channels\SmsChannel` adapts our SmsService. + - `RoutesByPreferences` trait routes via database + sms based on + per-user toggles. Notifications: `HouseholdApproved`, + `HouseholdRejected`, `QrBalanceLowNotification`, `CodesPurchased`. + Listeners auto-route via Laravel 11 discovery; rejection + + purchase notifications dispatched directly from the controller / + `StoreOperations`. + - `GET/PATCH /me/notification-preferences`. Defaults seeded on + register. +- [x] Module 13c: Payments — scaffolded (PayMongo + Manual) + - `payments` table. + - `PaymentDriver` interface with `ManualPaymentDriver` (admin marks + paid; default) and `PayMongoDriver` (activates when + `PAYMONGO_SECRET_KEY` is set; HMAC-SHA256 webhook verification). + - Resident `POST /me/payments/code-purchase` → driver returns + checkout URL. Webhook `POST /api/v1/webhooks/paymongo` applies + paid/failed events. Admin `POST /admin/live/payments/{uuid}/mark-paid` + forces fulfillment for cash-paid or stuck payments. + - Fulfillment runs `StoreOperations::sellToHousehold()` — codes + allocated → active for the household + `CodesPurchased` notification. +- [x] Module 13d: Live Tracking (HTTP polling) — complete + - `truck_location_history` (POINT 4326 + SPATIAL INDEX). + - `TruckTracker::record()` writes history, updates + `trucks.last_known_coordinates`, Redis-caches latest position, + flags geofence-trigger when entering the active trip's dumpsite. + - Driver `POST /driver/trucks/{uuid}/location` (15-second cadence; + only the assigned-team driver may post). + - Admin `GET /admin/live/trucks` returns positions for active trucks + updated within the last hour. + - Reverb broadcast deferred — polling is the data source for now. +- Flow corrections from this batch: + - `QrAllocator::allocateFreeToHousehold()` is now **idempotent** — + if the household already has any QR codes assigned, the listener + skips. Re-approving a rejected→approved cycle no longer dispenses + a second free batch. + - `arrive-dumpsite` validates the GPS is **inside** the dumpsite + boundary via `Dumpsite::containsPoint`. `override_geofence: true` + bypasses for known-bad GPS — admin can audit later. +- All 171 feature tests passing - [ ] Deferred sub-modules: PayMongo payments, FCM notifications, Reverb live tracking