From e0abaf5c0c0e82fb5a3bbbe64f9dac166c521b18 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Wed, 24 Jun 2026 12:32:58 +0330 Subject: [PATCH] feat(appointment): enforce mandatory patient national code and gender with validation --- docs/api/appointment.md | 10 ++++---- .../Controller/AppointmentController.php | 24 +++++++++++++++++-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/docs/api/appointment.md b/docs/api/appointment.md index b40a4b4a..479b72ac 100644 --- a/docs/api/appointment.md +++ b/docs/api/appointment.md @@ -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` | --- diff --git a/src/Appointment/Controller/AppointmentController.php b/src/Appointment/Controller/AppointmentController.php index ce0ea5d1..c28d86a8 100644 --- a/src/Appointment/Controller/AppointmentController.php +++ b/src/Appointment/Controller/AppointmentController.php @@ -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); }