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-B2B/docs/backend/OVERVIEW.md
kirukib 3778801ef5 Ship Gishen B2B institutional portal with polished layout and mock-backed flows.
Deliver role-aware shell (sidebar, breadcrumbs, quick search, tables, detail/create layouts), locale-ready pages, shared backend/feature docs, and Vercel project config so HR, finance, and members can demo against typed mocks.

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

5.5 KiB

Backend overview

Living spec for the shared platform API consumed by Gishen-B2B. This repo implements mocks typed to this contract; the backend service is consolidated later from B2B, Ecom, Mobile, and Admin spec sheets.

Workspace: /Users/kirukib/Desktop/Yaltopia Project/Gishen-B2B

Base URL (future)

https://api.gishenpharmacy.org/v1

Mock adapters in this repo live under src/lib/api/ and src/mocks/.

Tenancy

  • Every authenticated request (except public registration) is scoped to an organisation via orgId on the session or explicit path prefix.
  • Org lifecycle: pending_activation → active → suspended | closed.
  • Pending orgs: SUPER_USER may read status and submitted registration; cannot create members, packages, or migration commits until Admin activates.
X-Org-Id: org_01H...

For single-org sessions, orgId is implicit from JWT/session. Multi-org users (rare in B2B) pass X-Org-Id.

Authentication

Mode (this phase) Description
Mock demo /login role selector sets session cookie with role + org + user
Production (future) OAuth2 / magic link / SSO — TBD with platform auth

Session shape

See entities/session-user.md.

JWT claims (future)

{
  "sub": "usr_01H...",
  "org_id": "org_01H...",
  "roles": ["HR_ADMIN", "FINANCE"],
  "locale": "am",
  "iat": 1710000000,
  "exp": 1710003600
}

RBAC matrix

Resource / action SUPER_USER HR_ADMIN FINANCE MEMBER
Org profile (commercial read) ✓ ✓ (active only) ✓ (active only) —
Org registration submit ✓ (public path) — — —
Departments CRUD ✓ ✓ read —
Members CRUD / import / invite ✓ ✓ read metadata own row
Packages CRUD ✓ ✓ read own assignment
Migration jobs ✓ ✓ read history —
Finance spend / statements ✓ read aggregates ✓ —
Finance approvals ✓ — ✓ —
Member allowance / orders ✓ — — ✓
Prescriptions (clinical) ✓ full withheld withheld own only
Settings / verification ✓ ✓ — —

Clinical withhold: HR_ADMIN and FINANCE never receive prescription images, medicine line items, dosages, prescriber notes, or diagnosis-related fields. Aggregates (e.g. “Rx order — ETB 450, category: chronic”) may appear in finance spend. SUPER_USER bypasses withhold for support/disputes.

Error model

All errors return:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Human-readable summary",
    "details": [
      { "field": "email", "code": "INVALID_FORMAT", "message": "..." }
    ],
    "request_id": "req_01H..."
  }
}

Standard HTTP status codes

Status Usage
400 Validation failed, malformed JSON
401 Missing or expired session
403 Authenticated but role/org forbids action; clinical withhold
404 Resource not found or not visible in tenant
409 Conflict (duplicate member, job already committed)
422 Business rule violation (org pending, credit exceeded)
429 Rate limit
500 Internal error

Error codes (catalog)

Code HTTP Description
UNAUTHENTICATED 401 No valid session
FORBIDDEN 403 Role cannot perform action
CLINICAL_WITHHELD 403 Clinical field requested by HR/Finance
ORG_PENDING 422 Org not yet activated by Admin
ORG_SUSPENDED 422 Org suspended
VALIDATION_FAILED 400 Field-level validation
DUPLICATE_MEMBER 409 Phone/email/employee_id conflict
CREDIT_LIMIT_EXCEEDED 422 Would exceed org credit
MIGRATION_JOB_LOCKED 409 Job already committed or rolled back
INVITE_EXPIRED 422 Invite token expired
NOT_FOUND 404 Generic not found

Pagination

List endpoints accept:

?page=1&page_size=25&sort=-created_at&q=search

Response envelope:

{
  "data": [ ... ],
  "pagination": {
    "page": 1,
    "page_size": 25,
    "total_items": 142,
    "total_pages": 6
  }
}

Default page_size: 25. Max: 100.

Filtering & date ranges

Finance and spend endpoints accept:

?from=2026-01-01&to=2026-01-31&department_id=dept_01H...

ISO 8601 dates in org timezone (default Africa/Addis_Ababa).

File uploads

Multipart for Rx images and migration files:

POST /v1/... 
Content-Type: multipart/form-data

Max file size (Rx page): 10 MB. Accepted: image/jpeg, image/png, application/pdf.

Migration uploads: 50 MB .xlsx, .xls, .csv.

Idempotency

Mutating endpoints that create billing or migration commits accept:

Idempotency-Key: <uuid>

Duplicate keys within 24h return the original response.

Webhooks / events

Domain events published to platform bus; see events/README.md. B2B emits and consumes events for org registration, migration, and prescriptions.

Environment (Vercel frontend)

Variable Purpose
NEXT_PUBLIC_API_BASE_URL Platform API base (mock or real)
NEXT_PUBLIC_MOCK_AUTH true for demo role selector
NEXT_PUBLIC_DEFAULT_LOCALE en

Document production URL in this file when first Vercel deploy is finalized.