Skip to content

cases and backend

Author: Ridwan Egbeyemi (PM, Swap) Date: 18 May 2026

The 16 operational scenarios we’ve designed for, and the backend services needed to power resolution across the swap app (station manager) and Atlas (support specialist / PM).


# Scenario Captured in the swap app Resolved in Atlas Severity
Station
1 Temporary swap (away from primary station) Inline alert on rider profile · request authorization · park while support decides Three decisions: allow + ₦500 fee · allow + waive fee · deny (rider returns to primary) · pattern flag if 3+/week Med
2 Primary station change Initiated from support page · scan/license lookup → 2-step form → pending status → approval push Approve/deny · both stations & rider notified · effective immediately or scheduled Low
Wallet & payments — scenarios 4, 6, 7, 8 share one entry point: the “How is the rider paying?” alert on the rider profile (4 actions: pay from station wallet · show funding accounts · log rider’s receipt · funds at another station). The four backend paths below remain distinct.
3 Wallet not loading Inline alert · retry · park while support rebuilds record Force wallet rebuild from ledger · push manager when ready Med
4 Insufficient balance Consolidated alert · “Show funding accounts” opens Opay / Paystack / Monnify n/a — resolves itself when funds arrive Med
5 Daily-fee deduction fails Manager taps “Draw daily fee”, service rejects · retry · send to support Engineering follow-up · safe retry (idempotent · no double-charge) Med
6 Funding not reflecting Consolidated alert · “Log rider’s receipt” opens reconcile sheet · single OR multiple payments · virtual-account + source-bank pickers Live settlement-feed tail · one-time overdraft / wait / deny High
7 Station-wallet subscription payment failed Consolidated alert · “Pay from station wallet” then transfer fails · retry · escalate to support Confirm engineering fix · retry transfer on station’s behalf Med
8 Funds at another station Consolidated alert · “Funds at another station” opens dispute sheet · photo evidence + manager picker Click-to-call both managers · move ₦12,000 from station A’s wallet → rider wallet · resolve High
8a Funding account number invalid Consolidated alert · “Funding account invalid” opens capture sheet (provider · shown account number · rider bank error) · waiting card · resume push when fixed Support escalates internally to engineering to compare provider-generated account vs what the rider sees · audit captures the affected VA and provider Med
Battery — every battery issue traces back to a single root cause: a field-support staff did a swap without using the app, so both batteries (old + new) end up with the wrong digital position. That single off-app swap surfaces as up to three downstream scenarios (9, 10, 11) on later swaps. Scenario 16 is a separate problem — a typo/worn printed serial that returns no inventory data when scanned. Scenarios 9/10/11 resolve with a single-click record mutation in Atlas (no relabel). Only 16 keeps the print-and-stick mechanic.
9 Release-and-reassign (old battery) Inline alert on scan-new-battery · “Send to support” → captured-context sheet (rider · scanned serial · last-known keke) · waiting card · resume push when released Support reviews + calls manager · one click releases the battery from the previous rider and reassigns it to this station · audit captures the actor + delta Med
10 Station claim (new battery) Inline alert on scan-new-battery · “Send to support” → captured-context sheet (where system thinks it is) · waiting card · resume push when claimed Support reviews + calls manager (and other-station manager when relevant) · one click claims it for the calling station · audit captures the inter-station transfer Med
11 Old-battery attribution (rider) Empty-state on the VCU “Current battery in keke” card · “Send to support” → captured-context sheet (rider + keke history) · waiting card · resume push when attributed Support reviews keke history + calls manager · one click attributes a candidate old-battery serial to the keke · swap-app refreshes the VCU card so the manager can advance Med
16 Serial mismatch (new battery) Inline alert on scan-new-battery — scanned serial returns no data · “Send to support” → captured-context sheet · waiting card · ready card with corrected serial · manager copies, prints, sticks, rescans (validated against corrected serial) Support finds the closest match in inventory and pushes the corrected serial back; audit records the relabel; rescan mismatches captured separately Low
VCU connection Scenarios 12 / 13 / 14 deferred — bluetooth pairing stays in the swap app, but the unlock-fail / internet-fallback / manual-code path is being redesigned to live entirely in-app (no support specialist in the loop). Until that design lands these are not surfaced in the backoffice.
Next-day follow-up
15 Outstanding overdraft blocks new swap Inline danger alert on rider profile · single CTA “Open case ISS-XXXX” · no manager override Atlas Ops must reconcile against late settlement, or write off the prior swap, before another is permitted High

Numbering: battery group went from 2 → 4 — 9/10/11 are the three downstream surfaces of the same off-app-swap root cause; 16 is the standalone serial-mismatch path. VCU connection still covers three distinct paths through the same screen; #15 is the next-day consequence of an unreconciled #6.


Eight services are needed end-to-end. Some exist today; most need to be built or extended.

  • Balance, debit, credit (all idempotent — keyed by swap_id or txn_id).
  • Support for overdraft with auto-reconciliation against the next inbound settlement.
  • Overdraft eligibility guardrail. The overdraft_credit endpoint must reject requests unless the originating case type is in the wallet group (funding-not-reflecting, funds-at-another-station, station-wallet-payment-failed, daily-fee-deduction-failed, funding-account-invalid). A case ID is mandatory on every overdraft call and the server cross-checks the case type before crediting. The Atlas UI mirrors this with an explicit “case eligible · confirm” checkbox; the “Issue overdraft” button stays disabled until the support specialist ticks it. Closes the loophole from the 17 May incident where an overdraft was credited to a rider whose case had no wallet need.
  • Outstanding-overdraft flag that survives across days: while a prior overdraft is unsettled, the wallet exposes swap_eligible: false with a pointer to the originating case. Swap-app reads this on every scan and blocks the swap at the rider-profile step until Ops reconciles or writes off. Powers scenario 15.
  • Read API streams to swap-app on every screen that surfaces wallet state.
  • Powers scenarios 3, 4, 5, 6, 7, 8, 15.
  • Each station has a wallet balance. The on-duty manager operates it; ownership and reconciliation belong to the station, not the individual operator.
  • Station wallet → rider subscription payment (idempotent, atomic, with reversal hooks).
  • Cross-station transfer (debit station A’s wallet, credit rider’s wallet at station B) — powers scenario 8.
  • Powers scenarios 4 (station-pays path), 7, 8.
  • Webhook + polling endpoints for Opay, Paystack, Sterling.
  • Match inbound transfers to rider phone numbers / sender accounts.
  • Live tail visible to support in Atlas for the funding-not-reflecting flow.
  • Store: virtual account hit, sender bank, amount, timestamp, rider-match confidence.
  • Powers scenarios 4 (funding path), 6. The sender-bank field is the dataset for “which banks settle slowest?” reports.
  • Battery serial → current location mapping. Location is either a station, a keke, a charge-hub, or in-transit between any two.
  • States: at-station, in-transit, in-keke, at-charge-hub, quarantined.
  • Release-and-reassign endpoint — atomically detach a battery from a previous keke and attach it to a station. Powers scenario 9. Idempotent on (battery_serial, target_station_id).
  • Station-claim endpoint — atomically move a battery from its current (incorrect) location to the calling station. Same shape as release-and-reassign but does not require a “from-keke” — the from-side can be another station or another keke. Powers scenario 10.
  • Old-battery-attribute endpoint — assign a candidate battery serial to a keke that has no current battery on record. Used when the rider arrives and the VCU pair returns no current-battery info. Powers scenario 11.
  • Issue-corrected-serial endpoint — when a manager scans a new battery and the serial returns no data (typo / worn / off-by-one printed label), support reviews and pushes back the closest matching BP-YYMMDD-NNNNNNNN serial. Manager copies, prints, sticks; subsequent scan is validated against the issued serial. Mismatches are captured for audit. Powers scenario 16.
  • All four endpoints write audit entries with the support actor, the manager, both location records (before/after), and the originating case ID.
  • No record is ever delisted; corrections move position only. The bad-position population dies out over time as future swaps trigger these flows.
  • Powers scenarios 9, 10, 11, 16.
  • Station record (location, type, capacity, opening hours).
  • Manager record (name, phone, current station, station-wallet balance).
  • Rider → primary station assignment with history (for primary-change requests).
  • Powers scenarios 1, 2, 8 (and the contact-card click-to-call data everywhere in Atlas).
  • Bluetooth route (mobile-app-initiated, low-latency) — the pairing that the manager runs at every swap.
  • Internet / manual-unlock fallbacks deferred — the team is redesigning the unlock-fail path to live entirely in-app, with no support specialist in the loop. Until that design lands, the backoffice carries no VCU resolution surface.
  • Case state machine: open → in-progress → pending-external → resolved | denied | escalated.
  • Routing: round-robin within severity weight, with SLA timers.
  • Issue typing — each of the 16 scenarios above has a canonical case type.
  • Linked engineering tickets (for scenarios 5, 7).
  • Powers everything in Atlas — queue dashboard, issue detail, resolution actions.
  • Append-only log: every approve / deny / transfer / call / note / code-issue / retry by every staff member.
  • Captures actor, action_type, target, delta, timestamp, linked_case_id, internal_note.
  • Query API filterable by staff, action type, issue type, time window — powers both Tunde’s “My audit trail” and Ridwan’s PM dashboard team feed & anomaly detection.
  • Immutable — no edits, no deletes; corrections are new entries that reference the original.

Every money-moving action (wallet debit, manager transfer, overdraft credit, daily-fee draw, retry of a failed transfer) must accept a client-generated idempotency key. Retries with the same key return the original result; never double-charge.

Push to manager phone (deep-linking back into the swap), in-app notification banner for the parked-swap resume flow. Triggered by: case-resolved, funding-arrived, ops-approved, code-issued. Audit-trail entries are written first, notification fires second.

  • Swap-app polls GET /v1/wallet/balance every 30s when a parked swap is active, so the resume push can be triggered from inbound settlement.
  • Atlas streams the settlement feed via SSE / WebSocket for the support specialist’s live reconciliation view (scenario 6).
  • Urgent in-swap blockers (funding-not-reflecting, funds-other, daily-fee-fail): 5–15 min.
  • Medium (wallet-fail, battery-transfer, manager-top-up-fail): 15 min.
  • Low (primary-change, battery-conflict-audit): 24 h.

Atlas dialer routes through the support specialist’s soft-phone (Twilio/Africa’s Talking). Number-of-calls and call-duration are written to the audit trail automatically — no user action needed.


For engineering scoping, which services each scenario touches:

Scenario Rider wallet Stn wallet VA ingest Inventory Stn/mgr registry VCU bus Case svc Audit
1 Temp swap ● ● ●
2 Primary change ● ● ●
3 Wallet not loading ● ● ●
4 Insufficient balance ● ● ● ● ●
5 Deduction fails ● ● ●
6 Funding not reflecting ● ● ● ●
7 Mgr top-up failed ● ● ● ●
8 Funds at another stn ● ● ● ● ●
9 Release & reassign (old) ● ● ● ●
10 Station claim (new) ● ● ● ●
11 Old-battery attribution ● ● ● ●
16 Serial mismatch (new) ● ● ●
15 Overdraft pending ● ● ●