Commit Graph

39 Commits

Author SHA1 Message Date
Developer
968f4467bf test: Implement comprehensive E2E Golden Path Integration Test 2026-07-02 13:57:40 +08:00
Developer
8e3577c9d1 remove tmp test 2026-07-02 13:57:39 +08:00
Developer
ba30a5fcdf fix: QrCode relation bug and Endroid create() error 2026-07-02 13:57:39 +08:00
Developer
7745a57e84 style: apply additional linting fixes across the codebase 2026-07-02 13:56:02 +08:00
Developer
c4cbdb42c7 feat(store): complete partner store overhaul with mapping, household search, financial analytics, and resident notification system 2026-07-02 13:55:08 +08:00
ramram1515
647af45b99 Fix PartnerStoreSettlementTest and QrCode replacement 2026-07-02 13:47:49 +08:00
Developer
4a4b88ffe4 feat: partner store financial settlements, qr replacements, and tenant resolution fix 2026-07-01 16:38:49 +08:00
Developer
62bcf68bdb feat: add partner store analytics, history logs, and global SRP validation 2026-07-01 15:02:43 +08:00
Developer
92f8ee95fc feat: Add Geofence Leaflet drawing tool for DOPs and Dumpsites 2026-06-30 13:31:36 +08:00
Developer
54de35b03d Update trip tenancy and models 2026-06-30 13:12:15 +08:00
Developer
64d442ec2e feat: add proof of residency upload option during admin household creation 2026-06-30 10:27:49 +08:00
Super Admin
0d1defe3b6 feat: implement route edit modal with leaflet map and fix auth tests 2026-06-30 07:53:15 +08:00
Super Admin
cfd7166a24 feat: implement drop-off points & dumpsites edit/delete and status transition logic 2026-06-29 23:15:55 +08:00
Super Admin
f2c1573f00 feat: Implement Truck edit, delete, and automatic trip cancellation when moved to maintenance/retired status 2026-06-29 22:59:47 +08:00
ramram1515
1b7cabef4c Implement missing proof of residency tests 2026-06-29 17:03:05 +08:00
Developer
7dc074e3c3 Implement household, QR sale, team helpers assignment, and helper endpoints 2026-06-29 16:56:33 +08:00
Developer
b85fc255cf feat: implement barangay and household management with associated tests 2026-06-29 15:02:52 +08:00
Developer
2c7c3528e4 feat: implement interactive Barangay polygon map selector in Service Areas 2026-06-29 13:22:45 +08:00
Developer
8dbc87b44f feat: add super admin LGU management and global user creator dashboard screens 2026-06-29 12:45:07 +08:00
Developer
167abdc6ad fix: resolve super_admin login, echo crash and GD extension test failures 2026-06-29 11:43:40 +08:00
306f8fb4e8 feat(backend): customer-site API gaps + CORS
- GET /partner-stores/nearby — public, residents browse active stores
  ranked by distance via ST_Distance_Sphere; PublicPartnerStoreResource
  excludes commission rate / owner / permit (only what a buyer needs).
- GET /partner-stores/{uuid} — public details, 404 if not active.
- GET /me/collections — paginated resident QR scan history with
  optional from/to date filters.
- GET /me/upcoming-pickups — finds scheduled/in-progress trips whose
  route includes the resident's assigned drop-off point. Returns
  household_assigned: false when no household yet.
- GET /me/notifications — paginated database notifications inbox
  with unread_only filter + unread_count in meta.
- POST /me/notifications/{id}/read, POST .../mark-all-read,
  GET .../unread-count.
- config/cors.php — allow CUSTOMER_APP_URL and any EXTRA_CORS_ORIGINS
  to call the API with credentials. Same-origin admin web is
  unaffected.

202 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:55:10 +08:00
86ea731eb0 feat(backend): finish all deferred items — Sentry, audit, bulk, FCM, Reverb, PSGC
- **Sentry** wired in bootstrap/app.php via Sentry\Laravel\Integration.
  No-op when SENTRY_LARAVEL_DSN is empty.

- **Audit logging** broadened: LogsActivity applied to Household, QrCode,
  Trip, Payment with tight logOnly whitelists and named log channels
  ('household', 'qr_code', 'trip', 'payment') to keep the activity
  stream useful.

- **Bulk admin actions**:
  POST /admin/households/bulk-approve — skips already-approved /
  no-proof / unknown ids, reports per-id outcomes
  POST /admin/bulk/users/{suspend,activate} — admins protected
  POST /admin/bulk/qr-codes/void — respects state machine transitions

- **FCM push scaffold**: PushDriver contract with LogPushDriver
  (default) and FcmPushDriver (activates when FCM_SERVER_KEY is set).
  PushChannel adapts notifications. RoutesByPreferences now also
  routes via push when push_enabled + fcm_token. toPush() payloads
  added to HouseholdApproved / QrBalanceLow / PickupImminent.

- **Reverb WebSocket broadcast**: laravel/reverb installed.
  TruckLocationBroadcast fires on every TruckTracker::record().
  routes/channels.php authenticates: admins → private-admin.live,
  residents → area.{id}.trucks (only if their household barangay is
  covered by the service area).

- **PSGC seeder** expanded: all 17 PH regions, 4 NCR districts,
  all 17 NCR cities. Sample barangays still carry rectangular
  boundaries for point-in-polygon resolution tests.

- **Conditional SPATIAL INDEX migration** for barangays.boundary —
  safe no-op until every row has a polygon (i.e., after full PSA
  dataset import). Re-running `php artisan migrate` after import
  flips the column to NOT NULL and adds the index.

196 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:22:43 +08:00
58a7d3680a feat(backend): hardening sprint — docs, schedulers, validation, email + pickup
1. API docs via dedoc/scramble at /docs/api (scoped to api/v1).
   Linked from the admin sidebar Settings group.

2. Scheduled commands registered in routes/console.php:
   - reports:aggregate (02:00) — daily/weekly/monthly aggregations
   - qr:expire (02:30) — flips past-due allocated/active codes to expired
   - trucks:prune-locations (03:00) — drops history older than retention
     window (default 7 days, config('verde.location_retention_days'))
   All idempotent + withoutOverlapping. --dry flags on qr:expire and
   trucks:prune-locations for safe inspection.

3. Trip double-booking validation: AdminTripController::store rejects
   new trips when the team or truck already has a non-cancelled trip on
   the same date. override_conflicts: true bypasses for emergencies.
   Cancelled trips don't block rebooking.

4a. Email verification: User implements MustVerifyEmail.
    VerifyEmailNotification overrides verificationUrl() for our
    namespaced route. Register sends the link automatically (best
    effort, won't block signup). POST /auth/email/resend (auth) +
    GET /auth/email/verify/{id}/{hash} (signed URL).

4b. Password change while logged in: POST /me/password validates
    current_password, requires the new password to differ, revokes
    every other active token on success — current session stays.

5a. PickupImminent notification: when TripStop -> arrived,
    TripExecutor::notifyAssignedHouseholds() finds households whose
    assigned_drop_off_point_id matches and sends DB + SMS.

5b. Auto-geofence on truck location: TruckTracker::record() now
    auto-fires TripExecutor::arriveAtDumpsite() when an in-progress
    trip's truck pings inside its dumpsite boundary. The executor's
    status guard prevents duplicate timeline events if the driver also
    presses arrive-dumpsite manually.

190 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:13:00 +08:00
c2115b767e feat(web): replace remaining "Soon" stubs with real pages
- Live Tracking: Leaflet map (CDN) showing active truck positions,
  auto-refresh every 10s, sidebar list with speed + last update.
- Finance / Payments: filterable list of payments with mark-paid
  action that runs admin fulfillment.
- Settings: notification-preferences form bound to /me/notification-
  preferences.

Backend:
- New admin payments index endpoint
  GET /admin/payments + POST /admin/payments/{uuid}/mark-paid (moved
  out of /admin/live/* for clarity).

Sidebar groups now reflect what's live: Operations (Trips, Live
Tracking), Planning (Routes, Teams, Trucks, DOPs, Dumpsites), People
(Users, Households, Partner Stores), QR, Areas, Finance, Reports,
Settings. Trip Calendar + Incidents remain "Soon" — backends ready,
UI work pending. Dashboard backend-status copy updated to 13/13
modules / 171 tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 14:07:59 +08:00
15d56d0e98 feat(backend): finish Module 13 sub-modules + flow fixes
Notifications: notification_preferences + Laravel notifications inbox.
SmsChannel adapter for our SmsService. RoutesByPreferences trait reads
per-user toggles. HouseholdApproved/Rejected, QrBalanceLow, and
CodesPurchased notifications wired in via auto-discovered listeners
or direct dispatch from controllers/StoreOperations.

Payments: payments table + PaymentDriver interface. ManualPaymentDriver
works out of the box; PayMongoDriver activates when
PAYMONGO_SECRET_KEY is set, falls back to manual otherwise. Resident
initiates code-purchase, admin can mark paid manually, webhook applies
real provider events. Fulfillment runs StoreOperations::sellToHousehold.

Live tracking (HTTP polling): truck_location_history (with SPATIAL
INDEX + 7-day retention plan). Driver POST /driver/trucks/{uuid}/location
writes history, updates trucks.last_known_coordinates, caches in Redis,
flags geofence-trigger when entering active trip dumpsite. Admin
GET /admin/live/trucks returns active truck positions. Reverb broadcast
deferred.

Flow corrections:
- QrAllocator now idempotent — re-approving a household no longer
  re-dispenses free codes.
- arrive-dumpsite enforces dumpsite geofence via ST_Contains; can be
  bypassed with override_geofence: true.

171 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 14:01:38 +08:00
0a2e187f45 feat(backend): complete Module 13 reports + analytics
daily_collection_stats, weekly_route_performance, monthly_store_sales
aggregation tables. Aggregator service is idempotent — wipes the slice
and re-inserts. php artisan reports:aggregate (default: yesterday) for
the nightly cron. Admin endpoints: daily-collection / trip-performance
/ store-sales chart series + totals, compliance.csv stream of dumpsite
releases (DENR-style), POST rebuild for on-demand aggregation.

Payments, notifications, and live tracking sub-modules of Module 13
are deferred per scope.

164 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:58:09 +08:00
989f4b87b9 feat(backend): complete Module 12 (partner stores)
partner_stores, store_inventories, store_purchases, store_sales tables.
Promotes qr_code_batches.target_store_id and qr_codes.assigned_to_store_id
to real FKs. StoreOperations service handles wholesale issuance
(generates fresh batch -> codes go allocated to store -> inventory tops
up -> StorePurchase recorded) and resident sales (codes flip allocated
-> active to a household, commission computed at the store's rate).
Admin endpoints: store CRUD, issue-inventory, record-sale.

160 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:55:29 +08:00
8643057c81 feat(backend): complete Module 11 (scanning + collection logs)
collection_logs table. ScanService validates code state (active only;
used = duplicate, expired = expired, unassigned/allocated = invalid),
geo proximity (≤200m from DOP via ST_Distance_Sphere), then atomically
transitions code -> Used and writes a CollectionLog. Scans inside a
trip context bump trip_stop.total_scans + emit qr_scanned timeline event.
Bulk scan endpoint processes each scan independently for offline sync.
Triggers QrBalanceLow when household active count drops below threshold.

155 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:53:25 +08:00
13148fab97 feat(backend): complete Module 10 (trips + timeline)
trips, trip_stops, trip_timeline_events. Admin: schedule/show/cancel.
Driver: start, arrive/depart/skip stops, report incident, arrive at
dumpsite, release load (creates dumpsite_release row + tallies trip
load), complete. Every action writes a typed timeline event with GPS.
Trip number auto-generated TRIP-YYYYMMDD-NNN. Promotes
dumpsite_releases.trip_id to a real FK now that trips exists.

148 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:51:52 +08:00
15f9295d34 feat(backend): complete Module 9 (teams + trucks)
trucks (with optional last_known_coordinates POINT 4326),
collection_teams, team_members. Admin CRUD for both. TeamConflictDetector
flags double-assignment of driver/scanner/truck/helper across active
teams; override_conflicts: true bypasses for emergencies. Promotes
routes.default_team_id to a real FK now that collection_teams exists.

144 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:48:40 +08:00
6643b0b1da feat(web): add login + dashboard scaffold with Verde branding
Modern minimalist split-layout login (left brand panel, right form) at
/login. Sign-in posts to /api/v1/auth/login, stores the bearer token in
localStorage, redirects to /dashboard. Demo-account expander auto-fills
the form. Placeholder dashboard fetches /me, shows top nav + stat cards
(values pending), and supports sign-out.

AdminUserSeeder now seeds 4 demo admins (admin/ops/audit/demo @verde.local,
all "password"). Tailwind config gets a Verde green palette + Inter font;
component classes for buttons + form inputs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:35:39 +08:00
de77503cdd feat(backend): complete Module 8 (routes)
routes + route_stops tables. Admin CRUD with stops submitted as an
ordered array (drag-reorder is client-side; sequence is array-index).
Cloning produces an inactive copy with -COPY-XXXX suffix. RouteCalculator
recomputes total_distance_km via ST_Distance_Sphere across stop
coordinates + dumpsite, and estimated_duration_minutes from dwell time
+ travel time at config-driven avg speed (default 25 km/h).
default_team_id stays nullable bigint until Module 9 adds the FK.

139 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:25:04 +08:00
d458e74301 feat(backend): complete Module 7 — QR code system (core)
qr_code_batches + qr_codes tables. State machine via
spatie/laravel-model-states (unassigned → allocated → active → used,
plus expired/voided). Serial format PH-{area}-{YYMM}-{batch}-{code}-
{checksum} with 2-char SHA-256-derived checksum. BatchGenerator
bulk-inserts in chunks. QrAllocator allocates free codes to verified
households (prefers area-targeted batch, falls back to any). Real
HouseholdVerified listener replaces the placeholder. QrBalanceLow
event for Module 11.

Admin: batch CRUD, mark-printed, void code, lifecycle search, PDF
print sheet (24/A4 via dompdf + endroid/qr-code + picqer/barcode).
Resident: list own codes, balance with low_balance flag, activate
allocated codes.

Removed explicit Event::listen for HouseholdVerified — Laravel 11
auto-discovers it via handle() type-hint, and double-registering was
causing double-dispatch.

130 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 02:12:41 +08:00
474b1cfe0b feat(backend): complete Module 6 (dumpsites + geofence)
dumpsites table with both coordinates POINT and boundary_polygon
POLYGON (SRID 4326). Admin CRUD accepts boundary as a list of {lat,lng}
points; ring is auto-closed. Dumpsite::containsPoint() runs ST_Contains
for geofence checks (Module 10 will fire arrived_at_dumpsite from this).
dumpsite_releases schema in place — trip_id stays nullable bigint until
Module 10 adds the FK.

109 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 00:39:14 +08:00
1150a518e8 feat(backend): complete Module 5 (drop-off points + auto-assign)
drop_off_points (with SPATIAL INDEX on coordinates) +
drop_off_capacity_logs. Public nearby query via ST_Distance_Sphere
returns DOPs sorted by distance with distance_meters in payload.
Admin CRUD plus capacity-log endpoint. Household creation auto-assigns
to the nearest active DOP within 25km; resident can re-run the lookup
via POST /households/{uuid}/reassign-drop-off.

97 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 00:11:22 +08:00
4eb2d14e52 feat(backend): complete Module 4 (household registration)
households + household_members tables. Resident endpoints to create one
household (auto-resolves barangay from GPS), upload proof of residency,
manage members. Admin endpoints to list/approve/reject. Approving fires
HouseholdVerified event with a placeholder listener; Module 7 replaces
the body with actual QR batch allocation. Approved households are
immutable to residents; resubmitting after rejection resets to pending.

84 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 00:06:37 +08:00
c8404564fe feat(backend): complete Modules 2 + 3 (geo + user management)
Module 2 — Geographic Data: PSGC tables (regions/provinces/cities/
barangays) with native geometry(polygon|point, 4326) columns; cascading
dropdown endpoints; ST_Contains-based GPS resolution; service-area CRUD
with barangay attach/detach; SamplePsgcSeeder + psgc:import command.

Module 3 — User Management: 5 role-specific profile tables (driver/
helper/scanner/store_partner with verification_status + rejection
reason); profile auto-created on register; admin user CRUD with
filters/pagination, suspend/activate, profile approve/reject;
self-service /me + /me/profile with role-aware validation that blocks
self-approval and resets rejected profiles to pending on resubmit.

69 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:59:56 +08:00
dc297d4cd7 feat(backend): complete Module 1 auth (register/login/OTP/reset)
Closes Module 1: 9 auth endpoints under /api/v1/auth, OTP via SMS
(Semaphore + log + fake drivers), role middleware, role + admin seeders,
27 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:46:53 +08:00
a58e5eb60e feat(backend): scaffold Laravel 11 API with Module 1 foundation
- Laravel 11.51 + PHP 8.4 in backend/
- MySQL 9 connection (DBngin, db: verde)
- Installed Sanctum, Spatie permission/activitylog/model-states,
  matanyadaev/laravel-eloquent-spatial
- API routes prefixed /api/v1 in bootstrap/app.php
- Standard response envelope { success, data, message, errors, meta }
  via ApiResponse + ApiController base class
- Global exception handlers for validation/auth/not-found/http errors
  on api/* routes (always JSON, never redirect to login)
- Extended users migration: uuid, phone+verified_at, role enum
  (admin/resident/driver/helper/scanner/store_partner), status,
  first/middle/last name, avatar_path, preferred_language, fcm_token,
  last_login_at, soft deletes
- User model: HasApiTokens, HasRoles, LogsActivity, SoftDeletes,
  role/status constants, auto-uuid on create
- Health endpoint at GET /api/v1/health verifies DB connection
- backend/CLAUDE.md documenting backend conventions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:34:40 +08:00