From c60cb61a531e378971de9af576e5d03c2522ef68 Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Tue, 21 Jan 2025 16:35:26 +0100 Subject: [PATCH 1/7] =?UTF-8?q?fix(rgcp):=20correction=20du=20calcul=20de?= =?UTF-8?q?=20la=20r=C3=A9gularisation=20annuelle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "site/source/utils/r\303\251ductionDeCotisations.ts" | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git "a/site/source/utils/r\303\251ductionDeCotisations.ts" "b/site/source/utils/r\303\251ductionDeCotisations.ts" index 66eb315147..b242576b2e 100644 --- "a/site/source/utils/r\303\251ductionDeCotisations.ts" +++ "b/site/source/utils/r\303\251ductionDeCotisations.ts" @@ -375,10 +375,10 @@ export const reevaluateRéductionMoisParMois = ( reevaluatedData.map((monthData) => monthData.réduction.value) ) régularisation.value = - réductionTotale - currentRéductionGénéraleCumulée + réduction.value + (réductionTotale - currentRéductionGénéraleCumulée) - if (réduction.value + régularisation.value > 0) { - réduction.value += régularisation.value + if (régularisation.value > 0) { + réduction.value = régularisation.value réduction.répartition = getRépartition( dottedName, rémunérationBrute, @@ -393,6 +393,7 @@ export const reevaluateRéductionMoisParMois = ( régularisation.value, engine ) + réduction.value = 0 } } } From 184262603de9a5ee0d57020ae708d63aab1e9a08 Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Tue, 21 Jan 2025 16:51:51 +0100 Subject: [PATCH 2/7] =?UTF-8?q?fix(rgcp):=20correction=20du=20calcul=20de?= =?UTF-8?q?=20la=20r=C3=A9duction=20pour=20les=20mois=20incomplets=20avec?= =?UTF-8?q?=20la=20r=C3=A9gul=20annuelle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/mon-entreprise/lodeom.ts | 2 +- .../mon-entreprise/reduction-generale.ts | 1 - .../utils/r\303\251ductionDeCotisations.ts" | 104 +++++++++++------- 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/site/cypress/integration/mon-entreprise/lodeom.ts b/site/cypress/integration/mon-entreprise/lodeom.ts index cf00f7150c..ecd6e60958 100755 --- a/site/cypress/integration/mon-entreprise/lodeom.ts +++ b/site/cypress/integration/mon-entreprise/lodeom.ts @@ -282,7 +282,6 @@ describe('Simulateur lodeom', { testIsolation: false }, function () { }) it('should include a recap table', function () { - cy.contains('Régularisation progressive').click() cy.get('div[id="simulator-legend"]').should( 'include.text', 'Récapitulatif trimestriel' @@ -310,6 +309,7 @@ describe('Simulateur lodeom', { testIsolation: false }, function () { }) it('should display code in recap table based on scale', function () { + cy.contains('Régularisation progressive').click() cy.contains('Récapitulatif trimestriel').next().as('recapTable') cy.get('@recapTable').should('include.text', 'code 462') diff --git a/site/cypress/integration/mon-entreprise/reduction-generale.ts b/site/cypress/integration/mon-entreprise/reduction-generale.ts index 83b35f0281..ebb13e8f6c 100755 --- a/site/cypress/integration/mon-entreprise/reduction-generale.ts +++ b/site/cypress/integration/mon-entreprise/reduction-generale.ts @@ -201,7 +201,6 @@ describe( }) it('should handle incomplete months', function () { - cy.contains('Régularisation progressive').click() cy.get(inputSelector).first().type('{selectall}1500') cy.get('input[id="option-heures-sup-janvier"]').type('{selectall}5') cy.get('input[id="option-rémunération-etp-janvier"]') diff --git "a/site/source/utils/r\303\251ductionDeCotisations.ts" "b/site/source/utils/r\303\251ductionDeCotisations.ts" index b242576b2e..c4c7ea07f4 100644 --- "a/site/source/utils/r\303\251ductionDeCotisations.ts" +++ "b/site/source/utils/r\303\251ductionDeCotisations.ts" @@ -375,7 +375,8 @@ export const reevaluateRéductionMoisParMois = ( reevaluatedData.map((monthData) => monthData.réduction.value) ) régularisation.value = - réduction.value + (réductionTotale - currentRéductionGénéraleCumulée) + réduction.value + + (réductionTotale - currentRéductionGénéraleCumulée) if (régularisation.value > 0) { réduction.value = régularisation.value @@ -505,14 +506,19 @@ const getMonthlyRéduction = ( options: Options, engine: Engine ): number => { + const SMIC = getSMICMensuelAvecOptions( + date, + rémunérationBrute, + options, + engine + ) const réduction = engine.evaluate({ valeur: dottedName, unité: '€/mois', contexte: { date, [rémunérationBruteDottedName]: rémunérationBrute, - [heuresSupplémentairesDottedName]: options.heuresSupplémentaires, - [heuresComplémentairesDottedName]: options.heuresComplémentaires, + 'salarié . temps de travail . SMIC': SMIC, }, }) @@ -526,7 +532,7 @@ const getTotalRéduction = ( coefT: number, engine: Engine ): number => { - const réductionGénérale = engine.evaluate({ + const réduction = engine.evaluate({ valeur: dottedName, arrondi: 'non', contexte: { @@ -536,7 +542,7 @@ const getTotalRéduction = ( }, }) - return réductionGénérale.nodeValue as number + return réduction.nodeValue as number } const getRépartition = ( @@ -575,6 +581,51 @@ const getRépartition = ( } } +const getSMICMensuelAvecOptions = ( + date: string, + rémunérationBrute: number, + options: Options, + engine: Engine +): number => { + const contexte = { + date, + } as Situation + + if (!options.rémunérationETP) { + contexte[heuresSupplémentairesDottedName] = options.heuresSupplémentaires + contexte[heuresComplémentairesDottedName] = options.heuresComplémentaires + } + + const SMICMensuel = engine.evaluate({ + valeur: 'salarié . temps de travail . SMIC', + unité: '€/mois', + contexte, + }).nodeValue as number + + if (!options.rémunérationETP) { + return SMICMensuel + } + + const SMICHoraire = engine.evaluate({ + valeur: 'SMIC . horaire', + contexte, + }).nodeValue as number + // On retranche les primes et le paiements des heures supplémentaires à la rémunération versée + // et on la compare à la rémunération équivalente "mois complet" sans les primes + const prorata = + (rémunérationBrute - + options.rémunérationPrimes - + options.rémunérationHeuresSup) / + options.rémunérationETP + + // On applique ce prorata au SMIC mensuel et on y ajoute les heures supplémentaires et complémentaires + return ( + SMICMensuel * prorata + + SMICHoraire * + (options.heuresSupplémentaires + options.heuresComplémentaires) + ) +} + const getSMICCumulés = ( data: MonthState[], year: number, @@ -589,42 +640,13 @@ const getSMICCumulés = ( return SMICCumulés } - const contexte = { - date: getDateForContexte(monthIndex, year), - } as Situation - - if (!monthData.options.rémunérationETP) { - contexte[heuresSupplémentairesDottedName] = - monthData.options.heuresSupplémentaires - contexte[heuresComplémentairesDottedName] = - monthData.options.heuresComplémentaires - } - - let SMIC = engine.evaluate({ - valeur: 'salarié . temps de travail . SMIC', - unité: '€/mois', - contexte, - }).nodeValue as number - - if (monthData.options.rémunérationETP) { - const SMICHoraire = engine.evaluate({ - valeur: 'SMIC . horaire', - contexte, - }).nodeValue as number - // On retranche les primes et le paiements des heures supplémentaires à la rémunération versée - // et on la compare à la rémunération équivalente "mois complet" sans les primes - const prorata = - (monthData.rémunérationBrute - - monthData.options.rémunérationPrimes - - monthData.options.rémunérationHeuresSup) / - monthData.options.rémunérationETP - // On applique ce prorata au SMIC mensuel et on y ajoute les heures supplémentaires et complémentaires - SMIC = - SMIC * prorata + - SMICHoraire * - (monthData.options.heuresSupplémentaires + - monthData.options.heuresComplémentaires) - } + const date = getDateForContexte(monthIndex, year) + const SMIC = getSMICMensuelAvecOptions( + date, + monthData.rémunérationBrute, + monthData.options, + engine + ) let SMICCumulé = SMIC if (monthIndex > 0) { From 778f17d51d352c1042f84fb5048fb8b711635e85 Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Tue, 21 Jan 2025 16:55:45 +0100 Subject: [PATCH 3/7] =?UTF-8?q?fix(rgcp):=20ajout=20de=20la=20r=C3=A9parti?= =?UTF-8?q?tion=20de=20la=20r=C3=A9duction=20avec=20la=20r=C3=A9gul=20annu?= =?UTF-8?q?elle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "site/source/utils/r\303\251ductionDeCotisations.ts" | 7 +++++++ 1 file changed, 7 insertions(+) diff --git "a/site/source/utils/r\303\251ductionDeCotisations.ts" "b/site/source/utils/r\303\251ductionDeCotisations.ts" index c4c7ea07f4..60bba8f3c9 100644 --- "a/site/source/utils/r\303\251ductionDeCotisations.ts" +++ "b/site/source/utils/r\303\251ductionDeCotisations.ts" @@ -396,6 +396,13 @@ export const reevaluateRéductionMoisParMois = ( ) réduction.value = 0 } + } else { + réduction.répartition = getRépartition( + dottedName, + rémunérationBrute, + réduction.value, + engine + ) } } From d52c43628a2e2579b426ca03d895bd9f77e2ad8c Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Wed, 22 Jan 2025 18:47:32 +0100 Subject: [PATCH 4/7] =?UTF-8?q?feat(lodeom):=20d=C3=A9place=20le=20calcul?= =?UTF-8?q?=20du=20SMIC=20mois=20incomplet=20dans=20modele-social?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../salari\303\251/contrat.publicodes" | 1 + .../salari\303\251/mois-incomplet.publicodes" | 99 ++++++++++++++++ .../r\303\251mun\303\251ration.publicodes" | 1 - site/source/locales/rules-en.yaml | 109 ++++++++++++++++++ .../utils/r\303\251ductionDeCotisations.ts" | 41 +++---- 5 files changed, 230 insertions(+), 21 deletions(-) create mode 100644 "modele-social/r\303\250gles/salari\303\251/mois-incomplet.publicodes" diff --git "a/modele-social/r\303\250gles/salari\303\251/contrat.publicodes" "b/modele-social/r\303\250gles/salari\303\251/contrat.publicodes" index 1bf6342cc2..344ff64a68 100644 --- "a/modele-social/r\303\250gles/salari\303\251/contrat.publicodes" +++ "b/modele-social/r\303\250gles/salari\303\251/contrat.publicodes" @@ -470,6 +470,7 @@ salarié . contrat . salaire brut: SMIC: temps de travail . SMIC inversion numérique: - coût total employeur + # - rémunération . brut - rémunération . net . à payer avant impôt - rémunération . net . payé après impôt - équivalent temps plein diff --git "a/modele-social/r\303\250gles/salari\303\251/mois-incomplet.publicodes" "b/modele-social/r\303\250gles/salari\303\251/mois-incomplet.publicodes" new file mode 100644 index 0000000000..3801e7c96b --- /dev/null +++ "b/modele-social/r\303\250gles/salari\303\251/mois-incomplet.publicodes" @@ -0,0 +1,99 @@ +salarié . mois incomplet: + experimental: oui + description: | + Gestion des mois incomplets (absence, embauche, départ, etc), notamment pour le + calcul de la réduction générale des cotisations ou de l’exonération Lodeom. + références: + Bulletin Officiel de la Sécurité Sociale: https://boss.gouv.fr/portail/accueil/exonerations/allegements-generaux.html#titre-chapitre-1--la-reduction-general-section-2---determination-du-mon-ii-calcul-du-montant-de-la-reduc-d-determination-de-la-valeur-du-4-determination-de-la-valeur-du + +salarié . mois incomplet . rémunération non impactée par l'absence: + somme: + - rémunération . primes + - rémunération . indemnités CDD + unité: €/mois + +salarié . mois incomplet . rémunération de base mois incomplet: + # TODO: décommenter la formule lorsque "rémunération . brut" n'incluera plus + # les frais professionnels. + # Décommenter aussi la ligne "rémunération . brut" dans "salarié . contrat . salaire brut" + + # valeur: rémunération . brut + # abattement: + # somme: + # - rémunération . heures supplémentaires + # - rémunération . heures complémentaires + # - rémunération non impactée par l'absence + unité: €/mois + description: | + Exclure de cette rémunération : + - le paiement des heures supplémentaires et complémentaires, + - les primes, indemnités de CDD et autres éléments de rémunération non impactés par l'absence. + +salarié . mois incomplet . rémunération équivalente mois complet: + # par défaut: contrat . salaire brut + unité: €/mois + question: Quelle rémunération brute aurait été versée pour un mois complet ? + note: | + Exclure de cette rémunération : + - le paiement des heures supplémentaires et complémentaires, + - les primes, indemnités de CDD et autres éléments de rémunération non impactés par l'absence. + +salarié . mois incomplet . prorata: + produit: + - rémunération de base mois incomplet + - 1 / rémunération équivalente mois complet + unité: '%' + description: | + Le prorata correspond au rapport entre la rémunération du mois incomplet et + la rémunération qui aurait été versée pour un mois complet. + + Plus précisément, ce prorata est le rapport entre : + - la rémunération brute versée pour le mois incomplet, sans les primes (et + autres éléments non impactés par l’absence) ni le paiements des heures + supplémentaires + - et la rémunération équivalente "mois complet" sans les primes et autres + éléments non impactés par l’absence. + références: + Bulletin Officiel de la Sécurité Sociale: https://boss.gouv.fr/portail/accueil/exonerations/allegements-generaux.html#titre-chapitre-1--la-reduction-general-section-2---determination-du-mon-ii-calcul-du-montant-de-la-reduc-d-determination-de-la-valeur-du-4-determination-de-la-valeur-du + +salarié . mois incomplet . SMIC équivalent: + somme: + - SMIC mensuel proratisé + - SMIC heures supplémentaires + - SMIC heures complémentaires + unité: €/mois + références: + Bulletin Officiel de la Sécurité Sociale: https://boss.gouv.fr/portail/accueil/exonerations/allegements-generaux.html#titre-chapitre-1--la-reduction-general-section-2---determination-du-mon-ii-calcul-du-montant-de-la-reduc-d-determination-de-la-valeur-du + + avec: + SMIC mensuel proratisé: + produit: + - SMIC + - prorata + unité: €/mois + description: | + Ce montant correspond au SMIC équivalent au mois incomplet, c’est-à-dire en + tenant compte du prorata du temps de travail et les heures supplémentaires et + complémentaires. + + Ce prorata du temps de travail est en réalité calculé comme un prorata des + rémunérations, entre celle du mois incomplet et celle qui aurait été versée + pour un mois complet. + références: + Bulletin Officiel de la Sécurité Sociale: https://boss.gouv.fr/portail/accueil/exonerations/allegements-generaux.html#titre-chapitre-1--la-reduction-general-section-2---determination-du-mon-ii-calcul-du-montant-de-la-reduc-d-determination-de-la-valeur-du-4-determination-de-la-valeur-du + + SMIC heures supplémentaires: + produit: + - temps de travail . heures supplémentaires + - SMIC . horaire + unité: €/mois + références: + Bulletin Officiel de la Sécurité Sociale: https://boss.gouv.fr/portail/accueil/exonerations/allegements-generaux.html#titre-chapitre-1--la-reduction-general-section-2---determination-du-mon-ii-calcul-du-montant-de-la-reduc-e-prise-en-compte-des-heures-com-1-heures-supplementaires + + SMIC heures complémentaires: + produit: + - temps de travail . heures complémentaires + - SMIC . horaire + unité: €/mois + références: + Bulletin Officiel de la Sécurité Sociale: https://boss.gouv.fr/portail/accueil/exonerations/allegements-generaux.html#titre-chapitre-1--la-reduction-general-section-2---determination-du-mon-ii-calcul-du-montant-de-la-reduc-e-prise-en-compte-des-heures-com-2-heures-complementaires diff --git "a/modele-social/r\303\250gles/salari\303\251/r\303\251mun\303\251ration.publicodes" "b/modele-social/r\303\250gles/salari\303\251/r\303\251mun\303\251ration.publicodes" index b9f9195299..375f2a13f3 100644 --- "a/modele-social/r\303\250gles/salari\303\251/r\303\251mun\303\251ration.publicodes" +++ "b/modele-social/r\303\250gles/salari\303\251/r\303\251mun\303\251ration.publicodes" @@ -323,7 +323,6 @@ salarié . rémunération . indemnités CDD: - primes . ancienneté - primes . activité - indemnités CDD . fin de contrat - références: congés payés . Méthode du dixième: produit: diff --git a/site/source/locales/rules-en.yaml b/site/source/locales/rules-en.yaml index 1f43ddeca1..c7581276df 100644 --- a/site/source/locales/rules-en.yaml +++ b/site/source/locales/rules-en.yaml @@ -10984,6 +10984,115 @@ salarié . coût total employeur . aides . emploi franc . éligible: question.fr: Cette embauche est-elle éligible à l'aide emploi-franc ? titre.en: '[automatic] eligible' titre.fr: éligible +salarié . mois incomplet: + description.en: > + [automatic] Management of incomplete months (absence, hiring, departure, + etc.), in particular for calculating + + calculating the general reduction in contributions or the Lodeom exemption. + description.fr: > + Gestion des mois incomplets (absence, embauche, départ, etc), notamment pour + le + + calcul de la réduction générale des cotisations ou de l’exonération Lodeom. + titre.en: '[automatic] incomplete month' + titre.fr: mois incomplet +salarié . mois incomplet . SMIC équivalent: + avec: + SMIC heures complémentaires: + titre.en: '[automatic] SMIC overtime' + titre.fr: SMIC heures complémentaires + SMIC heures supplémentaires: + titre.en: '[automatic] SMIC overtime' + titre.fr: SMIC heures supplémentaires + SMIC mensuel proratisé: + description.en: > + [automatic] This amount corresponds to the SMIC equivalent for an + incomplete month, i.e. taking + + taking into account the pro rata of working time and overtime and + + and overtime. + + + This prorata of working time is in fact calculated as a prorata of remuneration, between that of the incomplete month and that which would have been paid for the full month. + + between the remuneration for the incomplete month and that which would have been paid for a full month. + + for a full month. + description.fr: > + Ce montant correspond au SMIC équivalent au mois incomplet, c’est-à-dire + en + + tenant compte du prorata du temps de travail et les heures supplémentaires et + + complémentaires. + + + Ce prorata du temps de travail est en réalité calculé comme un prorata des + + rémunérations, entre celle du mois incomplet et celle qui aurait été versée + + pour un mois complet. + titre.en: '[automatic] Adjusted monthly minimum wage' + titre.fr: SMIC mensuel proratisé + titre.en: '[automatic] SMIC equivalent' + titre.fr: SMIC équivalent +salarié . mois incomplet . prorata: + description.en: > + [automatic] The prorata corresponds to the ratio between the remuneration + for the incomplete month and the remuneration that would have been paid for + a full month. + + the remuneration that would have been paid for a full month. + + + More precisely, the prorata is the ratio between : + - the gross remuneration paid for the incomplete month, excluding bonuses (and other + other items not affected by the absence) and overtime payments. + + overtime + - and the equivalent "full month" remuneration without bonuses and other + not affected by the absence. + description.fr: | + Le prorata correspond au rapport entre la rémunération du mois incomplet et + la rémunération qui aurait été versée pour un mois complet. + + Plus précisément, ce prorata est le rapport entre : + - la rémunération brute versée pour le mois incomplet, sans les primes (et + autres éléments non impactés par l’absence) ni le paiements des heures + supplémentaires + - et la rémunération équivalente "mois complet" sans les primes et autres + éléments non impactés par l’absence. + titre.en: '[automatic] prorata' + titre.fr: prorata +salarié . mois incomplet . rémunération de base mois incomplet: + description.en: > + [automatic] Exclude from this remuneration : + - payment for overtime and complementary hours, + - bonuses, fixed-term contract allowances and other remuneration not affected by the absence. + description.fr: > + Exclure de cette rémunération : + - le paiement des heures supplémentaires et complémentaires, + - les primes, indemnités de CDD et autres éléments de rémunération non impactés par l'absence. + titre.en: '[automatic] basic remuneration incomplete month' + titre.fr: rémunération de base mois incomplet +salarié . mois incomplet . rémunération non impactée par l'absence: + titre.en: '[automatic] compensation not affected by absence' + titre.fr: rémunération non impactée par l'absence +salarié . mois incomplet . rémunération équivalente mois complet: + note.en: > + [automatic] Exclude from this remuneration : + - payment for overtime and complementary hours, + - bonuses, fixed-term contract allowances and other remuneration not affected by the absence. + note.fr: > + Exclure de cette rémunération : + - le paiement des heures supplémentaires et complémentaires, + - les primes, indemnités de CDD et autres éléments de rémunération non impactés par l'absence. + question.en: '[automatic] What gross salary would have been paid for a full month?' + question.fr: Quelle rémunération brute aurait été versée pour un mois complet ? + titre.en: '[automatic] equivalent remuneration for a full month' + titre.fr: rémunération équivalente mois complet salarié . régimes spécifiques: titre.en: '[automatic] specific regimes' titre.fr: régimes spécifiques diff --git "a/site/source/utils/r\303\251ductionDeCotisations.ts" "b/site/source/utils/r\303\251ductionDeCotisations.ts" index 60bba8f3c9..249cb8d68f 100644 --- "a/site/source/utils/r\303\251ductionDeCotisations.ts" +++ "b/site/source/utils/r\303\251ductionDeCotisations.ts" @@ -596,13 +596,11 @@ const getSMICMensuelAvecOptions = ( ): number => { const contexte = { date, + [rémunérationBruteDottedName]: rémunérationBrute, + [heuresSupplémentairesDottedName]: options.heuresSupplémentaires, + [heuresComplémentairesDottedName]: options.heuresComplémentaires, } as Situation - if (!options.rémunérationETP) { - contexte[heuresSupplémentairesDottedName] = options.heuresSupplémentaires - contexte[heuresComplémentairesDottedName] = options.heuresComplémentaires - } - const SMICMensuel = engine.evaluate({ valeur: 'salarié . temps de travail . SMIC', unité: '€/mois', @@ -613,24 +611,27 @@ const getSMICMensuelAvecOptions = ( return SMICMensuel } - const SMICHoraire = engine.evaluate({ - valeur: 'SMIC . horaire', + // TODO: enlever 'salarié . mois incomplet . rémunération de base mois incomplet' + // du contexte une fois que la formule de cette règle sera décommentée + // (cf TODO dans `mois-incomplet.publicodes`) + // On pourra donc enlever le champ "rémunération des heures sup" du formulaire ! + contexte['salarié . mois incomplet . rémunération de base mois incomplet'] = + rémunérationBrute - + options.rémunérationPrimes - + options.rémunérationHeuresSup + contexte['salarié . mois incomplet . rémunération équivalente mois complet'] = + options.rémunérationETP + if (options.rémunérationPrimes) { + contexte[ + "salarié . mois incomplet . rémunération non impactée par l'absence" + ] = options.rémunérationPrimes + } + const SMIC = engine.evaluate({ + valeur: 'salarié . mois incomplet . SMIC équivalent', contexte, }).nodeValue as number - // On retranche les primes et le paiements des heures supplémentaires à la rémunération versée - // et on la compare à la rémunération équivalente "mois complet" sans les primes - const prorata = - (rémunérationBrute - - options.rémunérationPrimes - - options.rémunérationHeuresSup) / - options.rémunérationETP - // On applique ce prorata au SMIC mensuel et on y ajoute les heures supplémentaires et complémentaires - return ( - SMICMensuel * prorata + - SMICHoraire * - (options.heuresSupplémentaires + options.heuresComplémentaires) - ) + return SMIC } const getSMICCumulés = ( From d3aec18743a349de599c36673d99b707597e4114 Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Wed, 22 Jan 2025 18:49:59 +0100 Subject: [PATCH 5/7] =?UTF-8?q?fix(lodeom):=20correction=20du=20bug=20Lode?= =?UTF-8?q?om=20zone=202=20(r=C3=A9partition)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../R\303\251ductionBasique.tsx" | 5 +- .../source/pages/simulateurs/lodeom/Goals.tsx | 26 +++-- .../utils/r\303\251ductionDeCotisations.ts" | 108 +++++++++++------- 3 files changed, 88 insertions(+), 51 deletions(-) diff --git "a/site/source/components/R\303\251ductionDeCotisations/R\303\251ductionBasique.tsx" "b/site/source/components/R\303\251ductionDeCotisations/R\303\251ductionBasique.tsx" index 2a661c77e5..63f3d94d02 100644 --- "a/site/source/components/R\303\251ductionDeCotisations/R\303\251ductionBasique.tsx" +++ "b/site/source/components/R\303\251ductionDeCotisations/R\303\251ductionBasique.tsx" @@ -39,7 +39,8 @@ export default function RéductionBasique({ const currentUnit = useSelector(targetUnitSelector) const { t } = useTranslation() - const répartition = getRépartitionBasique(dottedName, currentUnit, engine) + const répartition = + withRépartition && getRépartitionBasique(dottedName, currentUnit, engine) return ( <> @@ -65,7 +66,7 @@ export default function RéductionBasique({ round={false} /> - {withRépartition && ( + {répartition && ( )} diff --git a/site/source/pages/simulateurs/lodeom/Goals.tsx b/site/source/pages/simulateurs/lodeom/Goals.tsx index f86b63acd8..22449f0197 100644 --- a/site/source/pages/simulateurs/lodeom/Goals.tsx +++ b/site/source/pages/simulateurs/lodeom/Goals.tsx @@ -56,10 +56,17 @@ export default function LodeomSimulationGoals({ 'salarié . cotisations . exonérations . lodeom . code régularisation' ).nodeValue as string + const withRépartition = currentZone === 'zone un' + const initializeLodeomMoisParMoisData = useCallback(() => { - const data = getInitialRéductionMoisParMois(lodeomDottedName, year, engine) + const data = getInitialRéductionMoisParMois( + lodeomDottedName, + year, + engine, + withRépartition + ) setData(data) - }, [engine, year]) + }, [engine, withRépartition, year]) useEffect(() => { if (lodeomMoisParMoisData.length === 0) { @@ -76,10 +83,11 @@ export default function LodeomSimulationGoals({ previousData, year, engine, - régularisationMethod + régularisationMethod, + withRépartition ) }) - }, [engine, situation, régularisationMethod, year]) + }, [engine, situation, régularisationMethod, year, withRépartition]) const onRémunérationChange = ( monthIndex: number, @@ -94,7 +102,8 @@ export default function LodeomSimulationGoals({ year, engine, dispatch, - régularisationMethod + régularisationMethod, + withRépartition ) }) } @@ -108,7 +117,8 @@ export default function LodeomSimulationGoals({ previousData, year, engine, - régularisationMethod + régularisationMethod, + withRépartition ) }) } @@ -153,7 +163,7 @@ export default function LodeomSimulationGoals({ code: codeRégularisation, }) } - withRépartitionAndRégularisation={currentZone === 'zone un'} + withRépartitionAndRégularisation={withRépartition} /> ) : ( } - withRépartition={currentZone === 'zone un'} + withRépartition={withRépartition} /> ))} diff --git "a/site/source/utils/r\303\251ductionDeCotisations.ts" "b/site/source/utils/r\303\251ductionDeCotisations.ts" index 249cb8d68f..afaab5662a 100644 --- "a/site/source/utils/r\303\251ductionDeCotisations.ts" +++ "b/site/source/utils/r\303\251ductionDeCotisations.ts" @@ -74,6 +74,12 @@ export type Répartition = { chômage: number } +const defaultRépartition = { + IRC: 0, + Urssaf: 0, + chômage: 0, +} + export const getDataAfterSituationChange = ( dottedName: RéductionDottedName, situation: SituationType, @@ -81,10 +87,16 @@ export const getDataAfterSituationChange = ( previousData: MonthState[], year: number, engine: Engine, - régularisationMethod?: RégularisationMethod + régularisationMethod?: RégularisationMethod, + withRépartition: boolean = true ): MonthState[] => { if (!Object.keys(situation).length) { - return getInitialRéductionMoisParMois(dottedName, year, engine) + return getInitialRéductionMoisParMois( + dottedName, + year, + engine, + withRépartition + ) } const newOptions = getOptionsFromSituations(previousSituation, situation) @@ -104,6 +116,7 @@ export const getDataAfterSituationChange = ( updatedData, year, engine, + withRépartition, régularisationMethod ) } @@ -116,7 +129,8 @@ export const getDataAfterRémunérationChange = ( year: number, engine: Engine, dispatch: Dispatch, - régularisationMethod?: RégularisationMethod + régularisationMethod?: RégularisationMethod, + withRépartition: boolean = true ): MonthState[] => { const updatedData = [...previousData] updatedData[monthIndex] = { @@ -131,6 +145,7 @@ export const getDataAfterRémunérationChange = ( updatedData, year, engine, + withRépartition, régularisationMethod ) } @@ -142,7 +157,8 @@ export const getDataAfterOptionsChange = ( previousData: MonthState[], year: number, engine: Engine, - régularisationMethod?: RégularisationMethod + régularisationMethod?: RégularisationMethod, + withRépartition: boolean = true ): MonthState[] => { const updatedData = [...previousData] updatedData[monthIndex] = { @@ -155,6 +171,7 @@ export const getDataAfterOptionsChange = ( updatedData, year, engine, + withRépartition, régularisationMethod ) } @@ -162,7 +179,8 @@ export const getDataAfterOptionsChange = ( export const getInitialRéductionMoisParMois = ( dottedName: RéductionDottedName, year: number, - engine: Engine + engine: Engine, + withRépartition: boolean = true ): MonthState[] => { const rémunérationBrute = (engine.evaluate({ @@ -221,12 +239,9 @@ export const getInitialRéductionMoisParMois = ( }, engine ) - const répartition = getRépartition( - dottedName, - rémunérationBrute, - réduction, - engine - ) + const répartition = withRépartition + ? getRépartition(dottedName, rémunérationBrute, réduction, engine) + : defaultRépartition return { rémunérationBrute, @@ -254,6 +269,7 @@ export const reevaluateRéductionMoisParMois = ( data: MonthState[], year: number, engine: Engine, + withRépartition: boolean, régularisationMethod?: RégularisationMethod ): MonthState[] => { const totalRémunérationBrute = sumAll( @@ -330,20 +346,24 @@ export const reevaluateRéductionMoisParMois = ( if (régularisation.value > 0) { réduction.value = régularisation.value - réduction.répartition = getRépartition( - dottedName, - rémunérationBrute, - réduction.value, - engine - ) + réduction.répartition = withRépartition + ? getRépartition( + dottedName, + rémunérationBrute, + réduction.value, + engine + ) + : defaultRépartition régularisation.value = 0 } else if (régularisation.value < 0) { - régularisation.répartition = getRépartition( - dottedName, - rémunérationBrute, - régularisation.value, - engine - ) + régularisation.répartition = withRépartition + ? getRépartition( + dottedName, + rémunérationBrute, + régularisation.value, + engine + ) + : defaultRépartition } } else { const date = getDateForContexte(monthIndex, year) @@ -380,29 +400,35 @@ export const reevaluateRéductionMoisParMois = ( if (régularisation.value > 0) { réduction.value = régularisation.value - réduction.répartition = getRépartition( - dottedName, - rémunérationBrute, - réduction.value, - engine - ) + réduction.répartition = withRépartition + ? getRépartition( + dottedName, + rémunérationBrute, + réduction.value, + engine + ) + : defaultRépartition régularisation.value = 0 } else if (régularisation.value < 0) { - régularisation.répartition = getRépartition( - dottedName, - rémunérationBrute, - régularisation.value, - engine - ) + régularisation.répartition = withRépartition + ? getRépartition( + dottedName, + rémunérationBrute, + régularisation.value, + engine + ) + : defaultRépartition réduction.value = 0 } } else { - réduction.répartition = getRépartition( - dottedName, - rémunérationBrute, - réduction.value, - engine - ) + réduction.répartition = withRépartition + ? getRépartition( + dottedName, + rémunérationBrute, + réduction.value, + engine + ) + : defaultRépartition } } From b288ca9fe9efd09c006207a1d557923fcdb6f591 Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Wed, 22 Jan 2025 18:50:18 +0100 Subject: [PATCH 6/7] =?UTF-8?q?tests(lodeom):=20mise=20=C3=A0=20jour=20du?= =?UTF-8?q?=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/cypress/integration/mon-entreprise/lodeom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/cypress/integration/mon-entreprise/lodeom.ts b/site/cypress/integration/mon-entreprise/lodeom.ts index ecd6e60958..4077a821d1 100755 --- a/site/cypress/integration/mon-entreprise/lodeom.ts +++ b/site/cypress/integration/mon-entreprise/lodeom.ts @@ -12,7 +12,7 @@ describe('Simulateur lodeom', { testIsolation: false }, function () { }) it('should not crash', function () { - cy.contains('Rémunération brute') + cy.contains('Quelle est votre localisation ?') }) it('should display a warning when no zone is selected', function () { From 971139dfeea24feca1d2039988901086ab4e79c9 Mon Sep 17 00:00:00 2001 From: Alice Dahan Date: Wed, 22 Jan 2025 18:50:40 +0100 Subject: [PATCH 7/7] =?UTF-8?q?chore(modele-social):=20mise=20=C3=A0=20jou?= =?UTF-8?q?r=20du=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modele-social/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modele-social/CHANGELOG.md b/modele-social/CHANGELOG.md index 263b561914..9d13d35914 100644 --- a/modele-social/CHANGELOG.md +++ b/modele-social/CHANGELOG.md @@ -1,6 +1,9 @@ # Journal des modifications ## next +### Nouveautés +- Ajout du calcul Lodeom pour toutes les zones et tous les barèmes +- Ajout du calcul du SMIC équivalent pour un mois incomplet ## 4.1.0 ### Nouveautés