feat(appointment): implement immutable booking mode after first save and update API documentation

This commit is contained in:
hamed
2026-07-15 23:33:00 +03:30
parent ad94c165e8
commit 2df16c6d29
5 changed files with 176 additions and 32 deletions
@@ -41,6 +41,18 @@ class AppointmentSettingsController extends BaseController
* در حالت نوبت‌دهی سرویسی، پزشک باید حداقل یک سرویسِ «نمایش در نوبت‌دهی»
* (bookable) داشته باشد؛ وگرنه هیچ نوبتی قابل‌محاسبه نیست.
*/
/**
* نوع نوبت‌دهی پس از اولین ثبت غیرقابل‌تغییر است. اگر قبلاً mode ذخیره شده بود
* ($prevMode !== null) و meta جدید آن را تغییر دهد، خطای 422 برمی‌گرداند.
*/
private function assertModeImmutable(?string $prevMode, array $newMeta): ?JsonResponse
{
if ($prevMode !== null && ($newMeta['booking_mode'] ?? null) !== $prevMode) {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'نوع نوبت‌دهی پس از ثبت قابل تغییر نیست', 422, 'booking_mode');
}
return null;
}
private function serviceModeHasNoBookable(array $meta, \App\Doctor\Entity\Doctor $doctor): bool
{
return ($meta['booking_mode'] ?? WeeklySchedule::MODE_SLOT) === WeeklySchedule::MODE_SERVICE
@@ -70,6 +82,7 @@ class AppointmentSettingsController extends BaseController
// Only one schedule per doctor — upsert
$schedule = $this->scheduleRepo->findByDoctor($doctor);
$prevMode = $schedule?->getStoredBookingMode();
if ($schedule !== null) {
$schedule->setSetting($data['schedule'] ?? []);
} else {
@@ -80,6 +93,10 @@ class AppointmentSettingsController extends BaseController
$schedule->setMeta($data['meta']);
}
if (($err = $this->assertModeImmutable($prevMode, $schedule->getMeta())) !== null) {
return $err;
}
if ($this->serviceModeHasNoBookable($schedule->getMeta(), $doctor)) {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'برای نوبت‌دهی سرویسی حداقل یک سرویس با «نمایش در نوبت‌دهی» لازم است', 422, 'booking_mode');
}
@@ -107,6 +124,7 @@ class AppointmentSettingsController extends BaseController
return $this->error(ErrorCodes::ERR_AUTH_006, 'دسترسی ممنوع', 403);
}
$prevMode = $schedule->getStoredBookingMode();
$data = json_decode($request->getContent(), true) ?? [];
if (isset($data['schedule'])) {
if (($err = $this->validateSessionsHaveLocation($data['schedule'])) !== null) {
@@ -118,6 +136,10 @@ class AppointmentSettingsController extends BaseController
$schedule->setMeta($data['meta']);
}
if (($err = $this->assertModeImmutable($prevMode, $schedule->getMeta())) !== null) {
return $err;
}
if ($this->serviceModeHasNoBookable($schedule->getMeta(), $schedule->getDoctor())) {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'برای نوبت‌دهی سرویسی حداقل یک سرویس با «نمایش در نوبت‌دهی» لازم است', 422, 'booking_mode');
}