feat(doctor): prevent duplicate doctor imports based on medical system code
This commit is contained in:
@@ -39,6 +39,10 @@
|
||||
- اگر وجود داشته باشد و `owner_status != claimed` → **بهروزرسانی** میشود (`200`).
|
||||
- اگر وجود داشته باشد و `owner_status == claimed` → **رد** میشود (`200`, `skipped: "claimed"`)
|
||||
تا دادهٔ مالک واقعی بازنویسی نشود.
|
||||
- **تکرار بین منابع:** اگر پزشکی با همان `medical_system_code` ولی `source` متفاوت
|
||||
(مثلاً ثبت دستی در پنل) وجود داشته باشد → **رد** میشود (`200`, `skipped: "duplicate"`)؛
|
||||
نه رکورد جدیدی ساخته میشود و نه رکورد موجود بازنویسی میشود. `uuid` همان رکورد موجود
|
||||
برگردانده میشود (تست: `DoctorImportTest::testManualDoctorWithSameCodeIsNeverDuplicated`).
|
||||
|
||||
---
|
||||
|
||||
@@ -108,6 +112,11 @@
|
||||
{ "success": true, "data": { "uuid": "…", "created": false, "skipped": "claimed" } }
|
||||
```
|
||||
|
||||
### `200 OK` (رد بهدلیل کد نظام پزشکی تکراری با منبع دیگر)
|
||||
```json
|
||||
{ "success": true, "data": { "uuid": "…", "created": false, "skipped": "duplicate" } }
|
||||
```
|
||||
|
||||
### `422` (اعتبارسنجی)
|
||||
```json
|
||||
{ "success": false, "data": null, "errors": [ { "code": "…", "message": "کد نظام پزشکی الزامی است", "field": "medical_system_code" } ] }
|
||||
|
||||
@@ -65,6 +65,15 @@ class DoctorImportService
|
||||
return new DoctorImportResult($doctor, false, 'claimed');
|
||||
}
|
||||
|
||||
if ($doctor === null) {
|
||||
// جلوگیری از تکرار بین منابع: اگر همین کد نظام پزشکی با هر source دیگری
|
||||
// (مثلاً ثبت دستی) وجود دارد، ایمپورت نه میسازد و نه بازنویسی میکند.
|
||||
$existing = $doctorRepo->findOneBy(['medicalSystemCode' => $code]);
|
||||
if ($existing !== null) {
|
||||
return new DoctorImportResult($existing, false, 'duplicate');
|
||||
}
|
||||
}
|
||||
|
||||
if ($doctor === null) {
|
||||
// کاربر جانشینِ یکتا و غیرفعال؛ شناسهٔ مصنوعی قطعی از روی کد نظام پزشکی
|
||||
$synthetic = 'imp_' . substr(md5($source . ':' . $code), 0, 14); // ≤ ۱۸ کاراکتر، ASCII، یکتا
|
||||
|
||||
@@ -164,6 +164,32 @@ class DoctorImportTest extends ApiTestCase
|
||||
$this->assertSame('مطب دکتر صفورا حجازی نیا', $doctor->getAddresses()->first()->getName());
|
||||
}
|
||||
|
||||
public function testManualDoctorWithSameCodeIsNeverDuplicated(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']);
|
||||
$code = $this->freshCode();
|
||||
|
||||
$owner = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
|
||||
$manual = new Doctor($owner, 'پزشک دستی');
|
||||
$manual->setMedicalSystemCode($code);
|
||||
$this->em->persist($manual);
|
||||
$this->em->flush();
|
||||
|
||||
$data = $this->authJson('POST', '/api/v1/admin/doctors/import', $admin, $this->importPayload($code));
|
||||
|
||||
$this->assertSame(200, $this->responseCode());
|
||||
$this->assertFalse($data['data']['created']);
|
||||
$this->assertSame('duplicate', $data['data']['skipped']);
|
||||
$this->assertSame($manual->getUuid(), $data['data']['uuid']);
|
||||
|
||||
$this->em->clear();
|
||||
$count = $this->em->getRepository(Doctor::class)->count(['medicalSystemCode' => $code]);
|
||||
$this->assertSame(1, $count);
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['medicalSystemCode' => $code]);
|
||||
$this->assertSame('پزشک دستی', $doctor->getName());
|
||||
$this->assertSame('manual', $doctor->getSource());
|
||||
}
|
||||
|
||||
public function testValidationErrors(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']);
|
||||
|
||||
Reference in New Issue
Block a user