diff --git a/règles/rémunération-travail/cdd/indemnité_compensatrice_congés_payés.simplifiée.yaml b/règles/rémunération-travail/cdd/indemnité_compensatrice_congés_payés.simplifiée.yaml
index 619a438f0..8104f5e20 100644
--- a/règles/rémunération-travail/cdd/indemnité_compensatrice_congés_payés.simplifiée.yaml
+++ b/règles/rémunération-travail/cdd/indemnité_compensatrice_congés_payés.simplifiée.yaml
@@ -1,4 +1,4 @@
-- Cotisation: Indemnité compensatrice congés payés simplifiée
+- Cotisation: simplifiée
attache: Salariat . CDD
non applicable si:
l'une de ces conditions:
@@ -14,7 +14,7 @@
assiette: salaire de base
taux: 10%
# prorata: congés non pris / 25
- prorata: 0.12 # 3/25
+ # prorata: 0.12 # 3/25
#
# - description: Méthode "maintien du salaire"
# note: Cette méthode sera le plus souvent favorable au salarié lorsque celui-ci a bénéficié d’une augmentation de salaire.
@@ -27,7 +27,7 @@
# # Comment ?
# # mensuel / nombre moyen de jours ouvrés par an
- - 789
+ - 80
notes: |
diff --git a/source/.eslintrc b/source/.eslintrc
index 5b700a975..098dedeef 100644
--- a/source/.eslintrc
+++ b/source/.eslintrc
@@ -12,7 +12,7 @@ rules:
no-console: 1
no-global-assign: 0
no-unsafe-negation: 0
- no-undef: 0
+ no-undef: 1
parser: babel-eslint
diff --git a/source/components/CDD.js b/source/components/CDD.js
index 252303ba5..dc70df262 100644
--- a/source/components/CDD.js
+++ b/source/components/CDD.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, {Component} from 'react'
import './CDD.css'
import IntroCDD from './IntroCDD'
import Results from './Results'
@@ -8,43 +8,42 @@ import './conversation/conversation.css'
import {START_CONVERSATION} from '../actions'
import Aide from './Aide'
-
let situationSelector = formValueSelector('conversation')
-@reduxForm(
- {form: 'conversation', destroyOnUnmount: false}
-)
-@connect(state => ({
+@reduxForm({form: 'conversation', destroyOnUnmount: false})
+@connect(
+ state => ({
situation: variableName => situationSelector(state, variableName),
steps: state.steps,
themeColours: state.themeColours,
- analysedSituation: state.analysedSituation
-}), dispatch => ({
- startConversation: () => dispatch({type: START_CONVERSATION})
-}))
+ analysedSituation: state.analysedSituation,
+}),
+ dispatch => ({
+ startConversation: () => dispatch({type: START_CONVERSATION}),
+}),
+)
export default class CDD extends Component {
componentDidMount() {
this.props.startConversation()
}
render() {
-
let {steps} = this.props
- let conversation = steps.map(step =>
-
- )
+ let conversation = steps.map(step => (
+
+ ))
return (
-
+
)
}
}
diff --git a/source/components/Rule.css b/source/components/Rule.css
index 041ee4064..2bdd3b1a6 100644
--- a/source/components/Rule.css
+++ b/source/components/Rule.css
@@ -85,14 +85,12 @@
border: 1px solid black;
background: #d5911a
}
-.expression {
+.mecanism li {
+ margin-bottom: .6em;
}
-.expression > div > .name {
- padding: 0 1em;
- border: 1px solid black;
- background: #6666ea;
-}
+
+
#rule-rules .value {
padding-left: 1em;
font-weight: bold;
@@ -111,6 +109,12 @@
background: #6666ea;
}
+.comparison .name {
+ padding: 0 1em;
+ border: 1px solid black;
+ background: #407ee7;
+}
+
.rate .name {
padding: 0 1em;
border: 1px solid black;
@@ -123,3 +127,7 @@
vertical-align: sub;
display: block;
}
+
+.json {
+ font-size: 60%;
+}
diff --git a/source/components/Rule.js b/source/components/Rule.js
index b5aafecb5..489333b66 100644
--- a/source/components/Rule.js
+++ b/source/components/Rule.js
@@ -14,9 +14,9 @@ let testingSituationGate = v => R.path(v.split('.'))(
"Salariat ":{
" CDD ":{
" événements": "_",
- " motif":"usage",
+ " motif":"saisonnier",
" engagement employeur complément formation":"non",
- " durée contrat":"2"
+ " durée contrat": 2
},
" contrat aidé":"non",
" salaire de base": 1481,
@@ -118,9 +118,6 @@ let RuleProp = ({nodeValue, explanation, name}) =>
{
explanation.category == 'mecanism' &&
}
- {
- explanation.category == 'expression' &&
- }
let Mecanism = ({nodeValue, name, explanation}) =>
@@ -131,9 +128,12 @@ let Mecanism = ({nodeValue, name, explanation}) =>
{R.contains(name)(["l'une de ces conditions", 'toutes ces conditions']) &&
- {explanation.map(item => -
- {item.category == 'expression' ?
- :
+ {explanation.map(item =>
-
+ {item.category == 'variable' ?
+
+ : item.category == 'comparison' ?
+
+ :
}
)}
@@ -166,22 +166,25 @@ let Variable = ({nodeValue, variableName}) =>
+let Comparison = ({nodeValue, text}) =>
+
+ {text}
+
+
+
+
+
+
+
+
let Percentage = ({percentage}) =>
{percentage}
-let Expression = ({nodeValue, expression}) =>
-
let NodeValue = ({data}) => do {
- console.log('NodeValue', data)
let valeur = data == null ?
'?'
: ( R.is(Number)(data) ?
@@ -203,13 +206,17 @@ let Formula = ({explanation, nodeValue}) => do {
}
-let JSONView = ({o, rootKey}) =>
- ''}
- theme={theme}
- hideRoot={true}
- shouldExpandNode={() => true}
- data={rootKey ? {[rootKey]: o} : o} />
+let JSONView = ({o, rootKey}) => (
+
+ ''}
+ theme={theme}
+ hideRoot={true}
+ shouldExpandNode={() => true}
+ data={rootKey ? {[rootKey]: o} : o}
+ />
+
+)
diff --git a/source/engine/expressions.js b/source/engine/expressions.js
index f853dd45c..f89244bfd 100644
--- a/source/engine/expressions.js
+++ b/source/engine/expressions.js
@@ -120,7 +120,11 @@ export let knownVariable = (situationGate, variableName) =>
|| situationGate(parentName(variableName)) != null
// pour 'usage', 'motif' ( le parent de 'usage') = 'usage'
+export let evaluateVariable = (situationGate, variableName) => {
+ let value = situationGate(variableName)
-export let evaluateVariable = (situationGate, variableName) => //console.log('variableName', variableName, situationGate(parentName(variableName))) ||
- situationGate(variableName) == 'oui'
-|| situationGate(parentName(variableName)) == nameLeaf(variableName)
+ return R.is(Number)(value)
+ ? value
+ : value == 'oui' ||
+ situationGate(parentName(variableName)) == nameLeaf(variableName)
+}
diff --git a/source/engine/grammar.ne b/source/engine/grammar.ne
index 509423abd..09c810764 100644
--- a/source/engine/grammar.ne
+++ b/source/engine/grammar.ne
@@ -1,25 +1,28 @@
-@{% function buildNode(type, d){return ({nodeType: type, explanation: d})} %}
-
main ->
CalcExpression {% id %}
| Variable {% id %}
| ModifiedVariable {% id %}
| Comparison {% id %}
-Comparison -> Comparable _ ComparisonOperator _ Comparable {% d => ({nodeType: 'Comparison', operator: d[2][0], explanation: [d[0], d[4]]}) %}
+Comparison -> Comparable _ ComparisonOperator _ Comparable {% d => ({
+ category: 'comparison',
+ type: 'boolean',
+ operator: d[2][0],
+ explanation: [d[0], d[4]]
+}) %}
Comparable -> (int | CalcExpression | Variable) {% d => d[0][0] %}
ComparisonOperator -> ">" | "<" | ">=" | "<=" | "="
-ModifiedVariable -> Variable _ Modifier {% d => ({nodeType: 'ModifiedVariable', modifier: d[2], variable: d[0] }) %}
+ModifiedVariable -> Variable _ Modifier {% d => ({category: 'modifiedVariable', modifier: d[2], variable: d[0] }) %}
Modifier -> "[" TemporalModifier "]" {% d =>d[1][0] %}
TemporalModifier -> "annuel" | "mensuel" | "jour ouvré" {% id %}
CalcExpression -> Term _ ArithmeticOperator _ Term {% d => ({
- nodeType: 'CalcExpression',
+ category: 'calcExpression',
operator: d[2],
explanation: [d[0], d[4]],
type: 'numeric'
@@ -38,7 +41,7 @@ ArithmeticOperator -> "+" {% id %}
Variable -> VariableFragment (_ Dot _ VariableFragment {% d => d[3] %}):* {% d => ({
- nodeType: 'Variable',
+ category: 'variable',
fragments: [d[0], ...d[1]],
type: 'numeric | boolean'
}) %}
@@ -54,4 +57,4 @@ Dot -> [\.] {% d => null %}
_ -> [\s] {% d => null %}
-int -> [0-9]:+ {% d => ({nodeType: 'value', value: d[0].join("")}) %}
+int -> [0-9]:+ {% d => ({category: 'value', nodeValue: +d[0].join("")}) %}
diff --git a/source/engine/traverse.js b/source/engine/traverse.js
index 7cf3e2c34..802ab8fe3 100644
--- a/source/engine/traverse.js
+++ b/source/engine/traverse.js
@@ -7,7 +7,6 @@ import Grammar from './grammar.ne'
let nearley = () => new Parser(Grammar.ParserRules, Grammar.ParserStart)
-console.log('a', nearley().feed('allez on essaie plusieurs combinaisons accentuées'))
/*
Dans ce fichier, les règles YAML sont parsées.
Elles expriment un langage orienté expression, les expressions étant
@@ -23,8 +22,8 @@ let selectedRules = rules.filter(rule =>
[
'CIF CDD',
'fin de contrat',
- // 'majoration chômage CDD',
- // 'Indemnité compensatrice congés payés simplifiée'
+ 'majoration chômage CDD',
+ 'simplifiée'
]
)
)
@@ -63,6 +62,25 @@ par exemple ainsi : https://github.com/Engelberg/instaparse#transforming-the-tre
*/
+let fillVariableNode = (rule, situationGate) => (parseResult) => {
+ let
+ {fragments} = parseResult,
+ variablePartialName = fragments.join(' . '),
+ variableName = completeVariableName(rule, variablePartialName),
+ known = knownVariable(situationGate, variableName),
+ nodeValue = !known ? null : evaluateVariable(situationGate, variableName)
+
+ return {
+ nodeValue,
+ category: 'variable',
+ fragments: fragments,
+ variableName,
+ type: 'boolean | numeric',
+ explanation: null,
+ missingVariables: known ? [] : [variableName]
+ }
+}
+
let treat = (situationGate, rule) => rawNode => {
if (R.is(String)(rawNode)) {
@@ -72,45 +90,47 @@ let treat = (situationGate, rule) => rawNode => {
Cet objet est alors rebalancé à 'treat'.
*/
- let [parseResults, ...additionnalResults] = nearley().feed(rawNode).results
+ let [parseResult, ...additionnalResults] = nearley().feed(rawNode).results
if (additionnalResults && additionnalResults.length > 0) throw "Attention ! L'expression <" + rawNode + '> ne peut être traitée de façon univoque'
- if (!R.contains(parseResults.nodeType)(['Variable', 'CalcExpression', 'ModifiedVariable', 'Comparison']))
+ if (!R.contains(parseResult.category)(['variable', 'calcExpression', 'modifiedVariable', 'comparison']))
throw "Attention ! Erreur de traitement de l'expression : " + rawNode
- if (parseResults.nodeType == 'Variable') {
+ if (parseResult.category == 'variable')
+ return fillVariableNode(rule, situationGate)(parseResult, rawNode)
+
+ if (parseResult.category == 'comparison') {
let
- variablePartialName = parseResults.fragments.join(' . '),
- variableName = completeVariableName(rule, variablePartialName),
- known = knownVariable(situationGate, variableName)
- debugger
+ // variablePartialName = parseResult.fragments.join(' . '),
+ // variableName = completeVariableName(rule, variablePartialName),
+ // known = knownVariable(situationGate, variableName)
+ filledExplanation = parseResult.explanation.map(
+ R.when(R.propEq('category', 'variable'), fillVariableNode(rule, situationGate))
+ ),
+ [{nodeValue: value1}, {nodeValue: value2}] = filledExplanation,
+ comparatorFunctionName = {
+ '<': 'lt',
+ '<=': 'lte',
+ '>': 'gt',
+ '>=': 'gte'
+ //TODO '='
+ }[parseResult.operator],
+ comparatorFunction = R[comparatorFunctionName],
+ nodeValue = value1 == null || value2 == null ?
+ null
+ : comparatorFunction(value1, value2)
+
+
return {
- expression: rawNode,
- nodeValue: !known ? null : evaluateVariable(situationGate, variableName),
- category: 'expression',
- type: 'boolean | numeric',
- explanation: null,
- missingVariables: known ? [] : [variableName]
+ text: rawNode,
+ nodeValue: nodeValue,
+ category: 'comparison',
+ type: 'boolean',
+ explanation: filledExplanation
}
}
- // if (parseResults.nodeType == 'CalcExpression') {
- //
- // let
- // variablePartialName = parseResults.fragments.join(' . '),
- // variableName = completeVariableName(rule, variablePartialName),
- // known = knownVariable(situationGate, variableName)
- //
- // return {
- // expression: rawNode,
- // nodeValue: situationGate(baseVariableName),
- // category: 'expression',
- // type: 'boolean | numeric',
- // explanation: null,
- // missingVariables: known ? [] : [variableName]
- // }
- // }
}
//TODO C'est pas bien ça. Devrait être traité par le parser plus haut !
@@ -123,7 +143,6 @@ let treat = (situationGate, rule) => rawNode => {
}
if (!R.is(Object)(rawNode)) {
- console.log('This node : ', rawNode)
throw ' should be string or object'
}
@@ -195,15 +214,15 @@ let treat = (situationGate, rule) => rawNode => {
),
R.toPairs,
R.reduce( (memo, [condition, consequence]) => {
- let {nodeValue, explanation} = memo,
- [variableName, evaluation] = recognizeExpression(rule, condition),
+ let
+ {nodeValue, explanation} = memo,
+ conditionNode = treat(situationGate, rule)(condition), // can be a 'comparison', a 'variable', TODO a 'negation'
childNumericalLogic = treatNumericalLogicRec(consequence),
- known = knownVariable(situationGate, variableName),
- nextNodeValue = !known ?
+ nextNodeValue = conditionNode.nodeValue == null ?
// Si la proposition n'est pas encore résolvable
null
// Si la proposition est résolvable
- : evaluation(situationGate) ?
+ : conditionNode.nodeValue == true ?
// Si elle est vraie
childNumericalLogic.nodeValue
// Si elle est fausse
@@ -215,16 +234,15 @@ let treat = (situationGate, rule) => rawNode => {
: nodeValue !== false ?
nodeValue // l'une des propositions renvoie déjà une valeur numérique donc différente de false
: nextNodeValue,
- // condition: condition,
explanation: [...explanation, {
nodeValue: nextNodeValue,
category: 'condition',
- condition,
- conditionValue: evaluation(situationGate),
+ text: condition,
+ condition: conditionNode,
+ conditionValue: conditionNode.nodeValue,
type: 'boolean',
explanation: childNumericalLogic
}],
- missingVariables: known ? [] : [variableName]
}
}, {
nodeValue: false,
@@ -262,17 +280,25 @@ let treat = (situationGate, rule) => rawNode => {
}
if (k === 'multiplication') {
+
let base = v['assiette'],
parsed = nearley().feed(base),
- baseVariableFound = parsed.results[0].nodeType == 'Variable',
- variablePartialName = baseVariableFound && parsed.results[0].fragments.join(' . '),
+ baseVariableFound = parsed.results[0].category == 'variable'
+ if (!baseVariableFound) throw "L'assiette d'une multiplication doit pour le moment être une variable"
+
+ let
+ variablePartialName = parsed.results[0].fragments.join(' . '),
baseVariableName = completeVariableName(rule, variablePartialName),
baseValue = situationGate(baseVariableName),
rateNode = treat(situationGate, rule)({taux: v['taux']}),
rate = rateNode.nodeValue
return {
- nodeValue: ((baseValue && rate) || null) && +baseValue * rate, // null * 6 = 0 :-o
+ nodeValue: (rate === 0 || rate === false || baseValue === 0) ?
+ 0
+ : (rate == null || baseValue == null) ?
+ null
+ : +baseValue * rate,
category: 'mecanism',
name: 'multiplication',
type: 'numeric',
@@ -309,7 +335,6 @@ let treat = (situationGate, rule) => rawNode => {
}
}
- console.log('rawNode', rawNode)
throw "Le mécanisme qui vient d'être loggué est inconnu !"
}