feat(appointment): update patient identification to use national code from profile and enhance appointment creation logic

This commit is contained in:
hamed
2026-07-15 18:46:56 +03:30
parent 0dc1ab949a
commit de6fe1bd56
8 changed files with 94 additions and 32 deletions
@@ -2,16 +2,19 @@
namespace App\Tests\Appointment;
use App\Appointment\Entity\Appointment;
use App\Auth\Entity\User;
use App\Doctor\Entity\Doctor;
use App\Shared\Constant\ErrorCodes;
use App\Tests\ApiTestCase;
use App\UserProfile\Entity\UserProfile;
/**
* POST /api/v1/my/appointment must identify the patient by national code:
* it is required + validated, and the patient User (hence the case-file) is
* resolved by national code first so one person keeps a single record even
* when booked under a different mobile.
* POST /api/v1/my/appointment must identify the patient by national code.
* National code is stored on the patient's UserProfile (profiles.national_code,
* unique), so the patient User — and thus the case-file — is resolved by that
* profile first. One person keeps a single record even when booked under
* several mobiles.
*/
class AppointmentNationalCodeTest extends ApiTestCase
{
@@ -50,17 +53,23 @@ class AppointmentNationalCodeTest extends ApiTestCase
];
}
public function testCreatesUserWithNationalCode(): void
private function profileByNationalCode(string $nc): ?UserProfile
{
return $this->em->getRepository(UserProfile::class)->findOneBy(['nationalCode' => $nc]);
}
public function testStoresNationalCodeOnProfile(): void
{
[$owner, $doctor] = $this->doctor();
$nc = $this->nationalCode();
$nc = $this->nationalCode();
$mobile = $this->mobile();
$this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body($doctor->getUuid(), $this->mobile(), $nc));
$this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body($doctor->getUuid(), $mobile, $nc));
self::assertSame(201, $this->responseCode());
$patient = $this->em->getRepository(User::class)->findOneBy(['nationalCode' => $nc]);
self::assertNotNull($patient);
self::assertSame($nc, $patient->getNationalCode());
$profile = $this->profileByNationalCode($nc);
self::assertNotNull($profile);
self::assertSame($mobile, $profile->getUser()->getMobileNumber());
}
public function testSameNationalCodeDifferentMobileReusesSinglePatient(): void
@@ -68,7 +77,7 @@ class AppointmentNationalCodeTest extends ApiTestCase
[$owner, $doctor] = $this->doctor();
$nc = $this->nationalCode();
// First booking under mobile A creates the patient.
// First booking under mobile A creates the patient + profile.
$this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body($doctor->getUuid(), $this->mobile(), $nc));
self::assertSame(201, $this->responseCode());
@@ -77,8 +86,38 @@ class AppointmentNationalCodeTest extends ApiTestCase
$this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body($doctor->getUuid(), $this->mobile(), $nc));
self::assertSame(201, $this->responseCode());
$patients = $this->em->getRepository(User::class)->findBy(['nationalCode' => $nc]);
self::assertCount(1, $patients);
$profiles = $this->em->getRepository(UserProfile::class)->findBy(['nationalCode' => $nc]);
self::assertCount(1, $profiles);
}
/**
* The reported bug: a patient already exists whose national code sits on
* their profile. Booking under a brand-new mobile with that same national
* code must attach to the existing patient, not stamp the code onto a new
* user.
*/
public function testExistingProfileNationalCodeIsReusedNotDuplicated(): void
{
[$owner, $doctor] = $this->doctor();
$nc = $this->nationalCode();
// Existing patient with the national code on their profile.
$existing = $this->createUser(['ROLE_USER'], $this->mobile());
$profile = new UserProfile($existing);
$profile->setNationalCode($nc);
$this->em->persist($profile);
$this->em->flush();
// Book under a different mobile but the same national code.
$res = $this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body($doctor->getUuid(), $this->mobile(), $nc));
self::assertSame(201, $this->responseCode());
// No duplicate profile, and the appointment is attached to the existing user.
$profiles = $this->em->getRepository(UserProfile::class)->findBy(['nationalCode' => $nc]);
self::assertCount(1, $profiles);
$appointment = $this->em->getRepository(Appointment::class)->findOneBy(['uuid' => $res['data']['uuid']]);
self::assertSame($existing->getId(), $appointment->getUser()->getId());
}
public function testMissingNationalCodeIs422(): void