⚙️ un début de propreté dans les mécanismes
POC de mécanisme dznsnun style nouveau et dans un nouveau fichier. reste à abstraire la fonction vindeps-catégorie-activité
parent
209694a4c6
commit
19537e1d87
|
@ -42,7 +42,6 @@ import {
|
|||
evaluateNode,
|
||||
rewriteNode,
|
||||
evaluateArray,
|
||||
evaluateArrayWithFilter,
|
||||
evaluateObject,
|
||||
parseObject,
|
||||
collectNodeMissing,
|
||||
|
@ -64,55 +63,10 @@ import BarèmeContinu from './mecanismViews/BarèmeContinu'
|
|||
import InversionNumérique from './mecanismViews/InversionNumérique'
|
||||
import Variations from './mecanismViews/Variations'
|
||||
import Allègement from './mecanismViews/Allègement'
|
||||
import Composantes from './mecanismViews/Composantes'
|
||||
import { trancheValue } from './mecanisms/barème'
|
||||
import buildSelectionView from './mecanismViews/Selection'
|
||||
import uniroot from './uniroot'
|
||||
|
||||
let decompose = (recurse, k, v) => {
|
||||
let subProps = dissoc('composantes')(v),
|
||||
explanation = v.composantes.map(c => ({
|
||||
...recurse(
|
||||
objOf(k, {
|
||||
...subProps,
|
||||
...dissoc('attributs')(c)
|
||||
})
|
||||
),
|
||||
composante: c.nom ? { nom: c.nom } : c.attributs
|
||||
}))
|
||||
|
||||
let filter = situationGate => c =>
|
||||
!situationGate('sys.filter') ||
|
||||
!c.composante ||
|
||||
((!c.composante['dû par'] ||
|
||||
c.composante['dû par'] == situationGate('sys.filter')) &&
|
||||
(!c.composante['impôt sur le revenu'] ||
|
||||
c.composante['impôt sur le revenu'] == situationGate('sys.filter')))
|
||||
|
||||
return {
|
||||
explanation,
|
||||
jsx: Composantes,
|
||||
evaluate: evaluateArrayWithFilter(filter, add, 0),
|
||||
category: 'mecanism',
|
||||
name: 'composantes',
|
||||
type: 'numeric'
|
||||
}
|
||||
}
|
||||
|
||||
let devariateExplanation = (recurse, mecanismKey, v) => {
|
||||
let fixedProps = dissoc('variations')(v),
|
||||
explanation = v.variations.map(({ si, alors, sinon }) => ({
|
||||
consequence: recurse({
|
||||
[mecanismKey]: {
|
||||
...fixedProps,
|
||||
...(sinon || alors)
|
||||
}
|
||||
}),
|
||||
condition: sinon ? undefined : recurse(si)
|
||||
}))
|
||||
|
||||
return explanation
|
||||
}
|
||||
import { decompose, devariateExplanation } from 'Engine/mecanisms/utils'
|
||||
import { desugarScale } from 'Engine/mecanisms/barème'
|
||||
|
||||
/* @devariate = true => This function will produce variations of a same mecanism (e.g. product) that share some common properties */
|
||||
export let mecanismVariations = (recurse, k, v, devariate) => {
|
||||
|
@ -726,16 +680,6 @@ export let mecanismProduct = (recurse, k, v) => {
|
|||
à: 1
|
||||
```
|
||||
*/
|
||||
let desugarScale = recurse => tranches =>
|
||||
tranches
|
||||
.map(t =>
|
||||
has('en-dessous de')(t)
|
||||
? { ...t, de: 0, à: t['en-dessous de'] }
|
||||
: has('au-dessus de')(t)
|
||||
? { ...t, de: t['au-dessus de'], à: Infinity }
|
||||
: t
|
||||
)
|
||||
.map(evolve({ taux: recurse }))
|
||||
|
||||
export let mecanismLinearScale = (recurse, k, v) => {
|
||||
if (v.composantes) {
|
||||
|
@ -782,47 +726,6 @@ export let mecanismLinearScale = (recurse, k, v) => {
|
|||
}
|
||||
}
|
||||
|
||||
export let mecanismScale = (recurse, k, v) => {
|
||||
// Sous entendu : barème en taux marginaux.
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
return decompose(recurse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
return mecanismVariations(recurse, k, v, true)
|
||||
}
|
||||
|
||||
let tranches = desugarScale(recurse)(v['tranches']),
|
||||
objectShape = {
|
||||
assiette: false,
|
||||
multiplicateur: defaultNode(1)
|
||||
}
|
||||
|
||||
let effect = ({ assiette, multiplicateur: multiplicateur, tranches }) => {
|
||||
let nulled = val(assiette) == null || val(multiplicateur) == null
|
||||
|
||||
return nulled
|
||||
? null
|
||||
: sum(tranches.map(trancheValue('marginal')(assiette, multiplicateur)))
|
||||
}
|
||||
|
||||
let explanation = {
|
||||
...parseObject(recurse, objectShape, v),
|
||||
tranches
|
||||
},
|
||||
evaluate = evaluateObject(objectShape, effect)
|
||||
|
||||
return {
|
||||
evaluate,
|
||||
jsx: Barème('marginal'),
|
||||
explanation,
|
||||
category: 'mecanism',
|
||||
name: 'barème',
|
||||
barème: 'en taux marginaux',
|
||||
type: 'numeric'
|
||||
}
|
||||
}
|
||||
|
||||
export let mecanismContinuousScale = (recurse, k, v) => {
|
||||
let objectShape = {
|
||||
assiette: false,
|
||||
|
|
|
@ -1,4 +1,26 @@
|
|||
import { val } from 'Engine/traverse-common-functions'
|
||||
import { decompose } from 'Engine/mecanisms/utils'
|
||||
import { mecanismVariations } from 'Engine/mecanisms'
|
||||
import { has, evolve, sum } from 'ramda'
|
||||
import {
|
||||
defaultNode,
|
||||
evaluateNode,
|
||||
mergeMissing,
|
||||
rewriteNode
|
||||
} from 'Engine/evaluation'
|
||||
|
||||
import Barème from 'Engine/mecanismViews/Barème'
|
||||
|
||||
export let desugarScale = recurse => tranches =>
|
||||
tranches
|
||||
.map(t =>
|
||||
has('en-dessous de')(t)
|
||||
? { ...t, de: 0, à: t['en-dessous de'] }
|
||||
: has('au-dessus de')(t)
|
||||
? { ...t, de: t['au-dessus de'], à: Infinity }
|
||||
: t
|
||||
)
|
||||
.map(evolve({ taux: recurse }))
|
||||
|
||||
export let trancheValue = barèmeType => (assiette, multiplicateur) =>
|
||||
barèmeType === 'marginal'
|
||||
|
@ -15,3 +37,60 @@ export let trancheValue = barèmeType => (assiette, multiplicateur) =>
|
|||
? val(assiette) * val(taux)
|
||||
: montant
|
||||
: 0
|
||||
|
||||
export default (recurse, k, v) => {
|
||||
// Barème en taux marginaux.
|
||||
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
return decompose(recurse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
return mecanismVariations(recurse, k, v, true)
|
||||
}
|
||||
|
||||
let tranches = desugarScale(recurse)(v['tranches'])
|
||||
|
||||
let explanation = {
|
||||
assiette: recurse(v['assiette']),
|
||||
multiplicateur:
|
||||
v['multiplicateur'] != null
|
||||
? recurse(v['multiplicateur'])
|
||||
: defaultNode(1),
|
||||
tranches
|
||||
}
|
||||
|
||||
let evaluate = (cache, situationGate, parsedRules, node) => {
|
||||
let mv = {}
|
||||
|
||||
let v = element => {
|
||||
let evaluated = evaluateNode(cache, situationGate, parsedRules, element)
|
||||
// automatically add missing variables when a variable is evaluated and thus needed in this mecanism's evaluation
|
||||
mv = mergeMissing(mv, evaluated.missingVariables)
|
||||
|
||||
return evaluated.nodeValue
|
||||
},
|
||||
{ assiette, multiplicateur } = node.explanation,
|
||||
trancheValues = node.explanation.tranches.map(
|
||||
({ de: min, à: max, taux }) =>
|
||||
v(assiette) < min * v(multiplicateur)
|
||||
? 0
|
||||
: (Math.min(v(assiette), max * v(multiplicateur)) -
|
||||
min * v(multiplicateur)) *
|
||||
v(taux)
|
||||
),
|
||||
nodeValue = sum(trancheValues)
|
||||
|
||||
return rewriteNode(node, nodeValue, explanation, mv)
|
||||
}
|
||||
|
||||
return {
|
||||
explanation,
|
||||
evaluate,
|
||||
jsx: () => null,
|
||||
// jsx: Barème('marginal'),
|
||||
category: 'mecanism',
|
||||
name: 'barème',
|
||||
barème: 'marginal'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import Composantes from 'Engine/mecanismViews/Composantes'
|
||||
import { add, dissoc, objOf } from 'ramda'
|
||||
import { evaluateArrayWithFilter } from 'Engine/evaluation'
|
||||
|
||||
export let decompose = (recurse, k, v) => {
|
||||
let subProps = dissoc('composantes')(v),
|
||||
explanation = v.composantes.map(c => ({
|
||||
...recurse(
|
||||
objOf(k, {
|
||||
...subProps,
|
||||
...dissoc('attributs')(c)
|
||||
})
|
||||
),
|
||||
composante: c.nom ? { nom: c.nom } : c.attributs
|
||||
}))
|
||||
|
||||
let filter = situationGate => c =>
|
||||
!situationGate('sys.filter') ||
|
||||
!c.composante ||
|
||||
((!c.composante['dû par'] ||
|
||||
c.composante['dû par'] == situationGate('sys.filter')) &&
|
||||
(!c.composante['impôt sur le revenu'] ||
|
||||
c.composante['impôt sur le revenu'] == situationGate('sys.filter')))
|
||||
|
||||
return {
|
||||
explanation,
|
||||
jsx: Composantes,
|
||||
evaluate: evaluateArrayWithFilter(filter, add, 0),
|
||||
category: 'mecanism',
|
||||
name: 'composantes',
|
||||
type: 'numeric'
|
||||
}
|
||||
}
|
||||
|
||||
export let devariateExplanation = (recurse, mecanismKey, v) => {
|
||||
let fixedProps = dissoc('variations')(v),
|
||||
explanation = v.variations.map(({ si, alors, sinon }) => ({
|
||||
consequence: recurse({
|
||||
[mecanismKey]: {
|
||||
...fixedProps,
|
||||
...(sinon || alors)
|
||||
}
|
||||
}),
|
||||
condition: sinon ? undefined : recurse(si)
|
||||
}))
|
||||
|
||||
return explanation
|
||||
}
|
|
@ -31,13 +31,19 @@ import {
|
|||
} from './treatVariable'
|
||||
import { treat } from './traverse'
|
||||
import knownMecanisms from './known-mecanisms.yaml'
|
||||
|
||||
// This should be the new way to implement mecanisms
|
||||
// In a specific file
|
||||
// TODO import them automatically
|
||||
// TODO convert the legacy functions to new files
|
||||
import barème from 'Engine/mecanisms/barème.js'
|
||||
|
||||
import {
|
||||
mecanismOneOf,
|
||||
mecanismAllOf,
|
||||
mecanismNumericalSwitch,
|
||||
mecanismSum,
|
||||
mecanismProduct,
|
||||
mecanismScale,
|
||||
mecanismLinearScale,
|
||||
mecanismContinuousScale,
|
||||
mecanismMax,
|
||||
|
@ -251,7 +257,7 @@ export let treatObject = (rules, rule, treatOptions) => rawNode => {
|
|||
'aiguillage numérique': mecanismNumericalSwitch,
|
||||
somme: mecanismSum,
|
||||
multiplication: mecanismProduct,
|
||||
barème: mecanismScale,
|
||||
barème,
|
||||
'barème linéaire': mecanismLinearScale,
|
||||
'barème continu': mecanismContinuousScale,
|
||||
'le maximum de': mecanismMax,
|
||||
|
|
Loading…
Reference in New Issue