Home-beauty services booking platform (Wecasa-style) for the Dakar / Senegal market. French-only, FCFA, mobile-money payments. Design and frontend are delivered and validated; this brief covers the backend + admin build. (Internal build doc — no commercial terms.)
Stack
- Mobile apps (client + professional): React Native
- Admin dashboard: React JS (web)
- Backend: Node.js + MongoDB
- Payments: built behind a gateway abstraction (
payments.gatewayenum + adapter interface); the concrete mobile-money adapter (Wave / Orange Money via PayDunya or CinetPay) is wired at integration — booking / commission / wallet / webhook logic is built against the interface now. - Native: push notifications (FCM/APNs), maps/geolocation + geocoding (address & booking), SMS (phone-OTP).
Roles (3)
| Role | Created by | Surface |
|---|---|---|
client |
Self-signup (phone, women-only — no gender selection) | Client app |
provider |
Admin only — NO public provider signup | Professional app |
admin |
Admin only | Admin dashboard |
Lock the exact role enum strings against the validated frontend at integration.
Core flows
Authentication — phone number + mandatory OTP (SMS); email optional secondary identifier. Sensitive actions (delete account, password change) re-verified.
Booking (auto-assign — "Uber-style"):
flowchart LR
A[Client: service / time / address] --> B{Confirm + pay}
B --> C[Broadcast to in-zone pros]
C --> D((First to accept wins))
D --> E[ongoing]
E --> F[completed]
B -.-> X[cancelled]
- Client picks service → date/time → address → confirms.
- Payment is taken (cashless).
- Request is broadcast to available, in-zone professionals.
- First professional to accept wins the job; others see it close.
- Status lifecycle:
pending → confirmed → ongoing → completed → cancelled.
The client does not pick a specific professional in MVP (deferred — keep the "browse providers" screen out of the booking path).
Payments & wallet:
- Client pays in-app → platform receives funds → platform commission deducted (admin-configurable %) → remainder credited to the professional's in-app wallet ledger.
- Professionals request withdrawals; admin approves/rejects. Wallet is a funded ledger — every balance change has a traceable source.
- Admin never sees client card/wallet credentials.
Admin panel — required capabilities
- Manage professionals (create, edit, deactivate/block) and clients (block).
- Manage bookings — view all, accept/reject/edit, assign a professional, change status.
- Manage service categories, services, prices, and photos (fully editable, no code change).
- Manage service zones / areas.
- View commissions / transactions and basic stats (users, bookings, revenue overview).
- Send notifications / announcements.
Data model (key entities)
users (role, phone, verification state, profile, addresses) · providers (services offered, availability, zones, wallet balance, rating) · services & categories (admin-managed collections, with price + photo) · bookings (service, slot, address, status, assigned provider, amount) · transactions (payment, commission split, wallet credits) · withdrawals (request, status, approver) · zones · notifications. Declare soft vs hard delete per entity; pick-lists (categories) are admin-managed collections, not free-text.
Business rules (highlights)
- Auto-assign integrity — a job can be accepted by exactly one provider; race-safe.
- 5-day / availability rules as specified for request lifecycle.
- Commission split is atomic with payment settlement; wallet credit and withdrawal never produce an unfunded balance.
- Ownership & authorization — every read/write scoped to the correct role; providers/admins are admin-provisioned only.
- Never return fake/dummy data — real empty states everywhere.
Out of scope (do NOT build now)
- Promo / discount codes — readiness only ("prepared-for" in schema), not built.
- Client-chooses-provider.
- Premium-provider subscription.
- English localisation (French-only at launch).
Acceptance gates
- Clean typecheck + build (entry and exit).
- Backend e2e smoke green — booking → payment (abstracted) → commission → wallet credit → withdrawal all transition correctly.
- Contract smoke green (standard response envelope + auth-guarded endpoints).
- No dummy strings / placeholder images / mock arrays.
- Every screen wired to a real endpoint; 0 unaccounted screens.
Open confirmations (pre/at kickoff)
- Email = full alternate login (password) or optional profile field only?
- Routing mode the frontend uses (Expo Router vs React Navigation).
- Native provider keys (push / maps / SMS) — own them before build, or these ship simulated.
Full 31-section requirement document + PRD available internally. Build brief — distribute to the build team.