Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9979c9a19 | ||
| 1091147100 |
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.74'
|
app.version: '0.1.75'
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ Tous les filtres checkbox sont cochés par défaut à l'ouverture du drawer.
|
|||||||
- pour `FORFAIT`:
|
- pour `FORFAIT`:
|
||||||
- pris: basé sur toutes les absences (demi-journées incluses)
|
- pris: basé sur toutes les absences (demi-journées incluses)
|
||||||
- restants = acquis - pris (borné à 0)
|
- restants = acquis - pris (borné à 0)
|
||||||
|
- paiement congés N-1: saisie RH via `PATCH /employees/{id}/paid-leave-days` (body: `paidLeaveDays`, `year`). Stocké dans `employee_leave_balances.paid_leave_days`. Les jours payés sont soustraits du reste à prendre N-1 (`previousYearRemainingDays = max(0, acquis_N-1 - pris_N-1 - payés)`). Uniquement pour les contrats forfait.
|
||||||
- report annuel:
|
- report annuel:
|
||||||
- le reliquat (`restants`) de l'exercice précédent est reporté dans les acquis de l'exercice courant
|
- le reliquat (`restants`) de l'exercice précédent est reporté dans les acquis de l'exercice courant
|
||||||
- pour `CDI`/`CDD` non forfait: report séparé jours + samedis
|
- pour `CDI`/`CDD` non forfait: report séparé jours + samedis
|
||||||
|
|||||||
@@ -32,6 +32,18 @@
|
|||||||
<p v-if="isForfaitRule" class="col-start-3 p-[10px] border-r-primary-500 bg-primary-500 text-white"><span class="uppercase font-semibold">Reste à prendre :</span>
|
<p v-if="isForfaitRule" class="col-start-3 p-[10px] border-r-primary-500 bg-primary-500 text-white"><span class="uppercase font-semibold">Reste à prendre :</span>
|
||||||
{{ formatCount(summary?.previousYearRemainingDays) }} Jours
|
{{ formatCount(summary?.previousYearRemainingDays) }} Jours
|
||||||
</p>
|
</p>
|
||||||
|
<div v-if="isForfaitRule" class="col-start-4 p-[10px] flex gap-7 items-center">
|
||||||
|
<div>
|
||||||
|
<span class="uppercase font-semibold">Année n-1 payés : </span>
|
||||||
|
<span> {{ formatCount(summary?.previousYearPaidDays) }} Jours</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="flex items-center"
|
||||||
|
@click="openPaidLeaveDrawer"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:edit-box" size="24"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div v-if="!isForfaitRule" class="col-start-4 p-[10px] flex gap-7 items-center">
|
<div v-if="!isForfaitRule" class="col-start-4 p-[10px] flex gap-7 items-center">
|
||||||
<div>
|
<div>
|
||||||
<span class="uppercase font-semibold">Fractionné acquis : </span>
|
<span class="uppercase font-semibold">Fractionné acquis : </span>
|
||||||
@@ -112,6 +124,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</AppDrawer>
|
</AppDrawer>
|
||||||
|
<AppDrawer v-model="isPaidLeaveDrawerOpen" title="Congés N-1 payés">
|
||||||
|
<form class="space-y-4" @submit.prevent="handleSubmitPaidLeave">
|
||||||
|
<div>
|
||||||
|
<label class="text-md font-semibold text-neutral-700" for="paid-leave-days">
|
||||||
|
Nombre de jours <span class="text-red-600">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="paid-leave-days"
|
||||||
|
v-model="paidLeaveForm.days"
|
||||||
|
type="number"
|
||||||
|
step="0.5"
|
||||||
|
min="0"
|
||||||
|
class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end gap-3 pt-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="rounded-lg border border-neutral-200 px-4 py-2 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
|
||||||
|
@click="isPaidLeaveDrawerOpen = false"
|
||||||
|
>
|
||||||
|
Annuler
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
|
||||||
|
>
|
||||||
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</AppDrawer>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -136,11 +181,15 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: 'update-fractioned-days', days: number): void
|
(event: 'update-fractioned-days', days: number): void
|
||||||
|
(event: 'update-paid-leave-days', days: number): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const isFractionedDrawerOpen = ref(false)
|
const isFractionedDrawerOpen = ref(false)
|
||||||
const fractionedForm = reactive({days: 0})
|
const fractionedForm = reactive({days: 0})
|
||||||
|
|
||||||
|
const isPaidLeaveDrawerOpen = ref(false)
|
||||||
|
const paidLeaveForm = reactive({days: 0})
|
||||||
|
|
||||||
const openFractionedDrawer = () => {
|
const openFractionedDrawer = () => {
|
||||||
fractionedForm.days = props.summary?.fractionedDays ?? 0
|
fractionedForm.days = props.summary?.fractionedDays ?? 0
|
||||||
isFractionedDrawerOpen.value = true
|
isFractionedDrawerOpen.value = true
|
||||||
@@ -153,6 +202,18 @@ const handleSubmitFractioned = () => {
|
|||||||
isFractionedDrawerOpen.value = false
|
isFractionedDrawerOpen.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openPaidLeaveDrawer = () => {
|
||||||
|
paidLeaveForm.days = props.summary?.previousYearPaidDays ?? 0
|
||||||
|
isPaidLeaveDrawerOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmitPaidLeave = () => {
|
||||||
|
const value = Number(paidLeaveForm.days)
|
||||||
|
if (Number.isNaN(value) || value < 0) return
|
||||||
|
emit('update-paid-leave-days', value)
|
||||||
|
isPaidLeaveDrawerOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
const monthLabels = [
|
const monthLabels = [
|
||||||
'Janvier',
|
'Janvier',
|
||||||
'Fevrier',
|
'Fevrier',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { EmployeeLeaveSummary } from '~/services/dto/employee-leave-summary
|
|||||||
import type { Employee } from '~/services/dto/employee'
|
import type { Employee } from '~/services/dto/employee'
|
||||||
import { CONTRACT_TYPES } from '~/services/dto/contract'
|
import { CONTRACT_TYPES } from '~/services/dto/contract'
|
||||||
import { listAbsences } from '~/services/absences'
|
import { listAbsences } from '~/services/absences'
|
||||||
import { getEmployeeLeaveSummary, updateFractionedDays } from '~/services/employee-leave-summary'
|
import { getEmployeeLeaveSummary, updateFractionedDays, updatePaidLeaveDays } from '~/services/employee-leave-summary'
|
||||||
import { listPublicHolidays } from '~/services/public-holidays'
|
import { listPublicHolidays } from '~/services/public-holidays'
|
||||||
|
|
||||||
export const useEmployeeLeave = (employee: Ref<Employee | null>, reloadEmployee: () => Promise<void>) => {
|
export const useEmployeeLeave = (employee: Ref<Employee | null>, reloadEmployee: () => Promise<void>) => {
|
||||||
@@ -57,6 +57,13 @@ export const useEmployeeLeave = (employee: Ref<Employee | null>, reloadEmployee:
|
|||||||
await reloadEmployee()
|
await reloadEmployee()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const submitPaidLeaveDays = async (days: number) => {
|
||||||
|
if (!employee.value) return
|
||||||
|
const year = leaveSummary.value?.year ?? undefined
|
||||||
|
await updatePaidLeaveDays(employee.value.id, days, year)
|
||||||
|
await reloadEmployee()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
employeeAbsences,
|
employeeAbsences,
|
||||||
leaveSummary,
|
leaveSummary,
|
||||||
@@ -65,6 +72,7 @@ export const useEmployeeLeave = (employee: Ref<Employee | null>, reloadEmployee:
|
|||||||
leaveDataLoaded,
|
leaveDataLoaded,
|
||||||
loadLeaveData,
|
loadLeaveData,
|
||||||
resetLoaded,
|
resetLoaded,
|
||||||
submitFractionedDays
|
submitFractionedDays,
|
||||||
|
submitPaidLeaveDays
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,6 +148,7 @@
|
|||||||
:summary="leaveSummary"
|
:summary="leaveSummary"
|
||||||
:public-holidays="publicHolidays"
|
:public-holidays="publicHolidays"
|
||||||
@update-fractioned-days="submitFractionedDays"
|
@update-fractioned-days="submitFractionedDays"
|
||||||
|
@update-paid-leave-days="submitPaidLeaveDays"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="showRttTab && activeTab === 'rtt'" class="h-full">
|
<div v-else-if="showRttTab && activeTab === 'rtt'" class="h-full">
|
||||||
@@ -259,6 +260,7 @@ const {
|
|||||||
submitContractUpdate,
|
submitContractUpdate,
|
||||||
submitCreateContract,
|
submitCreateContract,
|
||||||
submitFractionedDays,
|
submitFractionedDays,
|
||||||
|
submitPaidLeaveDays,
|
||||||
submitRttPayment,
|
submitRttPayment,
|
||||||
suspensionForms,
|
suspensionForms,
|
||||||
isSuspensionSubmitting,
|
isSuspensionSubmitting,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export type EmployeeLeaveSummary = {
|
|||||||
previousYearAcquiredDays: number
|
previousYearAcquiredDays: number
|
||||||
previousYearTakenDays: number
|
previousYearTakenDays: number
|
||||||
previousYearRemainingDays: number
|
previousYearRemainingDays: number
|
||||||
|
previousYearPaidDays: number
|
||||||
presenceDaysByMonth: Record<string, number>
|
presenceDaysByMonth: Record<string, number>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,3 +16,11 @@ export const updateFractionedDays = async (employeeId: number, fractionedDays: n
|
|||||||
return api.patch(`/employees/${employeeId}/fractioned-days`, body)
|
return api.patch(`/employees/${employeeId}/fractioned-days`, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const updatePaidLeaveDays = async (employeeId: number, paidLeaveDays: number, year?: number) => {
|
||||||
|
const api = useApi()
|
||||||
|
const body: Record<string, unknown> = { paidLeaveDays }
|
||||||
|
if (year) body.year = year
|
||||||
|
|
||||||
|
return api.patch(`/employees/${employeeId}/paid-leave-days`, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
27
migrations/Version20260402064647.php
Normal file
27
migrations/Version20260402064647.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20260402064647 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add paid_leave_days column to employee_leave_balances for forfait N-1 leave payment';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE employee_leave_balances ADD paid_leave_days DOUBLE PRECISION DEFAULT 0 NOT NULL');
|
||||||
|
$this->addSql("COMMENT ON COLUMN employee_leave_balances.paid_leave_days IS 'Jours de conges N-1 payes par la RH (forfait uniquement).'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE employee_leave_balances DROP paid_leave_days');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ final class EmployeeLeaveSummary
|
|||||||
public float $previousYearAcquiredDays = 0.0;
|
public float $previousYearAcquiredDays = 0.0;
|
||||||
public float $previousYearTakenDays = 0.0;
|
public float $previousYearTakenDays = 0.0;
|
||||||
public float $previousYearRemainingDays = 0.0;
|
public float $previousYearRemainingDays = 0.0;
|
||||||
|
public float $previousYearPaidDays = 0.0;
|
||||||
|
|
||||||
/** @var array<string, float> YYYY-MM => count (0.5 for half-days) */
|
/** @var array<string, float> YYYY-MM => count (0.5 for half-days) */
|
||||||
public array $presenceDaysByMonth = [];
|
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.'])]
|
#[ORM\Column(type: 'float', options: ['default' => 0, 'comment' => 'Jours de fractionnement saisis par la RH.'])]
|
||||||
private float $fractionedDays = 0.0;
|
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).'])]
|
#[ORM\Column(type: 'boolean', options: ['default' => false, 'comment' => 'Indique si le solde de l exercice est fige (verrouille RH).'])]
|
||||||
private bool $isLocked = false;
|
private bool $isLocked = false;
|
||||||
|
|
||||||
@@ -222,6 +225,18 @@ class EmployeeLeaveBalance
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPaidLeaveDays(): float
|
||||||
|
{
|
||||||
|
return $this->paidLeaveDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPaidLeaveDays(float $paidLeaveDays): self
|
||||||
|
{
|
||||||
|
$this->paidLeaveDays = $paidLeaveDays;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function isLocked(): bool
|
public function isLocked(): bool
|
||||||
{
|
{
|
||||||
return $this->isLocked;
|
return $this->isLocked;
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$fractionedDays = $this->resolveFractionedDays($employee, $yearSummary['ruleCode'], $year);
|
$fractionedDays = $this->resolveFractionedDays($employee, $yearSummary['ruleCode'], $year);
|
||||||
|
$paidLeaveDays = $this->resolvePaidLeaveDays($employee, $yearSummary['ruleCode'], $year);
|
||||||
|
|
||||||
$summary->isSupported = true;
|
$summary->isSupported = true;
|
||||||
$summary->ruleCode = $yearSummary['ruleCode'];
|
$summary->ruleCode = $yearSummary['ruleCode'];
|
||||||
@@ -106,7 +107,8 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
|||||||
$summary->remainingSaturdays = $yearSummary['remainingSaturdays'];
|
$summary->remainingSaturdays = $yearSummary['remainingSaturdays'];
|
||||||
$summary->previousYearAcquiredDays = $yearSummary['previousYearAcquiredDays'];
|
$summary->previousYearAcquiredDays = $yearSummary['previousYearAcquiredDays'];
|
||||||
$summary->previousYearTakenDays = $yearSummary['previousYearTakenDays'];
|
$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);
|
[$periodFrom, $periodTo] = $this->resolvePeriodBounds($employee, $year);
|
||||||
$summary->presenceDaysByMonth = $this->computePresenceDaysByMonth($employee, $periodFrom, $periodTo);
|
$summary->presenceDaysByMonth = $this->computePresenceDaysByMonth($employee, $periodFrom, $periodTo);
|
||||||
@@ -765,6 +767,13 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
|||||||
return null !== $balance ? $balance->getFractionedDays() : 0.0;
|
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
|
private function resolveCurrentLeaveYear(DateTimeImmutable $today): int
|
||||||
{
|
{
|
||||||
$year = (int) $today->format('Y');
|
$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