From 9fe239738607207556ed0eaa961917bbd5ea4d7d Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 12 Mar 2026 11:23:09 +0100 Subject: [PATCH] =?UTF-8?q?feat=20:=20ajout=20d'une=20date=20d'entr=C3=A9e?= =?UTF-8?q?=20pour=20les=20employ=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 13 +++++- frontend/pages/employees/[id].vue | 7 +++- frontend/pages/employees/index.vue | 1 + frontend/services/dto/employee.ts | 1 + migrations/Version20260312120000.php | 26 ++++++++++++ src/Entity/Employee.php | 19 +++++++++ src/State/EmployeeWriteProcessor.php | 3 ++ tests/State/EmployeeWriteProcessorTest.php | 49 ++++++++++++++++++++++ 8 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 migrations/Version20260312120000.php diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 78cf90c..5add14a 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -7,7 +7,18 @@ "Bash(docker compose:*)", "Bash(make test:*)", "Bash(grep:*)", - "Bash(docker exec:*)" + "Bash(docker exec:*)", + "Bash(php8.3 bin/phpunit tests/State/EmployeeWriteProcessorTest.php --filter=testSetsEntryDateOnNewEmployee 2>&1)", + "Read(//usr/bin/**)", + "Read(//usr/local/bin/**)", + "Bash(command -v php8.2)", + "Bash(command -v php8.1)", + "Bash(ls /usr/bin/php*)", + "Read(//opt/**)", + "Read(//home/m-tristan/.nix-profile/**)", + "Read(//home/m-tristan/.local/bin/**)", + "Bash(env)", + "Bash(ls /home/m-tristan/workspace/SIRH/docker* /home/m-tristan/workspace/SIRH/Makefile 2>/dev/null; cat /home/m-tristan/workspace/SIRH/Makefile 2>/dev/null | grep -E \"\\(phpunit|test|php\\)\" | head -20)" ] } } diff --git a/frontend/pages/employees/[id].vue b/frontend/pages/employees/[id].vue index a913583..7061be9 100644 --- a/frontend/pages/employees/[id].vue +++ b/frontend/pages/employees/[id].vue @@ -12,9 +12,12 @@
-

{{ employee.firstName }} {{ employee.lastName }}

+
+

{{ employee.firstName }} {{ employee.lastName }}

+

Date d'entrée : {{ employee.entryDate ? employee.entryDate.split('-').reverse().join('/') : '-' }}

+
-

{{ contractNatureLabel(employee.currentContractNature) }} {{ employeeContractWorkLabel }}

+

{{ contractNatureLabel(employee.currentContractNature) }} {{ employeeContractWorkLabel }}

{{ employee.site?.name ?? '-' }}

diff --git a/frontend/pages/employees/index.vue b/frontend/pages/employees/index.vue index b67493b..2159e91 100644 --- a/frontend/pages/employees/index.vue +++ b/frontend/pages/employees/index.vue @@ -51,6 +51,7 @@

Type: {{ contractNatureLabel(employee.currentContractNature) }}

Temps de travail: {{ employee.contract?.name ?? '-' }}

Site: {{ employee.site?.name ?? '-' }}

+

Date d'entrée : {{ employee.entryDate ? employee.entryDate.split('-').reverse().join('/') : '-' }}

diff --git a/frontend/services/dto/employee.ts b/frontend/services/dto/employee.ts index ceaac93..c22472e 100644 --- a/frontend/services/dto/employee.ts +++ b/frontend/services/dto/employee.ts @@ -22,4 +22,5 @@ export type Employee = { currentContractEndDate?: string | null contractHistory?: ContractHistoryItem[] displayOrder?: number + entryDate?: string | null } diff --git a/migrations/Version20260312120000.php b/migrations/Version20260312120000.php new file mode 100644 index 0000000..a07ad80 --- /dev/null +++ b/migrations/Version20260312120000.php @@ -0,0 +1,26 @@ +addSql('ALTER TABLE employees ADD entry_date DATE DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE employees DROP entry_date'); + } +} diff --git a/src/Entity/Employee.php b/src/Entity/Employee.php index 8c97575..bb1d88f 100644 --- a/src/Entity/Employee.php +++ b/src/Entity/Employee.php @@ -14,7 +14,9 @@ use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Attribute\Context; use Symfony\Component\Serializer\Attribute\Groups; +use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; #[ApiResource( normalizationContext: ['groups' => ['employee:read', 'site:read']], @@ -57,6 +59,11 @@ class Employee #[Groups(['employee:read', 'employee:write'])] private int $displayOrder = 0; + #[ORM\Column(type: 'date_immutable', nullable: true)] + #[Groups(['employee:read'])] + #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])] + private ?DateTimeImmutable $entryDate = null; + #[ORM\Column(type: 'datetime_immutable')] private DateTimeImmutable $createdAt; @@ -166,6 +173,18 @@ class Employee return $this; } + public function getEntryDate(): ?DateTimeImmutable + { + return $this->entryDate; + } + + public function setEntryDate(?DateTimeImmutable $entryDate): self + { + $this->entryDate = $entryDate; + + return $this; + } + public function getContractNature(): ?string { return $this->contractNature; diff --git a/src/State/EmployeeWriteProcessor.php b/src/State/EmployeeWriteProcessor.php index 56a320e..56c9dc3 100644 --- a/src/State/EmployeeWriteProcessor.php +++ b/src/State/EmployeeWriteProcessor.php @@ -68,6 +68,9 @@ final readonly class EmployeeWriteProcessor implements ProcessorInterface nature: $nature ); + $data->setEntryDate($startDate); + $this->entityManager->flush(); + return $result; } diff --git a/tests/State/EmployeeWriteProcessorTest.php b/tests/State/EmployeeWriteProcessorTest.php index 9481d32..d5a79e1 100644 --- a/tests/State/EmployeeWriteProcessorTest.php +++ b/tests/State/EmployeeWriteProcessorTest.php @@ -6,6 +6,7 @@ namespace App\Tests\State; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use ApiPlatform\State\ProcessorInterface; use App\Entity\Contract; use App\Entity\Employee; @@ -194,6 +195,54 @@ final class EmployeeWriteProcessorTest extends TestCase self::assertSame($employee, $result); } + public function testSetsEntryDateOnNewEmployee(): void + { + $employee = new Employee(); + $employee->setFirstName('Jane'); + $employee->setLastName('Doe'); + $employee->setContractStartDate('2026-04-01'); + $employee->setContractNature('CDI'); + + $contract = new Contract() + ->setName('35h') + ->setTrackingMode(Contract::TRACKING_TIME) + ->setWeeklyHours(35) + ; + $employee->setContract($contract); + + $persistProcessor = $this->createMock(ProcessorInterface::class); + $removeProcessor = $this->createStub(ProcessorInterface::class); + $entityManager = $this->createStub(EntityManagerInterface::class); + $periodRepository = $this->createStub(EmployeeContractPeriodReadRepositoryInterface::class); + $changeRequestFactory = new EmployeeContractChangeRequestFactory(); + $periodManager = $this->createMock(EmployeeContractPeriodManagerInterface::class); + + $persistProcessor + ->expects(self::once()) + ->method('process') + ->willReturn($employee) + ; + + $periodManager + ->expects(self::once()) + ->method('ensureContractPeriodExists') + ; + + $processor = new EmployeeWriteProcessor( + $persistProcessor, + $removeProcessor, + $entityManager, + $periodRepository, + $changeRequestFactory, + $periodManager + ); + + $processor->process($employee, new Post()); + + self::assertNotNull($employee->getEntryDate()); + self::assertSame('2026-04-01', $employee->getEntryDate()->format('Y-m-d')); + } + public function testDeleteOperationDelegatesToRemoveProcessor(): void { $employee = $this->buildEmployeeWithId(45);