feat(appointment): derive service section from service item when missing in appointment

This commit is contained in:
hamed
2026-08-08 07:14:40 +03:30
parent da07e3ad9c
commit b699476305
5 changed files with 144 additions and 22 deletions
@@ -0,0 +1,87 @@
<?php
namespace App\Tests\Appointment;
use App\ClinicService\Entity\ServiceItem;
use App\ClinicService\Entity\ServiceSection;
use App\Doctor\Entity\Doctor;
use App\Tests\ApiTestCase;
/**
* `GET /api/v1/appointment/{uuid}` وقتی نوبت بخش ندارد، بخش را از سرویسش درمی‌آورد.
*
* گزارش ۲۰۲۶-۰۸-۰۸: در فرم ویرایش نوبت، «بخش» و «سرویس» هر دو خالی دیده می‌شدند
* با اینکه نوبت سرویس داشت. علت: نوبتِ سرویسیِ کلینیک `service_section_id` را
* ذخیره نمی‌کند، و فرم فهرست سرویس‌ها را از بخش می‌گیرد — پس بخشِ خالی یعنی
* فهرست خالی و سرویسِ بی‌برچسب.
*/
class AppointmentDetailSectionFallbackTest extends ApiTestCase
{
/** @return array{0: Doctor, 1: ServiceSection, 2: ServiceItem} */
private function doctorWithOneService(): array
{
$owner = $this->createUser(['ROLE_DOCTOR']);
$doctor = new Doctor($owner, 'دکتر تست بخش');
$this->em->persist($doctor);
// بخش به شناسهٔ پزشک نیاز دارد، پس پزشک باید پیش از ساختش flush شود.
$this->em->flush();
$section = new ServiceSection('doctor', $doctor->getId(), 'بخش لیزر');
$this->em->persist($section);
$item = new ServiceItem($section, 'لیزر توتال', 0);
$item->setDurationMinutes(40)->setBookable(true);
$this->em->persist($item);
$this->em->flush();
return [$doctor, $section, $item];
}
/** ✅ موفق — بخشِ ذخیره‌نشده از روی سرویس پر می‌شود. */
public function testSectionIsDerivedFromTheServiceItemWhenMissing(): void
{
[$doctor, $section, $item] = $this->doctorWithOneService();
$patient = $this->createUser(['ROLE_USER']);
$start = strtotime('+5 days 10:00');
$appt = $this->newAppointment($doctor, $patient, $start, $start + 2400);
$appt->replaceServiceItems([$item]);
self::assertNull($appt->getServiceSection(), 'پیش‌فرضِ این سناریو: نوبت بخش ندارد');
$this->em->persist($appt);
$this->em->flush();
$res = $this->authJson('GET', '/api/v1/appointment/' . $appt->getUuid(), $doctor->getUser());
self::assertSame(200, $this->responseCode());
$payload = $res['data']['data'];
self::assertSame($section->getUuid(), $payload['service_section']['uuid']);
self::assertSame('بخش لیزر', $payload['service_section']['name']);
self::assertSame($item->getUuid(), $payload['service_item']['uuid']);
}
/** ⚠️ مرزی — نوبتِ بدون هیچ سرویسی چیزی برای استنتاج ندارد و `null` می‌ماند. */
public function testSectionStaysNullWhenTheAppointmentHasNoService(): void
{
[$doctor] = $this->doctorWithOneService();
$patient = $this->createUser(['ROLE_USER']);
$start = strtotime('+6 days 10:00');
$appt = $this->newAppointment($doctor, $patient, $start, $start + 1800);
$this->em->persist($appt);
$this->em->flush();
$res = $this->authJson('GET', '/api/v1/appointment/' . $appt->getUuid(), $doctor->getUser());
self::assertSame(200, $this->responseCode());
self::assertNull($res['data']['data']['service_section']);
}
/** ❌ خطا — نوبتِ ناموجود همچنان ۴۰۴ است؛ fallback مسیر خطا را عوض نمی‌کند. */
public function testUnknownAppointmentStillReturns404(): void
{
[$doctor] = $this->doctorWithOneService();
$this->authJson('GET', '/api/v1/appointment/00000000-0000-0000-0000-000000000000', $doctor->getUser());
self::assertSame(404, $this->responseCode());
}
}