feat(practice-domain): add practice domains and let a clinic select one
A practice domain is the field a clinic operates in — beauty, dentistry —
and unlike Specialty it is configuration, not a label: treatment workflows
will bind to its code, so the code is immutable once created and only a
platform admin can mint one. A clinic that has not chosen a domain keeps
behaving exactly as it does today.
Assignment reuses PATCH /api/v1/clinic/{uuid} rather than adding a second
endpoint. An unknown domain uuid is rejected instead of silently dropped,
because a lost selection would only surface at the first protocol-driven
booking.
Also corrects ADR-0003: resource occupancy does not in fact guard the panel
booking path, which writes appointments.resource_id and no occupancy row at
all, so the doctor slot key cannot simply be dropped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,16 @@ class Clinic
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private ?string $name = null;
|
||||
|
||||
/**
|
||||
* حوزهٔ فعالیت کلینیک — تعیین میکند کدام `TreatmentWorkflow` صدا زده شود.
|
||||
*
|
||||
* `null` یعنی تنظیمنشده و رفتار پیشفرض، نه خطا: کلینیکهای موجود بدون انتخاب
|
||||
* حوزه باید دقیقاً مثل امروز کار کنند.
|
||||
*/
|
||||
#[ORM\ManyToOne(targetEntity: \App\PracticeDomain\Entity\PracticeDomain::class)]
|
||||
#[ORM\JoinColumn(name: 'practice_domain_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?\App\PracticeDomain\Entity\PracticeDomain $practiceDomain = null;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private ?string $info = null;
|
||||
|
||||
@@ -153,6 +163,7 @@ class Clinic
|
||||
public function getCreatedAt(): int { return $this->createdAt; }
|
||||
public function getUpdatedAt(): int { return $this->updatedAt; }
|
||||
public function getDoctors(): Collection { return $this->doctors; }
|
||||
public function getPracticeDomain(): ?\App\PracticeDomain\Entity\PracticeDomain { return $this->practiceDomain; }
|
||||
|
||||
public function hasDoctor(Doctor $doctor): bool { return $this->doctors->contains($doctor); }
|
||||
|
||||
@@ -184,6 +195,7 @@ class Clinic
|
||||
public function setSocialMedia(?array $v): self { $this->socialMedia = $v; $this->touch(); return $this; }
|
||||
public function setClinicLogo(?string $v): self { $this->clinicLogo = $v; $this->touch(); return $this; }
|
||||
public function setNotificationMobile(?string $v): self { $this->notificationMobile = $v; $this->touch(); return $this; }
|
||||
public function setPracticeDomain(?\App\PracticeDomain\Entity\PracticeDomain $v): self { $this->practiceDomain = $v; $this->touch(); return $this; }
|
||||
|
||||
private function touch(): void { $this->updatedAt = time(); }
|
||||
|
||||
@@ -231,6 +243,7 @@ class Clinic
|
||||
], $this->specialties->toArray()),
|
||||
'doctors' => $this->doctors->count(),
|
||||
'doctor_list' => null,
|
||||
'practice_domain' => $this->practiceDomain?->toArray(),
|
||||
'city' => $cityData ? [$cityData] : [],
|
||||
'state' => $provinceData ? [$provinceData] : [],
|
||||
'location' => $address,
|
||||
|
||||
Reference in New Issue
Block a user