This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-Admin/docs/admin-backend-spec.md
kirukib c2fd9d6431 first commit
Scaffold Gishen Admin: React/Vite shadcn console with role modules, EN/AM i18n, mocks, and backend spec.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 18:01:56 +03:00

216 lines
8.8 KiB
Markdown

# Gishen Admin — Backend Spec Sheet
**Repo:** Gishen-Admin
**Audience:** Shared backend team (consolidate with Ecom / Mobile / B2B sheets later)
**Base URL (TBD):** `https://api.gishen.example/v1`
**Auth:** Bearer JWT for staff roles
**Mocks:** Admin SPA uses in-memory mocks until `VITE_USE_MOCKS=false` and `VITE_API_BASE_URL` point here.
## Changelog
| Date | Change |
| --- | --- |
| 2026-08-06 | Scaffold: conventions, roles, auth, empty module sections |
| 2026-08-06 | Shell + RBAC + preferredLocale |
| 2026-08-06 | Pharmacist: prescriptions, branch orders |
| 2026-08-06 | Stock + Procurement |
| 2026-08-06 | Finance, orgs create + pending self-reg approval |
| 2026-08-06 | Marketing CRM / loyalty / campaigns |
| 2026-08-06 | Dispatch board + Telegram bot events |
| 2026-08-06 | Super Admin team/inbox/audit/settings + FAQ bilingual |
| 2026-08-06 | Data migration import jobs |
## Conventions
| Item | Convention |
| --- | --- |
| Content type | `application/json` (multipart for imports / uploads) |
| IDs | UUID v4 |
| Money | Integer ETB (major units for Admin UI demos; align platform-wide later) |
| Errors | `{ "error": { "code": string, "message": string, "details"?: object } }` |
| Pagination | `?page=&limit=` → `{ data, meta: { page, limit, total } }` |
## Staff roles
`pharmacist` · `stock_manager` · `procurement` · `finance` · `marketing_manager` · `operations` · `super_admin`
Pharmacist (and optionally stock) sessions include `branchId`.
---
## Auth & me
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| POST | `/auth/staff/login` | — | Email/password → tokens + user |
| POST | `/auth/refresh` | refresh | Rotate access |
| POST | `/auth/logout` | staff | Revoke |
| GET | `/auth/me` | staff | Current principal, roles, branchId |
| PATCH | `/users/me` | staff | `{ preferredLocale?: "en"\|"am", name? }` |
**Login response sketch:**
```json
{
"accessToken": "...",
"refreshToken": "...",
"user": {
"id": "uuid",
"name": "Hana Pharmacist",
"email": "pharmacist@gishen.et",
"role": "pharmacist",
"branchId": "uuid",
"preferredLocale": "en"
}
}
```
Mock key: `authStore.login` → `/auth/staff/login`
---
## Orders (branch inbox)
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/pharmacy/orders` | pharmacist, operations, super_admin | `?branchId=` required for pharmacist |
| POST | `/orders/:id/confirm` | pharmacist, super_admin | Confirm stock |
| POST | `/orders/:id/assign-rider` | pharmacist, operations, super_admin | `{ riderId }` |
| PATCH | `/orders/:id/status` | pharmacist, operations, super_admin | Status lifecycle |
Mock: `mocks/data.orders`
---
## Prescriptions
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/pharmacy/prescriptions` | pharmacist, super_admin | Branch-scoped queue |
| POST | `/admin/prescriptions/:id/verify` | pharmacist, super_admin | `{ status: approved\|queried\|rejected, qtyAdjustments?, substitute?, notes? }` |
| POST | `/pharmacy/prescriptions/:id/dispense` | pharmacist | `{ batch, quantity }` stamped pharmacistId + time |
| GET | `/pharmacy/prescriptions/controlled-report` | pharmacist, super_admin | Controlled-substance report |
| GET | `/pharmacy/refills` | pharmacist, super_admin | Days-of-supply / script expiry oversight |
---
## Stock & ERP
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/pharmacy/inventory` | stock_manager, pharmacist (read), procurement (read), super_admin | Per-branch stock |
| GET | `/integrations/erp/sync-status` | stock_manager, super_admin | Last sync |
| GET | `/admin/stock/discrepancies` | stock_manager, super_admin | Platform vs ERP |
| POST | `/admin/stock/discrepancies/:id/resolve` | stock_manager, super_admin | One-click resolve |
| GET/PUT | `/admin/stock/field-ownership` | stock_manager, super_admin | ERP vs platform field owners |
| POST | `/admin/stock/entry/suggest` | stock_manager, super_admin | Fuzzy duplicate suggestions body `{ query }` |
| GET | `/admin/stock/merge-proposals` | stock_manager, super_admin | Merge queue |
| POST | `/admin/stock/merge-proposals/:id/approve` | stock_manager, super_admin | Human approve; reversible 30d |
| GET | `/admin/stock/alerts` | stock_manager, super_admin | Low stock / expiry watchlist |
| POST | `/admin/stock/transfers` | stock_manager, super_admin | Create/approve transfer (owner) |
---
## Procurement
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/admin/procurement/reports` | procurement, stock_manager, super_admin | Dead-stock / fast-mover |
| GET | `/admin/procurement/reorder-recommendations` | procurement, super_admin | From velocity |
| POST | `/admin/stock/transfers/request` | procurement, super_admin | Request only; Stock Manager approves |
---
## Finance & organisations
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/admin/finance/settlements` | finance, super_admin | Daily by channel |
| GET | `/admin/finance/reconciliations` | finance, super_admin | Matched to orders |
| GET/PUT | `/admin/finance/gateways` | finance, super_admin | Enable/disable Chapa, ArifPay, Telebirr, M-Pesa |
| POST | `/admin/finance/refunds` | finance, super_admin | Refund handling |
| GET | `/admin/finance/loyalty-liability` | finance, super_admin | Monthly Birr liability |
| GET | `/admin/organisations` | finance, super_admin | List |
| POST | `/admin/organisations` | finance, super_admin | **Create org from Admin** (active) |
| GET | `/admin/organisations/pending` | finance, super_admin | Self-register queue |
| POST | `/admin/organisations/:id/approve` | finance, super_admin | Activate credit |
| POST | `/admin/organisations/:id/reject` | finance, super_admin | Reject |
| GET | `/admin/organisations/:id/statements` | finance, super_admin | Consolidated invoices |
**Cross-repo:** B2B portal `POST /company/register` creates `status=pending`. Admin approve activates credit.
---
## Marketing
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/admin/crm/customers` | marketing_manager, super_admin | Read profiles |
| GET | `/admin/crm/segments` | marketing_manager, super_admin | Self-updating segments |
| GET/POST | `/admin/campaigns` | marketing_manager, super_admin | Compose/schedule SMS/Telegram/push |
| GET/PUT | `/admin/loyalty/config` | marketing_manager, super_admin | Earn/tiers/referral bonus |
| GET | `/admin/kpi/summary` | marketing_manager, finance, super_admin | Scoped KPIs |
---
## Dispatch & Telegram bot
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/dispatch/board` | operations, super_admin | Paid + Rx-approved queue |
| POST | `/dispatch/trips` | operations, super_admin | Batch fulfilments |
| POST | `/dispatch/trips/:id/assign` | operations, super_admin | `{ riderId }` → emits Telegram manifest |
| POST | `/dispatch/bot/webhook` | service | Bot status + PoD callbacks |
| GET | `/dispatch/intake` | operations, super_admin | Partner/POS webhook monitor |
| POST | `/dispatch/riders` | operations, super_admin | Link Telegram account |
**Events:** `trip.assigned` → bot push; `trip.status_updated` → board + customer tracking.
---
## FAQ (bilingual)
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/admin/faq` | all staff | Published articles |
| POST | `/admin/faq` | marketing_manager, super_admin | Create |
| PUT | `/admin/faq/:id` | marketing_manager, super_admin | Update / publish |
| DELETE | `/admin/faq/:id` | super_admin | Delete |
Fields: `title_en`, `title_am`, `body_en`, `body_am`, `category`, `published`.
---
## Team, inbox, audit, settings
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET/POST | `/admin/users` | super_admin | Staff + role + branch |
| GET | `/admin/inbox/threads` | super_admin | Chatwoot/Telegram/WhatsApp attached to customer |
| GET | `/admin/audit` | super_admin | Audit log |
| GET/PUT | `/admin/settings` | super_admin | Retention, access controls |
---
## Data migration / imports
| Method | Path | Roles | Description |
| --- | --- | --- | --- |
| GET | `/admin/imports/templates` | stock_manager, finance, operations, super_admin | Entity schemas |
| POST | `/admin/imports` | same | Multipart file upload |
| POST | `/admin/imports/:id/map` | same | Column mapping (+ save template) |
| POST | `/admin/imports/:id/validate` | same | Dry-run row errors |
| POST | `/admin/imports/:id/commit` | same | Upsert commit |
| GET | `/admin/imports` | same | Job history |
| CRUD | `/admin/imports/mapping-templates` | same | Saved presets |
Entity templates: `stock`, `catalog`, `hr_members`, `branches`, `riders`, `generic`.
---
## Open questions
1. Money units: ETB major vs cents — keep consistent with Ecom/B2B sheets
2. Driver channel assumption: Telegram bot (flag if SMS/WhatsApp preferred)
3. Checkout entitlement-split: shared component across Ecom/Mobile/B2B (out of Admin UI)