From 6ceedfea15ad1fb7b5b949a5c7b269691ade261e Mon Sep 17 00:00:00 2001 From: Alexandre Hajjar Date: Fri, 13 Nov 2020 22:25:33 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20Rm=20r=C3=A9gularisation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../source/rules/exemple-régularisation.yaml | 106 ----------- publicodes/docs/mecanisms.yaml | 118 ------------ publicodes/source/mecanisms/régularisation.ts | 168 ------------------ publicodes/source/parse.tsx | 2 - .../test/mécanismes/régularisation.yaml | 96 ---------- 5 files changed, 490 deletions(-) delete mode 100644 mon-entreprise/source/rules/exemple-régularisation.yaml delete mode 100644 publicodes/source/mecanisms/régularisation.ts delete mode 100644 publicodes/test/mécanismes/régularisation.yaml diff --git a/mon-entreprise/source/rules/exemple-régularisation.yaml b/mon-entreprise/source/rules/exemple-régularisation.yaml deleted file mode 100644 index 7463922b6..000000000 --- a/mon-entreprise/source/rules/exemple-régularisation.yaml +++ /dev/null @@ -1,106 +0,0 @@ -SMIC: 1521.22 €/mois - -primes: - formule: - somme: - - 2470 €/mois | du 01/01/2019 | au 31/01/2019 - - 1470 €/mois | du 01/05/2019 | au 31/05/2019 - -rémunération: - formule: - somme: - - 1530 €/mois | du 01/01/2019 | au 31/12/2019 - - primes - -effectif 20 salarié ou plus: - formule: oui - -réduction sur AC au 1er janvier: - formule: non - -réduction générale . urssaf . constante: - formule: - variations: - - si: effectif 20 salarié ou plus - alors: 0.284 - - sinon: 0.2809 - -réduction générale . urssaf . coefficient: - formule: - arrondi: - valeur: (constante / 0.60 ) * (1.60 * SMIC / rémunération - 1) - décimales: 4 - -réduction générale . urssaf . réduction sans régularisation: - formule: - produit: - assiette: rémunération - taux: coefficient - arrondi: 2 décimales - plancher: 0 - -réduction générale . urssaf: - formule: - régularisation: - règle: réduction sans régularisation - valeurs cumulées: - - SMIC - - rémunération - -réduction générale . chômage . constante: - formule: 0.0405 - -réduction générale . chômage . coefficient: - formule: - arrondi: - valeur: (constante / 0.60 ) * (1.60 * SMIC / rémunération - 1) - décimales: 4 - -réduction générale . chômage . réduction sans régularisation: - formule: - produit: - assiette: rémunération - taux: coefficient - arrondi: 2 décimales - plancher: 0 - -réduction générale . début: - non applicable si: réduction sur AC au 1er janvier - formule: 01/10/2019 - -réduction générale . chômage: - formule: - régularisation: - règle: réduction sans régularisation - valeurs cumulées: - - 'SMIC | à partir de : début' - - 'rémunération | à partir de : début' - -réduction générale: - formule: urssaf + chômage - -réduction lodeom . constante: - formule: 0.3214 - -réduction lodeom: - formule: - régularisation: - valeurs cumulées: - - SMIC - - rémunération - règle: - produit: - assiette: rémunération - facteur [ref coefficient]: - grille: - assiette: rémunération - multiplicateur: SMIC - tranches: - - montant: constante - plafond: 1.7 - - montant: constante * 1.7 * SMIC / rémunération - plafond: 2.5 - - montant: 1.7 * constante * (3.5 * SMIC / rémunération - 1) - arrondi: 4 décimales - arrondi: 2 décimales - plancher: 0 diff --git a/publicodes/docs/mecanisms.yaml b/publicodes/docs/mecanisms.yaml index 5787955d8..421dc750a 100644 --- a/publicodes/docs/mecanisms.yaml +++ b/publicodes/docs/mecanisms.yaml @@ -212,124 +212,6 @@ arrondi: valeur: 12.45 décimales: 1 -régularisation: - description: | - Permet de régulariser progressivement un calcul de cotisation en fonction du - cumul de variables numériques mensuelles. - - Ce mécanisme spécifique est utilisé pour le calcul des cotisations - mensuelles, afin de "lisser" un plafond ou un calcul sur plusieurs mois. - - La régularisation progressive s'opère le long d'une année civile complète. - - ## Explication du calcul - - Pour chaque mois, on évalue la valeur à régulariser en faisant le cumul des - éléments nécessaires au calcul sur la période écoulée depuis le premier - jour de l’année. - - Par exemple, pour la cotisation suivante : - - ```yaml - cotisation: - formule: - produit: - assiette: brut - plafond: 2000 €/mois - taux: 10% - ``` - - Avec un brut de 1000 € en janvier et 3500 € en février et 1000€ en mars, le cumul sera le - suivant : - - | | brut | plafond | cotisation | - | --- | ------ | ------- |------------------- | - | JAN | 1000 € | 2000 € | 1000 × 10% = 100 € | - | FEV | 4500 € | 4000 € | 4000 × 10% = 400 € | - | MAR | 5500 € | 6000 € | 5500 × 10% = 550 € | - - - On regarde ensuite le cumul des valeurs déjà versées les mois précédents, pour - ne garder que la différence entre les deux montants. Dans notre exemple, on - aboutit aux valeurs suivantes : - - | | cotisation cumul | cotisation régularisée | - | --- | ---------------- | ---------------------- | - | JAN | 100 € | 100 € | - | FEV | 400 € | 400 € - 100 € = 300 € | - | MAR | 550 € | 550 € - 300 € = 150 € | - - arguments: - règle: règle à régulariser - valeurs cumulées: - - liste de variables cumulée mensuellement pour calculer la régularisation. Doivent être - numérique, et avoir une unité `/mois` - - exemples: - base: >- - brut: - formule: - somme: - - 1000 €/mois | du 01/01/2020 | au 31/01/2020 - - 3500 €/mois | du 01/02/2020 | au 29/02/2020 - - 1000 €/mois | du 01/03/2020 | au 31/03/2020 - - cotisation: - formule: - régularisation: - règle: - produit: - assiette: brut - plafond [ref]: 2000 €/mois - taux: 10% - valeurs cumulées: - - brut - - plafond - - valeur cumulée à partir d'une date: >- - SMIC: 1521.22 €/mois - - primes: - formule: - somme: - - 2470 €/mois | du 01/01/2019 | au 31/01/2019 - - 1470 €/mois | du 01/05/2019 | au 31/05/2019 - - rémunération: - formule: - somme: - - 1530 €/mois | du 01/01/2019 | au 31/12/2019 - - primes - - réduction sur AC au 1er janvier: - formule: non - - réduction générale chômage . coefficient: - formule: - arrondi: - valeur: (0.0405 / 0.60 ) * (1.60 * SMIC / rémunération - 1) - décimales: 4 - - réduction générale chômage . réduction sans régularisation: - formule: - encadrement: - plancher: 0 - valeur: - arrondi: - valeur: - multiplication: - assiette: rémunération - taux: coefficient - décimales: 2 - - réduction générale chômage: - formule: - régularisation: - règle: réduction sans régularisation - valeurs cumulées: - - 'SMIC | à partir du 01/10/2019' - - 'rémunération | à partir du 01/10/2019' - recalcul: description: >- Relance le calcul d'une règle dans une situation différente de la situation diff --git a/publicodes/source/mecanisms/régularisation.ts b/publicodes/source/mecanisms/régularisation.ts deleted file mode 100644 index 211a5b128..000000000 --- a/publicodes/source/mecanisms/régularisation.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { map } from 'ramda' -import { evaluationFunction } from '..' -import { convertToString, getYear } from '../date' -import { evaluationError } from '../error' -import { registerEvaluationFunction } from '../evaluation' -import { - createTemporalEvaluation, - groupByYear, - liftTemporal2, - pureTemporal, - Temporal, - temporalAverage, - temporalCumul -} from '../temporal' -import { Evaluation, Unit } from '../types' -import { coerceArray } from '../utils' - -function stripTemporalTransform(node) { - if (!node?.explanation?.period) { - return node - } - return stripTemporalTransform(node.explanation.value) -} -export default function parse(parse, v) { - const rule = parse(v.règle) - if (!v['valeurs cumulées']) { - throw new Error( - 'Il manque la clé `valeurs cumulées` dans le mécanisme régularisation' - ) - } - - const variables = coerceArray(v['valeurs cumulées']).map(variable => { - if (typeof variable !== 'string') { - throw new Error( - 'Les `valeurs cumulées` du mécanisme de régularisation doivent être des noms de règles existantes' - ) - } - - const value = parse(variable) - const reference = stripTemporalTransform(value) - if (reference.category !== 'reference') { - throw new Error( - 'Le mécanisme régularisation attend des noms de règles existantes dans les `valeurs cumulées`' - ) - } - return { value, dottedName: reference.dottedName } - }) as Array<{ dottedName: Name; value: Record }> - - return { - explanation: { - rule, - variables - }, - category: 'mecanism', - name: 'taux progressif', - nodeKind: 'régularisation', - type: 'numeric', - unit: rule.unit - } -} - -function getMonthlyCumulatedValuesOverYear( - year: number, - variable: Temporal>, - unit: Unit -): Temporal> { - const start = convertToString(new Date(year, 0, 1)) - const cumulatedPeriods = [...Array(12).keys()] - .map(monthNumber => ({ - start, - end: convertToString(new Date(year, monthNumber + 1, 0)) - })) - .map(period => { - const temporal = liftTemporal2( - (filter, value) => filter && value, - createTemporalEvaluation(true, period), - variable - ) - return { - ...period, - value: temporalCumul(temporal, unit) - } - }) - - return cumulatedPeriods -} - -const evaluate: evaluationFunction = function(node) { - const recalculWith = (newSituation, node) => { - const originalCache = this.cache - const originalSituation = this.parsedSituation - this.cache = { _meta: originalCache._meta } - this.parsedSituation = { ...originalSituation, ...newSituation } - const res = this.evaluateNode(node) - this.cache = originalCache - this.parsedSituation = originalSituation - return res - } - - const regulariseYear = (temporalEvaluation: Temporal>) => { - if (temporalEvaluation.filter(({ value }) => value !== false).length <= 1) { - return temporalEvaluation - } - - const currentYear = getYear(temporalEvaluation[0].start as string) - const cumulatedVariables = (node.explanation.variables as Array<{ - dottedName: string - value: Record - }>).reduce>>>( - (acc, { dottedName, value }) => { - const evaluation = this.evaluateNode(value) - if (!evaluation.unit.denominators.some(unit => unit === 'mois')) { - evaluationError( - this.cache._meta.contextRule, - `Dans le mécanisme régularisation, la valeur cumulée '${dottedName}' n'est pas une variable numérique définie sur le mois` - ) - } - return { - ...acc, - [dottedName]: getMonthlyCumulatedValuesOverYear( - currentYear, - evaluation.temporalValue ?? pureTemporal(evaluation.nodeValue), - evaluation.unit - ) - } - }, - {} - ) - - const cumulatedMonthlyEvaluations = [...Array(12).keys()].map(i => ({ - start: convertToString(new Date(currentYear, i, 1)), - end: convertToString(new Date(currentYear, i + 1, 0)), - value: recalculWith( - map( - cumulatedVariable => cumulatedVariable?.[i].value, - cumulatedVariables - ), - node.explanation.rule - ).nodeValue - })) - const temporalRégularisée = cumulatedMonthlyEvaluations.map( - (period, i) => ({ - ...period, - value: period.value - (cumulatedMonthlyEvaluations[i - 1]?.value ?? 0) - }) - ) - - return temporalRégularisée as Temporal> - } - - const evaluation = this.evaluateNode(node.explanation.rule) - const temporalValue = evaluation.temporalValue - const evaluationWithRegularisation = groupByYear( - temporalValue as Temporal> - ) - .map(regulariseYear) - .flat() - return { - ...node, - temporalValue: evaluationWithRegularisation, - explanation: evaluation, - nodeValue: temporalAverage(evaluationWithRegularisation, evaluation.unit), - missingVariables: evaluation.missingVariables, - unit: evaluation.unit - } -} - -registerEvaluationFunction('régularisation', evaluate) diff --git a/publicodes/source/parse.tsx b/publicodes/source/parse.tsx index 7c812f156..bc1935308 100644 --- a/publicodes/source/parse.tsx +++ b/publicodes/source/parse.tsx @@ -23,7 +23,6 @@ import plancher from './mecanisms/plancher' import { mecanismProduct } from './mecanisms/product' import { mecanismRecalcul } from './mecanisms/recalcul' import { mecanismReduction } from './mecanisms/reduction' -import régularisation from './mecanisms/régularisation' import { mecanismSum } from './mecanisms/sum' import { mecanismSynchronisation } from './mecanisms/synchronisation' import tauxProgressif from './mecanisms/tauxProgressif' @@ -190,7 +189,6 @@ const statelessParseFunction = { 'une de ces conditions': mecanismOneOf, 'toutes ces conditions': mecanismAllOf, somme: mecanismSum, - régularisation, multiplication: mecanismProduct, produit: mecanismProduct, temporalValue: variableTemporelle, diff --git a/publicodes/test/mécanismes/régularisation.yaml b/publicodes/test/mécanismes/régularisation.yaml deleted file mode 100644 index 0114a26ed..000000000 --- a/publicodes/test/mécanismes/régularisation.yaml +++ /dev/null @@ -1,96 +0,0 @@ -salaire: - unité: €/mois - formule: - somme: - - 3300 €/mois | du 01/01/2020 | au 29/02/2020 - - 3600 €/mois | du 01/03/2020 | au 31/12/2020 - -plafond sécurité sociale: - unité: €/mois - formule: 3500 €/mois | du 01/01/2020 | au 31/12/2020 - -retraite: - unité: €/mois - formule: - multiplication: - assiette: salaire - plafond: plafond sécurité sociale - taux: 10% - -retraite . avec régularisation: - formule: - régularisation: - règle: retraite - valeurs cumulées: - - salaire - - plafond sécurité sociale - -régularisation . avant passage: - formule: retraite . avec régularisation | du 01/01/2020 | au 29/02/2020 - exemples: - - valeur attendue: 330 - -régularisation . test mois régularisés: - formule: retraite . avec régularisation | du 01/03/2020 | au 30/06/2020 - exemples: - - valeur attendue: 360 - -régularisation . test mois après régularisation: - formule: retraite . avec régularisation | du 01/07/2020 | au 31/12/2020 - exemples: - - valeur attendue: 350 - -# ====================== -# Exemple plus complexe -# ====================== - -heures d'absences: - # TODO : mettre les heures chaque jour - formule: - somme: - - 2 heures/mois | du 01/01/2020 | au 31/01/2020 - - 3 heures/mois | du 01/03/2020 | au 31/03/2020 - -temps contractuel: - formule: 145 heures/mois -temps de travail effectif: - formule: temps contractuel - heures d'absences -plafond sécurité sociale proratisé: - formule: - multiplication: - assiette: plafond sécurité sociale - facteur: temps de travail effectif / 151.67 heures/mois - -taux variable: - formule: - variations: - - si: salaire < plafond sécurité sociale proratisé - alors: 10% - - sinon: 20% - -cotisation spéciale: - unité: €/mois - formule: - régularisation: - règle: - multiplication: - assiette: salaire - taux: taux variable - valeurs cumulées: - - salaire - - plafond sécurité sociale proratisé - -régularisation . test variations 1: - formule: cotisation spéciale | du 01/01/2020 | au 31/12/2020 - exemples: - - valeur attendue: 710 - -régularisation . test variations 2: - formule: cotisation spéciale | du 01/02/2020 | au 29/02/2020 - exemples: - - valeur attendue: 0 - -régularisation . test variations 3: - formule: cotisation spéciale | du 01/03/2020 | au 31/03/2020 - exemples: - - valeur attendue: 1380