feat : ajout d'un champ commentaire sur les contrats + correction de plusieurs bugs

This commit is contained in:
2026-03-06 16:58:29 +01:00
parent 4cf2608cdd
commit e794ad2514
28 changed files with 235 additions and 59 deletions

View File

@@ -21,5 +21,7 @@ final class ContractHistoryItem
public string $startDate,
#[Groups(['employee:read'])]
public ?string $endDate,
#[Groups(['employee:read'])]
public ?string $comment = null,
) {}
}

View File

@@ -78,6 +78,9 @@ class Employee
#[Groups(['employee:write'])]
private ?bool $contractPaidLeaveSettled = null;
#[Groups(['employee:write'])]
private ?string $contractComment = null;
public function __construct()
{
$this->createdAt = new DateTimeImmutable();
@@ -202,6 +205,18 @@ class Employee
return $this;
}
public function getContractComment(): ?string
{
return $this->contractComment;
}
public function setContractComment(?string $contractComment): self
{
$this->contractComment = $contractComment;
return $this;
}
#[Groups(['employee:read'])]
public function getCurrentContractNature(): string
{
@@ -243,6 +258,7 @@ class Employee
contractNature: $period->getContractNatureEnum()->value,
startDate: $period->getStartDate()->format('Y-m-d'),
endDate: $period->getEndDate()?->format('Y-m-d'),
comment: $period->getComment(),
);
},
$periods

View File

@@ -40,6 +40,9 @@ class EmployeeContractPeriod
#[ORM\Column(type: 'boolean', options: ['default' => false])]
private bool $paidLeaveSettled = false;
#[ORM\Column(type: 'text', nullable: true)]
private ?string $comment = null;
#[ORM\Column(type: 'datetime_immutable')]
private DateTimeImmutable $createdAt;
@@ -136,4 +139,16 @@ class EmployeeContractPeriod
return $this;
}
public function getComment(): ?string
{
return $this->comment;
}
public function setComment(?string $comment): self
{
$this->comment = $comment;
return $this;
}
}

View File

@@ -14,6 +14,7 @@ use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use App\Repository\WorkHourRepository;
use App\State\WorkHourSiteValidationProcessor;
use DateTimeImmutable;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;
@@ -106,6 +107,10 @@ class WorkHour
#[Groups(['work_hour:read', 'work_hour:site_validate'])]
private bool $isSiteValid = false;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
#[Groups(['work_hour:read'])]
private ?DateTimeImmutable $updatedAt = null;
public function getId(): ?int
{
return $this->id;
@@ -274,4 +279,16 @@ class WorkHour
return $this;
}
public function getUpdatedAt(): ?DateTimeImmutable
{
return $this->updatedAt;
}
public function setUpdatedAt(?DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}

View File

@@ -14,6 +14,7 @@ final readonly class EmployeeContractChangeRequest
public ?DateTimeImmutable $contractStartDate,
public ?DateTimeImmutable $contractEndDate,
public ?bool $contractPaidLeaveSettled,
public ?string $contractComment,
) {}
public function hasPeriodChangeRequest(): bool
@@ -21,7 +22,8 @@ final readonly class EmployeeContractChangeRequest
return null !== $this->contractNature
|| null !== $this->contractStartDate
|| null !== $this->contractEndDate
|| null !== $this->contractPaidLeaveSettled;
|| null !== $this->contractPaidLeaveSettled
|| null !== $this->contractComment;
}
public function isCloseOnlyRequest(bool $contractChanged): bool

View File

@@ -18,6 +18,7 @@ final class EmployeeContractChangeRequestFactory
contractStartDate: $this->parseOptionalYmd($employee->getContractStartDate(), 'contractStartDate'),
contractEndDate: $this->parseOptionalYmd($employee->getContractEndDate(), 'contractEndDate'),
contractPaidLeaveSettled: $employee->getContractPaidLeaveSettled(),
contractComment: $employee->getContractComment(),
);
}

View File

@@ -43,7 +43,8 @@ final readonly class EmployeeContractPeriodManager implements EmployeeContractPe
public function closeCurrentPeriod(
?EmployeeContractPeriod $todayPeriod,
DateTimeImmutable $requestedEndDate,
bool $paidLeaveSettled
bool $paidLeaveSettled,
?string $comment = null
): void {
if (null === $todayPeriod) {
throw new UnprocessableEntityHttpException('No active contract period to close.');
@@ -58,6 +59,7 @@ final readonly class EmployeeContractPeriodManager implements EmployeeContractPe
$todayPeriod->setEndDate($requestedEndDate);
$todayPeriod->setPaidLeaveSettled($paidLeaveSettled);
$todayPeriod->setComment($comment);
$this->entityManager->flush();
}

View File

@@ -23,7 +23,8 @@ interface EmployeeContractPeriodManagerInterface
public function closeCurrentPeriod(
?EmployeeContractPeriod $todayPeriod,
DateTimeImmutable $requestedEndDate,
bool $paidLeaveSettled
bool $paidLeaveSettled,
?string $comment = null
): void;
public function createNextPeriod(

View File

@@ -69,13 +69,8 @@ final readonly class WorkedHoursCreditPolicy
return 0.0;
}
// Règle forfait:
// - demi-journée d'absence => 0.5 travaillé
// - journée complète d'absence => 0 travaillé
if ($absentMorning xor $absentAfternoon) {
return 0.5;
}
// Règle forfait: les absences ne créditent jamais de présence.
// Seules les checkboxes cochées par l'employé comptent.
return 0.0;
}

View File

@@ -90,7 +90,8 @@ final readonly class EmployeeWriteProcessor implements ProcessorInterface
$this->periodManager->closeCurrentPeriod(
$todayPeriod,
$requestedEndDate,
$changeRequest->contractPaidLeaveSettled ?? false
$changeRequest->contractPaidLeaveSettled ?? false,
$changeRequest->contractComment
);
return $result;

View File

@@ -98,6 +98,7 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
$normalized = $this->normalizeEntry($entry, $employeeId, $isPresenceTracking);
$existing = $existingByEmployeeId[$employeeId] ?? null;
$isAdmin = in_array('ROLE_ADMIN', $user->getRoles(), true);
$isSelf = in_array('ROLE_SELF', $user->getRoles(), true);
if ($existing?->isValid()) {
if (!$this->isSameAsExisting($existing, $normalized)) {
@@ -145,6 +146,9 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
->setWorkDate($workDate)
;
$this->hydrateWorkHour($workHour, $normalized);
if ($isSelf) {
$workHour->setUpdatedAt(new DateTimeImmutable());
}
$this->entityManager->persist($workHour);
$existingByEmployeeId[$employeeId] = $workHour;
++$result->created;
@@ -169,6 +173,9 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
}
$this->hydrateWorkHour($workHour, $normalized);
if (!$isAdmin) {
$workHour->setUpdatedAt(new DateTimeImmutable());
}
++$result->processed;
}