feat(appointment): identify admin-booked patient by national code
Admin-side booking (POST /api/v1/my/appointment and /api/v1/admin/appointment) resolved the patient User by mobile only, so one person booked under two mobiles produced two User rows — and two case-files, since PatientRecord is keyed on user_id. National code is the real unique identity (User.national_code is already unique); a person may have several mobiles. Booking now requires + validates patient_national_code and resolves the patient national-code-first (then mobile) via a shared PatientResolver, so the case-file stays unique per national code even across mobiles. Reusing a mobile already bound to a different national code returns 422 ERR_PROFILE_MOBILE_TAKEN. The admin create form and NewAppointmentDrawer gain a national-code field and send it; both had a dead patient-picker URL (/api/v1/patient) fixed to the real /api/v1/patients, whose payload already carries user_national_code for autofill. Docs (appointment.md, admin.md) and tests updated; new AppointmentNationalCodeTest covers success, single-file reuse, missing, invalid, and identity-conflict cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
-2
@@ -598,11 +598,12 @@ Create a new appointment for a patient. If no user exists with the given mobile,
|
||||
"slot_end": 1718439600,
|
||||
"patient_mobile": "09123456789",
|
||||
"patient_name": "علی محمدی",
|
||||
"patient_national_code": "0012345678",
|
||||
"note": "optional note"
|
||||
}
|
||||
```
|
||||
|
||||
> `patient_mobile` و `patient_name` هر دو اجباری هستند. اگر کاربری با این شماره موبایل نداشته باشیم، یک کاربر جدید با نقش `ROLE_USER` ساخته میشود.
|
||||
> `patient_mobile`، `patient_name` و `patient_national_code` هر سه اجباری هستند. کد ملی باید ۱۰ رقم معتبر باشد. بیمار **اول با کد ملی** و سپس با موبایل resolve میشود، تا پرونده برای هر کد ملی یکتا بماند (یک شخص میتواند چند موبایل داشته باشد). اگر کاربری یافت نشود، کاربر جدید با نقش `ROLE_USER` و همان کد ملی ساخته میشود.
|
||||
|
||||
### Response `201`
|
||||
```json
|
||||
@@ -620,7 +621,8 @@ Create a new appointment for a patient. If no user exists with the given mobile,
|
||||
### Error Responses
|
||||
| Code | HTTP | Description |
|
||||
|------|------|-------------|
|
||||
| `VALIDATION` | 422 | Missing required fields (doctor_uuid, slot_start, slot_end, patient_mobile, patient_name) |
|
||||
| `VALIDATION` | 422 | Missing required fields (doctor_uuid, slot_start, slot_end, patient_mobile, patient_name), or missing/invalid `patient_national_code` (`field: patient_national_code`) |
|
||||
| `ERR_PROFILE_MOBILE_TAKEN` | 422 | این شماره موبایل با کد ملی دیگری ثبت شده است (`field: patient_mobile`) |
|
||||
| `DOCTOR_NOT_FOUND` | 404 | Doctor UUID not found |
|
||||
| `SLOT_TAKEN` | 409 | Slot already booked |
|
||||
|
||||
|
||||
+10
-2
@@ -397,11 +397,18 @@ Create a new appointment for a patient. Used by doctor/clinic/secretary to book
|
||||
"slot_end": 1718439600,
|
||||
"patient_mobile": "09123456789",
|
||||
"patient_name": "علی محمدی",
|
||||
"patient_national_code": "0012345678",
|
||||
"note": "optional note"
|
||||
}
|
||||
```
|
||||
|
||||
> اگر کاربری با این شماره موبایل وجود نداشته باشد، یک کاربر جدید با نقش `ROLE_USER` ساخته میشود.
|
||||
| Field | Type | Required | Notes |
|
||||
|-------|------|----------|-------|
|
||||
| `patient_mobile` | string | ✅ | راه تماس بیمار |
|
||||
| `patient_name` | string | ✅ | نام بیمار |
|
||||
| `patient_national_code` | string | ✅ | کد ملی بیمار — باید ۱۰ رقم معتبر باشد (`isValidIranNationalCode`)؛ ارقام فارسی به انگلیسی تبدیل میشوند |
|
||||
|
||||
> **هویت بیمار بر پایهی کد ملی:** بیمار **اول با کد ملی** پیدا میشود، سپس با موبایل. کد ملی یکتاست (`User.national_code unique`)، پس یک شخص میتواند چند موبایل داشته باشد ولی پروندهاش (`PatientRecord`) یکتا میماند. اگر موبایلی که قبلاً با کد ملی دیگری ثبت شده دوباره با کد ملی متفاوت ارسال شود، خطای 422 برمیگردد. اگر هیچ کاربری یافت نشود، کاربر جدید با نقش `ROLE_USER` و همان کد ملی ساخته میشود.
|
||||
|
||||
### Response `201`
|
||||
```json
|
||||
@@ -420,7 +427,8 @@ Create a new appointment for a patient. Used by doctor/clinic/secretary to book
|
||||
| Code | HTTP | Description |
|
||||
|------|------|-------------|
|
||||
| `FORBIDDEN` | 403 | Role not allowed, or caller not scoped to this doctor |
|
||||
| `VALIDATION` | 422 | Missing required fields |
|
||||
| `VALIDATION` | 422 | Missing required fields, or missing/invalid `patient_national_code` (`field: patient_national_code`) |
|
||||
| `ERR_PROFILE_MOBILE_TAKEN` | 422 | این شماره موبایل با کد ملی دیگری ثبت شده است (`field: patient_mobile`) |
|
||||
| `DOCTOR_NOT_FOUND` | 404 | Doctor UUID not found |
|
||||
| `SLOT_TAKEN` | 409 | Slot already booked |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user