⚙️ Implémentation des contrôles a posteriori

pull/492/head
Mael 2019-03-04 14:21:15 +01:00 committed by Johan Girod
parent f9580f15b5
commit 05845db5e6
6 changed files with 59 additions and 31 deletions

View File

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

View File

@ -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 (
<div id="targetSelection">
<QuickLinks />
<Controls
controls={chain(({ contrôles }) => contrôles, analysis.cache)}
/>
{!noUserInput && <Controls controls={analysis.controls} />}
<div style={{ height: '10px' }}>
<Progress percent={progress} />
</div>

25
source/engine/controls.js vendored Normal file
View File

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

View File

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

View File

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

View File

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