feat(leave) : prorate forfait work-target days in employee header
The header hardcoded '218 jours' and '218 - presence restants', wrong for a
forfait entered mid-year. Expose forfaitWorkTargetDays = businessDays(period) -
acquiredDays (218 full year, prorated otherwise) and show
'Forfait - {target} jours ({presence} présence · {target-presence} restants)'.
Grégory: 155 jours (11 présence · 144 restants).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,16 @@ export const useEmployeeDetailPage = () => {
|
||||
const showLeaveTab = computed(() => employee.value?.currentContractNature !== 'INTERIM')
|
||||
const showRttTab = computed(() => phase.selectedPhase.value?.contractType !== CONTRACT_TYPES.FORFAIT)
|
||||
const isForfait = computed(() => phase.selectedPhase.value?.contractType === CONTRACT_TYPES.FORFAIT)
|
||||
// Jours à travailler du forfait : prorata exposé par le backend (218 sur année pleine,
|
||||
// moins sur une entrée en cours d'année). Fallback 218 tant que le récap n'est pas chargé.
|
||||
const forfaitWorkTargetDays = computed(() => {
|
||||
const target = leave.leaveSummary.value?.forfaitWorkTargetDays
|
||||
return (target === null || target === undefined) ? 218 : Math.round(target)
|
||||
})
|
||||
const employeeContractWorkLabel = computed(() => {
|
||||
const contract = employee.value?.contract
|
||||
if (!contract) return '-'
|
||||
if (contract.type === CONTRACT_TYPES.FORFAIT) return 'Forfait - 218 jours'
|
||||
if (contract.type === CONTRACT_TYPES.FORFAIT) return `Forfait - ${forfaitWorkTargetDays.value} jours`
|
||||
if (contract.weeklyHours !== null && contract.weeklyHours !== undefined) return `${contract.weeklyHours} heures`
|
||||
return contract.name || '-'
|
||||
})
|
||||
@@ -75,8 +81,10 @@ export const useEmployeeDetailPage = () => {
|
||||
if (!isForfait.value) return ''
|
||||
const presence = leave.leaveSummary.value?.presenceDaysToToday
|
||||
if (presence === undefined || presence === null) return ''
|
||||
const remaining = 218 - presence
|
||||
return ` (${remaining} restants)`
|
||||
const fmt = (n: number) => (Number.isInteger(n) ? String(n) : (Math.round(n * 100) / 100).toFixed(2).replace('.', ','))
|
||||
// restant à travailler = jours à travailler (prorata) − jours de présence déjà effectués
|
||||
const remaining = forfaitWorkTargetDays.value - presence
|
||||
return ` (${fmt(presence)} présence · ${fmt(remaining)} restants)`
|
||||
})
|
||||
const rtt = useEmployeeRtt(employee, loadEmployee, phase.selectedPhase)
|
||||
const mileage = useEmployeeMileage(employee, loadEmployee)
|
||||
|
||||
@@ -16,6 +16,7 @@ export type EmployeeLeaveSummary = {
|
||||
previousYearPaidDays: number
|
||||
presenceDaysByMonth: Record<string, number>
|
||||
presenceDaysToToday: number
|
||||
forfaitWorkTargetDays: number | null
|
||||
dataStartDate: string | null
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,14 @@ final class EmployeeLeaveSummary
|
||||
/** Cumul des jours de présence depuis le début de l'année de congé jusqu'à aujourd'hui (forfait). */
|
||||
public float $presenceDaysToToday = 0.0;
|
||||
|
||||
/**
|
||||
* FORFAIT uniquement : jours à travailler sur l'exercice = jours ouvrés de la période − congés acquis.
|
||||
* Vaut 218 sur une année pleine (252 − 34) et le prorata sur une entrée en cours d'année
|
||||
* (ex. Grégory : 168 − 13 ≈ 155). Null pour les non-forfait. Le « restant à travailler »
|
||||
* affiché = forfaitWorkTargetDays − presenceDaysToToday.
|
||||
*/
|
||||
public ?float $forfaitWorkTargetDays = null;
|
||||
|
||||
/** Date de mise en service du logiciel (env RTT_START_DATE) — borne minimale pour les sélecteurs d'historique. */
|
||||
public ?string $dataStartDate = null;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,14 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
|
||||
$summary->previousYearPaidDays = $paidLeaveDays;
|
||||
|
||||
[$periodFrom, $periodTo] = $this->resolvePeriodBounds($employee, $year, $phase);
|
||||
|
||||
// Forfait : jours à travailler sur l'exercice = jours ouvrés de la période − congés acquis.
|
||||
// Année pleine → 218 (252 − 34) ; entrée en cours d'année → prorata (ex. 168 − 13 ≈ 155).
|
||||
if (LeaveRuleCode::FORFAIT_218->value === $summary->ruleCode) {
|
||||
$businessDaysInPeriod = $this->countBusinessDays($periodFrom, $periodTo, $this->buildRawPublicHolidayMap($periodFrom, $periodTo));
|
||||
$summary->forfaitWorkTargetDays = $businessDaysInPeriod - $summary->acquiredDays;
|
||||
}
|
||||
|
||||
// Forfait-only: leaves taken from N-1 stock do NOT decrement presence days.
|
||||
// For non-forfait, previousYearTakenDays is always 0, so the budget has no effect.
|
||||
$n1AbsencesBudget = $yearSummary['previousYearTakenDays'];
|
||||
|
||||
Reference in New Issue
Block a user