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:
@@ -33,6 +33,32 @@ final class CategoryClosureResolver
|
||||
return $this->walk((int) $category->getId(), $map);
|
||||
}
|
||||
|
||||
/**
|
||||
* برگهای زیرمجموعه — دستههایی که خودشان زیرمجموعهای ندارند.
|
||||
*
|
||||
* نواحیِ درمانِ یک سرویس همینهایند: «توتال» شامل «بیکینی» و «پا» و «دست» است و
|
||||
* درمان روی آن سه انجام میشود، نه روی خودِ «توتال». دستهٔ میانی فقط گروهبندی است.
|
||||
*
|
||||
* دستهای که هیچ زیرمجموعهای ندارد، خودش تنها ناحیه است — «لیزر دست» یک سرویس
|
||||
* واقعی است و باید یک ناحیه داشته باشد، نه صفر.
|
||||
*
|
||||
* @return list<int>
|
||||
*/
|
||||
public function leaves(CatalogCategory $category): array
|
||||
{
|
||||
$map = $this->includes->edgeMapFor($category->getEntityType(), $category->getEntityId());
|
||||
$descendants = $this->walk((int) $category->getId(), $map);
|
||||
|
||||
if ($descendants === []) {
|
||||
return [(int) $category->getId()];
|
||||
}
|
||||
|
||||
return array_values(array_filter(
|
||||
$descendants,
|
||||
static fn (int $id): bool => ($map[$id] ?? []) === [],
|
||||
));
|
||||
}
|
||||
|
||||
/** آیا یکی از این دو، دیگری را در بر میگیرد؟ (رابطه متقارن نیست، ولی تعارض هست) */
|
||||
public function overlaps(CatalogCategory $a, CatalogCategory $b): bool
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user