Admin Commerce Modules
The Commerce group in the ops panel (ops.pasarseken.id) gives admins financial and logistical visibility into the live platform. Four modules: Escrow Manager, Logistics Hub, Logistics Heatmap, and Voucher Engine.
Escrow Manager​
KPI cards​
| Card | Source |
|---|---|
| Total Held in Escrow | orders, sum of total_paid where funds_status = "HELD" |
| Frozen (Disputes) | orders, sum of total_paid in dispute states |
| Ready for Payout | orders, sum of item_price for COMPLETED orders |
| BPF Revenue | ledger_entries, sum of protection fee entries |
The Escrow Balance Trend area chart shows daily held vs released for the last 7 days, computed from getCachedOrders().
Endpoints​
| Endpoint | Purpose |
|---|---|
GET /admin/escrow-summary-live | Live KPIs, reads orders + ledger cache |
GET /admin/escrow-trend | 7-day held/released trend, reads orders cache |
POST /admin/escrow-check/run | Trigger escrow automation timer |
Implementation notes​
_ledgerCacheInstinshared-cache.tsxmust havefetchFn: getLedgerFromTablepointing toSupabaseOrderRepository.findAllLedgerEntries(). Without it,getCachedLedger()reads from the retired KV prefixledger:and always returns empty, BPF Revenue shows Rp 0. (Fixed PS-360, 2026-05-12.)- Allowed roles for escrow endpoints:
administrator,finance.
Logistics Hub​
What it shows​
- Active Shipments table: all shipments with order context: seller name, buyer name, order status, funds status.
- Late Orders table: orders in
SHIPPEDstatus for more than 72 hours.
Endpoint​
GET /admin/shipments
The shipments table only stores: id, order_id, courier, tracking_no, status, extra, created_at, updated_at. It does not store seller_name, buyer_name, order_status, or funds_status.
The endpoint fetches getCachedOrders() in parallel with shipmentRepo.findAllRaw(), builds an order_id → order map, and merges the four missing fields into each shipment row before pagination.
Logistics Heatmap (Logistics Control Tower)​
Three panels​
- Indonesia map: SVG regions colored by delivery speed status.
- Courier Health: per-courier on-time rate, average delivery days, active shipments.
- Waybill Management: full shipment table with search, filter, sort, and per-row refresh.
Region status vocabulary​
Computed from avgDeliveryDays in GET /admin/logistics-stats:
| avgDeliveryDays | status | Color |
|---|---|---|
| ≤ 2 | fast | Teal (#006D77) |
| ≤ 3 | normal | Blue (#3B82F6) |
| ≤ 5 | slow | Orange (#F97316) |
| > 5 | delayed | Red (#EF4444) |
The frontend statusColor() function in LogisticsHeatmap.tsx handles exactly these four values. Any other value renders gray.
Waybill refresh​
Each row has a refresh button that calls GET /shipping/track/:tracking_no?courier=<code>. On success, the row's status and last-update timestamp are updated in local state and the latest courier status appears in a success toast. Rows with no tracking number ("N/A") show an error toast immediately without hitting the API.
Voucher Engine​
Voucher types​
| Type | Color | Behaviour |
|---|---|---|
flat_discount | Teal (#006D77) | Fixed IDR amount off |
percentage | Amber (#F59E0B) | Percentage off, optionally capped |
free_shipping | Green (#059669) | Waives shipping cost |
bpf_waiver | Blue (#2563EB) | Waives buyer protection fee |
CRUD endpoints​
All five endpoints accept roles administrator and marketing:
| Method | Path | Action |
|---|---|---|
GET | /admin/vouchers | List all vouchers + aggregate stats |
POST | /admin/vouchers | Create voucher |
PUT | /admin/vouchers/:id | Update voucher fields |
PUT | /admin/vouchers/:id/status | Activate or deactivate |
DELETE | /admin/vouchers/:id | Soft-delete (sets deleted_at) |
Constraints​
- Purple (
#8B5CF6) is banned fromVoucherEngine.tsxper BRAND-01. Use amber (#F59E0B) for the percentage type chip and green (#10B981) for positive revenue metrics. - Both
administratorandmarketingroles must be in every voucher endpoint's role array. Marketing-only restriction locks out ops admins.