Pharmacists can flag and resolve Rx risk/ops issues on the queue and detail pages; master and admin backend sheets document the flags contract (Mob still TBD). Co-authored-by: Cursor <cursoragent@cursor.com>
262 lines
7.3 KiB
TypeScript
262 lines
7.3 KiB
TypeScript
export type StaffRole =
|
|
| 'pharmacist'
|
|
| 'stock_manager'
|
|
| 'procurement'
|
|
| 'finance'
|
|
| 'marketing_manager'
|
|
| 'operations'
|
|
| 'super_admin'
|
|
|
|
export type ModuleKey =
|
|
| 'dashboard'
|
|
| 'orders'
|
|
| 'pos'
|
|
| 'prescriptions'
|
|
| 'stock'
|
|
| 'procurement'
|
|
| 'finance'
|
|
| 'organisations'
|
|
| 'marketing'
|
|
| 'crm'
|
|
| 'loyalty'
|
|
| 'campaigns'
|
|
| 'dispatch'
|
|
| 'team'
|
|
| 'audit'
|
|
| 'faq'
|
|
| 'faq_write'
|
|
| 'settings'
|
|
| 'migrations'
|
|
| 'analytics'
|
|
|
|
/** How the current session was established (mock or real IdP). */
|
|
export type AuthProvider = 'email' | 'google' | 'phone' | 'telegram'
|
|
|
|
export interface StaffUser {
|
|
id: string
|
|
name: string
|
|
email: string
|
|
role: StaffRole
|
|
branchId?: string
|
|
branchName?: string
|
|
preferredLocale?: 'en' | 'am'
|
|
/** Profile photo URL when the account has one. */
|
|
avatarUrl?: string
|
|
/** Provider used for this session (email, Google, phone OTP, Telegram). */
|
|
authProvider?: AuthProvider
|
|
}
|
|
|
|
export interface Branch {
|
|
id: string
|
|
name: string
|
|
zone: string
|
|
phone: string
|
|
}
|
|
|
|
export type OrganisationType = 'corporate' | 'hospital' | 'clinic' | 'ngo' | 'other'
|
|
|
|
/**
|
|
* How often a prescribed medication should be taken.
|
|
* Aligns with common sig codes; `QXH` uses `intervalHours`, `custom` relies on `times`.
|
|
*/
|
|
export type DosingFrequency = 'QD' | 'BID' | 'TID' | 'QID' | 'QXH' | 'custom'
|
|
|
|
/** Single medication line on a prescription (Rx item / sig). */
|
|
export interface PrescriptionItem {
|
|
name: string
|
|
qty: number
|
|
controlled?: boolean
|
|
/** Dosing frequency (BID, TID, every N hours, etc.). */
|
|
frequency?: DosingFrequency
|
|
/** Hours between doses when `frequency === 'QXH'`. */
|
|
intervalHours?: number
|
|
/**
|
|
* Clock times (HH:mm, 24h) when the dose should be taken.
|
|
* Same shape as mobile `Reminder.times` for patient notifications.
|
|
*/
|
|
times?: string[]
|
|
}
|
|
|
|
/**
|
|
* Pharmacist / staff operational review flags on a prescription
|
|
* (distinct from line-item `controlled` and Rx workflow `status`).
|
|
*/
|
|
export type PrescriptionFlagCode =
|
|
| 'controlled_substance'
|
|
| 'interaction_concern'
|
|
| 'incomplete_rx'
|
|
| 'fraud_suspicion'
|
|
| 'stock_shortage'
|
|
| 'needs_clarification'
|
|
| 'allergy_concern'
|
|
| 'dosing_concern'
|
|
| 'other'
|
|
|
|
export type PrescriptionFlagSeverity = 'info' | 'warning' | 'critical'
|
|
export type PrescriptionFlagStatus = 'open' | 'resolved'
|
|
|
|
export interface PrescriptionFlag {
|
|
id: string
|
|
code: PrescriptionFlagCode
|
|
severity: PrescriptionFlagSeverity
|
|
note: string
|
|
createdBy: string
|
|
createdAt: string
|
|
status: PrescriptionFlagStatus
|
|
resolvedBy?: string
|
|
resolvedAt?: string
|
|
resolutionNote?: string
|
|
}
|
|
|
|
export interface Prescription {
|
|
id: string
|
|
customerName: string
|
|
branchId: string
|
|
status: 'submitted' | 'under_review' | 'approved' | 'queried' | 'rejected'
|
|
items: PrescriptionItem[]
|
|
submittedAt: string
|
|
/** Display name of the prescribing clinician (denormalised). */
|
|
prescriber?: string
|
|
/** Linked Doctor actor when the Rx was authored or attributed in-platform. */
|
|
doctorId?: string
|
|
/** Hospital org the prescription is associated with (usually the doctor's hospital). */
|
|
orgId?: string
|
|
/** Set when a pharmacist picks the Rx up off the queue. */
|
|
reviewStartedAt?: string
|
|
/** Pharmacist who approved, queried or rejected. */
|
|
reviewedBy?: string
|
|
reviewedAt?: string
|
|
decisionNote?: string
|
|
/** Operational / clinical review flags (open + resolved history). */
|
|
flags?: PrescriptionFlag[]
|
|
}
|
|
|
|
/** End-customer on an order — platform account vs walk-in / phone / guest. */
|
|
export type OrderCustomerType = 'registered' | 'guest'
|
|
|
|
export interface Order {
|
|
id: string
|
|
customerName: string
|
|
/**
|
|
* Whether the end customer is a logged-in platform user or an unauthenticated
|
|
* guest (walk-in, phone, POS, doctor-assisted patient without an account).
|
|
* Defaults to `guest` when omitted on legacy mock rows whose name starts with "Guest".
|
|
*/
|
|
customerType?: OrderCustomerType
|
|
/** CRM / platform customer id when `customerType === 'registered'`. */
|
|
customerId?: string
|
|
/** Contact phone — required for guests; optional denormalised copy for registered. */
|
|
customerPhone?: string
|
|
/** Free-text staff / doctor notes (allergy, pickup name, etc.). */
|
|
notes?: string
|
|
branchId: string
|
|
fulfillment: 'delivery' | 'pickup'
|
|
status: string
|
|
totalEtb: number
|
|
channel: string
|
|
assignedRiderId?: string
|
|
zone?: string
|
|
address?: string
|
|
createdAt: string
|
|
paid: boolean
|
|
rxApproved?: boolean
|
|
/** Doctor who initiated / authored the order when placed as a clinical actor. */
|
|
doctorId?: string
|
|
/** Hospital org that scoped the doctor-initiated order. */
|
|
orgId?: string
|
|
}
|
|
|
|
/**
|
|
* External clinical actor affiliated with a hospital (or clinic) organisation.
|
|
* Not pharmacy staff — doors open from hospital orgs; doctors create orders & Rx
|
|
* scoped to their affiliation. Managed in Admin under Organisations / Doctors.
|
|
*/
|
|
export interface Doctor {
|
|
id: string
|
|
name: string
|
|
specialty: string
|
|
/** Medical registration / license number (e.g. FMHACA / MoH). */
|
|
licenseNumber: string
|
|
phone: string
|
|
email: string
|
|
status: 'active' | 'inactive'
|
|
orgId: string
|
|
orgName: string
|
|
/** Optional Gishen fulfilment branch the doctor typically routes to. */
|
|
branchId?: string
|
|
branchName?: string
|
|
/** Whether a login principal has been provisioned for this doctor. */
|
|
hasLinkedAccount: boolean
|
|
createdAt: string
|
|
updatedAt: string
|
|
avatarUrl?: string
|
|
}
|
|
|
|
/** Platform Money — decimal major ETB (aligned with B2B). */
|
|
export interface Money {
|
|
amount: string
|
|
currency: 'ETB'
|
|
}
|
|
|
|
/** Admin-written commercial terms — matches B2B `Organisation.commercial`. */
|
|
export interface CommercialTerms {
|
|
credit_limit: Money
|
|
credit_used: Money
|
|
payment_terms_days: number
|
|
price_list_id?: string
|
|
contract_start?: string
|
|
contract_end?: string
|
|
activated_at?: string
|
|
activated_by?: string
|
|
}
|
|
|
|
/** Canonical org lifecycle (B2B + Admin). Prefer over bare `pending`. */
|
|
export type OrgStatus = 'pending_activation' | 'active' | 'suspended' | 'closed' | 'rejected'
|
|
|
|
export interface Organisation {
|
|
id: string
|
|
name: string
|
|
/** B2B account kind — hospital/clinic unlocks the Doctors roster. */
|
|
orgType: OrganisationType
|
|
/** Tax Identification Number (10 digits). */
|
|
tin: string
|
|
/** VAT registration number — often mirrors TIN once VAT-registered. */
|
|
vatNumber?: string
|
|
/** Trade / business license number issued by the city administration. */
|
|
businessLicense?: string
|
|
/** Commercial registration number (Ministry of Trade). */
|
|
commercialRegistration?: string
|
|
status: OrgStatus
|
|
/**
|
|
* Platform commercial terms. Null while `pending_activation`.
|
|
* Set on Admin create (active) or `POST .../activate`.
|
|
*/
|
|
commercial: CommercialTerms | null
|
|
/**
|
|
* Demo UI convenience (major ETB). Prefer `commercial.credit_*` for API wiring;
|
|
* keep in sync when activating / adjusting credit.
|
|
*/
|
|
creditLimitEtb: number
|
|
usedEtb: number
|
|
billingContact: string
|
|
source: 'admin' | 'self_register'
|
|
createdAt: string
|
|
/** Finance reviewer who approved or rejected the credit account. */
|
|
reviewedBy?: string
|
|
reviewedAt?: string
|
|
decisionNote?: string
|
|
}
|
|
|
|
export interface FaqArticle {
|
|
id: string
|
|
category: string
|
|
title_en: string
|
|
title_am: string
|
|
body_en: string
|
|
body_am: string
|
|
published: boolean
|
|
updatedAt: string
|
|
/** Staff help-center reads since publication — drives the knowledge base KPIs. */
|
|
views: number
|
|
}
|