feat(treatment): open a treatment case with snapshotted areas and its sessions

Opening a case copies what must not move afterwards — the session count and the
list of body areas, each with its category name — because a treatment record is
a medical document and editing settings tomorrow must not rewrite what was done
yesterday. The areas are the leaf categories under the service's own category:
"توتال" contains bikini, leg and hand, and treatment happens on those three, not
on the grouping node above them. A category with no children is its own single
area, so "لیزر دست" gets one area rather than none.

Every session in the course is created up front so that "session 5 of 8" has
somewhere to live, but none of them is booked: creating eight real appointments
would lock eight months of slots for a patient who may not attend session three.

CategoryClosureResolver gains leaves(); the graph walk it already does is what
tells a leaf from a grouping node, so this belongs next to descendants() rather
than in a second traversal elsewhere.

TreatmentCase and TreatmentSession carry no money field, and must not: billing
lives on PatientSession, which is created when an appointment is confirmed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-08-06 16:53:50 +03:30
co-authored by Claude Opus 5
parent e2e3e6b43b
commit 6847a473d4
13 changed files with 1278 additions and 0 deletions
+5
View File
@@ -117,6 +117,11 @@ final class GlobalTables
\App\Treatment\Entity\TreatmentProtocol::class => \App\ClinicService\Entity\ServiceItem::class,
\App\Treatment\Entity\TreatmentProtocolStep::class => \App\Treatment\Entity\TreatmentProtocol::class,
\App\Treatment\Entity\TreatmentProtocolStaff::class => \App\Treatment\Entity\TreatmentProtocol::class,
// فهرست نواحیِ یک پرونده فقط از خودِ پرونده پیمایش می‌شود و uuidش هیچ‌جا از
// درخواست نمی‌آید. جلسه و رکورد ناحیه برعکس‌اند — پنل پرسنل uuidشان را مستقیم
// می‌فرستد — پس آن دو جفت محیط خودشان را دارند، نه اینجا.
\App\Treatment\Entity\TreatmentCaseArea::class => \App\Treatment\Entity\TreatmentCase::class,
// یال «این دسته شامل آن دسته است» جزئی از تعریف دستهٔ والد است؛ هر دو سرِ یال
// در یک محیط‌اند و سازندهٔ یال همین را اجبار می‌کند.
\App\ClinicService\Entity\CatalogCategoryInclude::class => \App\ClinicService\Entity\CatalogCategory::class,