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/entities/member.md
kirukib 8fe6d58a09 Document portal auth, profile, and pharmacy ID contracts in backend specs.
Keep the living API sheet aligned with demo personas, avatars, ID-card QR scan, list filters, and Admin/Ecom coordination.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 22:10:07 +03:00

152 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Entity: Member
Employee or dependant enrolled under an organisation's corporate medical benefit.
**Workspace:** `/Users/kirukib/Desktop/Yaltopia Project/Gishen-B2B`
## Fields
| Field | Type | Required | Notes |
|-------|------|----------|-------|
| `id` | `string` | ✓ | `mbr_*` |
| `org_id` | `string` | ✓ | |
| `customer_id` | `string` | | Shared Gishen customer identity (Ecom/Mob) |
| `employee_id` | `string` | | Org HR identifier |
| `full_name` | `string` | ✓ | |
| `email` | `string` | | |
| `phone` | `Phone` | ✓ | Primary contact |
| `department_id` | `string` | | FK → Department |
| `package_id` | `string` | | Assigned benefit plan |
| `role` | `MemberPortalRole` | ✓ | Portal access |
| `member_type` | `MemberType` | ✓ | |
| `primary_member_id` | `string` \| null | | For dependants |
| `status` | `MemberStatus` | ✓ | |
| `start_date` | `date` | | Coverage start |
| `end_date` | `date` \| null | | Offboarding |
| `overrides` | `MemberOverrides` | | Per-member entitlement tweaks |
| `verification_id` | `string` | | Employee verification token used in pharmacy QR payload |
| `card_id` | `string` | | Printed pharmacy card number (e.g. `GSH-1001`) |
| `avatar_url` | `string` | | Profile / ID-card photo URL |
| `invite_id` | `string` | | If joined via invite |
| `allowance_summary` | `AllowanceSummary` | | Read-only computed |
| `prescription_count` | `integer` | | Aggregate only for HR/Finance |
| `created_at` | `Timestamp` | ✓ | |
| `updated_at` | `Timestamp` | ✓ | |
| `version` | `integer` | ✓ | |
### MemberPortalRole
```
MEMBER | HR_ADMIN | FINANCE | SUPER_USER
```
A user may hold multiple portal roles; stored on linked `User`, reflected here for display.
### MemberType
```
primary | dependant
```
### MemberStatus
```
invited | active | inactive | offboarded
```
### MemberOverrides
| Field | Type | Notes |
|-------|------|-------|
| `allowance_cap` | `Money` \| null | Overrides package cap |
| `copay_percent` | `number` \| null | 0–100 |
| `excluded_categories` | `string[]` | |
| `included_perks` | `string[]` | Extra perk codes |
### AllowanceSummary
| Field | Type | Notes |
|-------|------|-------|
| `period_start` | `date` | |
| `period_end` | `date` | |
| `allowance_total` | `Money` | |
| `allowance_used` | `Money` | |
| `allowance_remaining` | `Money` | Shown to member pre-checkout |
## Validation rules
| Rule | Error code |
|------|------------|
| Org must be `active` for create (except migration draft) | `ORG_PENDING` |
| Unique `phone` per org (active members) | `DUPLICATE_MEMBER` |
| Unique `employee_id` per org if set | `DUPLICATE_MEMBER` |
| Dependant requires `primary_member_id` | `VALIDATION_FAILED` |
| Dependant count ≤ org `dependant_limit` | `DEPENDANT_LIMIT_EXCEEDED` |
| `package_id` must exist and be active | `NOT_FOUND` |
## Clinical withhold
When `SessionUser.roles` includes HR_ADMIN or FINANCE **without** SUPER_USER:
| Field | Visible |
|-------|---------|
| `full_name`, `email`, `phone`, `employee_id`, `department_id`, `package_id`, `status` | ✓ |
| `verification_id`, `card_id`, `avatar_url` | ✓ (pharmacy verification / ID card) |
| `allowance_summary` (amounts only) | ✓ |
| `prescription_count` | ✓ (count only) |
| Prescription list / images / medicine lines | ✗ |
| `customer_id` order line medicine detail | ✗ (category + amount in finance spend only) |
SUPER_USER and MEMBER (own record) receive full clinical linkage via prescription endpoints.
## Sample payload (HR view)
```json
{
"id": "mbr_01HMEM001",
"org_id": "org_01HQXYZ",
"customer_id": "cus_01HSHARED",
"employee_id": "EMP-1042",
"full_name": "Abel Mekonnen",
"email": "abel.m@acme.et",
"phone": "+251911111111",
"department_id": "dept_01HABC",
"package_id": "pkg_01HGOLD",
"role": "MEMBER",
"member_type": "primary",
"primary_member_id": null,
"status": "active",
"start_date": "2026-01-01",
"end_date": null,
"overrides": null,
"verification_id": "EMP-1042",
"card_id": "GSH-1042",
"avatar_url": "https://api.dicebear.com/9.x/lorelei/svg?seed=mbr_01HMEM001",
"allowance_summary": {
"period_start": "2026-03-01",
"period_end": "2026-03-31",
"allowance_total": { "amount": "15000.00", "currency": "ETB" },
"allowance_used": { "amount": "4200.00", "currency": "ETB" },
"allowance_remaining": { "amount": "10800.00", "currency": "ETB" }
},
"prescription_count": 2,
"created_at": "2026-01-05T10:00:00Z",
"updated_at": "2026-03-10T14:00:00Z",
"version": 8
}
```
## Invite token (related)
| Field | Type |
|-------|------|
| `token` | `string` |
| `member_id` | `string` |
| `expires_at` | `Timestamp` |
| `accepted_at` | `Timestamp` \| null |
## Related endpoints
- [`../endpoints/members.md`](../endpoints/members.md) — including `GET /v1/members/:id/id-card`
- Pharmacy QR scan consumed by Admin / POS — see [`../../coordination/gishen-admin.md`](../../coordination/gishen-admin.md)