🔥 Rm régularisation
parent
4087bdd959
commit
6ceedfea15
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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<Name extends string>(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<string, unknown> }>
|
||||
|
||||
return {
|
||||
explanation: {
|
||||
rule,
|
||||
variables
|
||||
},
|
||||
category: 'mecanism',
|
||||
name: 'taux progressif',
|
||||
nodeKind: 'régularisation',
|
||||
type: 'numeric',
|
||||
unit: rule.unit
|
||||
}
|
||||
}
|
||||
|
||||
function getMonthlyCumulatedValuesOverYear(
|
||||
year: number,
|
||||
variable: Temporal<Evaluation<number>>,
|
||||
unit: Unit
|
||||
): Temporal<Evaluation<number>> {
|
||||
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<Evaluation<number>>) => {
|
||||
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<string, unknown>
|
||||
}>).reduce<Record<string, Temporal<Evaluation<number>>>>(
|
||||
(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<Evaluation<number>>
|
||||
}
|
||||
|
||||
const evaluation = this.evaluateNode(node.explanation.rule)
|
||||
const temporalValue = evaluation.temporalValue
|
||||
const evaluationWithRegularisation = groupByYear(
|
||||
temporalValue as Temporal<Evaluation<number>>
|
||||
)
|
||||
.map(regulariseYear)
|
||||
.flat()
|
||||
return {
|
||||
...node,
|
||||
temporalValue: evaluationWithRegularisation,
|
||||
explanation: evaluation,
|
||||
nodeValue: temporalAverage(evaluationWithRegularisation, evaluation.unit),
|
||||
missingVariables: evaluation.missingVariables,
|
||||
unit: evaluation.unit
|
||||
}
|
||||
}
|
||||
|
||||
registerEvaluationFunction('régularisation', evaluate)
|
|
@ -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,
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue