From 05845db5e6427c1324a8b14a222c7ae682d226c3 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 4 Mar 2019 14:21:15 +0100 Subject: [PATCH] =?UTF-8?q?:gear:=20Impl=C3=A9mentation=20des=20contr?= =?UTF-8?q?=C3=B4les=20a=20posteriori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + source/components/TargetSelection.js | 6 ++---- source/engine/controls.js | 25 +++++++++++++++++++++++++ source/engine/traverse.js | 25 +++++++------------------ source/engine/treatVariable.js | 9 ++++----- test/contrôles.test.js | 24 ++++++++++++++++++++---- 6 files changed, 59 insertions(+), 31 deletions(-) create mode 100644 source/engine/controls.js diff --git a/package.json b/package.json index 7e4143606..406768b82 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "test-watch": "yarn test-common --watch", "test-common": "mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js \"./{,!(node_modules)/**/}!(webpack).test.js\"", "test": "yarn test-common", + "test-one": "yarn mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js", "test-components": "mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage ---require test/helpers/browser.js \"source/components/**/*.test.js\" --watch", "test-lib": "yarn test-common --grep 'library'", "compile-lib": "yarn webpack --config source/webpack.lib.js", diff --git a/source/components/TargetSelection.js b/source/components/TargetSelection.js index 69a83e30e..36707c385 100644 --- a/source/components/TargetSelection.js +++ b/source/components/TargetSelection.js @@ -58,14 +58,12 @@ export default compose( )( class TargetSelection extends Component { render() { - let { colours, analysis, progress } = this.props + let { colours, noUserInput, analysis, progress } = this.props return (
- contrôles, analysis.cache)} - /> + {!noUserInput && }
diff --git a/source/engine/controls.js b/source/engine/controls.js new file mode 100644 index 000000000..b3f769faf --- /dev/null +++ b/source/engine/controls.js @@ -0,0 +1,25 @@ +import { evaluateNode } from 'Engine/evaluation' +import { values, unnest, filter, map, pipe, path } from 'ramda' + +let getControls = path(['explanation', 'contrôles']) +export let evaluateControls = (cache, situationGate, parsedRules) => + pipe( + values, + filter(getControls), + map(rule => + getControls(rule).map( + control => + !rule.inactiveParent && { + ...control, + evaluated: evaluateNode( + cache, + situationGate, + parsedRules, + control.testExpression + ) + } + ) + ), + unnest, + filter(control => control.evaluated.nodeValue === true) + )(cache) diff --git a/source/engine/traverse.js b/source/engine/traverse.js index d89360c96..c2a5f7b88 100644 --- a/source/engine/traverse.js +++ b/source/engine/traverse.js @@ -30,6 +30,7 @@ import { } from './evaluation' import { anyNull, val, undefOrTrue } from './traverse-common-functions' import { ShowValuesConsumer } from 'Components/rule/ShowValuesContext' +import { evaluateControls } from 'Engine/controls' /* Dans ce fichier, les règles YAML sont parsées. @@ -86,7 +87,7 @@ export let treat = (rules, rule) => rawNode => { export let treatRuleRoot = (rules, rule) => { /* The treatRuleRoot function will traverse the tree of the `rule` and produce an AST, an object containing other objects containing other objects... - Some of the attributes of the rule are dynamic, they need to be parsed. It is the case of `non applicable si`, `applicable si`, `formule`, `contrôles`. + Some of the attributes of the rule are dynamic, they need to be parsed. It is the case of `non applicable si`, `applicable si`, `formule`. These attributes' values themselves may have mechanism properties (e. g. `barème`) or inline expressions (e. g. `maVariable + 3`). These mechanisms or variables are in turn traversed by `treat()`. During this processing, 'evaluate' and'jsx' functions are attached to the objects of the AST. They will be evaluated during the evaluation phase, called "analyse". */ @@ -159,20 +160,6 @@ export let treatRuleRoot = (rules, rule) => { formulaMissingVariables ) - let evaluateControls = node.contrôles && val(parentDependency) !== false - console.log(node.name, evaluateControls) - let contrôles = - evaluateControls && - node.contrôles.map(control => ({ - ...control, - evaluated: evaluateNode( - cache, - situationGate, - parsedRules, - control.testExpression - ) - })) - cache.parseLevel-- // if (keys(condMissing).length) console.log("".padStart(cache.parseLevel-1),{conditions:condMissing, formule:formMissing}) // else console.log("".padStart(cache.parseLevel-1),{formule:formMissing}) @@ -180,10 +167,10 @@ export let treatRuleRoot = (rules, rule) => { ...node, ...evaluatedAttributes, ...{ formule: evaluatedFormula }, - contrôles, nodeValue, isApplicable, - missingVariables + missingVariables, + inactiveParent: parentDependency && val(parentDependency) == false } } @@ -358,7 +345,9 @@ export let analyseMany = (parsedRules, targetNames) => situationGate => { cache[t.dottedName] || // This check exists because it is not done in treatRuleRoot's eval, while it is in treatVariable. This should be merged : we should probably call treatVariable here : targetNames could be expressions (hence with filters) TODO evaluateNode(cache, situationGate, parsedRules, t) ) - return { targets, cache } + + let controls = evaluateControls(cache, situationGate, parsedRules) + return { targets, cache, controls } } export let analyse = (parsedRules, target) => { diff --git a/source/engine/treatVariable.js b/source/engine/treatVariable.js index 761562c85..94048bf47 100644 --- a/source/engine/treatVariable.js +++ b/source/engine/treatVariable.js @@ -25,11 +25,10 @@ export let treatVariable = (rules, rule, filter) => parseResult => { variable['non applicable si'] != null, situationValue = getSituationValue(situation, dottedName, variable), needsEvaluation = - variable['contrôles'] || - (situationValue == null && - (variableHasCond || - variableHasFormula || - findParentDependency(rules, variable))) + situationValue == null && + (variableHasCond || + variableHasFormula || + findParentDependency(rules, variable)) // if (dottedName.includes('jeune va')) debugger diff --git a/test/contrôles.test.js b/test/contrôles.test.js index 3ceb10834..9c12d1ead 100644 --- a/test/contrôles.test.js +++ b/test/contrôles.test.js @@ -58,14 +58,30 @@ describe('controls', function() { }) it('Should allow imbricated conditions', function() { - let situationGate = dottedName => ({ brut: 2000000 }[dottedName]), - cache = analyseMany(parsedRules, ['net'])(situationGate).cache, - controls = chain(prop('contrôles'), values(cache)) - + let controls = analyseMany(parsedRules, ['net'])( + dottedName => ({ brut: 2000000 }[dottedName]) + ).controls expect( controls.find( ({ message }) => message === 'Vous êtes un contribuable hors-pair !' ) ).to.exist + + let controls2 = analyseMany(parsedRules, ['net'])( + dottedName => ({ brut: 100001 }[dottedName]) + ).controls + expect(controls2.find(({ message }) => message === 'Oulah ! Oulah !')).to + .exist + + let controls3 = analyseMany(parsedRules, ['net'])( + dottedName => ({ brut: 100 }[dottedName]) + ).controls + expect( + controls3.find( + ({ message }) => + message === + 'Malheureux, je crois que vous vous êtes trompé dans votre saisie.' + ) + ).to.exist }) })