feat: implement specialty hierarchy handling in doctor and representation APIs, add backfill command and tests
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Doctor;
|
||||
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Specialty\Entity\Specialty;
|
||||
use App\Specialty\Repository\SpecialtyRepository;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* Specialties are a tree. Whenever a child specialty is attached to a doctor,
|
||||
* every ancestor up to the root must be attached too — clients (the IRIMC
|
||||
* crawler, the admin panel) only ever send the leaf id.
|
||||
*/
|
||||
class DoctorSpecialtyParentsTest extends ApiTestCase
|
||||
{
|
||||
private function makeSpecialty(string $name, ?Specialty $parent = null): Specialty
|
||||
{
|
||||
$specialty = new Specialty($name, 'sp-' . bin2hex(random_bytes(6)), $parent);
|
||||
$this->em->persist($specialty);
|
||||
$this->em->flush();
|
||||
|
||||
return $specialty;
|
||||
}
|
||||
|
||||
private function repo(): SpecialtyRepository
|
||||
{
|
||||
return $this->em->getRepository(Specialty::class);
|
||||
}
|
||||
|
||||
public function testExpandWithAncestorsWalksTheWholeChain(): void
|
||||
{
|
||||
$root = $this->makeSpecialty('داخلی');
|
||||
$child = $this->makeSpecialty('گوارش و کبد', $root);
|
||||
$grand = $this->makeSpecialty('آندوسکوپی', $child);
|
||||
|
||||
$expected = [$root->getId(), $child->getId(), $grand->getId()];
|
||||
sort($expected);
|
||||
|
||||
$this->assertSame($expected, $this->repo()->expandWithAncestors([$grand->getId()]));
|
||||
}
|
||||
|
||||
public function testExpandWithAncestorsDeduplicatesAndDropsUnknownIds(): void
|
||||
{
|
||||
$root = $this->makeSpecialty('داخلی');
|
||||
$child = $this->makeSpecialty('گوارش و کبد', $root);
|
||||
|
||||
$expected = [$root->getId(), $child->getId()];
|
||||
sort($expected);
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->repo()->expandWithAncestors([$child->getId(), $root->getId(), $child->getId(), 99_999_999])
|
||||
);
|
||||
}
|
||||
|
||||
public function testExpandWithAncestorsReturnsEmptyForNoInput(): void
|
||||
{
|
||||
$this->assertSame([], $this->repo()->expandWithAncestors([]));
|
||||
$this->assertSame([], $this->repo()->expandWithAncestors([99_999_999]));
|
||||
}
|
||||
|
||||
public function testImportAttachesParentSpecialty(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']);
|
||||
$root = $this->makeSpecialty('داخلی');
|
||||
$child = $this->makeSpecialty('گوارش و کبد', $root);
|
||||
|
||||
$data = $this->authJson('POST', '/api/v1/admin/doctors/import', $admin, [
|
||||
'name' => 'دکتر تست تخصص',
|
||||
'medical_system_code' => 'T' . random_int(100_000, 999_999) . random_int(100, 999),
|
||||
'specialties' => [$child->getId()],
|
||||
]);
|
||||
|
||||
$this->assertSame(201, $this->responseCode());
|
||||
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['uuid' => $data['data']['uuid']]);
|
||||
$attached = array_map(static fn (Specialty $s) => $s->getId(), $doctor->getSpecialties()->toArray());
|
||||
sort($attached);
|
||||
|
||||
$expected = [$root->getId(), $child->getId()];
|
||||
sort($expected);
|
||||
|
||||
$this->assertSame($expected, $attached);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user