Door-to-door delivery
Registered customers order from a store for home delivery. Managers accept and assign (or riders self-claim from the open pool). Riders use the installable /delivery PWA, the Flutter mobile app, or the Sanctum JSON API. After COD deliveries, cash is returned to the store cashier and settled against the rider’s balance.
Store setup
- Edit the store → enable Door-to-door delivery, optionally open job pool, and set the service charge.
- Create a staff user with the Delivery role for that store.
- Enable customer portal login and password.
- Give cashiers the Receive COD permission (
delivery.cod.receive) so they can take cash handovers — built-in Cashier and Manager roles include this by default. - Configure payment gateways (Settings → Payment gateways) for real online pay; without gateways, online is mocked.
- Configure SMS/FCM under Settings → SMS & Push (Twilio, Bangladesh HTTP SMS, or log driver).
Customer ordering
Sign in at /customer/login. Checkout supports COD or online. When gateways are enabled, checkout opens a payment link and polls until paid. Optional browser GPS is stored on the order for the live map.
Store operations
Sales → Delivery orders: accept, assign, print, cancel. Filter by channel (online storefront, customer portal, API). Storefront orders show an Online storefront badge. The order live map shows the customer destination (home pin) and all store delivery staff currently sharing GPS (scooter pins). Hover a pin for customer or rider details; the assigned rider is highlighted in blue with route/ETA.
Public web shop setup is documented under Online storefront. Portal vs storefront share the same delivery order screens and rider tools.
Sales → COD cash (/admin/delivery-cod): store-wide COD summary by delivery staff — amounts still to collect, cash outstanding with riders (item total, service charge, COD total), and settlements in a date range. Recent handovers list who returned cash and which cashier received it.
COD cash flow
- Customer pays COD at the door. The rider confirms collection on the order (status becomes COD collected). The rider may still be holding that cash.
- Rider returns cash to the store. On the delivery portal, open COD to see totals: still to collect from customers, cash to hand over, and settlements today — each broken into item total, delivery service charge, and COD total.
- Cashier receives COD at Operations → Receive COD (
/cashier/cod-receive), or from the POS overflow menu. Pick the rider, select orders, confirm. Orders become COD settled. If the cashier has an open shift, the amount is recorded as a cash pay-in on that shift.
Permissions: riders use delivery.orders.collect_cod and can view their own summary; cashiers use delivery.cod.receive; managers/admins see the full COD cash report via delivery.orders.view / delivery.cod.view_summary.
Rider portal (PWA)
- My jobs and Open pool (self-claim).
- Overview KPIs with a period selector: Today, Last 3 days, Last week, Last 15 days, This month, Last month, Last 90 days. Charts and “delivered in period” / delivered value follow the selection; live COD and active-job figures stay current.
- COD tab — personal COD summary (to collect / to return / settled today).
- Status: picked up → out for delivery → delivered; COD confirm.
- GPS sharing while the portal is open; Leaflet live map; Install app prompt.
Period is passed as ?range= on /delivery and /delivery/pool (keys: today, 3d, 7d, 15d, this_month, last_month, 90d). Default is last week (7d).
Rider mobile API
Base path /api/delivery. Auth: POST /login → Bearer token (Sanctum).
GET /me,GET /dashboard?range=7d(KPIs / earnings; same range keys as the PWA; response includesrange,range_label, andranges)GET /cod-summary(rider’s COD to collect / to return / settled today)GET /orders,GET /orders/pool,POST /orders/{id}/claimPOST /orders/{id}/status,POST /orders/{id}/collect-codPOST /location,GET /orders/{id}/tracking(includesdistance_km,eta_minutes)POST /device-tokens(FCM)
Demo rider: delivery@demo.test / delivery1234.
Customer mobile API
Base path /api/customer. Auth: POST /login with store_code, login (email/phone), password → Bearer token (Sanctum on customers).
GET /me,PUT /password,GET /catalogGET/POST /addresses,PUT/DELETE /addresses/{id}POST /checkout,GET /orders,GET /orders/{id}GET /orders/{id}/tracking(rider pin + ETA/distance)POST /orders/{id}/pay,GET /orders/{id}/payment-statusPOST /orders/{id}/cancel,POST /orders/{id}/reorderPOST /device-tokens(FCM)
Flutter app
Dual-role Customer & Rider app lives in /mobile. See mobile/README.md. Maps use OpenStreetMap via flutter_map; tracking polls every 5 seconds while the map screen is open.
- Home and Earnings share a period menu (same ranges as the web portal) and call
GET /api/delivery/dashboard?range=…. - Riders still confirm COD on the job; store settlement is done by the cashier on the web POS / Receive COD screen.