feat(appointment): enforce mandatory patient national code and gender with validation

This commit is contained in:
hamed
2026-06-24 12:32:58 +03:30
parent b7df8cf9ee
commit e0abaf5c0c
2 changed files with 27 additions and 7 deletions
+5 -5
View File
@@ -133,7 +133,7 @@ Book an appointment slot.
"patient_name": "علی احمدی",
"patient_mobile": "09120000000",
"patient_national_code": "0012345678",
"patient_gender": "male",
"patient_gender": "man",
"patient_reason": "چکاپ",
"note": "لطفاً سریع ویزیت شوم"
}
@@ -147,8 +147,8 @@ Book an appointment slot.
| `for_self` | boolean | ❌ | `true` (default) = patient is the logged-in payer; `false` = booking for someone else |
| `patient_name` | string | ⚠️ | Required when `for_self=false`; otherwise filled from the payer's profile |
| `patient_mobile` | string | ⚠️ | Required when `for_self=false`; otherwise the payer's mobile |
| `patient_national_code` | string | | Patient national code (only when for another person) |
| `patient_gender` | string | | `male` / `female` |
| `patient_national_code` | string | | کد ملی بیمار — **همیشه الزامی** (هر دو حالت `for_self`). باید ۱۰ رقم معتبر باشد (`isValidIranNationalCode`)؛ ارقام فارسی به انگلیسی تبدیل می‌شوند |
| `patient_gender` | string | | جنسیت بیمار — **همیشه الزامی**. ورودی `man`/`male` یا `woman`/`female` پذیرفته می‌شود و به فرمِ متعارف `man`/`woman` ذخیره می‌گردد |
| `patient_reason` | string | ❌ | Reason for visit |
| `note` | string | ❌ | Patient note |
@@ -174,7 +174,7 @@ Book an appointment slot.
"patient_name": "علی احمدی",
"patient_mobile": "09120000000",
"patient_national_code": "0012345678",
"patient_gender": "male",
"patient_gender": "man",
"patient_reason": "چکاپ",
"version": 1,
"created_at": 1717000000
@@ -197,7 +197,7 @@ Book an appointment slot.
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_VALIDATION_002` | 404 | Doctor not found |
| `ERR_CONFLICT_001` | 409 | Slot already booked (incl. concurrent booking — the booking is atomic) |
| `ERR_VALIDATION_001` | 422 | Invalid slot times, past slot, or missing patient name/mobile when `for_self=false` |
| `ERR_VALIDATION_001` | 422 | Invalid slot times, past slot, missing patient name/mobile when `for_self=false`, missing/invalid `patient_national_code`, or `patient_gender` not in `man`/`male`/`woman`/`female` |
---
@@ -12,6 +12,7 @@ use App\Doctor\Entity\Doctor;
use App\Auth\Entity\User;
use App\Doctor\Repository\DoctorRepository;
use App\Patient\Service\PatientService;
use App\Shared\Service\InputValidator;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Controller\BaseController;
use Doctrine\ORM\OptimisticLockException;
@@ -234,7 +235,28 @@ class AppointmentController extends BaseController
$forSelf = (bool) ($data['for_self'] ?? true);
// کد ملی و جنسیت بیمار همیشه الزامی است (چه برای خود، چه برای دیگری).
$nationalCode = InputValidator::toEnglishDigits(trim((string) ($data['patient_national_code'] ?? '')));
// فرانت‌اند male/female می‌فرستد؛ به فرمِ متعارفِ بک‌اند (man/woman) نگاشت می‌شود.
$gender = match (strtolower(trim((string) ($data['patient_gender'] ?? '')))) {
'man', 'male' => 'man',
'woman', 'female' => 'woman',
default => '',
};
if ($nationalCode === '') {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'کد ملی بیمار الزامی است', 422, 'patient_national_code');
}
if (!InputValidator::isValidIranNationalCode($nationalCode)) {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'کد ملی نامعتبر است', 422, 'patient_national_code');
}
if ($gender === '') {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'جنسیت بیمار الزامی است', 422, 'patient_gender');
}
$appointment = new Appointment($doctor, $user, $slotStart, $slotEnd);
$appointment->setPatientNationalCode($nationalCode);
$appointment->setPatientGender($gender);
if (isset($data['note'])) $appointment->setNote($data['note']);
// آدرس نوبت از روی session متناظر در برنامه‌ی هفتگی تعیین می‌شود (location_id).
@@ -254,8 +276,6 @@ class AppointmentController extends BaseController
}
$appointment->setPatientName($patientName);
$appointment->setPatientMobile($patientMobile);
$appointment->setPatientNationalCode($data['patient_national_code'] ?? null);
$appointment->setPatientGender($data['patient_gender'] ?? null);
$appointment->setPatientReason($data['patient_reason'] ?? null);
}