feat : ajouter pour les forfaits le paiement de congés N-1
This commit is contained in:
@@ -34,6 +34,7 @@ final class EmployeeLeaveSummary
|
||||
public float $previousYearAcquiredDays = 0.0;
|
||||
public float $previousYearTakenDays = 0.0;
|
||||
public float $previousYearRemainingDays = 0.0;
|
||||
public float $previousYearPaidDays = 0.0;
|
||||
|
||||
/** @var array<string, float> YYYY-MM => count (0.5 for half-days) */
|
||||
public array $presenceDaysByMonth = [];
|
||||
|
||||
27
src/ApiResource/EmployeePaidLeaveDaysInput.php
Normal file
27
src/ApiResource/EmployeePaidLeaveDaysInput.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\ApiResource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use App\State\EmployeePaidLeaveDaysProcessor;
|
||||
use App\State\EmployeePaidLeaveDaysProvider;
|
||||
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Patch(
|
||||
uriTemplate: '/employees/{id}/paid-leave-days',
|
||||
security: "is_granted('ROLE_ADMIN')",
|
||||
provider: EmployeePaidLeaveDaysProvider::class,
|
||||
processor: EmployeePaidLeaveDaysProcessor::class
|
||||
),
|
||||
],
|
||||
paginationEnabled: false
|
||||
)]
|
||||
final class EmployeePaidLeaveDaysInput
|
||||
{
|
||||
public float $paidLeaveDays = 0.0;
|
||||
public ?int $year = null;
|
||||
}
|
||||
@@ -57,6 +57,9 @@ class EmployeeLeaveBalance
|
||||
#[ORM\Column(type: 'float', options: ['default' => 0, 'comment' => 'Jours de fractionnement saisis par la RH.'])]
|
||||
private float $fractionedDays = 0.0;
|
||||
|
||||
#[ORM\Column(type: 'float', options: ['default' => 0, 'comment' => 'Jours de conges N-1 payes par la RH (forfait uniquement).'])]
|
||||
private float $paidLeaveDays = 0.0;
|
||||
|
||||
#[ORM\Column(type: 'boolean', options: ['default' => false, 'comment' => 'Indique si le solde de l exercice est fige (verrouille RH).'])]
|
||||
private bool $isLocked = false;
|
||||
|
||||
@@ -222,6 +225,18 @@ class EmployeeLeaveBalance
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPaidLeaveDays(): float
|
||||
{
|
||||
return $this->paidLeaveDays;
|
||||
}
|
||||
|
||||
public function setPaidLeaveDays(float $paidLeaveDays): self
|
||||
{
|
||||
$this->paidLeaveDays = $paidLeaveDays;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isLocked(): bool
|
||||
{
|
||||
return $this->isLocked;
|
||||
|
||||
@@ -93,6 +93,7 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
||||
}
|
||||
|
||||
$fractionedDays = $this->resolveFractionedDays($employee, $yearSummary['ruleCode'], $year);
|
||||
$paidLeaveDays = $this->resolvePaidLeaveDays($employee, $yearSummary['ruleCode'], $year);
|
||||
|
||||
$summary->isSupported = true;
|
||||
$summary->ruleCode = $yearSummary['ruleCode'];
|
||||
@@ -106,7 +107,8 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
||||
$summary->remainingSaturdays = $yearSummary['remainingSaturdays'];
|
||||
$summary->previousYearAcquiredDays = $yearSummary['previousYearAcquiredDays'];
|
||||
$summary->previousYearTakenDays = $yearSummary['previousYearTakenDays'];
|
||||
$summary->previousYearRemainingDays = $yearSummary['previousYearRemainingDays'];
|
||||
$summary->previousYearRemainingDays = max(0.0, $yearSummary['previousYearRemainingDays'] - $paidLeaveDays);
|
||||
$summary->previousYearPaidDays = $paidLeaveDays;
|
||||
|
||||
[$periodFrom, $periodTo] = $this->resolvePeriodBounds($employee, $year);
|
||||
$summary->presenceDaysByMonth = $this->computePresenceDaysByMonth($employee, $periodFrom, $periodTo);
|
||||
@@ -765,6 +767,13 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
||||
return null !== $balance ? $balance->getFractionedDays() : 0.0;
|
||||
}
|
||||
|
||||
private function resolvePaidLeaveDays(Employee $employee, string $ruleCode, int $year): float
|
||||
{
|
||||
$balance = $this->leaveBalanceRepository->findOneByEmployeeRuleAndYear($employee, $ruleCode, $year);
|
||||
|
||||
return null !== $balance ? $balance->getPaidLeaveDays() : 0.0;
|
||||
}
|
||||
|
||||
private function resolveCurrentLeaveYear(DateTimeImmutable $today): int
|
||||
{
|
||||
$year = (int) $today->format('Y');
|
||||
|
||||
101
src/State/EmployeePaidLeaveDaysProcessor.php
Normal file
101
src/State/EmployeePaidLeaveDaysProcessor.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\State;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use App\ApiResource\EmployeePaidLeaveDaysInput;
|
||||
use App\Entity\Employee;
|
||||
use App\Entity\EmployeeLeaveBalance;
|
||||
use App\Enum\ContractType;
|
||||
use App\Enum\LeaveRuleCode;
|
||||
use App\Repository\EmployeeLeaveBalanceRepository;
|
||||
use App\Repository\EmployeeRepository;
|
||||
use App\Service\AuditLogger;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
|
||||
|
||||
final readonly class EmployeePaidLeaveDaysProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private EmployeeRepository $employeeRepository,
|
||||
private EmployeeLeaveBalanceRepository $leaveBalanceRepository,
|
||||
private EntityManagerInterface $entityManager,
|
||||
private AuditLogger $auditLogger,
|
||||
) {}
|
||||
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): EmployeePaidLeaveDaysInput
|
||||
{
|
||||
if (!$data instanceof EmployeePaidLeaveDaysInput) {
|
||||
throw new UnprocessableEntityHttpException('Invalid payload.');
|
||||
}
|
||||
|
||||
$employeeId = (int) ($uriVariables['id'] ?? 0);
|
||||
if ($employeeId <= 0) {
|
||||
throw new UnprocessableEntityHttpException('id must be a positive integer.');
|
||||
}
|
||||
|
||||
$employee = $this->employeeRepository->find($employeeId);
|
||||
if (!$employee instanceof Employee) {
|
||||
throw new NotFoundHttpException('Employee not found.');
|
||||
}
|
||||
|
||||
$year = $data->year ?? $this->resolveCurrentYear($employee);
|
||||
$ruleCode = $this->resolveRuleCode($employee);
|
||||
|
||||
$balance = $this->leaveBalanceRepository->findOneByEmployeeRuleAndYear($employee, $ruleCode, $year);
|
||||
|
||||
if (null === $balance) {
|
||||
$balance = new EmployeeLeaveBalance();
|
||||
$balance->setEmployee($employee);
|
||||
$balance->setRuleCode($ruleCode);
|
||||
$balance->setYear($year);
|
||||
$this->entityManager->persist($balance);
|
||||
}
|
||||
|
||||
$balance->setPaidLeaveDays($data->paidLeaveDays);
|
||||
$balance->touch();
|
||||
|
||||
$empName = trim(($employee->getLastName() ?? '').' '.($employee->getFirstName() ?? ''));
|
||||
$this->auditLogger->log(
|
||||
$employee,
|
||||
'update',
|
||||
'paid_leave_days',
|
||||
$balance->getId(),
|
||||
sprintf('Congés N-1 payés modifiés pour %s (année %d) : %s', $empName, $year, (string) $data->paidLeaveDays),
|
||||
['new' => ['paidLeaveDays' => $data->paidLeaveDays, 'year' => $year]],
|
||||
);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$data->year = $year;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function resolveRuleCode(Employee $employee): LeaveRuleCode
|
||||
{
|
||||
if (ContractType::FORFAIT === $employee->getContract()?->getType()) {
|
||||
return LeaveRuleCode::FORFAIT_218;
|
||||
}
|
||||
|
||||
return LeaveRuleCode::CDI_CDD_NON_FORFAIT;
|
||||
}
|
||||
|
||||
private function resolveCurrentYear(Employee $employee): int
|
||||
{
|
||||
$today = new DateTimeImmutable('today');
|
||||
|
||||
if (ContractType::FORFAIT === $employee->getContract()?->getType()) {
|
||||
return (int) $today->format('Y');
|
||||
}
|
||||
|
||||
$month = (int) $today->format('n');
|
||||
|
||||
return $month >= 6 ? (int) $today->format('Y') + 1 : (int) $today->format('Y');
|
||||
}
|
||||
}
|
||||
17
src/State/EmployeePaidLeaveDaysProvider.php
Normal file
17
src/State/EmployeePaidLeaveDaysProvider.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\State;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\ApiResource\EmployeePaidLeaveDaysInput;
|
||||
|
||||
final readonly class EmployeePaidLeaveDaysProvider implements ProviderInterface
|
||||
{
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): EmployeePaidLeaveDaysInput
|
||||
{
|
||||
return new EmployeePaidLeaveDaysInput();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user