feat(doctor): ensure default office address creation during doctor import
This commit is contained in:
@@ -75,6 +75,22 @@
|
||||
|
||||
---
|
||||
|
||||
## آدرس پیشفرض (مطب)
|
||||
|
||||
هر پزشک ایمپورتشده **همیشه دستکم یک آدرس** (`doctor_addresses`، type=`personal`) دارد:
|
||||
|
||||
- اگر پزشک هیچ آدرسی نداشته باشد، یک آدرس با نام **«مطب دکتر {نام}»** ساخته میشود و
|
||||
شهر/استان آن از **اولین** عنصر آرایههای `cities`/`states` همان درخواست پر میشود.
|
||||
- در ایمپورت مجدد آدرس تکراری ساخته نمیشود؛ فقط فیلدهای **خالیِ** آدرس موجود
|
||||
(نام/شهر/استان) backfill میشوند — مقادیر ویرایششده توسط کاربر بازنویسی نمیشوند.
|
||||
- اگر `cities`/`states` در درخواست نباشند، آدرس فقط با نام ساخته میشود (کرالر در حالت
|
||||
auto همیشه هر دو را میفرستد).
|
||||
|
||||
(تستها: `DoctorImportTest::testImportCreatesDefaultOfficeAddressWithCityAndProvince`،
|
||||
`testImportWithoutLocationStillCreatesOfficeAddress`)
|
||||
|
||||
---
|
||||
|
||||
## Response
|
||||
|
||||
### `201 Created` (ساخته شد)
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Doctor\Service;
|
||||
|
||||
use App\Auth\Entity\User;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Doctor\Entity\DoctorAddress;
|
||||
use App\Location\Entity\City;
|
||||
use App\Location\Entity\Province;
|
||||
use App\Specialty\Entity\Specialty;
|
||||
@@ -106,6 +107,8 @@ class DoctorImportService
|
||||
$this->syncRefCollection($doctor->getProvinces(), $data['states'] ?? null, Province::class);
|
||||
$this->syncRefCollection($doctor->getCities(), $data['cities'] ?? null, City::class);
|
||||
|
||||
$this->ensureDefaultAddress($doctor, $name, $data);
|
||||
|
||||
$this->em->persist($doctor);
|
||||
$this->em->flush();
|
||||
|
||||
@@ -113,6 +116,38 @@ class DoctorImportService
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* هر پزشک ایمپورتشده باید دستکم یک آدرس «مطب دکتر …» با شهر و استان داشته باشد.
|
||||
* اگر آدرسی ندارد میسازد؛ فیلدهای خالیِ آدرس موجود را backfill میکند و
|
||||
* مقادیر واردشده توسط کاربر را بازنویسی نمیکند.
|
||||
*/
|
||||
private function ensureDefaultAddress(Doctor $doctor, string $name, array $data): void
|
||||
{
|
||||
$city = !empty($data['cities'])
|
||||
? $this->em->getRepository(City::class)->find((int) $data['cities'][0])
|
||||
: null;
|
||||
$province = !empty($data['states'])
|
||||
? $this->em->getRepository(Province::class)->find((int) $data['states'][0])
|
||||
: null;
|
||||
|
||||
$address = $doctor->getAddresses()->first() ?: null;
|
||||
if ($address === null) {
|
||||
$address = DoctorAddress::forDoctor($doctor);
|
||||
$doctor->getAddresses()->add($address);
|
||||
$this->em->persist($address);
|
||||
}
|
||||
|
||||
if ($address->getName() === null || $address->getName() === '') {
|
||||
$address->setName('مطب دکتر ' . $name);
|
||||
}
|
||||
if ($address->getCity() === null && $city !== null) {
|
||||
$address->setCity($city);
|
||||
}
|
||||
if ($address->getProvince() === null && $province !== null) {
|
||||
$address->setProvince($province);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* یک مجموعهٔ ManyToMany پزشک را با آرایهای از شناسههای مرجع همگام میکند.
|
||||
* اگر $ids null باشد دست نمیخورد؛ اگر آرایه باشد، پاک و از نو پر میشود.
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Tests\Doctor;
|
||||
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Location\Entity\City;
|
||||
use App\Location\Entity\Province;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
@@ -107,6 +109,61 @@ class DoctorImportTest extends ApiTestCase
|
||||
$this->assertSame('claimed', $doctor->getOwnerStatus());
|
||||
}
|
||||
|
||||
public function testImportCreatesDefaultOfficeAddressWithCityAndProvince(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']);
|
||||
$code = $this->freshCode();
|
||||
|
||||
$province = new Province('استان تست ' . $code);
|
||||
$city = new City('شهر تست ' . $code, $province);
|
||||
$this->em->persist($province);
|
||||
$this->em->persist($city);
|
||||
$this->em->flush();
|
||||
|
||||
$payload = $this->importPayload($code);
|
||||
$payload['states'] = [$province->getId()];
|
||||
$payload['cities'] = [$city->getId()];
|
||||
|
||||
$data = $this->authJson('POST', '/api/v1/admin/doctors/import', $admin, $payload);
|
||||
$this->assertSame(201, $this->responseCode());
|
||||
|
||||
$cityId = $city->getId();
|
||||
$provinceId = $province->getId();
|
||||
$this->em->clear();
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['uuid' => $data['data']['uuid']]);
|
||||
$this->assertCount(1, $doctor->getAddresses());
|
||||
$address = $doctor->getAddresses()->first();
|
||||
$this->assertSame('مطب دکتر صفورا حجازی نیا', $address->getName());
|
||||
$this->assertSame($cityId, $address->getCity()?->getId());
|
||||
$this->assertSame($provinceId, $address->getProvince()?->getId());
|
||||
|
||||
// ایمپورت مجدد نباید آدرس تکراری بسازد یا نام آدرس را بازنویسی کند
|
||||
$address->setName('مطب ویرایششده توسط کاربر');
|
||||
$this->em->flush();
|
||||
|
||||
$this->authJson('POST', '/api/v1/admin/doctors/import', $admin, $payload);
|
||||
$this->assertSame(200, $this->responseCode());
|
||||
|
||||
$this->em->clear();
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['uuid' => $data['data']['uuid']]);
|
||||
$this->assertCount(1, $doctor->getAddresses());
|
||||
$this->assertSame('مطب ویرایششده توسط کاربر', $doctor->getAddresses()->first()->getName());
|
||||
}
|
||||
|
||||
public function testImportWithoutLocationStillCreatesOfficeAddress(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']);
|
||||
$code = $this->freshCode();
|
||||
|
||||
$data = $this->authJson('POST', '/api/v1/admin/doctors/import', $admin, $this->importPayload($code));
|
||||
$this->assertSame(201, $this->responseCode());
|
||||
|
||||
$this->em->clear();
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['uuid' => $data['data']['uuid']]);
|
||||
$this->assertCount(1, $doctor->getAddresses());
|
||||
$this->assertSame('مطب دکتر صفورا حجازی نیا', $doctor->getAddresses()->first()->getName());
|
||||
}
|
||||
|
||||
public function testValidationErrors(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']);
|
||||
|
||||
Reference in New Issue
Block a user