From c674b325ffeec650cc765ebe138e1ff2a63514a7 Mon Sep 17 00:00:00 2001 From: Maxime Golfier <25312957+maxgfr@users.noreply.github.com> Date: Thu, 19 Oct 2023 09:38:39 +0200 Subject: [PATCH] fix(indemnite-licenciement): retours de la cc 1516 (#5392) --- .../src/modeles/common/factory/seniority.ts | 3 + .../indemnite-licenciement/anciennete.spec.ts | 36 +++++++ .../1516_organismes_formation/index.ts | 1 + .../1516_organismes_formation/seniority.ts | 95 +++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/__tests__/indemnite-licenciement/anciennete.spec.ts create mode 100644 packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/seniority.ts diff --git a/packages/code-du-travail-modeles/src/modeles/common/factory/seniority.ts b/packages/code-du-travail-modeles/src/modeles/common/factory/seniority.ts index b311570d13..33dc5c0eb3 100644 --- a/packages/code-du-travail-modeles/src/modeles/common/factory/seniority.ts +++ b/packages/code-du-travail-modeles/src/modeles/common/factory/seniority.ts @@ -11,6 +11,7 @@ import { Seniority1483, Seniority1486, Seniority1505, + Seniority1516, Seniority1517, Seniority1518, Seniority1527, @@ -75,6 +76,8 @@ export class SeniorityFactory { return new Seniority2609(); case SupportedCcIndemniteLicenciement.IDCC413: return new Seniority413() as ISeniority; + case SupportedCcIndemniteLicenciement.IDCC1516: + return new Seniority1516(); case SupportedCcIndemniteLicenciement.IDCC1517: return new Seniority1517(); case SupportedCcIndemniteLicenciement.IDCC2614: diff --git a/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/__tests__/indemnite-licenciement/anciennete.spec.ts b/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/__tests__/indemnite-licenciement/anciennete.spec.ts new file mode 100644 index 0000000000..1326e810d9 --- /dev/null +++ b/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/__tests__/indemnite-licenciement/anciennete.spec.ts @@ -0,0 +1,36 @@ +import { + MotifKeys, + SeniorityFactory, + SupportedCcIndemniteLicenciement, +} from "../../../../common"; + +describe("CC 1516", () => { + describe("Calcul de l'ancienneté", () => { + test.each` + absences | entryDate | exitDate | expectedAnciennete + ${[]} | ${"01/01/2020"} | ${"01/01/2021"} | ${1} + ${[{ motif: { key: MotifKeys.maladieNonPro } }, { motif: { key: MotifKeys.accidentTrajet } }, { motif: { key: MotifKeys.congesSabbatique } }, { motif: { key: MotifKeys.congesCreationEntreprise } }, { motif: { key: MotifKeys.congesParentalEducation } }, { motif: { key: MotifKeys.congesSansSolde } }, { motif: { key: MotifKeys.greve } }, { motif: { key: MotifKeys.miseAPied } }]} | ${"20/03/2020"} | ${"20/03/2021"} | ${1} + ${[{ durationInMonth: "1", motif: { key: MotifKeys.maladieNonPro } }, { durationInMonth: "1", motif: { key: MotifKeys.accidentTrajet } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSabbatique } }, { durationInMonth: "1", motif: { key: MotifKeys.congesCreationEntreprise } }, { durationInMonth: "1", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSansSolde } }, { durationInMonth: "1", motif: { key: MotifKeys.greve } }, { durationInMonth: "1", motif: { key: MotifKeys.miseAPied } }]} | ${"01/01/2000"} | ${"01/01/2023"} | ${22.416666666666668} + ${[{ durationInMonth: "1", motif: { key: MotifKeys.maladieNonPro } }, { durationInMonth: "1", motif: { key: MotifKeys.accidentTrajet } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSabbatique } }, { durationInMonth: "1", motif: { key: MotifKeys.congesCreationEntreprise } }, { durationInMonth: "35", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSansSolde } }, { durationInMonth: "1", motif: { key: MotifKeys.greve } }, { durationInMonth: "1", motif: { key: MotifKeys.miseAPied } }]} | ${"01/01/2000"} | ${"01/01/2023"} | ${22.416666666666668} + ${[{ durationInMonth: "1", motif: { key: MotifKeys.maladieNonPro } }, { durationInMonth: "1", motif: { key: MotifKeys.accidentTrajet } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSabbatique } }, { durationInMonth: "1", motif: { key: MotifKeys.congesCreationEntreprise } }, { durationInMonth: "36", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSansSolde } }, { durationInMonth: "1", motif: { key: MotifKeys.greve } }, { durationInMonth: "1", motif: { key: MotifKeys.miseAPied } }]} | ${"01/01/2000"} | ${"01/01/2023"} | ${22.416666666666668} + ${[{ durationInMonth: "1", motif: { key: MotifKeys.maladieNonPro } }, { durationInMonth: "1", motif: { key: MotifKeys.accidentTrajet } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSabbatique } }, { durationInMonth: "1", motif: { key: MotifKeys.congesCreationEntreprise } }, { durationInMonth: "18", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "18", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSansSolde } }, { durationInMonth: "1", motif: { key: MotifKeys.greve } }, { durationInMonth: "1", motif: { key: MotifKeys.miseAPied } }]} | ${"01/01/2000"} | ${"01/01/2023"} | ${22.416666666666668} + ${[{ durationInMonth: "1", motif: { key: MotifKeys.maladieNonPro } }, { durationInMonth: "1", motif: { key: MotifKeys.accidentTrajet } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSabbatique } }, { durationInMonth: "1", motif: { key: MotifKeys.congesCreationEntreprise } }, { durationInMonth: "37", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSansSolde } }, { durationInMonth: "1", motif: { key: MotifKeys.greve } }, { durationInMonth: "1", motif: { key: MotifKeys.miseAPied } }]} | ${"01/01/2000"} | ${"01/01/2023"} | ${22.375} + ${[{ durationInMonth: "1", motif: { key: MotifKeys.maladieNonPro } }, { durationInMonth: "1", motif: { key: MotifKeys.accidentTrajet } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSabbatique } }, { durationInMonth: "1", motif: { key: MotifKeys.congesCreationEntreprise } }, { durationInMonth: "18", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "19", motif: { key: MotifKeys.congesParentalEducation } }, { durationInMonth: "1", motif: { key: MotifKeys.congesSansSolde } }, { durationInMonth: "1", motif: { key: MotifKeys.greve } }, { durationInMonth: "1", motif: { key: MotifKeys.miseAPied } }]} | ${"01/01/2000"} | ${"01/01/2023"} | ${22.375} + `( + "Calcul de l'ancienneté avec $entryDate et $exitDate en attendant $expectedAnciennete an", + ({ absences, entryDate, exitDate, expectedAnciennete }) => { + const seniority = new SeniorityFactory().create( + SupportedCcIndemniteLicenciement.IDCC1516 + ); + + const result = seniority.computeSeniority({ + absencePeriods: absences, + dateEntree: entryDate, + dateSortie: exitDate, + }); + + expect(result.value).toEqual(expectedAnciennete); + } + ); + }); +}); diff --git a/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/index.ts b/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/index.ts index 0a1260c68f..028889ad2e 100644 --- a/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/index.ts +++ b/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/index.ts @@ -1 +1,2 @@ export * from "./salary"; +export * from "./seniority"; diff --git a/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/seniority.ts b/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/seniority.ts new file mode 100644 index 0000000000..f4862a88e3 --- /dev/null +++ b/packages/code-du-travail-modeles/src/modeles/conventions/1516_organismes_formation/seniority.ts @@ -0,0 +1,95 @@ +import { addDays, differenceInMonths } from "date-fns"; + +import { LEGAL_MOTIFS } from "../../base"; +import type { + Absence, + DefaultSeniorityRequiredProps, + ISeniority, + Motif, + RequiredSeniorityResult, + SeniorityProps, + SeniorityResult, + SupportedCcIndemniteLicenciement, +} from "../../common"; +import { MotifKeys, parseDate } from "../../common"; + +export class Seniority1516 + implements ISeniority +{ + getMotifs(): Motif[] { + return LEGAL_MOTIFS; + } + + computeSeniority({ + dateEntree, + dateSortie, + absencePeriods = [], + }: SeniorityProps): SeniorityResult { + return this.compute(dateEntree, dateSortie, absencePeriods); + } + + computeRequiredSeniority({ + dateEntree, + dateNotification, + absencePeriods = [], + }: DefaultSeniorityRequiredProps): RequiredSeniorityResult { + return this.compute(dateEntree, dateNotification, absencePeriods); + } + + protected compute( + from: string, + to: string, + absences: Absence[] + ): SeniorityResult { + const dEntree = parseDate(from); + const dSortie = addDays(parseDate(to), 1); + const MAXIMUM_CONGES_PARENTAL_EN_MOIS = 36; + const totalAbsenceSansCongesParental = absences + .filter((period) => Boolean(period.durationInMonth)) + .reduce((total, item) => { + const m = this.getMotifs().find( + (motif) => motif.key === item.motif.key + ); + if ( + !m || + !item.durationInMonth || + m.key === MotifKeys.congesParentalEducation + ) { + return total; + } + return total + item.durationInMonth * m.value; + }, 0); + const totalAbsenceAvecCongesParentalSansCoeff = absences + .filter((period) => Boolean(period.durationInMonth)) + .reduce((total, item: any) => { + const m = this.getMotifs().find( + (motif) => motif.key === item.motif.key + ); + if ( + !m || + !item.durationInMonth || + m.key !== MotifKeys.congesParentalEducation + ) { + return total; + } + return total + parseInt(item.durationInMonth); + }, 0); + const congesMotif = this.getMotifs().find( + (motif) => motif.key === MotifKeys.congesParentalEducation + ); + if (!congesMotif) { + throw new Error("Motif congé parental non trouvé"); + } + + const totalCongesParental = + totalAbsenceAvecCongesParentalSansCoeff >= MAXIMUM_CONGES_PARENTAL_EN_MOIS + ? (totalAbsenceAvecCongesParentalSansCoeff - + MAXIMUM_CONGES_PARENTAL_EN_MOIS) * + congesMotif.value + : 0; + const totalAbsence = totalCongesParental + totalAbsenceSansCongesParental; + return { + value: (differenceInMonths(dSortie, dEntree) - totalAbsence) / 12, + }; + } +}