valide. * * Le metier peut desormais enregistrer une pesee (bascule ou manuelle) SANS avoir * rempli la contrepartie ni l'immatriculation : le ticket est cree « brouillon » * des la 1ere pesee, puis « valide » (numero attribue, status VALIDATED) quand les * 3 champs requis (type + champ contrepartie + immatriculation) ET les 2 pesees * sont renseignes. * * Schema impacte : * - `counterparty_type`, `immatriculation`, `number` passent NULLABLE (un brouillon * n'a encore ni contrepartie, ni immat, ni numero — le numero n'est attribue * qu'a la validation pour eviter les trous de sequence). Les CHECK de branche * chk_wt_*_branch tolerent deja un counterparty_type NULL (NULL <> 'X' = NULL, * donc CHECK non viole). * - nouvelle colonne `status` (DRAFT|VALIDATED). Les tickets EXISTANTS (crees sous * l'ancien flux, donc complets) sont retro-marques VALIDATED ; le defaut des * nouvelles lignes est DRAFT. * * Namespace racine `DoctrineMigrations` (et non modulaire) : la migration ALTER une * table creee par la migration racine Version20260617150000. Doctrine Migrations * 3.x trie par FQCN alphabetique entre namespaces -> une migration modulaire * `App\Module\...` passerait AVANT la racine sur base vide (make db-reset) et * tenterait l'ALTER avant le CREATE. Le namespace racine garantit le tri par * timestamp (regle ABSOLUE n°11, cf. Version20260617170000 pour site.code). */ final class Version20260624100000 extends AbstractMigration { public function getDescription(): string { return 'ERP-193 : weighing_ticket brouillon/valide (counterparty_type/immatriculation/number nullable + colonne status).'; } public function up(Schema $schema): void { // Brouillon : ni contrepartie, ni immat, ni numero tant que non valide. $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN counterparty_type DROP NOT NULL'); $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN immatriculation DROP NOT NULL'); $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN number DROP NOT NULL'); // Statut du cycle de vie. Colonne ajoutee nullable, retro-remplie a VALIDATED // pour les tickets existants (complets), puis figee NOT NULL DEFAULT DRAFT. $this->addSql('ALTER TABLE weighing_ticket ADD COLUMN status VARCHAR(12)'); $this->addSql("UPDATE weighing_ticket SET status = 'VALIDATED'"); $this->addSql("ALTER TABLE weighing_ticket ALTER COLUMN status SET DEFAULT 'DRAFT'"); $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN status SET NOT NULL'); $this->addSql("ALTER TABLE weighing_ticket ADD CONSTRAINT chk_wt_status CHECK (status IN ('DRAFT','VALIDATED'))"); // Commentaires (regle ABSOLUE n°12). $this->comment('weighing_ticket', 'status', "Cycle de vie : DRAFT (En attente, pesee enregistree sans contrepartie/immat) ou VALIDATED (Terminee, valide avec numero). Defaut DRAFT."); $this->comment('weighing_ticket', 'number', "Numero {siteCode}-TP-{NNNN}, unique par site, immuable. NULL tant que le ticket est brouillon : attribue a la validation (RG-5.02, ERP-193)."); $this->comment('weighing_ticket', 'counterparty_type', "Contrepartie : CLIENT, FOURNISSEUR ou AUTRE (RG-5.03). NULL tant que brouillon ; requise a la validation. Pilote l'obligation client_id / supplier_id / other_label."); $this->comment('weighing_ticket', 'immatriculation', "Plaque du vehicule, partagee entre pesee vide et plein (RG-5.01). NULL tant que brouillon ; requise a la validation. Masque XX-000-XX sauf plate_free_format."); } public function down(Schema $schema): void { $this->addSql('ALTER TABLE weighing_ticket DROP CONSTRAINT IF EXISTS chk_wt_status'); $this->addSql('ALTER TABLE weighing_ticket DROP COLUMN IF EXISTS status'); // Restauration NOT NULL : echoue s'il subsiste des brouillons (number / // counterparty_type / immatriculation NULL) — irreversible en presence de // donnees brouillon, ce qui est attendu (le down sert au dev sur base saine). $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN number SET NOT NULL'); $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN immatriculation SET NOT NULL'); $this->addSql('ALTER TABLE weighing_ticket ALTER COLUMN counterparty_type SET NOT NULL'); } /** * Pose un COMMENT ON COLUMN en dollar-quoting Postgres ($_$...$_$) pour eviter * tout echappement d'apostrophes dans les descriptions. */ private function comment(string $table, string $column, string $description): void { $this->addSql(sprintf( 'COMMENT ON COLUMN %s.%s IS $_$%s$_$', '"'.str_replace('"', '""', $table).'"', '"'.str_replace('"', '""', $column).'"', $description, )); } }