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
Mael 2018-09-20 17:14:11 +02:00
parent bb02c73ed7
commit c58a7449d0
5 changed files with 62 additions and 15 deletions

View File

@ -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))

View File

@ -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

View File

@ -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:

View File

@ -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 + '', () => {

View File

@ -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)
})
})