Files
clinicpro/migrations/Version20260806131640.php
hamedandClaude Opus 5 6847a473d4 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>
2026-08-06 16:53:50 +03:30

57 lines
6.8 KiB
PHP

<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20260806131640 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add treatment cases, their snapshotted areas, sessions and per-area records';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE session_area_records (id INT AUTO_INCREMENT NOT NULL, uuid VARCHAR(36) NOT NULL, status VARCHAR(20) NOT NULL, parameters JSON DEFAULT NULL, started_at INT DEFAULT NULL, finished_at INT DEFAULT NULL, note LONGTEXT DEFAULT NULL, created_at INT NOT NULL, updated_at INT NOT NULL, entity_type VARCHAR(10) NOT NULL, entity_id INT NOT NULL, session_id INT NOT NULL, case_area_id INT NOT NULL, resource_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_51D08C3AD17F50A6 (uuid), INDEX IDX_51D08C3A613FECDF (session_id), INDEX IDX_51D08C3A12ACB597 (case_area_id), INDEX IDX_51D08C3A89329D25 (resource_id), INDEX idx_session_area_tenant (entity_type, entity_id), UNIQUE INDEX uq_session_area (session_id, case_area_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
$this->addSql('CREATE TABLE treatment_case_areas (id INT AUTO_INCREMENT NOT NULL, uuid VARCHAR(36) NOT NULL, name_snapshot VARCHAR(150) NOT NULL, sort_order SMALLINT DEFAULT 0 NOT NULL, treatment_case_id INT NOT NULL, catalog_category_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_1927F5A5D17F50A6 (uuid), INDEX IDX_1927F5A5B7D61639 (treatment_case_id), INDEX IDX_1927F5A53F2BC4C (catalog_category_id), UNIQUE INDEX uq_case_area_category (treatment_case_id, catalog_category_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
$this->addSql('CREATE TABLE treatment_cases (id INT AUTO_INCREMENT NOT NULL, uuid VARCHAR(36) NOT NULL, status VARCHAR(20) NOT NULL, total_sessions SMALLINT NOT NULL, opened_at INT NOT NULL, closed_at INT DEFAULT NULL, created_at INT NOT NULL, updated_at INT NOT NULL, entity_type VARCHAR(10) NOT NULL, entity_id INT NOT NULL, patient_record_id INT NOT NULL, service_item_id INT NOT NULL, protocol_id INT NOT NULL, supervisor_doctor_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_7668E0B5D17F50A6 (uuid), INDEX IDX_7668E0B5DDEB00C2 (service_item_id), INDEX IDX_7668E0B5CCD59258 (protocol_id), INDEX IDX_7668E0B5EB665C09 (supervisor_doctor_id), INDEX idx_treatment_cases_tenant (entity_type, entity_id, status), INDEX idx_treatment_cases_record (patient_record_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
$this->addSql('CREATE TABLE treatment_sessions (id INT AUTO_INCREMENT NOT NULL, uuid VARCHAR(36) NOT NULL, session_number SMALLINT NOT NULL, status VARCHAR(20) NOT NULL, due_at INT DEFAULT NULL, started_at INT DEFAULT NULL, finished_at INT DEFAULT NULL, note LONGTEXT DEFAULT NULL, created_at INT NOT NULL, updated_at INT NOT NULL, entity_type VARCHAR(10) NOT NULL, entity_id INT NOT NULL, treatment_case_id INT NOT NULL, appointment_id INT DEFAULT NULL, performed_by_staff_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_8CAD54AD17F50A6 (uuid), INDEX IDX_8CAD54AB7D61639 (treatment_case_id), INDEX IDX_8CAD54AE5B533F9 (appointment_id), INDEX IDX_8CAD54A94A09A49 (performed_by_staff_id), INDEX idx_treatment_sessions_tenant (entity_type, entity_id, status), INDEX idx_treatment_sessions_due (due_at), UNIQUE INDEX uq_session_case_number (treatment_case_id, session_number), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
$this->addSql('ALTER TABLE session_area_records ADD CONSTRAINT FK_51D08C3A613FECDF FOREIGN KEY (session_id) REFERENCES treatment_sessions (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE session_area_records ADD CONSTRAINT FK_51D08C3A12ACB597 FOREIGN KEY (case_area_id) REFERENCES treatment_case_areas (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE session_area_records ADD CONSTRAINT FK_51D08C3A89329D25 FOREIGN KEY (resource_id) REFERENCES clinic_resources (id) ON DELETE SET NULL');
$this->addSql('ALTER TABLE treatment_case_areas ADD CONSTRAINT FK_1927F5A5B7D61639 FOREIGN KEY (treatment_case_id) REFERENCES treatment_cases (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE treatment_case_areas ADD CONSTRAINT FK_1927F5A53F2BC4C FOREIGN KEY (catalog_category_id) REFERENCES service_catalog_categories (id) ON DELETE SET NULL');
$this->addSql('ALTER TABLE treatment_cases ADD CONSTRAINT FK_7668E0B5EB76A733 FOREIGN KEY (patient_record_id) REFERENCES patient_records (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE treatment_cases ADD CONSTRAINT FK_7668E0B5DDEB00C2 FOREIGN KEY (service_item_id) REFERENCES service_items (id) ON DELETE RESTRICT');
$this->addSql('ALTER TABLE treatment_cases ADD CONSTRAINT FK_7668E0B5CCD59258 FOREIGN KEY (protocol_id) REFERENCES treatment_protocols (id) ON DELETE RESTRICT');
$this->addSql('ALTER TABLE treatment_cases ADD CONSTRAINT FK_7668E0B5EB665C09 FOREIGN KEY (supervisor_doctor_id) REFERENCES doctors (id) ON DELETE SET NULL');
$this->addSql('ALTER TABLE treatment_sessions ADD CONSTRAINT FK_8CAD54AB7D61639 FOREIGN KEY (treatment_case_id) REFERENCES treatment_cases (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE treatment_sessions ADD CONSTRAINT FK_8CAD54AE5B533F9 FOREIGN KEY (appointment_id) REFERENCES appointments (id) ON DELETE SET NULL');
$this->addSql('ALTER TABLE treatment_sessions ADD CONSTRAINT FK_8CAD54A94A09A49 FOREIGN KEY (performed_by_staff_id) REFERENCES clinic_staff (id) ON DELETE SET NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE session_area_records DROP FOREIGN KEY FK_51D08C3A613FECDF');
$this->addSql('ALTER TABLE session_area_records DROP FOREIGN KEY FK_51D08C3A12ACB597');
$this->addSql('ALTER TABLE session_area_records DROP FOREIGN KEY FK_51D08C3A89329D25');
$this->addSql('ALTER TABLE treatment_case_areas DROP FOREIGN KEY FK_1927F5A5B7D61639');
$this->addSql('ALTER TABLE treatment_case_areas DROP FOREIGN KEY FK_1927F5A53F2BC4C');
$this->addSql('ALTER TABLE treatment_cases DROP FOREIGN KEY FK_7668E0B5EB76A733');
$this->addSql('ALTER TABLE treatment_cases DROP FOREIGN KEY FK_7668E0B5DDEB00C2');
$this->addSql('ALTER TABLE treatment_cases DROP FOREIGN KEY FK_7668E0B5CCD59258');
$this->addSql('ALTER TABLE treatment_cases DROP FOREIGN KEY FK_7668E0B5EB665C09');
$this->addSql('ALTER TABLE treatment_sessions DROP FOREIGN KEY FK_8CAD54AB7D61639');
$this->addSql('ALTER TABLE treatment_sessions DROP FOREIGN KEY FK_8CAD54AE5B533F9');
$this->addSql('ALTER TABLE treatment_sessions DROP FOREIGN KEY FK_8CAD54A94A09A49');
$this->addSql('DROP TABLE session_area_records');
$this->addSql('DROP TABLE treatment_case_areas');
$this->addSql('DROP TABLE treatment_cases');
$this->addSql('DROP TABLE treatment_sessions');
}
}