From 66bb94fc980a2db79cfd13c7b0a82d4924b5e144 Mon Sep 17 00:00:00 2001 From: matthieu Date: Tue, 10 Mar 2026 21:58:41 +0100 Subject: [PATCH] feat(backend) : add project relation to TaskStatus entity with migration and fixtures Add ManyToOne project field on TaskStatus, SearchFilter for API filtering, migration to add the column, and update fixtures to create statuses per project. Co-Authored-By: Claude Opus 4.6 --- frontend/pages/projects/[id].vue | 308 --------------------------- migrations/Version20260310201845.php | 35 +++ src/DataFixtures/AppFixtures.php | 56 ++--- src/Entity/TaskStatus.php | 20 ++ 4 files changed, 83 insertions(+), 336 deletions(-) delete mode 100644 frontend/pages/projects/[id].vue create mode 100644 migrations/Version20260310201845.php diff --git a/frontend/pages/projects/[id].vue b/frontend/pages/projects/[id].vue deleted file mode 100644 index 6f63992..0000000 --- a/frontend/pages/projects/[id].vue +++ /dev/null @@ -1,308 +0,0 @@ - - - diff --git a/migrations/Version20260310201845.php b/migrations/Version20260310201845.php new file mode 100644 index 0000000..4d49576 --- /dev/null +++ b/migrations/Version20260310201845.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE task_status ADD project_id INT NOT NULL'); + $this->addSql('ALTER TABLE task_status ADD CONSTRAINT FK_40A9E1CF166D1F9C FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE NOT DEFERRABLE'); + $this->addSql('CREATE INDEX IDX_40A9E1CF166D1F9C ON task_status (project_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE task_status DROP CONSTRAINT FK_40A9E1CF166D1F9C'); + $this->addSql('DROP INDEX IDX_40A9E1CF166D1F9C'); + $this->addSql('ALTER TABLE task_status DROP project_id'); + } +} diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index 97b1689..d3b18cf 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -89,36 +89,36 @@ class AppFixtures extends Fixture $projectInterne->setClient(null); $manager->persist($projectInterne); - // Task Statuses - $statusTodo = new TaskStatus(); - $statusTodo->setLabel('A faire'); - $statusTodo->setColor('#222783'); - $statusTodo->setPosition(0); - $manager->persist($statusTodo); + // Task Statuses (per project) + $defaultStatuses = [ + ['A faire', '#222783', 0], + ['En cours', '#4A90D9', 1], + ['Bloqué', '#C62828', 2], + ['En attente de validation', '#FF8F00', 3], + ['Terminé', '#26A69A', 4], + ]; - $statusInProgress = new TaskStatus(); - $statusInProgress->setLabel('En cours'); - $statusInProgress->setColor('#222783'); - $statusInProgress->setPosition(1); - $manager->persist($statusInProgress); + $statusesByProject = []; + foreach ([$projectSirh, $projectCrm, $projectErp, $projectInterne] as $proj) { + $projectStatuses = []; + foreach ($defaultStatuses as [$label, $color, $position]) { + $status = new TaskStatus(); + $status->setLabel($label); + $status->setColor($color); + $status->setPosition($position); + $status->setProject($proj); + $manager->persist($status); + $projectStatuses[$label] = $status; + } + $statusesByProject[spl_object_id($proj)] = $projectStatuses; + } - $statusBlocked = new TaskStatus(); - $statusBlocked->setLabel('Bloqué'); - $statusBlocked->setColor('#222783'); - $statusBlocked->setPosition(2); - $manager->persist($statusBlocked); - - $statusReview = new TaskStatus(); - $statusReview->setLabel('En attente de validation'); - $statusReview->setColor('#222783'); - $statusReview->setPosition(3); - $manager->persist($statusReview); - - $statusDone = new TaskStatus(); - $statusDone->setLabel('Terminé'); - $statusDone->setColor('#222783'); - $statusDone->setPosition(4); - $manager->persist($statusDone); + $sirhStatuses = $statusesByProject[spl_object_id($projectSirh)]; + $statusTodo = $sirhStatuses['A faire']; + $statusInProgress = $sirhStatuses['En cours']; + $statusBlocked = $sirhStatuses['Bloqué']; + $statusReview = $sirhStatuses['En attente de validation']; + $statusDone = $sirhStatuses['Terminé']; // Task Efforts $effortS = new TaskEffort(); diff --git a/src/Entity/TaskStatus.php b/src/Entity/TaskStatus.php index 45a7eaf..630194d 100644 --- a/src/Entity/TaskStatus.php +++ b/src/Entity/TaskStatus.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace App\Entity; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -26,6 +28,7 @@ use Symfony\Component\Serializer\Attribute\Groups; denormalizationContext: ['groups' => ['task_status:write']], order: ['position' => 'ASC'], )] +#[ApiFilter(SearchFilter::class, properties: ['project' => 'exact'])] #[ORM\Entity(repositoryClass: TaskStatusRepository::class)] class TaskStatus { @@ -47,6 +50,11 @@ class TaskStatus #[Groups(['task_status:read', 'task_status:write', 'task:read'])] private ?int $position = 0; + #[ORM\ManyToOne(targetEntity: Project::class)] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] + #[Groups(['task_status:read', 'task_status:write'])] + private ?Project $project = null; + public function getId(): ?int { return $this->id; @@ -87,4 +95,16 @@ class TaskStatus return $this; } + + public function getProject(): ?Project + { + return $this->project; + } + + public function setProject(?Project $project): static + { + $this->project = $project; + + return $this; + } }