Implémentation plus puissante de la dépendance parent
Elle est applicable à tous les parents calculables, et on fait attention à ne pas produire de boucles infinies.barème-continu
parent
bb02c73ed7
commit
c58a7449d0
|
@ -53,8 +53,11 @@ export let enrichRule = (rule, sharedData = {}) => {
|
|||
defaultValue = rule['par défaut'],
|
||||
examples = rule['exemples'],
|
||||
icon = rule['icônes'],
|
||||
booleanNamespace =
|
||||
rule.question && (!rule.format || rule.format === 'booléen')
|
||||
calculableNamespace =
|
||||
rule.question ||
|
||||
rule['non applicable si'] ||
|
||||
rule['applicable si'] ||
|
||||
rule.formule
|
||||
|
||||
return {
|
||||
...rule,
|
||||
|
@ -69,7 +72,7 @@ export let enrichRule = (rule, sharedData = {}) => {
|
|||
raw: rule,
|
||||
examples,
|
||||
icon,
|
||||
booleanNamespace
|
||||
calculableNamespace
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error('Problem enriching ' + JSON.stringify(rule))
|
||||
|
|
|
@ -18,7 +18,8 @@ import {
|
|||
merge,
|
||||
keys,
|
||||
is,
|
||||
T
|
||||
T,
|
||||
isEmpty
|
||||
} from 'ramda'
|
||||
import { Node } from './mecanismViews/common'
|
||||
import {
|
||||
|
@ -164,14 +165,12 @@ export let treatRuleRoot = (rules, rule) => {
|
|||
return { ...evaluated, nodeValue, isApplicable, missingVariables }
|
||||
}
|
||||
|
||||
// A parent dependency means that one of a rule's parents is a boolean question
|
||||
// When the question is resolved to false, then the whole branch under it is disactivate, non applicable
|
||||
// A parent dependency means that one of a rule's parents is not just a namespace holder, it is calculable, so it can be false
|
||||
// When it is resolved to false, then the whole branch under it is disactivate, non applicable
|
||||
// It lets those children omit parent applicability tests
|
||||
let parentDependencies = ruleParents(rule.dottedName)
|
||||
.reverse()
|
||||
.map(joinName),
|
||||
let parentDependencies = ruleParents(rule.dottedName).map(joinName),
|
||||
parentDependency = parentDependencies.find(
|
||||
parent => rules.find(r => r.dottedName === parent)?.booleanNamespace
|
||||
parent => rules.find(r => r.dottedName === parent)?.calculableNamespace
|
||||
)
|
||||
|
||||
let parsedRoot = evolve({
|
||||
|
@ -181,8 +180,15 @@ export let treatRuleRoot = (rules, rule) => {
|
|||
// condition d'applicabilité de la règle
|
||||
parentDependency: parent => {
|
||||
let evaluate = (cache, situationGate, parsedRules, node) => {
|
||||
let cpd = cache.checkingParentDependencies || []
|
||||
if (cpd.includes(rule.dottedName))
|
||||
return rewriteNode(node, true, null, {})
|
||||
|
||||
let explanation = evaluateNode(
|
||||
cache,
|
||||
{
|
||||
...cache,
|
||||
checkingParentDependencies: [...cpd, rule.dottedName]
|
||||
},
|
||||
situationGate,
|
||||
parsedRules,
|
||||
node.explanation
|
||||
|
|
|
@ -2356,7 +2356,6 @@
|
|||
formule: entreprise . taxe sur les salaires / entreprise . effectif
|
||||
|
||||
note: Cette implémentation de la taxe sur les salaires est spécifique aux associations à but non lucratif, elle est donc largement simplifiée. Plein d'autres organisations sont concernées, en fonction de la TVA qu'elles paient. Les associations y sont assujetties automatiquement.
|
||||
|
||||
exemples:
|
||||
- nom: non applicable par défaut
|
||||
situation:
|
||||
|
|
|
@ -36,7 +36,7 @@ let parsedRules = parseAll(rules)
|
|||
describe('Tests des règles de notre base de règles', () =>
|
||||
parsedRules.map(rule => {
|
||||
if (!rule.exemples) return null
|
||||
describe(rule.name, () => {
|
||||
describe(rule.dottedName, () => {
|
||||
let examples = runExamples(rule.exemples, rule)
|
||||
examples.map(example =>
|
||||
it(example.nom + '', () => {
|
||||
|
|
|
@ -507,14 +507,53 @@ describe('analyse with mecanisms', function() {
|
|||
})
|
||||
|
||||
describe('Implicit parent applicability', function() {
|
||||
it('should make a variable non applicable if one parent is non applicable', function() {
|
||||
it('should make a variable non applicable if one parent is input to false', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'CDD', question: 'CDD ?' },
|
||||
{ nom: 'surcoût', formule: 10, espace: 'CDD' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
analyse(rules, 'surcoût')(name => ({ CDD: false }[name])).targets[0]
|
||||
analyse(rules, 'CDD . surcoût')(name => ({ CDD: false }[name])).targets[0]
|
||||
).to.have.property('nodeValue', 0)
|
||||
})
|
||||
it('should make a variable non applicable if one parent is non applicable', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'CDD', question: 'CDD ?', 'non applicable si': 'exception' },
|
||||
{ nom: 'exception', question: 'Suivez-vous le lapin blanc ?' },
|
||||
{ nom: 'surcoût', formule: 10, espace: 'CDD' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
analyse(rules, 'CDD . surcoût')(name => ({ exception: true }[name]))
|
||||
.targets[0]
|
||||
).to.have.property('nodeValue', 0)
|
||||
})
|
||||
it('should not go through eval loops from parent to children to parent', function() {
|
||||
let rawRules = [
|
||||
{
|
||||
nom: 'CDD',
|
||||
question: 'CDD ?',
|
||||
'non applicable si': 'exception > 3'
|
||||
},
|
||||
{
|
||||
espace: 'CDD',
|
||||
nom: 'surcoût',
|
||||
formule: 'annuel / 12'
|
||||
},
|
||||
{
|
||||
espace: 'CDD . surcoût',
|
||||
nom: 'annuel',
|
||||
formule: 24
|
||||
},
|
||||
{
|
||||
nom: 'exception',
|
||||
formule: 'CDD . surcoût * 3'
|
||||
}
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
analyse(rules, 'CDD . surcoût . annuel')(name => ({}[name])).targets[0]
|
||||
).to.have.property('nodeValue', 0)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue