💚 corrige pour faire passer les tests de non regression
parent
553eef41e8
commit
e8722a46bc
|
@ -13,7 +13,7 @@ import { RootState } from 'Reducers/rootReducer'
|
|||
import './Notifications.css'
|
||||
import { Markdown } from './utils/markdown'
|
||||
import { ScrollToElement } from './utils/Scroll'
|
||||
import Engine, { EvaluatedRule, ASTNode } from 'publicodes'
|
||||
import Engine, { EvaluatedRule, ASTNode, evaluateRule } from 'publicodes'
|
||||
|
||||
// To add a new notification to a simulator, you should create a publicode rule
|
||||
// with the "type: notification" attribute. The display can be customized with
|
||||
|
@ -30,9 +30,8 @@ export function getNotifications(engine: Engine) {
|
|||
(rule: ASTNode & { nodeKind: 'rule' }) =>
|
||||
rule.rawNode['type'] === 'notification'
|
||||
)
|
||||
.map(node => engine.evaluateNode(node))
|
||||
.map(node => evaluateRule(engine, node.dottedName))
|
||||
.filter(node => !!node.nodeValue)
|
||||
.map(node => node.rawNode)
|
||||
}
|
||||
export default function Notifications() {
|
||||
const { t } = useTranslation()
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import { formatValue } from 'publicodes'
|
||||
import { Evaluation } from 'publicodes/dist/types/AST/types'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { debounce as debounceFn } from '../utils'
|
||||
import { InputCommonProps } from './conversation/RuleInput'
|
||||
import './PercentageField.css'
|
||||
|
||||
type PercentageFieldProps = InputCommonProps & { debounce: number }
|
||||
type PercentageFieldProps = InputCommonProps & {
|
||||
debounce: number
|
||||
value: Evaluation<string>
|
||||
}
|
||||
|
||||
export default function PercentageField({
|
||||
onChange,
|
||||
|
|
|
@ -100,7 +100,8 @@ const Target = ({ dottedName }: TargetProps) => {
|
|||
[target.dottedName, dispatch]
|
||||
)
|
||||
|
||||
const isSmallTarget = !!target.question !== !!target.formule
|
||||
const isSmallTarget =
|
||||
!target.question || !!target.question !== !!target.formule
|
||||
if (
|
||||
target.nodeValue === false ||
|
||||
(isSmallTarget && !target.question && !target.nodeValue)
|
||||
|
|
|
@ -85,7 +85,6 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
|
|||
<fieldset>
|
||||
<RuleInput
|
||||
dottedName={currentQuestion}
|
||||
value={situation[currentQuestion]}
|
||||
onChange={onChange}
|
||||
onSubmit={submit}
|
||||
/>
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import { RuleInputProps } from 'Components/conversation/RuleInput'
|
||||
import {
|
||||
InputCommonProps,
|
||||
RuleInputProps
|
||||
} from 'Components/conversation/RuleInput'
|
||||
import { EvaluatedRule } from 'publicodes'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import InputSuggestions from './InputSuggestions'
|
||||
|
||||
type DateInputProps = {
|
||||
onChange: RuleInputProps['onChange']
|
||||
id: RuleInputProps['id']
|
||||
onChange: InputCommonProps['onChange']
|
||||
id: InputCommonProps['id']
|
||||
onSubmit: RuleInputProps['onSubmit']
|
||||
value: RuleInputProps['value']
|
||||
value: InputCommonProps['value']
|
||||
suggestions: EvaluatedRule['suggestions']
|
||||
}
|
||||
|
||||
|
@ -28,7 +31,7 @@ export default function DateInput({
|
|||
const handleDateChange = useCallback(
|
||||
evt => {
|
||||
if (!evt.target.value) {
|
||||
return onChange(null)
|
||||
return
|
||||
}
|
||||
const [year, month, day] = evt.target.value.split('-')
|
||||
if (+year < 1700) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { formatValue } from 'publicodes'
|
||||
import { Unit } from 'publicodes/dist/types/AST/types'
|
||||
import { Evaluation, Unit } from 'publicodes/dist/types/AST/types'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import NumberFormat from 'react-number-format'
|
||||
|
@ -21,6 +21,7 @@ export default function Input({
|
|||
}: InputCommonProps & {
|
||||
onSubmit: (source: string) => void
|
||||
unit: Unit | undefined
|
||||
value: Evaluation<number>
|
||||
}) {
|
||||
const debouncedOnChange = useCallback(debounce(550, onChange), [])
|
||||
const { language } = useTranslation().i18n
|
||||
|
@ -43,7 +44,6 @@ export default function Input({
|
|||
autoFocus={autoFocus}
|
||||
className="suffixed ui__"
|
||||
id={id}
|
||||
placeholder={missing && value}
|
||||
thousandSeparator={thousandSeparator}
|
||||
decimalSeparator={decimalSeparator}
|
||||
allowEmptyFormatting={true}
|
||||
|
@ -54,8 +54,8 @@ export default function Input({
|
|||
debouncedOnChange({ valeur: floatValue, unité })
|
||||
}
|
||||
}}
|
||||
value={!missing && value}
|
||||
autoComplete="off"
|
||||
{...{ [missing ? 'placeholder' : 'value']: value || '' }}
|
||||
/>
|
||||
<span className="suffix"> {unité}</span>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Evaluation } from 'publicodes/dist/types/AST/types'
|
||||
import { useCallback } from 'react'
|
||||
import { debounce } from '../../utils'
|
||||
import { InputCommonProps } from './RuleInput'
|
||||
|
@ -8,7 +9,7 @@ export default function ParagrapheInput({
|
|||
id,
|
||||
missing,
|
||||
autoFocus
|
||||
}: InputCommonProps) {
|
||||
}: InputCommonProps & { value: Evaluation<string> }) {
|
||||
const debouncedOnChange = useCallback(debounce(1000, onChange), [])
|
||||
|
||||
return (
|
||||
|
@ -19,11 +20,14 @@ export default function ParagrapheInput({
|
|||
rows={6}
|
||||
style={{ resize: 'none' }}
|
||||
id={id}
|
||||
placeholder={missing && value?.replace('\\n', '\n')}
|
||||
onChange={({ target }) => {
|
||||
debouncedOnChange(`'${target.value.replace(/\n/g, '\\n')}'`)
|
||||
}}
|
||||
defaultValue={!missing && value?.replace('\\n', '\n')}
|
||||
{...{
|
||||
[missing ? 'placeholder' : 'defaultValue']: (
|
||||
(value as string) || ''
|
||||
).replace('\\n', '\n')
|
||||
}}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
ParsedRules,
|
||||
reduceAST,
|
||||
} from 'publicodes'
|
||||
import { Evaluation } from 'publicodes/dist/types/AST/types'
|
||||
import React, { useContext } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { DottedName } from 'Rules'
|
||||
|
@ -29,18 +30,18 @@ export type RuleInputProps<Name extends string = DottedName> = {
|
|||
isTarget?: boolean
|
||||
autoFocus?: boolean
|
||||
id?: string
|
||||
value: Value
|
||||
className?: string
|
||||
onSubmit?: (source: string) => void
|
||||
}
|
||||
|
||||
export type InputCommonProps<Name extends string = string> = Pick<
|
||||
RuleInputProps<Name>,
|
||||
'dottedName' | 'value' | 'onChange' | 'autoFocus' | 'className'
|
||||
'dottedName' | 'onChange' | 'autoFocus' | 'className'
|
||||
> &
|
||||
Pick<EvaluatedRule<Name>, 'title' | 'question' | 'suggestions'> & {
|
||||
key: string
|
||||
id: string
|
||||
value: any //TODO EvaluatedRule['nodeValue']
|
||||
missing: boolean
|
||||
required: boolean
|
||||
}
|
||||
|
@ -161,13 +162,22 @@ export default function RuleInput<Name extends string = DottedName>({
|
|||
}
|
||||
|
||||
if (rule.type === 'texte') {
|
||||
return <TextInput {...commonProps} />
|
||||
return <TextInput {...commonProps} value={value as Evaluation<string>} />
|
||||
}
|
||||
if (rule.type === 'paragraphe') {
|
||||
return <ParagrapheInput {...commonProps} />
|
||||
return (
|
||||
<ParagrapheInput {...commonProps} value={value as Evaluation<string>} />
|
||||
)
|
||||
}
|
||||
|
||||
return <Input {...commonProps} onSubmit={onSubmit} unit={rule.unit} />
|
||||
return (
|
||||
<Input
|
||||
{...commonProps}
|
||||
onSubmit={onSubmit}
|
||||
unit={rule.unit}
|
||||
value={value as Evaluation<number>}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const getVariant = (node: ASTNode & { nodeKind: 'rule' }) =>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Evaluation } from 'publicodes/dist/types/AST/types'
|
||||
import { useCallback } from 'react'
|
||||
import { debounce } from '../../utils'
|
||||
import { InputCommonProps } from './RuleInput'
|
||||
|
@ -8,7 +9,7 @@ export default function TextInput({
|
|||
id,
|
||||
missing,
|
||||
autoFocus
|
||||
}: InputCommonProps) {
|
||||
}: InputCommonProps & { value: Evaluation<string> }) {
|
||||
const debouncedOnChange = useCallback(debounce(1000, onChange), [])
|
||||
|
||||
return (
|
||||
|
@ -18,11 +19,12 @@ export default function TextInput({
|
|||
className="ui__"
|
||||
type="text"
|
||||
id={id}
|
||||
placeholder={missing && value}
|
||||
onChange={({ target }) => {
|
||||
debouncedOnChange(`'${target.value}'`)
|
||||
}}
|
||||
defaultValue={!missing && value}
|
||||
{...{
|
||||
[missing ? 'placeholder' : 'defaultValue']: (value as string) || ''
|
||||
}}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -91,7 +91,7 @@ export default function Select({ onChange, value, id }: InputCommonProps) {
|
|||
try {
|
||||
taux = await tauxVersementTransport(commune.code)
|
||||
} catch (error) {
|
||||
console.log(
|
||||
console.warn(
|
||||
'Erreur dans la récupération du taux de versement transport à partir du code commune',
|
||||
error
|
||||
)
|
||||
|
|
|
@ -133,7 +133,7 @@ export default function Select(props) {
|
|||
.then(json => setOptions(json))
|
||||
.catch(
|
||||
error =>
|
||||
console.log('Erreur dans la récupération des codes risques', error) // eslint-disable-line no-console
|
||||
console.warn('Erreur dans la récupération des codes risques', error) // eslint-disable-line no-console
|
||||
)
|
||||
}, [])
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
import { createContext } from 'react'
|
||||
export const IsEmbeddedContext = createContext(false)
|
||||
import { createContext } from 'react';
|
||||
export const IsEmbeddedContext = createContext(false);
|
||||
|
|
|
@ -91,6 +91,7 @@ export function getNextQuestions(
|
|||
liste: whitelist = [],
|
||||
'liste noire': blacklist = []
|
||||
} = questionConfig
|
||||
|
||||
let nextSteps = difference(getNextSteps(missingVariables), answeredQuestions)
|
||||
nextSteps = nextSteps.filter(
|
||||
step =>
|
||||
|
|
|
@ -883,30 +883,12 @@ contrat salarié . CSG et CRDS . revenus de remplacement:
|
|||
contrat salarié . CSG et CRDS . revenus de remplacement . CRDS:
|
||||
titre.en: '[automatic] CRDS replacement income'
|
||||
titre.fr: CRDS revenus de remplacement
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CRDS . montant:
|
||||
titre.en: '[automatic] DRES'
|
||||
titre.fr: CRDS
|
||||
? contrat salarié . CSG et CRDS . revenus de remplacement . CRDS . rémunération nette
|
||||
: titre.en: '[automatic] take-home pay'
|
||||
titre.fr: rémunération nette
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG déductible:
|
||||
titre.en: '[automatic] Deductible MSA replacement income'
|
||||
titre.fr: CSG déductible revenus de remplacement
|
||||
? contrat salarié . CSG et CRDS . revenus de remplacement . CSG déductible . montant
|
||||
: titre.en: '[automatic] deductible MSA'
|
||||
titre.fr: CSG déductible
|
||||
? contrat salarié . CSG et CRDS . revenus de remplacement . CSG déductible . rémunération nette
|
||||
: titre.en: '[automatic] take-home pay'
|
||||
titre.fr: rémunération nette
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG non déductible:
|
||||
titre.en: '[automatic] Non-deductible CSG replacement income'
|
||||
titre.fr: CSG non déductible revenus de remplacement
|
||||
? contrat salarié . CSG et CRDS . revenus de remplacement . CSG non déductible . montant
|
||||
: titre.en: '[automatic] non-deductible MSA'
|
||||
titre.fr: CSG non déductible
|
||||
? contrat salarié . CSG et CRDS . revenus de remplacement . CSG non déductible . rémunération nette
|
||||
: titre.en: '[automatic] take-home pay'
|
||||
titre.fr: rémunération nette
|
||||
contrat salarié . FNAL:
|
||||
description.en:
|
||||
The National Housing Fund (Fnal) is a contribution to ensure the
|
||||
|
@ -1294,16 +1276,13 @@ contrat salarié . apprentissage . ancienneté . moins de deux ans:
|
|||
titre.en: less than two years
|
||||
titre.fr: moins de deux ans
|
||||
contrat salarié . apprentissage . ancienneté . moins de quatre ans:
|
||||
titre.en: less than four years
|
||||
titre.fr: moins de quatre ans
|
||||
? contrat salarié . apprentissage . ancienneté . moins de quatre ans . information
|
||||
: description.en: '[automatic] The maximum duration of the contract may be
|
||||
description.en: '[automatic] The maximum duration of the contract may be
|
||||
extended to 4 years when the apprentice is recognised as a disabled worker.'
|
||||
description.fr:
|
||||
La durée maximale du contrat peut être portée à 4 ans lorsque la
|
||||
qualité de travailleur handicapé est reconnue à l'apprenti.
|
||||
titre.en: '[automatic] information'
|
||||
titre.fr: information
|
||||
titre.en: less than four years
|
||||
titre.fr: moins de quatre ans
|
||||
contrat salarié . apprentissage . ancienneté . moins de trois ans:
|
||||
titre.en: less than three years
|
||||
titre.fr: moins de trois ans
|
||||
|
@ -1471,8 +1450,8 @@ contrat salarié . contribution d'équilibre technique:
|
|||
titre.en: technical equilibrium contribution
|
||||
titre.fr: contribution d'équilibre technique
|
||||
contrat salarié . convention collective:
|
||||
question.en: 'Which "convention collective" is applicable to the company ? [beta] '
|
||||
question.fr: "Quelle convention collective est applicable à l'entreprise ? [beta] "
|
||||
question.en: '[automatic] Which collective agreement is applicable to the company?'
|
||||
question.fr: Quelle convention collective est applicable à l'entreprise ?
|
||||
titre.en: convention collective
|
||||
titre.fr: convention collective
|
||||
contrat salarié . convention collective . BTP:
|
||||
|
@ -1489,22 +1468,36 @@ contrat salarié . convention collective . BTP:
|
|||
contrat salarié . convention collective . BTP . OPPBTP:
|
||||
titre.en: '[automatic] OPPBTP'
|
||||
titre.fr: OPPBTP
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié:
|
||||
contrat salarié . convention collective . BTP . catégorie:
|
||||
question.en: '[automatic] To which category does the employee belong?'
|
||||
question.fr: À quelle catégorie la salarié appartient-t'il ?
|
||||
titre.en: '[automatic] employee category'
|
||||
titre.fr: catégorie du salarié
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié . cadre:
|
||||
titre.en: '[automatic] category'
|
||||
titre.fr: catégorie
|
||||
contrat salarié . convention collective . BTP . catégorie . cadre:
|
||||
titre.en: '[automatic] Framework'
|
||||
titre.fr: Cadre
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié . etam:
|
||||
description.en: '[automatic] Employee, technician, master angent'
|
||||
? contrat salarié . convention collective . BTP . catégorie . cadre . prévoyance complémentaire
|
||||
: titre.en: '[automatic] supplementary pension'
|
||||
titre.fr: prévoyance complémentaire
|
||||
contrat salarié . convention collective . BTP . catégorie . etam:
|
||||
description.en: '[automatic] Employee, technician, master angel'
|
||||
description.fr: Employé, technicien, angent de maîtrise
|
||||
note.en: '[automatic] Conventional distribution fixed by Article 5 of the
|
||||
Building and Public Works Agreement of 13 December 1990.'
|
||||
note.fr:
|
||||
Répartition conventionnelle fixée par l’article 5 de l’Accord du BTP du
|
||||
13 décembre 1990.
|
||||
titre.en: '[automatic] ETAM'
|
||||
titre.fr: ETAM
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié . ouvrier:
|
||||
? contrat salarié . convention collective . BTP . catégorie . etam . prévoyance complémentaire
|
||||
: titre.en: '[automatic] supplementary pension'
|
||||
titre.fr: prévoyance complémentaire
|
||||
contrat salarié . convention collective . BTP . catégorie . ouvrier:
|
||||
titre.en: '[automatic] Worker'
|
||||
titre.fr: Ouvrier
|
||||
? contrat salarié . convention collective . BTP . catégorie . ouvrier . prévoyance complémentaire
|
||||
: titre.en: '[automatic] supplementary pension'
|
||||
titre.fr: prévoyance complémentaire
|
||||
contrat salarié . convention collective . BTP . congés intempéries:
|
||||
titre.en: '[automatic] bad weather'
|
||||
titre.fr: congés intempéries
|
||||
|
@ -1546,30 +1539,6 @@ contrat salarié . convention collective . BTP . congés intempéries:
|
|||
contrat salarié . convention collective . BTP . cotisations conventionnelles:
|
||||
titre.en: '[automatic] conventional contributions'
|
||||
titre.fr: cotisations conventionnelles
|
||||
contrat salarié . convention collective . BTP . prévoyance complémentaire:
|
||||
titre.en: '[automatic] complementary providence'
|
||||
titre.fr: prévoyance complémentaire
|
||||
? contrat salarié . convention collective . BTP . prévoyance complémentaire . cadre
|
||||
: titre.en: '[automatic] framework'
|
||||
titre.fr: cadre
|
||||
? contrat salarié . convention collective . BTP . prévoyance complémentaire . etam
|
||||
: titre.en: '[automatic] etam'
|
||||
titre.fr: etam
|
||||
? contrat salarié . convention collective . BTP . prévoyance complémentaire . ouvrier
|
||||
: titre.en: '[automatic] worker'
|
||||
titre.fr: ouvrier
|
||||
contrat salarié . convention collective . BTP . retraite complémentaire:
|
||||
titre.en: '[automatic] retirement supplement'
|
||||
titre.fr: retraite complémentaire
|
||||
contrat salarié . convention collective . BTP . retraite complémentaire . etam:
|
||||
description.en:
|
||||
'[automatic] Conventional distribution fixed by Article 5 of the
|
||||
Building and Public Works Agreement of 13 December 1990.'
|
||||
description.fr:
|
||||
Répartition conventionnelle fixée par l’article 5 de l’Accord du
|
||||
BTP du 13 décembre 1990.
|
||||
titre.en: '[automatic] etam'
|
||||
titre.fr: etam
|
||||
contrat salarié . convention collective . HCR:
|
||||
description.en: The company is a hotel, café, restaurant or similar.
|
||||
description.fr: L'entreprise est un hôtel, café, restaurant ou assimilé.
|
||||
|
@ -2183,6 +2152,11 @@ contrat salarié . frais professionnels . titres-restaurant . montant unitaire:
|
|||
suggestions.moyenne.fr: moyenne
|
||||
titre.en: '[automatic] unitary amount'
|
||||
titre.fr: montant unitaire
|
||||
contrat salarié . frais professionnels . titres-restaurant . nombre:
|
||||
question.en: '[automatic] How many meal vouchers are distributed to the employee?'
|
||||
question.fr: Combien de titres-restaurant sont distribués au salarié ?
|
||||
titre.en: '[automatic] number'
|
||||
titre.fr: nombre
|
||||
contrat salarié . frais professionnels . titres-restaurant . part déductible:
|
||||
titre.en: '[automatic] Restaurant vouchers (deductible)'
|
||||
titre.fr: Titres-restaurant (déductible)
|
||||
|
@ -2201,11 +2175,6 @@ contrat salarié . frais professionnels . titres-restaurant . part déductible:
|
|||
suggestions.60%.fr: 60%
|
||||
titre.en: '[automatic] employer contribution rate'
|
||||
titre.fr: taux participation employeur
|
||||
? contrat salarié . frais professionnels . titres-restaurant . titres-restaurant par mois
|
||||
: question.en: '[automatic] How many meal vouchers are distributed to the employee?'
|
||||
question.fr: Combien de titres-restaurant sont distribués au salarié ?
|
||||
titre.en: '[automatic] meal vouchers per month'
|
||||
titre.fr: titres-restaurant par mois
|
||||
contrat salarié . intermittents du spectacle:
|
||||
question.en: To which "intermittent" status is the employee attached?
|
||||
question.fr: A quel statut d'intermittent est rattaché l'employé ?
|
||||
|
@ -2668,9 +2637,6 @@ contrat salarié . professionnalisation:
|
|||
contrat salarié . prévoyance:
|
||||
titre.en: '[automatic] foresight'
|
||||
titre.fr: prévoyance
|
||||
contrat salarié . prévoyance . employeur:
|
||||
titre.en: '[automatic] employer'
|
||||
titre.fr: employeur
|
||||
contrat salarié . prévoyance . exonération fiscale:
|
||||
titre.en: '[automatic] tax-exempt pension'
|
||||
titre.fr: prévoyance exonérée d'impôt
|
||||
|
@ -2680,9 +2646,6 @@ contrat salarié . prévoyance . part déductible:
|
|||
contrat salarié . prévoyance . plafond exonération sociale employeur:
|
||||
titre.en: "[automatic] ceiling employer's social security exemption"
|
||||
titre.fr: plafond exonération sociale employeur
|
||||
contrat salarié . prévoyance . salarié:
|
||||
titre.en: '[automatic] employee'
|
||||
titre.fr: salarié
|
||||
contrat salarié . prévoyance obligatoire cadre:
|
||||
titre.en: mandatory life insurance for "cadres"
|
||||
titre.fr: Prévoyance obligatoire pour les cadres
|
||||
|
@ -2697,9 +2660,6 @@ contrat salarié . retraite complémentaire:
|
|||
contrat salarié . retraite supplémentaire:
|
||||
titre.en: '[automatic] additional pension'
|
||||
titre.fr: retraite supplémentaire
|
||||
contrat salarié . retraite supplémentaire . employeur:
|
||||
titre.en: '[automatic] Employer Supplementary Retirement'
|
||||
titre.fr: Retraite supplémentaire employeur
|
||||
contrat salarié . retraite supplémentaire . exonération fiscale:
|
||||
titre.en: '[automatic] tax-exempt supplementary pension'
|
||||
titre.fr: retraite supplémentaire exonérée d'impôt
|
||||
|
@ -2709,9 +2669,6 @@ contrat salarié . retraite supplémentaire . part déductible:
|
|||
? contrat salarié . retraite supplémentaire . plafond d'exonération sociale employeur
|
||||
: titre.en: "[automatic] employer's social security ceiling"
|
||||
titre.fr: plafond d'exonération sociale employeur
|
||||
contrat salarié . retraite supplémentaire . salarié:
|
||||
titre.en: '[automatic] employee'
|
||||
titre.fr: salarié
|
||||
contrat salarié . réduction générale:
|
||||
description.en: >
|
||||
[automatic] Within the framework of the responsibility and solidarity pact,
|
||||
|
@ -3157,9 +3114,6 @@ contrat salarié . rémunération . net imposable . base:
|
|||
? contrat salarié . rémunération . net imposable . heures supplémentaires et complémentaires défiscalisées
|
||||
: titre.en: tax-free overtime hours
|
||||
titre.fr: heures supplémentaires et complémentaires défiscalisées
|
||||
? contrat salarié . rémunération . net imposable . heures supplémentaires et complémentaires défiscalisées . plafond brut
|
||||
: titre.en: gross cap
|
||||
titre.fr: plafond brut
|
||||
contrat salarié . rémunération . primes:
|
||||
description.en: |
|
||||
contrat de travail, de la convention collective, d'un usage d'entreprise, ou
|
||||
|
@ -5191,6 +5145,9 @@ dirigeant . indépendant . PL . retraite CNAVPL:
|
|||
existantes (CIPAV, CARPIMKO, CARCDSF, CAVEC etc..)
|
||||
titre.en: '[automatic] basic retirement (CNAVPL)'
|
||||
titre.fr: retraite de base (CNAVPL)
|
||||
dirigeant . indépendant . PL . retraite CNAVPL . remplace:
|
||||
titre.en: '[automatic] basic retirement (CNAVPL)'
|
||||
titre.fr: retraite de base (CNAVPL)
|
||||
dirigeant . indépendant . PL . régime général:
|
||||
description.en: |
|
||||
[automatic] Unregulated liberal professions affiliated to the general scheme
|
||||
|
@ -5403,6 +5360,11 @@ dirigeant . indépendant . conjoint collaborateur . cotisations . assiette:
|
|||
: titre.en: basic retirement
|
||||
titre.fr: retraite de base
|
||||
dirigeant . indépendant . contrats madelin:
|
||||
question.en:
|
||||
'[automatic] Have you subscribed to private complementary contracts
|
||||
("Madelins contracts")'
|
||||
question.fr: Avez-vous souscrit à des contrats de complémentaire privée dits
|
||||
("contrats Madelins")
|
||||
titre.en: Madelin Contracts
|
||||
titre.fr: Contrats Madelin
|
||||
dirigeant . indépendant . contrats madelin . contrôle montant charges:
|
||||
|
@ -5420,20 +5382,20 @@ dirigeant . indépendant . contrats madelin . montant:
|
|||
titre.en: Sum of subscriptions to Madelin contracts
|
||||
titre.fr: Somme des cotisations à contrats Madelin
|
||||
dirigeant . indépendant . contrats madelin . mutuelle:
|
||||
titre.en: Madelin healthcare contract
|
||||
titre.fr: Contrat Madelin mutuelle
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant:
|
||||
description.en: |
|
||||
If you subscribe to a Madelin-law healthcare contract, you can deduct
|
||||
part of the subscriptions from taxable earnings that you declare for a
|
||||
self-employed occupation.
|
||||
description.en: >
|
||||
[automatic] If you contribute under a mutual insurance contract such as the
|
||||
Madelin law,
|
||||
|
||||
you can deduct part of these contributions from your profits; and
|
||||
|
||||
taxable persons that you declare for your self-employed activity.
|
||||
description.fr: |
|
||||
Si vous cotisez au titre d'un contrat de mutuelle de type loi Madelin,
|
||||
vous pouvez déduire une partie de ces cotisations des bénéfices
|
||||
imposables que vous déclarez pour votre activité non salariée.
|
||||
question.en: How much do you subscribe to a Madelin healthcare contract?
|
||||
question.en: '[automatic] How much do you pay to a Madelin Mutual contract?'
|
||||
question.fr: Quel est le montant que vous versez à un contrat de mutuelle Madelin ?
|
||||
titre.en: Subscription to a Madelin healthcare contract
|
||||
titre.en: '[automatic] Subscription to a Madelin mutual insurance contract'
|
||||
titre.fr: Souscription à un contrat de mutuelle Madelin
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . plafond:
|
||||
titre.en: ceiling
|
||||
|
@ -5445,20 +5407,20 @@ dirigeant . indépendant . contrats madelin . part non-déductible fiscalement:
|
|||
titre.en: Part of the Madelin contract subscription which is not fiscally deductible
|
||||
titre.fr: Part de la cotisation à contrat Madelin qui n'est pas déductible fiscalement
|
||||
dirigeant . indépendant . contrats madelin . retraite:
|
||||
titre.en: Madelin pension contract
|
||||
titre.fr: Contrat Madelin retraite
|
||||
dirigeant . indépendant . contrats madelin . retraite . montant:
|
||||
description.en: |
|
||||
If you subscribe to a Madelin-law pension contract, you can deduct
|
||||
part of the subscriptions to taxable earnings that you declare for your
|
||||
self-employed activity.
|
||||
description.en: >
|
||||
[automatic] If you are contributing under a pension contract such as the
|
||||
Madelin law,
|
||||
|
||||
you can deduct part of these contributions from your profits; and
|
||||
|
||||
taxable persons that you declare for your self-employed activity.
|
||||
description.fr: |
|
||||
Si vous cotisez au titre d'un contrat retraite de type loi Madelin,
|
||||
vous pouvez déduire une partie de ces cotisations des bénéfices
|
||||
imposables que vous déclarez pour votre activité non salariée.
|
||||
question.en: How much do you subscribe to a Madelin pension contract?
|
||||
question.en: '[automatic] How much do you pay into your Madelin retraite contract?'
|
||||
question.fr: Quel est le montant que vous versez à votre contrat Madelin retraite ?
|
||||
titre.en: Subscription to a Madelin pension contract
|
||||
titre.en: '[automatic] Madelin Retirement Subscription'
|
||||
titre.fr: Souscription à une retraite Madelin
|
||||
dirigeant . indépendant . contrats madelin . retraite . plafond:
|
||||
titre.en: ceiling
|
||||
|
@ -6077,9 +6039,6 @@ entreprise . catégorie d'activité . libérale règlementée:
|
|||
question.fr: Est-ce une activité libérale règlementée ?
|
||||
titre.en: regulated liberal
|
||||
titre.fr: libérale règlementée
|
||||
? entreprise . catégorie d'activité . libérale règlementée . type d'activité libérale règlementée
|
||||
: titre.en: type of regulated liberal activity
|
||||
titre.fr: type d'activité libérale règlementée
|
||||
entreprise . catégorie d'activité . restauration ou hébergement:
|
||||
description.en: Your profits are classified in BIC - provision of housing or
|
||||
accommodation food.
|
||||
|
@ -6270,9 +6229,6 @@ entreprise . effectif . seuil:
|
|||
question.fr: Quel est l'effectif de l'entreprise ?
|
||||
titre.en: range
|
||||
titre.fr: seuil d'effectif
|
||||
entreprise . effectif . seuil . 251 et plus:
|
||||
titre.en: 251 or more
|
||||
titre.fr: 251 et plus
|
||||
entreprise . effectif . seuil . moins de 11:
|
||||
titre.en: less than 11
|
||||
titre.fr: moins de 11
|
||||
|
@ -6288,6 +6244,9 @@ entreprise . effectif . seuil . moins de 5:
|
|||
entreprise . effectif . seuil . moins de 50:
|
||||
titre.en: less than 50
|
||||
titre.fr: moins de 50
|
||||
entreprise . effectif . seuil . plus de 250:
|
||||
titre.en: '[automatic] 251 and more'
|
||||
titre.fr: 251 et plus
|
||||
entreprise . franchise de TVA:
|
||||
description.en: |
|
||||
[automatic] The VAT exemption is a device that exempts businesses from the
|
||||
|
|
|
@ -8,8 +8,9 @@ contrat salarié . convention collective . BTP:
|
|||
(employés, techniciens et agents de maîtrise) et les cadres.
|
||||
rend non applicable: CDD . compensation pour congés non pris
|
||||
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié:
|
||||
contrat salarié . convention collective . BTP . catégorie:
|
||||
question: À quelle catégorie la salarié appartient-t'il ?
|
||||
par défaut: "'ouvrier'"
|
||||
formule:
|
||||
une possibilité:
|
||||
choix obligatoire: oui
|
||||
|
@ -18,42 +19,30 @@ contrat salarié . convention collective . BTP . catégorie du salarié:
|
|||
- etam
|
||||
- cadre
|
||||
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié . ouvrier:
|
||||
contrat salarié . convention collective . BTP . catégorie . ouvrier:
|
||||
titre: Ouvrier
|
||||
icônes: 👨🔧
|
||||
formule: catégorie = 'ouvrier'
|
||||
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié . etam:
|
||||
contrat salarié . convention collective . BTP . catégorie . ouvrier . prévoyance complémentaire:
|
||||
produit:
|
||||
assiette: rémunération . brut de base
|
||||
plafond: 3 * plafond sécurité sociale
|
||||
composantes:
|
||||
- attributs:
|
||||
nom: employeur
|
||||
remplace: prévoyance . employeur
|
||||
taux: 1.72%
|
||||
- attributs:
|
||||
nom: salarié
|
||||
remplace: prévoyance . salarié
|
||||
taux: 0.87%
|
||||
|
||||
contrat salarié . convention collective . BTP . catégorie . etam:
|
||||
titre: ETAM
|
||||
description: Employé, technicien, angent de maîtrise
|
||||
icônes: 👷♂️
|
||||
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié . cadre:
|
||||
formule: catégorie du salarié = 'cadre'
|
||||
titre: Cadre
|
||||
icônes: 👩💼
|
||||
remplace:
|
||||
- règle: statut cadre
|
||||
par: oui
|
||||
|
||||
contrat salarié . convention collective . BTP . retraite complémentaire:
|
||||
valeur: oui
|
||||
non applicable si: catégorie du salarié = 'etam'
|
||||
remplace:
|
||||
- règle: retraite complémentaire . employeur . taux tranche 1
|
||||
par: 4.72%
|
||||
- règle: retraite complémentaire . employeur . taux tranche 2
|
||||
par: 12.95%
|
||||
- règle: retraite complémentaire . salarié . taux tranche 1
|
||||
par: 3.15%
|
||||
- règle: retraite complémentaire . salarié . taux tranche 2
|
||||
par: 8.64%
|
||||
|
||||
contrat salarié . convention collective . BTP . retraite complémentaire . etam:
|
||||
valeur: oui
|
||||
|
||||
applicable si: catégorie du salarié = 'etam'
|
||||
description: >-
|
||||
Répartition conventionnelle fixée par l’article 5 de l’Accord du BTP du 13 décembre 1990.
|
||||
formule: catégorie = 'etam'
|
||||
remplace:
|
||||
- règle: retraite complémentaire . employeur . taux tranche 1
|
||||
par: 4.47%
|
||||
|
@ -63,73 +52,58 @@ contrat salarié . convention collective . BTP . retraite complémentaire . etam
|
|||
par: 3.40%
|
||||
- règle: retraite complémentaire . salarié . taux tranche 2
|
||||
par: 8.89%
|
||||
note: >-
|
||||
Répartition conventionnelle fixée par l’article 5 de l’Accord du BTP du 13 décembre 1990.
|
||||
|
||||
contrat salarié . convention collective . BTP . prévoyance complémentaire: oui
|
||||
contrat salarié . convention collective . BTP . catégorie . etam . prévoyance complémentaire:
|
||||
produit:
|
||||
assiette: rémunération . brut de base
|
||||
plafond: 3 * plafond sécurité sociale
|
||||
composantes:
|
||||
- attributs:
|
||||
nom: employeur
|
||||
remplace: prévoyance . employeur
|
||||
taux: 1.25%
|
||||
- attributs:
|
||||
nom: salarié
|
||||
remplace: prévoyance . salarié
|
||||
taux: 0.60%
|
||||
|
||||
contrat salarié . convention collective . BTP . prévoyance complémentaire . ouvrier:
|
||||
valeur: oui
|
||||
applicable si: catégorie du salarié = 'ouvrier'
|
||||
contrat salarié . convention collective . BTP . catégorie . cadre:
|
||||
formule: catégorie = 'cadre'
|
||||
titre: Cadre
|
||||
icônes: 👩💼
|
||||
remplace:
|
||||
- règle: prévoyance . employeur
|
||||
par:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
tranches:
|
||||
- taux: 1.72%
|
||||
plafond: 3 * plafond sécurité sociale
|
||||
- règle: prévoyance . salarié
|
||||
par:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
tranches:
|
||||
- taux: 0.87%
|
||||
plafond: 3 * plafond sécurité sociale
|
||||
- règle: statut cadre
|
||||
par: oui
|
||||
|
||||
contrat salarié . convention collective . BTP . prévoyance complémentaire . etam:
|
||||
valeur: oui
|
||||
applicable si: catégorie du salarié = 'etam'
|
||||
remplace:
|
||||
- règle: prévoyance . employeur
|
||||
par:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
tranches:
|
||||
- taux: 1.25%
|
||||
plafond: 3 * plafond sécurité sociale
|
||||
- règle: prévoyance . salarié
|
||||
par:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
tranches:
|
||||
- taux: 0.60%
|
||||
plafond: 3 * plafond sécurité sociale
|
||||
|
||||
contrat salarié . convention collective . BTP . prévoyance complémentaire . cadre:
|
||||
valeur: oui
|
||||
applicable si: catégorie du salarié = 'cadre'
|
||||
remplace:
|
||||
- règle: prévoyance . employeur
|
||||
par:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
tranches:
|
||||
- taux: 1.50%
|
||||
plafond: plafond sécurité sociale
|
||||
- taux: 50% * 2.40%
|
||||
plafond: 4 * plafond sécurité sociale
|
||||
- taux: 50% * 3.60%
|
||||
plafond: 8 * plafond sécurité sociale
|
||||
- règle: prévoyance . salarié
|
||||
par:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
tranches:
|
||||
- taux: 0%
|
||||
plafond: plafond sécurité sociale
|
||||
- taux: 50% * 2.40%
|
||||
plafond: 4 * plafond sécurité sociale
|
||||
- taux: 50% * 3.60%
|
||||
plafond: 8 * plafond sécurité sociale
|
||||
contrat salarié . convention collective . BTP . catégorie . cadre . prévoyance complémentaire:
|
||||
barème:
|
||||
assiette: rémunération . brut de base
|
||||
multiplicateur: plafond sécurité sociale
|
||||
composantes:
|
||||
- attributs:
|
||||
nom: employeur
|
||||
remplace: prévoyance . employeur
|
||||
tranches:
|
||||
- taux: 1.50%
|
||||
plafond: 1
|
||||
- taux: 50% * 2.40%
|
||||
plafond: 4
|
||||
- taux: 50% * 3.60%
|
||||
plafond: 8
|
||||
- attributs:
|
||||
nom: salarié
|
||||
remplace: prévoyance . salarié
|
||||
tranches:
|
||||
- taux: 0%
|
||||
plafond: 1
|
||||
- taux: 50% * 2.40%
|
||||
plafond: 4
|
||||
- taux: 50% * 3.60%
|
||||
plafond: 8
|
||||
|
||||
|
||||
contrat salarié . convention collective . BTP . cotisations conventionnelles:
|
||||
remplace: cotisations . patronales . conventionnelles
|
||||
|
|
|
@ -689,36 +689,34 @@ dirigeant . indépendant . conjoint collaborateur . cotisations:
|
|||
- indemnités journalières maladie
|
||||
|
||||
dirigeant . indépendant . conjoint collaborateur . cotisations . assiette retraite:
|
||||
formule:
|
||||
le maximum de:
|
||||
- cotisations . assiette
|
||||
- 5.25% * plafond sécurité sociale temps plein
|
||||
- 200 heures/an * SMIC horaire
|
||||
arrondi: oui
|
||||
le maximum de:
|
||||
- cotisations . assiette
|
||||
- 5.25% * plafond sécurité sociale temps plein
|
||||
- 200 heures/an * SMIC horaire
|
||||
unité: €/an
|
||||
arrondi: oui
|
||||
|
||||
dirigeant . indépendant . conjoint collaborateur . cotisations . retraite de base:
|
||||
unité: €/an
|
||||
formule:
|
||||
barème:
|
||||
assiette: assiette retraite
|
||||
multiplicateur: plafond sécurité sociale temps plein
|
||||
tranches:
|
||||
- taux: 17.75%
|
||||
plafond: 1
|
||||
- taux: 0.6%
|
||||
arrondi: oui
|
||||
barème:
|
||||
assiette: assiette retraite
|
||||
multiplicateur: plafond sécurité sociale temps plein
|
||||
tranches:
|
||||
- taux: 17.75%
|
||||
plafond: 1
|
||||
- taux: 0.6%
|
||||
arrondi: oui
|
||||
|
||||
dirigeant . indépendant . conjoint collaborateur . cotisations . retraite complémentaire:
|
||||
unité: €/an
|
||||
formule:
|
||||
barème:
|
||||
assiette: retraite complémentaire . assiette
|
||||
tranches:
|
||||
- taux: 7%
|
||||
plafond: cotisations et contributions . retraite complémentaire . plafond
|
||||
- taux: 8%
|
||||
plafond: 4 * plafond sécurité sociale temps plein
|
||||
arrondi: oui
|
||||
barème:
|
||||
assiette: retraite complémentaire . assiette
|
||||
tranches:
|
||||
- taux: 7%
|
||||
plafond: cotisations et contributions . retraite complémentaire . plafond
|
||||
- taux: 8%
|
||||
plafond: 4 * plafond sécurité sociale temps plein
|
||||
arrondi: oui
|
||||
|
||||
dirigeant . indépendant . conjoint collaborateur . cotisations . retraite complémentaire . assiette:
|
||||
titre: assiette retraite complémentaire
|
||||
|
@ -738,20 +736,18 @@ dirigeant . indépendant . conjoint collaborateur . cotisations . invalidité et
|
|||
- 20% * plafond sécurité sociale temps plein
|
||||
dirigeant . indépendant . conjoint collaborateur . cotisations . invalidité et décès:
|
||||
unité: €/an
|
||||
formule:
|
||||
produit:
|
||||
assiette: assiette
|
||||
taux: 1.3%
|
||||
plafond: plafond sécurité sociale temps plein
|
||||
arrondi: oui
|
||||
produit:
|
||||
assiette: assiette
|
||||
taux: 1.3%
|
||||
plafond: plafond sécurité sociale temps plein
|
||||
arrondi: oui
|
||||
|
||||
dirigeant . indépendant . conjoint collaborateur . cotisations . indemnités journalières maladie:
|
||||
unité: €/an
|
||||
formule:
|
||||
produit:
|
||||
assiette: 40% * plafond sécurité sociale temps plein
|
||||
taux: cotisations et contributions . indemnités journalières maladie . taux
|
||||
arrondi: oui
|
||||
produit:
|
||||
assiette: 40% * plafond sécurité sociale temps plein
|
||||
taux: cotisations et contributions . indemnités journalières maladie . taux
|
||||
arrondi: oui
|
||||
|
||||
dirigeant . indépendant . cotisations et contributions . cotisations:
|
||||
références:
|
||||
|
@ -1043,12 +1039,11 @@ dirigeant . indépendant . cotisations et contributions . invalidité et décès
|
|||
Cotisation minimale: https://www.secu-independants.fr/cotisations/calcul-des-cotisations/cotisations-minimales/
|
||||
|
||||
dirigeant . indépendant . cotisations et contributions . exonération de cotisations minimales:
|
||||
applicable si: situation personnelle . RSA
|
||||
remplace:
|
||||
formule: situation personnelle . RSA
|
||||
rend non applicable:
|
||||
- invalidité et décès . assiette . plancher
|
||||
- maladie . assiette . plancher
|
||||
- retraite de base . assiette . plancher
|
||||
formule: non
|
||||
références:
|
||||
secu-independants.fr: https://www.secu-independants.fr/cotisations/calcul-des-cotisations/cotisations-minimales/
|
||||
|
||||
|
@ -1059,7 +1054,7 @@ dirigeant . indépendant . cotisations et contributions . CSG et CRDS:
|
|||
composantes:
|
||||
- attributs:
|
||||
nom: non déductible
|
||||
arrondi: oui
|
||||
arrondi: oui
|
||||
composantes:
|
||||
- taux: 2.9%
|
||||
- attributs:
|
||||
|
@ -1068,7 +1063,7 @@ dirigeant . indépendant . cotisations et contributions . CSG et CRDS:
|
|||
taux: 2.9%
|
||||
- attributs:
|
||||
nom: déductible
|
||||
arrondi: oui
|
||||
arrondi: oui
|
||||
composantes:
|
||||
- taux: 6.8%
|
||||
- attributs:
|
||||
|
@ -1112,17 +1107,17 @@ dirigeant . indépendant . cotisations et contributions . CSG et CRDS . assiette
|
|||
- dirigeant . indépendant . IJSS . imposable
|
||||
|
||||
dirigeant . indépendant . cotisations et contributions . formation professionnelle:
|
||||
formule:
|
||||
produit:
|
||||
assiette: plafond sécurité sociale temps plein
|
||||
taux:
|
||||
variations:
|
||||
- si: entreprise . catégorie d'activité = 'artisanale'
|
||||
alors: 0.29%
|
||||
- si: conjoint collaborateur
|
||||
alors: 0.34%
|
||||
- sinon: 0.25%
|
||||
arrondi: oui
|
||||
produit:
|
||||
assiette: plafond sécurité sociale temps plein
|
||||
taux:
|
||||
variations:
|
||||
- si: entreprise . catégorie d'activité = 'artisanale'
|
||||
alors: 0.29%
|
||||
- si: conjoint collaborateur
|
||||
alors: 0.34%
|
||||
- sinon: 0.25%
|
||||
unité: €/an
|
||||
arrondi: oui
|
||||
note: Le taux n'est pas majoré pour les artisans avec conjoint collaborateur
|
||||
|
||||
références:
|
||||
|
@ -1153,16 +1148,16 @@ dirigeant . indépendant . cotisations et contributions . exonérations:
|
|||
|
||||
dirigeant . indépendant . cotisations et contributions . exonérations . ZFU:
|
||||
applicable si: établissement . ZFU
|
||||
formule:
|
||||
produit:
|
||||
assiette: maladie
|
||||
taux: taux
|
||||
# TODO : Le plafond est proratisé en début / fin d'exonération
|
||||
plafond:
|
||||
recalcul:
|
||||
avec:
|
||||
dirigeant . indépendant . revenu professionnel: 3042 heures/an * SMIC horaire
|
||||
arrondi: oui
|
||||
produit:
|
||||
assiette: maladie
|
||||
taux: taux
|
||||
# TODO : Le plafond est proratisé en début / fin d'exonération
|
||||
plafond:
|
||||
recalcul:
|
||||
avec:
|
||||
dirigeant . indépendant . revenu professionnel: 3042 heures/an * SMIC horaire
|
||||
arrondi: oui
|
||||
unité: €/an
|
||||
|
||||
dirigeant . indépendant . cotisations et contributions . exonérations . âge:
|
||||
question: Bénéficiez-vous du dispositif d'exonération "âge"
|
||||
|
|
|
@ -59,10 +59,9 @@ aide déclaration revenu indépendant 2019 . ACRE:
|
|||
par défaut: non
|
||||
|
||||
aide déclaration revenu indépendant 2019 . nature de l'activité . libérale:
|
||||
remplace:
|
||||
- règle: dirigeant . indépendant . PL . CIPAV
|
||||
par: non
|
||||
- entreprise . catégorie d'activité . libérale
|
||||
rend non applicable: dirigeant . indépendant . PL . CIPAV
|
||||
remplace: entreprise . catégorie d'activité . libérale
|
||||
formule: nature de l'activité = 'libérale'
|
||||
titre: Libérale rattachée au régime général
|
||||
description: |
|
||||
Ce sont les professions "intellectuelles", qui ne sont rattachée à aucune
|
||||
|
@ -76,6 +75,7 @@ aide déclaration revenu indépendant 2019 . nature de l'activité . libérale:
|
|||
|
||||
aide déclaration revenu indépendant 2019 . nature de l'activité . commerciale ou industrielle:
|
||||
remplace: entreprise . catégorie d'activité . commerciale ou industrielle
|
||||
formule: nature de l'activité = 'commerciale ou industrielle'
|
||||
description: |
|
||||
### Activité commerciale
|
||||
- Achats de biens pour leur revente en l'état (commerce en gros ou de détail)
|
||||
|
@ -86,6 +86,7 @@ aide déclaration revenu indépendant 2019 . nature de l'activité . commerciale
|
|||
Activité de production ou de transformation grâce à l'utilisation d'outils industriels, extraction, industries minières, manutention, magasinage et stockage
|
||||
|
||||
aide déclaration revenu indépendant 2019 . nature de l'activité . artisanale:
|
||||
formule: nature de l'activité = 'artisanale'
|
||||
remplace: entreprise . catégorie d'activité . artisanale
|
||||
description: |
|
||||
C'est une activité de service, de production, de transformation, ou de réparation exercée par un professionnel qualifié, et qui nécessite des compétences et un savoir-faire spécifiques.
|
||||
|
@ -106,6 +107,7 @@ aide déclaration revenu indépendant 2019 . SMIC 2019:
|
|||
formule: 10.03 €/heure
|
||||
|
||||
aide déclaration revenu indépendant 2019 . période:
|
||||
formule: oui
|
||||
remplace:
|
||||
- règle: période . début d'année
|
||||
par: 01/01/2019
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
impôt:
|
||||
icônes: 🏛️
|
||||
unité: €/an
|
||||
description: Cet ensemble de formules est un modèle simplifié de l'impôt sur le revenu.
|
||||
titre: impôts sur le revenu
|
||||
formule:
|
||||
somme:
|
||||
- produit:
|
||||
assiette: revenu imposable
|
||||
taux: taux d'imposition
|
||||
- dirigeant . auto-entrepreneur . impôt . versement libératoire . montant
|
||||
arrondi: oui
|
||||
somme:
|
||||
- produit:
|
||||
assiette: revenu imposable
|
||||
taux: taux d'imposition
|
||||
- dirigeant . auto-entrepreneur . impôt . versement libératoire . montant
|
||||
arrondi: oui
|
||||
unité: €/an
|
||||
|
||||
impôt . taux d'imposition:
|
||||
formule:
|
||||
|
|
|
@ -145,6 +145,7 @@ dirigeant . indépendant . PL . régime général:
|
|||
dirigeant . indépendant . PL . régime général . taux spécifique retraite complémentaire:
|
||||
titre: taux spécifique profession libérale non reglementée
|
||||
question: Avez-vous opté pour des taux spécifiques de cotisation retraite complémentaire ?
|
||||
par défaut: non
|
||||
description: |
|
||||
Les professions libérales non règlementées qui ont débuté leur activité à
|
||||
compter du 1er janvier 2019 ou ceux qui ont débuté leur activité avant la
|
||||
|
@ -320,7 +321,7 @@ dirigeant . indépendant . PL . retraite CNAVPL:
|
|||
une de ces conditions:
|
||||
- régime général
|
||||
- PL . CNBF
|
||||
|
||||
|
||||
titre: retraite de base (CNAVPL)
|
||||
description: |
|
||||
Toutes les professions libérale (à l'exception des avocats)
|
||||
|
@ -330,7 +331,6 @@ dirigeant . indépendant . PL . retraite CNAVPL:
|
|||
libérales est l'organisme qui fédère les différentes caisses
|
||||
existantes (CIPAV, CARPIMKO, CARCDSF, CAVEC etc..)
|
||||
|
||||
remplace: cotisations et contributions . retraite de base
|
||||
formule:
|
||||
somme:
|
||||
- produit:
|
||||
|
@ -348,6 +348,13 @@ dirigeant . indépendant . PL . retraite CNAVPL:
|
|||
liste des caisses: https://www.cnavpl.fr/regimes-complementaires-et-prevoyance/
|
||||
Guide CNAVPL (PDF): https://www.cnavpl.fr/statuts-et-documents-de-reference/?wpdmdl=56215
|
||||
|
||||
#TODO: On ajoute une exception car la transitivité du remplacement ne fonctionne pas encore
|
||||
dirigeant . indépendant . PL . retraite CNAVPL . remplace:
|
||||
titre: retraite de base (CNAVPL)
|
||||
non applicable si: CARMF . retraite CNAVPL
|
||||
remplace: cotisations et contributions . retraite de base
|
||||
formule: retraite CNAVPL
|
||||
|
||||
dirigeant . indépendant . PL . PAMC:
|
||||
applicable si:
|
||||
une de ces conditions:
|
||||
|
@ -715,7 +722,7 @@ dirigeant . indépendant . PL . CARMF . retraite CNAVPL:
|
|||
applicable si: métier . secteur médecin = 'S1'
|
||||
description: |
|
||||
Pour compenser la hausse de la CSG, les médecins de secteur 1 bénéficient d'une participation de l'assurance maladie (avenant n°5 de la convention médicale) au financement de leurs cotisations du régime de base.
|
||||
remplace: PL . retraite CNAVPL
|
||||
remplace: cotisations et contributions . retraite de base
|
||||
formule:
|
||||
allègement:
|
||||
assiette: PL . retraite CNAVPL
|
||||
|
|
|
@ -206,7 +206,6 @@ contrat salarié . activité partielle:
|
|||
|
||||
La déclaration d'activité partielle est simplifiée et l'effet est
|
||||
rétroactif.
|
||||
|
||||
par défaut: non
|
||||
rend non applicable:
|
||||
- temps de travail . heures supplémentaires
|
||||
|
@ -1036,8 +1035,7 @@ contrat salarié . professionnalisation:
|
|||
devant durer entre 6 et 12 mois. Dans certains cas cette période peut être
|
||||
prolongée jusqu'à 36 mois.
|
||||
formule: contrat salarié = 'professionnalisation'
|
||||
rend non applicable:
|
||||
- rémunération . contrôle smic
|
||||
rend non applicable: rémunération . contrôle smic
|
||||
références:
|
||||
Contrat de professionnalisation: https://www.service-public.fr/particuliers/vosdroits/F15478
|
||||
|
||||
|
@ -1066,6 +1064,7 @@ contrat salarié . stage:
|
|||
- contrat salarié . activité partielle
|
||||
|
||||
contrat salarié . stage . avertissement:
|
||||
formule: oui
|
||||
type: notification
|
||||
sévérité: avertissement
|
||||
description: >-
|
||||
|
@ -1076,7 +1075,7 @@ contrat salarié . stage . avertissement:
|
|||
contrat salarié . stage . contrôle gratification minimale:
|
||||
type: notification
|
||||
sévérité: avertissement
|
||||
applicable si: rémunération . brut de base < stage . gratification minimale
|
||||
formule: rémunération . brut de base < stage . gratification minimale
|
||||
description: >-
|
||||
La rémunération du stage est inférieure à la [gratification minimale](https://www.service-public.fr/professionnels-entreprises/vosdroits/F32131).
|
||||
|
||||
|
@ -2837,7 +2836,6 @@ contrat salarié . CSG et CRDS . revenus de remplacement:
|
|||
Le prélèvement de la CSG et de la CRDS ne peut pas avoir pour effet de
|
||||
réduire le montant de la rémunération d’activité et des allocations de
|
||||
chômage à un seuil inférieur au Smic brut.
|
||||
|
||||
formule:
|
||||
somme:
|
||||
- revenus de remplacement . CSG déductible
|
||||
|
@ -2846,57 +2844,32 @@ contrat salarié . CSG et CRDS . revenus de remplacement:
|
|||
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG déductible:
|
||||
titre: CSG déductible revenus de remplacement
|
||||
applicable si: rémunération nette >= SMIC temps plein
|
||||
formule: montant
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG déductible . rémunération nette:
|
||||
formule:
|
||||
produit:
|
||||
assiette: CSG et CRDS . assiette revenu remplacements
|
||||
taux: 3.8%
|
||||
plafond [ref]:
|
||||
somme:
|
||||
- rémunération . net de cotisations
|
||||
- rémunération . revenus de remplacement
|
||||
- (- montant)
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG déductible . montant:
|
||||
titre: CSG déductible
|
||||
formule:
|
||||
produit:
|
||||
assiette: CSG et CRDS . assiette revenu remplacements
|
||||
taux: 3.8%
|
||||
- (- SMIC temps plein)
|
||||
plancher: 0€/mois
|
||||
note:
|
||||
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG non déductible:
|
||||
titre: CSG non déductible revenus de remplacement
|
||||
applicable si: rémunération nette >= SMIC temps plein
|
||||
formule: montant
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG non déductible . rémunération nette:
|
||||
formule:
|
||||
somme:
|
||||
- rémunération . net de cotisations
|
||||
- rémunération . revenus de remplacement
|
||||
- (- CSG déductible . montant)
|
||||
- (- montant)
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CSG non déductible . montant:
|
||||
titre: CSG non déductible
|
||||
formule:
|
||||
produit:
|
||||
assiette: CSG et CRDS . assiette revenu remplacements
|
||||
taux: CSG . taux non déductible
|
||||
produit:
|
||||
assiette: CSG et CRDS . assiette revenu remplacements
|
||||
taux: CSG . taux non déductible
|
||||
plafond [ref]:
|
||||
valeur: CSG déductible . plafond - CSG déductible
|
||||
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CRDS:
|
||||
titre: CRDS revenus de remplacement
|
||||
applicable si: rémunération nette >= SMIC temps plein
|
||||
formule: montant
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CRDS . rémunération nette:
|
||||
formule:
|
||||
somme:
|
||||
- rémunération . net de cotisations
|
||||
- rémunération . revenus de remplacement
|
||||
- (- CSG déductible . montant)
|
||||
- (- CSG non déductible . montant)
|
||||
- (- montant)
|
||||
contrat salarié . CSG et CRDS . revenus de remplacement . CRDS . montant:
|
||||
titre: CRDS
|
||||
formule:
|
||||
produit:
|
||||
assiette: assiette revenu remplacements
|
||||
taux: CRDS . taux
|
||||
produit:
|
||||
assiette: assiette revenu remplacements
|
||||
taux: CRDS . taux
|
||||
plafond:
|
||||
valeur: CSG non déductible . plafond - CSG non déductible
|
||||
|
||||
contrat salarié . FNAL:
|
||||
titre: Contribution au Fonds National d’Aide au Logement
|
||||
|
@ -3333,6 +3306,7 @@ contrat salarié . régime des impatriés:
|
|||
|
||||
contrat salarié . régime des impatriés . information:
|
||||
type: notification
|
||||
formule: oui
|
||||
description: >-
|
||||
Pour bénéficier de l'exonération de cotisations vieillesse, il faut remplir les conditions suivantes :
|
||||
- Pouvoir justifier d'une contribution minimale versée ailleurs pour une assurance vieillesse
|
||||
|
|
|
@ -16,7 +16,10 @@ export const objectifsSelector = createSelector([configSelector], config => {
|
|||
return objectifs
|
||||
})
|
||||
|
||||
const emptySituation: Partial<Record<DottedName, string | number | Object>> = {}
|
||||
const emptySituation: Partial<Record<
|
||||
DottedName,
|
||||
string | number | Record<string, unknown>
|
||||
>> = {}
|
||||
|
||||
export const situationSelector = (state: RootState) =>
|
||||
state.simulation?.situation ?? emptySituation
|
||||
|
|
|
@ -9,4 +9,5 @@ objectifs:
|
|||
situation:
|
||||
dirigeant: "'indépendant'"
|
||||
aide déclaration revenu indépendant 2019: oui
|
||||
dirigeant . indépendant . PL . CIPAV: non # TODO En attendant la transitivité des remplacements
|
||||
unité par défaut: '€/an'
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
import { setSimulationConfig, updateSituation } from 'Actions/actions'
|
||||
import Aide from 'Components/conversation/Aide'
|
||||
import { Explicable, ExplicableRule } from 'Components/conversation/Explicable'
|
||||
import RuleInput from 'Components/conversation/RuleInput'
|
||||
import { Condition } from 'Components/EngineValue'
|
||||
import RuleLink from 'Components/RuleLink'
|
||||
import 'Components/TargetSelection.css'
|
||||
import Animate from 'Components/ui/animate'
|
||||
import Warning from 'Components/ui/WarningBlock'
|
||||
import { EngineContext, useEngine } from 'Components/utils/EngineContext'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import useDisplayOnIntersecting from 'Components/utils/useDisplayOnIntersecting'
|
||||
import RuleInput from 'Components/conversation/RuleInput'
|
||||
import { EvaluatedRule, evaluateRule } from 'publicodes'
|
||||
import { Fragment, useCallback, useEffect, useState, useContext } from 'react'
|
||||
import { useNextQuestions } from 'Components/utils/useNextQuestion'
|
||||
import { EvaluatedRule, evaluateRule, formatValue } from 'publicodes'
|
||||
import { Fragment, useCallback, useContext, useEffect, useState } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { RootState } from 'Reducers/rootReducer'
|
||||
import { DottedName } from 'Rules'
|
||||
import { situationSelector } from 'Selectors/simulationSelectors'
|
||||
import styled from 'styled-components'
|
||||
import Animate from 'Components/ui/animate'
|
||||
import { CompanySection } from '../Home'
|
||||
import simulationConfig from './config.yaml'
|
||||
import { useNextQuestions } from 'Components/utils/useNextQuestion'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import RuleLink from 'Components/RuleLink'
|
||||
import { formatValue } from 'publicodes'
|
||||
import Skeleton from 'Components/ui/Skeleton'
|
||||
|
||||
export default function AideDéclarationIndépendant() {
|
||||
const dispatch = useDispatch()
|
||||
const rules = useContext(EngineContext).getParsedRules()
|
||||
const engine = useEngine()
|
||||
|
||||
const company = useSelector(
|
||||
(state: RootState) => state.inFranceApp.existingCompany
|
||||
)
|
||||
|
@ -38,17 +38,16 @@ export default function AideDéclarationIndépendant() {
|
|||
threshold: 0.5,
|
||||
unobserve: false
|
||||
})
|
||||
const dottedName = 'dirigeant . rémunération totale'
|
||||
const value = useSelector(situationSelector)[dottedName]
|
||||
const [currentIncome, setCurrentIncome] = useState(value)
|
||||
const displayForm = currentIncome != null
|
||||
useEffect(() => {
|
||||
if (resultsInViewPort && displayForm) {
|
||||
dispatch(updateSituation(dottedName, currentIncome))
|
||||
} else {
|
||||
dispatch(updateSituation(dottedName, null))
|
||||
}
|
||||
}, [dispatch, resultsInViewPort, displayForm, currentIncome])
|
||||
const setCurrentIncome = useCallback(
|
||||
currentIncome => {
|
||||
dispatch(
|
||||
updateSituation('dirigeant . rémunération totale', currentIncome)
|
||||
)
|
||||
},
|
||||
[dispatch, updateSituation]
|
||||
)
|
||||
const displayForm =
|
||||
evaluateRule(engine, 'dirigeant . rémunération totale').nodeValue !== null
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -113,7 +112,6 @@ export default function AideDéclarationIndépendant() {
|
|||
<RuleInput
|
||||
dottedName="dirigeant . rémunération totale"
|
||||
onChange={setCurrentIncome}
|
||||
value={currentIncome}
|
||||
autoFocus
|
||||
/>
|
||||
</BigInput>
|
||||
|
@ -138,9 +136,11 @@ export default function AideDéclarationIndépendant() {
|
|||
<SimpleField dottedName="entreprise . date de création" />
|
||||
<SubSection dottedName="aide déclaration revenu indépendant 2019 . nature de l'activité" />
|
||||
{/* PLNR */}
|
||||
<SimpleField dottedName="entreprise . catégorie d'activité . débit de tabac" />
|
||||
<SimpleField dottedName="dirigeant . indépendant . cotisations et contributions . déduction tabac" />
|
||||
<SimpleField dottedName="dirigeant . indépendant . PL . régime général . taux spécifique retraite complémentaire" />
|
||||
<Condition expression="aide déclaration revenu indépendant 2019 . nature de l'activité">
|
||||
<SimpleField dottedName="entreprise . catégorie d'activité . débit de tabac" />
|
||||
<SimpleField dottedName="dirigeant . indépendant . cotisations et contributions . déduction tabac" />
|
||||
<SimpleField dottedName="dirigeant . indépendant . PL . régime général . taux spécifique retraite complémentaire" />
|
||||
</Condition>
|
||||
|
||||
<h2>
|
||||
<Trans>Situation personnelle</Trans>
|
||||
|
@ -346,7 +346,7 @@ function SimpleField({ dottedName, question, summary }: SimpleFieldProps) {
|
|||
const engine = useContext(EngineContext)
|
||||
const evaluatedRule = evaluateRule(engine, dottedName)
|
||||
const value = useSelector(situationSelector)[dottedName]
|
||||
const [currentValue, setCurrentValue] = useState(value)
|
||||
const situation = useSelector(situationSelector)
|
||||
|
||||
const dispatchValue = useCallback(
|
||||
value => {
|
||||
|
@ -359,19 +359,11 @@ function SimpleField({ dottedName, question, summary }: SimpleFieldProps) {
|
|||
},
|
||||
[dispatch, dottedName]
|
||||
)
|
||||
const update = (value: unknown) => {
|
||||
dispatchValue(value)
|
||||
setCurrentValue(value)
|
||||
}
|
||||
useEffect(() => {
|
||||
setCurrentValue(value)
|
||||
}, [value])
|
||||
|
||||
if (
|
||||
// TODO
|
||||
// evaluatedRule.isApplicable === false ||
|
||||
// evaluatedRule.isApplicable === null
|
||||
evaluatedRule.nodeValue === false ||
|
||||
evaluatedRule.nodeValue === null
|
||||
!(dottedName in situation) &&
|
||||
evaluatedRule.nodeValue === false &&
|
||||
!(dottedName in evaluatedRule.missingVariables)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
@ -395,11 +387,7 @@ function SimpleField({ dottedName, question, summary }: SimpleFieldProps) {
|
|||
</p>
|
||||
<p className="ui__ notice">{summary ?? evaluatedRule.résumé}</p>
|
||||
</div>
|
||||
<RuleInput
|
||||
dottedName={dottedName}
|
||||
onChange={update}
|
||||
value={currentValue}
|
||||
/>
|
||||
<RuleInput dottedName={dottedName} onChange={dispatchValue} />
|
||||
</Question>
|
||||
</Animate.fromTop>
|
||||
</div>
|
||||
|
@ -411,8 +399,6 @@ function Results() {
|
|||
const results = (simulationConfig.objectifs as DottedName[]).map(objectif =>
|
||||
evaluateRule(engine, objectif, { unité: '€/an' })
|
||||
)
|
||||
const onGoingComputation = !results.filter(node => node.nodeValue != null)
|
||||
.length
|
||||
return (
|
||||
<div
|
||||
className="ui__ card lighter-bg"
|
||||
|
@ -424,33 +410,20 @@ function Results() {
|
|||
</Trans>
|
||||
{emoji('📄')}
|
||||
</h1>
|
||||
{onGoingComputation && (
|
||||
<h2>
|
||||
<small>
|
||||
<Trans i18nKey="aide-déclaration-indépendant.results.ongoing">
|
||||
Calcul en cours...
|
||||
</Trans>
|
||||
</small>
|
||||
</h2>
|
||||
)}
|
||||
<>
|
||||
<Animate.fromTop>
|
||||
{results.map(r => (
|
||||
<Fragment key={r.title}>
|
||||
<Fragment key={r.dottedName}>
|
||||
<h4>
|
||||
{r.title} <small>{r.résumé}</small>
|
||||
</h4>
|
||||
{r.description && <p className="ui__ notice">{r.description}</p>}
|
||||
<p className="ui__ lead" css="margin-bottom: 1rem;">
|
||||
<RuleLink dottedName={r.dottedName}>
|
||||
{r.nodeValue != null ? (
|
||||
formatValue(r, {
|
||||
displayedUnit: '€',
|
||||
precision: 0
|
||||
})
|
||||
) : (
|
||||
<Skeleton width={80} />
|
||||
)}
|
||||
{formatValue(r, {
|
||||
displayedUnit: '€',
|
||||
precision: 0
|
||||
})}
|
||||
</RuleLink>
|
||||
</p>
|
||||
</Fragment>
|
||||
|
|
|
@ -171,7 +171,6 @@ function FormulairePublicodes() {
|
|||
<RuleInput
|
||||
id={field.dottedName}
|
||||
dottedName={field.dottedName}
|
||||
value={situation[field.dottedName]}
|
||||
onChange={value => onChange(field.dottedName, value)}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -6,7 +6,7 @@ import SimulateurWarning from 'Components/SimulateurWarning'
|
|||
import AidesCovid from 'Components/simulationExplanation/AidesCovid'
|
||||
import 'Components/TargetSelection.css'
|
||||
import Animate from 'Components/ui/animate'
|
||||
import { EngineContext } from 'Components/utils/EngineContext'
|
||||
import { EngineContext, useEngine } from 'Components/utils/EngineContext'
|
||||
import { evaluateRule } from 'publicodes'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
|
@ -60,9 +60,8 @@ type SimpleFieldProps = {
|
|||
|
||||
function SimpleField({ dottedName }: SimpleFieldProps) {
|
||||
const dispatch = useDispatch()
|
||||
const rule = evaluateRule(useContext(EngineContext), dottedName)
|
||||
const rule = useEngine().getParsedRules()[dottedName]
|
||||
const initialRender = useContext(InitialRenderContext)
|
||||
const value = rule.nodeValue
|
||||
// TODO
|
||||
// if (rule.isApplicable === false || rule.isApplicable === null) {
|
||||
// return null
|
||||
|
@ -74,8 +73,10 @@ function SimpleField({ dottedName }: SimpleFieldProps) {
|
|||
<div className="main">
|
||||
<div className="header">
|
||||
<label htmlFor={dottedName}>
|
||||
<span className="optionTitle">{rule.question || rule.title}</span>
|
||||
<p className="ui__ notice">{rule.résumé}</p>
|
||||
<span className="optionTitle">
|
||||
{rule.rawNode.question || rule.title}
|
||||
</span>
|
||||
<p className="ui__ notice">{rule.rawNode.résumé}</p>
|
||||
</label>
|
||||
</div>
|
||||
<div className="targetInputOrValue">
|
||||
|
@ -83,7 +84,6 @@ function SimpleField({ dottedName }: SimpleFieldProps) {
|
|||
className="targetInput"
|
||||
isTarget
|
||||
dottedName={dottedName}
|
||||
value={value}
|
||||
onChange={(x) => dispatch(updateSituation(dottedName, x))}
|
||||
useSwitch
|
||||
/>
|
||||
|
|
|
@ -35,3 +35,4 @@ questions:
|
|||
unité par défaut: €/an
|
||||
situation:
|
||||
dirigeant: "'assimilé salarié'"
|
||||
contrat salarié . activité partielle: non #TODO : en attendant que la transitivité du remplacement soit implémentée
|
||||
|
|
|
@ -8,7 +8,7 @@ describe('DottedNames graph', () => {
|
|||
|
||||
expect(
|
||||
cyclesDependencies,
|
||||
`\nThe cycles have been found in the rules dependencies graph.\nSee below for a representation of each cycle.\n⬇️ is a node of the cycle.\n↘️ is each of the dependencies of this node.\n\t- ${cyclesDependencies
|
||||
`\nThe cycles have been found in the rules dependencies graph.\nSee below for a representation of each cycle.\n⬇️ is a node of the cycle.\n\t- ${cyclesDependencies
|
||||
.map(
|
||||
(cycleDependencies, idx) =>
|
||||
'#' +
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: ACRE 1`] = `"[50000,3177,11384,101,14662,35338]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: ACRE 1`] = `"[50000,3177,11383,101,14661,35339]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: ACRE 2`] = `"[15000,949,3261,101,4311,10689]"`;
|
||||
|
||||
|
@ -16,33 +16,33 @@ exports[`calculate aide-déclaration-indépendant: ACRE 5`] = `
|
|||
Notifications affichées : dirigeant . indépendant . avertissement base forfaitaire"
|
||||
`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: IJSS (indemnité sécurité sociale) 1`] = `"[50000,3024,11424,101,14549,35451]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: IJSS (indemnité sécurité sociale) 1`] = `"[50000,3024,11425,101,14550,35450]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: RSA 1`] = `"[500,25,82,101,208,292]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: RSA 2`] = `"[5000,312,1021,101,1434,3566]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 1`] = `"[50000,3175,17728,138,21041,28959]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 1`] = `"[50000,3175,17724,138,21037,28963]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 2`] = `"[50000,3175,16580,138,19893,30107]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 2`] = `"[50000,3175,16600,138,19913,30087]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 3`] = `"[50000,3175,14664,138,17977,32023]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 3`] = `"[50000,3175,14672,138,17985,32015]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 4`] = `"[50000,3176,17732,118,21026,28974]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 4`] = `"[50000,3176,17729,118,21023,28977]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 5`] = `"[50000,3175,16186,138,19499,30501]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: conjoint collaborateur 5`] = `"[50000,3175,16199,138,19512,30488]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: débit de tabac 1`] = `"[50000,3177,5672,101,8950,41050]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: international 1`] = `"[50000,0,14612,101,14713,35287]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: international 1`] = `"[50000,0,14610,101,14711,35289]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: international 2`] = `"[50000,1267,11893,101,13261,36739]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: nature de l'activité 1`] = `"[50000,3176,11379,118,14673,35327]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: nature de l'activité 1`] = `"[50000,3176,11380,118,14674,35326]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: nature de l'activité 2`] = `"[5000,311,1353,118,1782,3218]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: nature de l'activité 3`] = `"[50000,3177,11384,101,14662,35338]"`;
|
||||
exports[`calculate aide-déclaration-indépendant: nature de l'activité 3`] = `"[50000,3177,11383,101,14661,35339]"`;
|
||||
|
||||
exports[`calculate aide-déclaration-indépendant: nature de l'activité 4`] = `"[5000,312,1354,101,1767,3233]"`;
|
||||
|
||||
|
@ -146,23 +146,23 @@ exports[`calculate simulations-indépendant: impôt sur le revenu 2`] = `"[73025
|
|||
|
||||
exports[`calculate simulations-indépendant: impôt sur le revenu 3`] = `"[29085,9085,20000,20787,2079,17921,0,29085]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 1`] = `"[2000,1384,616,668,0,616,0,2000]"`;
|
||||
exports[`calculate simulations-indépendant: inversions 1`] = `"[2000,1385,615,667,0,615,0,2000]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 2`] = `"[50000,16003,33997,35352,3500,30497,0,50000]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 3`] = `"[14596,4596,10000,10394,0,10000,0,14596]"`;
|
||||
exports[`calculate simulations-indépendant: inversions 3`] = `"[14597,4597,10000,10394,0,10000,0,14597]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 4`] = `"[69940,22078,47862,49758,7862,40000,0,69940]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 5`] = `"[14596,4596,10000,10394,0,10000,1000,15596]"`;
|
||||
exports[`calculate simulations-indépendant: inversions 5`] = `"[14597,4597,10000,10394,0,10000,1000,15597]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 6`] = `"[19000,5928,13072,13585,0,13072,1000,20000]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: inversions 7`] = `"[18000,5625,12375,12861,0,12375,2000,20000]"`;
|
||||
exports[`calculate simulations-indépendant: inversions 7`] = `"[17999,5625,12374,12860,0,12374,2000,20000]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 1`] = `"[1859,1359,500,548,0,500,0,1859]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 2`] = `"[2467,1467,1000,1064,0,1000,0,2467]"`;
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 2`] = `"[2466,1466,1000,1064,0,1000,0,2466]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 3`] = `"[3075,1575,1500,1581,0,1500,0,3075]"`;
|
||||
|
||||
|
@ -170,9 +170,9 @@ exports[`calculate simulations-indépendant: échelle de revenus 4`] = `"[3682,1
|
|||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 5`] = `"[7428,2428,5000,5199,0,5000,0,7428]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 6`] = `"[14596,4596,10000,10394,0,10000,0,14596]"`;
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 6`] = `"[14597,4597,10000,10394,0,10000,0,14597]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 7`] = `"[139595,39595,100000,103788,24909,75091,0,139595]"`;
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 7`] = `"[139596,39596,100000,103788,24909,75091,0,139596]"`;
|
||||
|
||||
exports[`calculate simulations-indépendant: échelle de revenus 8`] = `"[1239955,239955,1000000,1033666,444476,555524,0,1239955]"`;
|
||||
|
||||
|
@ -184,13 +184,13 @@ exports[`calculate simulations-professions-libérales: CIPAV 3`] = `"[3905,0,240
|
|||
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 4`] = `"[4473,0,2473,2000,0,2000]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 5`] = `"[7934,0,2934,5000,0,5000]"`;
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 5`] = `"[7935,0,2935,5000,0,5000]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 6`] = `"[14188,0,4188,10000,0,10000]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 7`] = `"[144691,0,44691,100000,24942,75058]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 8`] = `"[1236171,0,236171,1000000,444432,555568]"`;
|
||||
exports[`calculate simulations-professions-libérales: CIPAV 8`] = `"[1236171,0,236171,1000000,444433,555567]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: auxiliaire médical 1`] = `"[30000,0,7751,22249,945,21304]"`;
|
||||
|
||||
|
@ -198,7 +198,7 @@ exports[`calculate simulations-professions-libérales: auxiliaire médical 2`] =
|
|||
|
||||
exports[`calculate simulations-professions-libérales: auxiliaire médical 3`] = `"[300000,0,61784,238216,81297,156919]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: avocat 1`] = `"[50000,0,11410,38589,4753,33836]"`;
|
||||
exports[`calculate simulations-professions-libérales: avocat 1`] = `"[50000,0,11410,38590,4753,33837]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: avocat 2`] = `"[50000,0,11770,38230,4711,33519]"`;
|
||||
|
||||
|
@ -212,11 +212,11 @@ exports[`calculate simulations-professions-libérales: médecin 2`] = `"[50000,0
|
|||
|
||||
exports[`calculate simulations-professions-libérales: médecin 3`] = `"[300000,0,86481,213519,73147,140372]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: médecin 4`] = `"[400000,0,106201,293799,115768,178031]"`;
|
||||
exports[`calculate simulations-professions-libérales: médecin 4`] = `"[400000,0,106201,293800,115768,178032]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: médecin 5`] = `"[120000,0,34595,85405,17732,67673]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: sage-femme 1`] = `"[50000,0,12383,37617,4638,32979]"`;
|
||||
exports[`calculate simulations-professions-libérales: sage-femme 1`] = `"[50000,0,12384,37617,4638,32979]"`;
|
||||
|
||||
exports[`calculate simulations-professions-libérales: sage-femme 2`] = `
|
||||
"[20000,0,5148,14852,0,14852]
|
||||
|
@ -270,9 +270,9 @@ exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): Co
|
|||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): Contrats Madelin 6`] = `"[917,0,0,10757,4,20]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): activités 1`] = `"[917,0,0,0,4,0]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): activités 1`] = `"[917,0,0,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): activités 2`] = `"[917,0,0,0,4,0]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): activités 2`] = `"[917,0,0,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): activités 3`] = `"[917,0,0,10757,4,20]"`;
|
||||
|
||||
|
@ -286,9 +286,9 @@ exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): av
|
|||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): échelle de rémunération 1`] = `"[0,0,0,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): échelle de rémunération 2`] = `"[14,0,0,139,0,1]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): échelle de rémunération 2`] = `"[14,0,0,140,0,1]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): échelle de rémunération 3`] = `"[62,0,0,324,0,2]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): échelle de rémunération 3`] = `"[62,0,0,323,0,2]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (assimilé salarié): échelle de rémunération 4`] = `"[204,0,0,2591,2,5]"`;
|
||||
|
||||
|
@ -330,9 +330,9 @@ Notifications affichées : dirigeant . auto-entrepreneur . contrôle seuil de CA
|
|||
|
||||
exports[`calculate simulations-rémunération-dirigeant (auto-entrepreneur): Contrats Madelin 6`] = `"[0,0,1446,4195,3,8]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (auto-entrepreneur): activités 1`] = `"[0,0,1298,0,4,0]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (auto-entrepreneur): activités 1`] = `"[0,0,1298,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (auto-entrepreneur): activités 2`] = `"[0,0,1297,0,4,0]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (auto-entrepreneur): activités 2`] = `"[0,0,1297,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (auto-entrepreneur): activités 3`] = `"[0,0,1445,4093,3,8]"`;
|
||||
|
||||
|
@ -378,24 +378,21 @@ exports[`calculate simulations-rémunération-dirigeant (indépendant): ACRE 3`]
|
|||
Notifications affichées : dirigeant . indépendant . avertissement base forfaitaire"
|
||||
`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 1`] = `"[0,20620,0,15102,4,29]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 1`] = `"[0,20619,0,15101,4,29]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 2`] = `"[0,20264,0,15647,4,30]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 2`] = `"[0,20619,0,15101,4,29]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 3`] = `"[0,20620,0,15102,4,29]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 3`] = `"[0,20619,0,15101,4,29]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 4`] = `"[0,13769,0,10084,4,21]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 5`] = `"[0,226877,0,57936,4,56]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 6`] = `
|
||||
"[0,13769,0,10084,4,21]
|
||||
Notifications affichées : dirigeant . indépendant . contrats madelin . contrôle montant charges"
|
||||
`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): Contrats Madelin 6`] = `"[0,13769,0,10084,4,21]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): activités 1`] = `"[0,14646,0,0,4,0]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): activités 1`] = `"[0,14646,0,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): activités 2`] = `"[0,14646,0,0,4,0]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): activités 2`] = `"[0,14646,0,0,0,0]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): activités 3`] = `"[0,13757,0,10075,4,21]"`;
|
||||
|
||||
|
@ -411,7 +408,7 @@ exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle
|
|||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle de rémunération 2`] = `"[0,-225,0,0,3,21]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle de rémunération 3`] = `"[0,616,0,471,3,21]"`;
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle de rémunération 3`] = `"[0,615,0,471,3,21]"`;
|
||||
|
||||
exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle de rémunération 4`] = `"[0,3084,0,2266,3,21]"`;
|
||||
|
||||
|
@ -424,7 +421,7 @@ exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle
|
|||
exports[`calculate simulations-rémunération-dirigeant (indépendant): échelle de rémunération 8`] = `"[0,69895,0,36431,4,56]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: CCN HCR 1`] = `
|
||||
"[4192,0,2500,2468,2351]
|
||||
"[3532,0,2500,1998,1887]
|
||||
Notifications affichées : contrat salarié . convention collective . contrôle décharge"
|
||||
`;
|
||||
|
||||
|
@ -444,7 +441,7 @@ Notifications affichées : contrat salarié . convention collective . contrôle
|
|||
`;
|
||||
|
||||
exports[`calculate simulations-salarié: CCN compta 1`] = `
|
||||
"[4132,0,2500,2478,2363]
|
||||
"[3470,0,2500,2006,1898]
|
||||
Notifications affichées : contrat salarié . convention collective . contrôle décharge"
|
||||
`;
|
||||
|
||||
|
@ -486,9 +483,9 @@ exports[`calculate simulations-salarié: activité partielle 6`] = `"[327,3750,3
|
|||
|
||||
exports[`calculate simulations-salarié: activité partielle 7`] = `"[427,0,4000,2594,2485]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: activité partielle 8`] = `"[409,0,2000,1578,1544]"`;
|
||||
exports[`calculate simulations-salarié: activité partielle 8`] = `"[409,0,2000,1539,1519]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: activité partielle 9`] = `"[1247,0,2000,1540,1506]"`;
|
||||
exports[`calculate simulations-salarié: activité partielle 9`] = `"[1247,0,2000,1539,1506]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: activité partielle 10`] = `"[927,0,6000,4182,3498]"`;
|
||||
|
||||
|
@ -569,7 +566,7 @@ Notifications affichées : contrat salarié . CDD . information"
|
|||
`;
|
||||
|
||||
exports[`calculate simulations-salarié: cdd 4`] = `
|
||||
"[3744,0,2400,1878,1799]
|
||||
"[3831,0,2400,1907,1828]
|
||||
Notifications affichées : contrat salarié . CDD . information, contrat salarié . convention collective . contrôle décharge"
|
||||
`;
|
||||
|
||||
|
@ -613,7 +610,7 @@ exports[`calculate simulations-salarié: frais pro - titres restaurant 3`] = `"[
|
|||
|
||||
exports[`calculate simulations-salarié: heures supplémentaires et complémentaires 1`] = `"[2583,0,2000,1636,1601]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: heures supplémentaires et complémentaires 2`] = `"[3105,0,2000,2009,1960]"`;
|
||||
exports[`calculate simulations-salarié: heures supplémentaires et complémentaires 2`] = `"[2541,0,2000,1606,1572]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: heures supplémentaires et complémentaires 3`] = `"[2654,0,2000,1636,1601]"`;
|
||||
|
||||
|
@ -623,12 +620,12 @@ Notifications affichées : contrat salarié . convention collective . contrôle
|
|||
`;
|
||||
|
||||
exports[`calculate simulations-salarié: heures supplémentaires et complémentaires 5`] = `
|
||||
"[3025,0,2000,1970,1936]
|
||||
"[2530,0,2000,1601,1566]
|
||||
Notifications affichées : contrat salarié . convention collective . contrôle décharge"
|
||||
`;
|
||||
|
||||
exports[`calculate simulations-salarié: heures supplémentaires et complémentaires 6`] = `
|
||||
"[3040,0,2000,1978,1943]
|
||||
"[2530,0,2000,1601,1566]
|
||||
Notifications affichées : contrat salarié . convention collective . contrôle décharge"
|
||||
`;
|
||||
|
||||
|
@ -681,10 +678,10 @@ exports[`calculate simulations-salarié: impôt sur le revenu 5`] = `
|
|||
Notifications affichées : contrat salarié . rémunération . contrôle salaire élevé"
|
||||
`;
|
||||
|
||||
exports[`calculate simulations-salarié: impôt sur le revenu 6`] = `"[4076,0,3000,2626,2481]"`;
|
||||
exports[`calculate simulations-salarié: impôt sur le revenu 6`] = `"[4076,0,3000,2626,2485]"`;
|
||||
|
||||
exports[`calculate simulations-salarié: impôt sur le revenu 7`] = `
|
||||
"[41831,0,30000,26966,16383]
|
||||
"[41831,0,30000,26966,16655]
|
||||
Notifications affichées : contrat salarié . rémunération . contrôle salaire élevé"
|
||||
`;
|
||||
|
||||
|
|
|
@ -42,4 +42,4 @@ impôt sur le revenu:
|
|||
impôt . méthode de calcul: "'taux neutre'"
|
||||
- dirigeant . indépendant . revenu net de cotisations: 20000 €/an
|
||||
impôt . méthode de calcul: "'taux personnalisé'"
|
||||
impôt . taux personnalisé: 10
|
||||
impôt . taux personnalisé: 10%
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
avec charges:
|
||||
- dirigeant . rémunération totale: 10000 €/an
|
||||
entreprise . charges: 2000
|
||||
entreprise . charges: 2000 €/an
|
||||
- dirigeant . rémunération totale: 20000 €/an
|
||||
entreprise . charges: 15000
|
||||
entreprise . charges: 15000 €/an
|
||||
|
||||
ACRE:
|
||||
- dirigeant . rémunération totale: 10000 €/an
|
||||
|
@ -46,29 +46,29 @@ Contrats Madelin:
|
|||
# cotisations (résultat comptable) n'est pas affecté car l'assiette des
|
||||
# cotisations ne change pas:
|
||||
- dirigeant . rémunération totale: 30000 €/an
|
||||
entreprise . charges: 10000
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant: 3800 # plafond: 10% PSS donc environ 4100
|
||||
entreprise . charges: 10000 €/an
|
||||
dirigeant . indépendant . contrats madelin . mutuelle: 3800 €/an # plafond: 10% PSS donc environ 4100
|
||||
# Cas retraite: la cotisation Madelin est supérieure au plafond => le revenu net de
|
||||
# cotisations est affecté car l'assiette des cotisations est plus élevée
|
||||
- dirigeant . rémunération totale: 30000 €/an
|
||||
entreprise . charges: 10000
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant: 5000 # plafond: 10% PSS donc environ 4100
|
||||
entreprise . charges: 10000 €/an
|
||||
dirigeant . indépendant . contrats madelin . mutuelle: 5000 €/an # plafond: 10% PSS donc environ 4100
|
||||
# Cas mutuelle
|
||||
- dirigeant . rémunération totale: 30000 €/an
|
||||
entreprise . charges: 10000
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant: 1000
|
||||
entreprise . charges: 10000 €/an
|
||||
dirigeant . indépendant . contrats madelin . mutuelle: 1000 €/an
|
||||
# Cas global madelin faible
|
||||
- dirigeant . rémunération totale: 20000 €/an
|
||||
entreprise . charges: 1000
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant: 200
|
||||
dirigeant . indépendant . contrats madelin . retraite . montant: 300
|
||||
entreprise . charges: 1000 €/an
|
||||
dirigeant . indépendant . contrats madelin . mutuelle: 200 €/an
|
||||
dirigeant . indépendant . contrats madelin . retraite: 300 €/an
|
||||
# Cas global madelin grand (plafonds calculés différemment)
|
||||
- dirigeant . rémunération totale: 300000 €/an
|
||||
entreprise . charges: 15000
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant: 1500
|
||||
dirigeant . indépendant . contrats madelin . retraite . montant: 5000
|
||||
entreprise . charges: 15000 €/an
|
||||
dirigeant . indépendant . contrats madelin . mutuelle: 1500 €/an
|
||||
dirigeant . indépendant . contrats madelin . retraite: 5000 €/an
|
||||
# Cas charges plus faibles que total madelin
|
||||
- dirigeant . rémunération totale: 20000 €/an
|
||||
entreprise . charges: 500
|
||||
dirigeant . indépendant . contrats madelin . mutuelle . montant: 300
|
||||
dirigeant . indépendant . contrats madelin . retraite . montant: 300
|
||||
entreprise . charges: 500 €/an
|
||||
dirigeant . indépendant . contrats madelin . mutuelle: 300 €/an
|
||||
dirigeant . indépendant . contrats madelin . retraite: 300 €/an
|
||||
|
|
|
@ -66,7 +66,7 @@ cdd:
|
|||
- contrat salarié: "'CDD'"
|
||||
contrat salarié . rémunération . brut de base: 2000 €/mois
|
||||
contrat salarié . CDD . durée contrat: 6 mois
|
||||
contrat salarié . CDD . congés non pris: 3 jours
|
||||
contrat salarié . CDD . congés non pris: 3 jours ouvrés
|
||||
- contrat salarié: "'CDD'"
|
||||
contrat salarié . rémunération . brut de base: 2400 €/mois
|
||||
contrat salarié . CDD . durée contrat: 10 mois
|
||||
|
@ -394,13 +394,13 @@ taux spécifiques retraite complémentaire:
|
|||
CCN batiment:
|
||||
- contrat salarié . rémunération . brut de base: 2500 €/mois
|
||||
contrat salarié . convention collective: "'BTP'"
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié: "'ouvrier'"
|
||||
contrat salarié . convention collective . BTP . catégorie: "'ouvrier'"
|
||||
- contrat salarié . rémunération . brut de base: 2500 €/mois
|
||||
contrat salarié . convention collective: "'BTP'"
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié: "'etam'"
|
||||
contrat salarié . convention collective . BTP . catégorie: "'etam'"
|
||||
- contrat salarié . rémunération . brut de base: 2500 €/mois
|
||||
contrat salarié . convention collective: "'BTP'"
|
||||
contrat salarié . convention collective . BTP . catégorie du salarié: "'cadre'"
|
||||
contrat salarié . convention collective . BTP . catégorie: "'cadre'"
|
||||
|
||||
CCN compta:
|
||||
- contrat salarié . rémunération . brut de base: 2500 €/mois
|
||||
|
@ -428,4 +428,4 @@ CCN spectacle vivant:
|
|||
|
||||
CCN sport:
|
||||
- contrat salarié . rémunération . brut de base: 500 €/mois
|
||||
contrat salarié . convention collective . sport . primes . nombre de manifestations: 2
|
||||
contrat salarié . convention collective . sport . primes . nombre de manifestations: 2 manifestations
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// renamed the test configuration may be adapted but the persisted snapshot will remain unchanged).
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
import Engine from 'publicodes'
|
||||
import Engine, { evaluateRule } from 'publicodes'
|
||||
import rules from '../../source/rules'
|
||||
import artisteAuteurConfig from '../../source/sites/mon-entreprise.fr/pages/Simulateurs/configs/artiste-auteur.yaml'
|
||||
import autoentrepreneurConfig from '../../source/sites/mon-entreprise.fr/pages/Simulateurs/configs/auto-entrepreneur.yaml'
|
||||
|
@ -44,7 +44,7 @@ const runSimulations = (situations, targets, baseSituation = {}) =>
|
|||
(rule) =>
|
||||
rule.rawNode['type'] === 'notification'
|
||||
)
|
||||
.map(node => engine.evaluateNode(node))
|
||||
.map(node => evaluateRule(engine, node.dottedName))
|
||||
.filter(node => !!node.nodeValue)
|
||||
.map(node => node.dottedName)
|
||||
|
||||
|
@ -60,7 +60,7 @@ const runSimulations = (situations, targets, baseSituation = {}) =>
|
|||
})
|
||||
)
|
||||
|
||||
it.only('calculate simulations-salarié', () => {
|
||||
it('calculate simulations-salarié', () => {
|
||||
runSimulations(
|
||||
employeeSituations,
|
||||
employeeConfig.objectifs,
|
||||
|
|
|
@ -25,8 +25,7 @@ function buildRuleDependancies(rule: RuleNode): Array<string> {
|
|||
case 'une possibilité':
|
||||
return acc
|
||||
case 'recalcul':
|
||||
node.explanation.amendedSituation.forEach(s => fn(s[1]))
|
||||
return
|
||||
return node.explanation.amendedSituation.flatMap(s => fn(s[1]))
|
||||
case 'reference':
|
||||
return [...acc, node.dottedName as string]
|
||||
case 'rule':
|
||||
|
@ -85,7 +84,7 @@ export function cyclicDependencies<Names extends string>(
|
|||
return cycles.map(cycle => {
|
||||
const c = cycle.reverse()
|
||||
|
||||
return c.reduce((acc, current) => {
|
||||
return [...c, c[0]].reduce((acc, current) => {
|
||||
const previous = acc.slice(-1)[0]
|
||||
if (previous && !rulesDependenciesObject[previous].includes(current)) {
|
||||
return acc
|
||||
|
|
|
@ -48,10 +48,10 @@ function gatherNodes(node: ASTNode): ASTNode[] {
|
|||
export function traverseParsedRules(
|
||||
fn: (n: ASTNode) => ASTNode,
|
||||
parsedRules: Record<string, RuleNode>
|
||||
): Record<string, ASTNode> {
|
||||
): Record<string, RuleNode> {
|
||||
return Object.fromEntries(
|
||||
Object.entries(parsedRules).map(([name, rule]) => [name, fn(rule)])
|
||||
)
|
||||
) as Record<string, RuleNode>
|
||||
}
|
||||
|
||||
const traverseASTNode: TraverseFunction<NodeKind> = (fn, node) => {
|
||||
|
|
|
@ -31,7 +31,7 @@ import { Temporal } from '../temporal'
|
|||
|
||||
export type ConstantNode = {
|
||||
type: 'boolean' | 'objet' | 'number' | 'string'
|
||||
nodeValue: boolean | Object | number | string | null
|
||||
nodeValue: Evaluation
|
||||
jsx: any
|
||||
nodeKind: 'constant'
|
||||
isDefault: boolean
|
||||
|
@ -69,7 +69,7 @@ export type ASTNode = (
|
|||
| ReplacementNode
|
||||
) & {
|
||||
isDefault?: boolean
|
||||
rawNode?: string | Object
|
||||
rawNode?: string | Record<string, unknown>
|
||||
} & (EvaluationDecoration<Types> | {}) // TODO : separate type for evaluated AST Tree
|
||||
|
||||
export type MecanismNode = Exclude<
|
||||
|
@ -77,9 +77,6 @@ export type MecanismNode = Exclude<
|
|||
RuleNode | ConstantNode | ReferenceNode
|
||||
>
|
||||
export type NodeKind = ASTNode['nodeKind']
|
||||
export type Value = ASTNode & {
|
||||
nodeValue: number | string | boolean
|
||||
}
|
||||
|
||||
export type TraverseFunction<Kind extends NodeKind> = (
|
||||
fn: (n: ASTNode) => ASTNode,
|
||||
|
@ -97,11 +94,11 @@ export type Unit = {
|
|||
// Une temporalEvaluation est une liste d'evaluation sur chaque période. : [(Evaluation, Period)]
|
||||
type EvaluationDecoration<T extends Types> = {
|
||||
nodeValue: Evaluation<T>
|
||||
missingVariables: Partial<Record<string, number>>
|
||||
missingVariables: Record<string, number>
|
||||
unit?: Unit
|
||||
temporalValue?: Temporal<Evaluation>
|
||||
}
|
||||
export type Types = number | boolean | string | Object
|
||||
export type Types = number | boolean | string | Record<string, unknown>
|
||||
export type Evaluation<T extends Types = Types> = T | false | null
|
||||
export type EvaluatedNode<T extends Types = Types> = ASTNode &
|
||||
EvaluationDecoration<T>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { toPairs } from 'ramda'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
import { makeJsx } from '../../evaluation'
|
||||
import writtenNumbers from '../../locales/writtenNumbers.yaml'
|
||||
import colors from './colors'
|
||||
|
|
|
@ -129,7 +129,7 @@ export const InfixMecanism = ({
|
|||
`}
|
||||
>
|
||||
{prefixed && children}
|
||||
<div className="value" css={dimValue ? `opacity: 0.5` : ''}>
|
||||
<div className="value" css={dimValue ? 'opacity: 0.5' : ''}>
|
||||
{makeJsx(value)}
|
||||
</div>
|
||||
{!prefixed && children}
|
||||
|
|
|
@ -73,7 +73,9 @@ export default function Rule({ dottedName, engine, language }) {
|
|||
<h3>Effets </h3>
|
||||
<ul>
|
||||
{rule.replacements.map(replacement => (
|
||||
<li>{makeJsx(replacement)}</li>
|
||||
<li key={replacement.replacedReference.dottedName}>
|
||||
{makeJsx(replacement)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
import Engine, { EvaluatedNode, evaluationFunction } from '.'
|
||||
import { typeWarning } from './error'
|
||||
import { evaluateApplicability } from './evaluateRule'
|
||||
import { mergeMissing } from './evaluation'
|
||||
import { convertNodeToUnit } from './nodeUnits'
|
||||
import { ParsedRule } from './types'
|
||||
import { areUnitConvertible, serializeUnit } from './units'
|
||||
|
||||
export const evaluateReference: evaluationFunction = function(node) {
|
||||
const rule = this.parsedRules[node.dottedName]
|
||||
// When a rule exists in different version (created using the `replace` mecanism), we add
|
||||
// a redirection in the evaluation of references to use a potential active replacement
|
||||
const [
|
||||
applicableReplacements,
|
||||
replacementMissingVariableList
|
||||
] = getApplicableReplacements.call(
|
||||
this,
|
||||
node.explanation?.contextRuleName ?? '',
|
||||
rule
|
||||
)
|
||||
if (applicableReplacements.length) {
|
||||
if (applicableReplacements.length > 1) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`
|
||||
Règle ${rule.dottedName}: plusieurs remplacements valides ont été trouvés :
|
||||
\n\t${applicableReplacements.map(node => node.rawNode).join('\n\t')}
|
||||
|
||||
Par défaut, seul le premier s'applique. Si vous voulez un autre comportement, vous pouvez :
|
||||
- Restreindre son applicabilité via "applicable si" sur la règle de définition
|
||||
- Restreindre sa portée en ajoutant une liste blanche (via le mot clé "dans") ou une liste noire (via le mot clé "sauf dans")
|
||||
`)
|
||||
}
|
||||
return this.evaluateNode(applicableReplacements[0])
|
||||
}
|
||||
const addReplacementMissingVariable = node => ({
|
||||
...node,
|
||||
missingVariables: replacementMissingVariableList.reduce(
|
||||
mergeMissing,
|
||||
node.missingVariables
|
||||
)
|
||||
})
|
||||
const dottedName = node.dottedName
|
||||
// On va vérifier dans le cache courant, dict, si la variable n'a pas été déjà évaluée
|
||||
// En effet, l'évaluation dans le cas d'une variable qui a une formule, est coûteuse !
|
||||
const cacheName =
|
||||
dottedName + (node.explanation.filter ? ' .' + node.explanation.filter : '')
|
||||
const cached = this.cache[cacheName]
|
||||
|
||||
if (cached) return addReplacementMissingVariable(cached)
|
||||
|
||||
const cacheNode = (
|
||||
nodeValue: EvaluatedNode['nodeValue'],
|
||||
missingVariables: EvaluatedNode['missingVariables'],
|
||||
explanation?: Record<string, unknown>
|
||||
) => {
|
||||
this.cache[cacheName] = {
|
||||
...node,
|
||||
nodeValue,
|
||||
...(explanation && {
|
||||
explanation
|
||||
}),
|
||||
...(explanation?.temporalValue
|
||||
? {
|
||||
temporalValue: explanation.temporalValue
|
||||
}
|
||||
: {}),
|
||||
...(explanation?.unit ? { unit: explanation.unit } : {}),
|
||||
missingVariables
|
||||
}
|
||||
return addReplacementMissingVariable(this.cache[cacheName])
|
||||
}
|
||||
const applicabilityEvaluation = evaluateApplicability.call(this, rule as any)
|
||||
|
||||
if (!applicabilityEvaluation.nodeValue) {
|
||||
return cacheNode(
|
||||
applicabilityEvaluation.nodeValue,
|
||||
applicabilityEvaluation.missingVariables,
|
||||
applicabilityEvaluation
|
||||
)
|
||||
}
|
||||
if (this.parsedSituation[dottedName]) {
|
||||
// Conditional evaluation is required because some mecanisms like
|
||||
// "synchronisation" store raw JS objects in the situation.
|
||||
const situationValue = this.parsedSituation[dottedName]?.nodeKind
|
||||
? this.evaluateNode(this.parsedSituation[dottedName])
|
||||
: this.parsedSituation[dottedName]
|
||||
const unit =
|
||||
!situationValue.unit || serializeUnit(situationValue.unit) === ''
|
||||
? rule.unit
|
||||
: situationValue.unit
|
||||
return cacheNode(
|
||||
situationValue?.nodeValue !== undefined
|
||||
? situationValue.nodeValue
|
||||
: situationValue,
|
||||
applicabilityEvaluation.missingVariables,
|
||||
{
|
||||
...rule,
|
||||
...(situationValue?.nodeValue !== undefined && situationValue),
|
||||
unit
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (rule.defaultValue != null) {
|
||||
const evaluation = this.evaluateNode(rule.defaultValue)
|
||||
return cacheNode(evaluation.nodeValue ?? evaluation, {
|
||||
...evaluation.missingVariables,
|
||||
[dottedName]: 1
|
||||
})
|
||||
}
|
||||
|
||||
if (rule.formule != null) {
|
||||
const evaluation = this.evaluateNode(rule)
|
||||
return cacheNode(
|
||||
evaluation.nodeValue,
|
||||
evaluation.missingVariables,
|
||||
evaluation
|
||||
)
|
||||
}
|
||||
|
||||
return cacheNode(null, { [dottedName]: 2 })
|
||||
}
|
||||
|
||||
// This function is a wrapper that can apply :
|
||||
// - unit transformations to the value of the variable.
|
||||
// See the unité-temporelle.yaml test suite for details
|
||||
// - filters on the variable to select one part of the variable's 'composantes'
|
||||
|
||||
export const evaluateReferenceTransforms: evaluationFunction = function(node) {
|
||||
// Filter transformation
|
||||
if (node.explanation.filter) {
|
||||
this.cache._meta.filter = node.explanation.filter
|
||||
}
|
||||
const filteredNode = this.evaluateNode(node.explanation.originalNode)
|
||||
if (node.explanation.filter) {
|
||||
delete this.cache._meta.filter
|
||||
}
|
||||
const { explanation, nodeValue } = filteredNode
|
||||
if (!explanation || nodeValue === null) {
|
||||
return filteredNode
|
||||
}
|
||||
const unit = node.explanation.unit
|
||||
if (unit) {
|
||||
try {
|
||||
return convertNodeToUnit(unit, filteredNode)
|
||||
} catch (e) {
|
||||
typeWarning(
|
||||
this.cache._meta.contextRule,
|
||||
`Impossible de convertir la reference '${filteredNode.name}'`,
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Statically filter out replacements from `replaceBy`.
|
||||
* Note: whitelist and blacklist filtering are applicable to the replacement
|
||||
* itself or any parent namespace.
|
||||
*/
|
||||
export const getApplicableReplacedBy = (contextRuleName, replacedBy) =>
|
||||
replacedBy
|
||||
.sort(
|
||||
(replacement1, replacement2) =>
|
||||
+!!replacement2.whiteListedNames - +!!replacement1.whiteListedNames
|
||||
)
|
||||
.filter(
|
||||
({ whiteListedNames }) =>
|
||||
!whiteListedNames ||
|
||||
whiteListedNames.some(name => contextRuleName.startsWith(name))
|
||||
)
|
||||
.filter(
|
||||
({ blackListedNames }) =>
|
||||
!blackListedNames ||
|
||||
blackListedNames.every(name => !contextRuleName.startsWith(name))
|
||||
)
|
||||
.filter(({ referenceNode }) => contextRuleName !== referenceNode.dottedName)
|
||||
|
||||
/**
|
||||
* Filter-out and apply all possible replacements at runtime.
|
||||
*/
|
||||
const getApplicableReplacements = function(
|
||||
this: Engine<string>,
|
||||
contextRuleName: string,
|
||||
rule: ParsedRule
|
||||
) {
|
||||
let missingVariableList: Array<EvaluatedNode['missingVariables']> = []
|
||||
if (contextRuleName.startsWith('[evaluation]')) {
|
||||
return [[], []]
|
||||
}
|
||||
const applicableReplacements = getApplicableReplacedBy(
|
||||
contextRuleName,
|
||||
rule.replacedBy
|
||||
)
|
||||
// Remove remplacement defined in a not applicable node
|
||||
.filter(({ referenceNode }) => {
|
||||
const referenceRule = this.parsedRules[referenceNode.dottedName]
|
||||
const {
|
||||
nodeValue: isApplicable,
|
||||
missingVariables
|
||||
} = evaluateApplicability.call(this, referenceRule as any)
|
||||
missingVariableList.push(missingVariables)
|
||||
return isApplicable
|
||||
})
|
||||
// Remove remplacement defined in a node whose situation value is false
|
||||
.filter(({ referenceNode }) => {
|
||||
const referenceRule = this.parsedRules[referenceNode.dottedName]
|
||||
const situationValue = this.parsedSituation[referenceRule.dottedName]
|
||||
if (referenceNode.question && situationValue == null) {
|
||||
missingVariableList.push({ [referenceNode.dottedName]: 1 })
|
||||
}
|
||||
return (situationValue as any)?.nodeValue !== false
|
||||
})
|
||||
// Remove remplacement defined in a boolean node whose evaluated value is false
|
||||
.filter(({ referenceNode }) => {
|
||||
const referenceRule = this.parsedRules[referenceNode.dottedName]
|
||||
if (referenceRule.formule?.explanation?.operationType !== 'comparison') {
|
||||
return true
|
||||
}
|
||||
const { nodeValue: isApplicable, missingVariables } = this.evaluateNode(
|
||||
referenceRule
|
||||
)
|
||||
missingVariableList.push(missingVariables)
|
||||
return isApplicable
|
||||
})
|
||||
.map(({ referenceNode, replacementNode }) =>
|
||||
replacementNode != null ? replacementNode : referenceNode
|
||||
)
|
||||
.map(replacementNode => {
|
||||
const replacedRuleUnit = rule.unit
|
||||
if (!areUnitConvertible(replacementNode.unit, replacedRuleUnit)) {
|
||||
typeWarning(
|
||||
contextRuleName,
|
||||
`L'unité de la règle de remplacement n'est pas compatible avec celle de la règle remplacée ${rule.dottedName}`
|
||||
)
|
||||
}
|
||||
return {
|
||||
...replacementNode,
|
||||
unit: replacementNode.unit || replacedRuleUnit
|
||||
}
|
||||
})
|
||||
|
||||
missingVariableList = missingVariableList.filter(
|
||||
missingVariables => !!Object.keys(missingVariables).length
|
||||
)
|
||||
|
||||
return [applicableReplacements, missingVariableList]
|
||||
}
|
|
@ -38,14 +38,20 @@ export const makeJsx = (node: ASTNode): JSX.Element => {
|
|||
return <Component {...node} />
|
||||
}
|
||||
|
||||
export const collectNodeMissing = node => node?.missingVariables || {}
|
||||
export const collectNodeMissing = (
|
||||
node: EvaluatedNode | ASTNode
|
||||
): Record<string, number> =>
|
||||
'missingVariables' in node ? node.missingVariables : {}
|
||||
|
||||
export const bonus = (missings, hasCondition = true) =>
|
||||
hasCondition ? map(x => x + 0.0001, missings || {}) : missings
|
||||
export const mergeAllMissing = missings =>
|
||||
export const mergeMissing = (
|
||||
left: Record<string, number> | undefined,
|
||||
right: Record<string, number> | undefined
|
||||
): Record<string, number> => mergeWith(add, left || {}, right || {})
|
||||
|
||||
export const mergeAllMissing = (missings: Array<EvaluatedNode | ASTNode>) =>
|
||||
missings.map(collectNodeMissing).reduce(mergeMissing, {})
|
||||
export const mergeMissing = (left, right) =>
|
||||
mergeWith(add, left || {}, right || {})
|
||||
|
||||
function convertNodesToSameUnit(nodes, contextRule, mecanismName) {
|
||||
const firstNodeWithUnit = nodes.find(node => !!node.unit)
|
||||
|
@ -144,7 +150,7 @@ export function evaluateObject<NodeName extends NodeKind>(
|
|||
) {
|
||||
return function(node) {
|
||||
const evaluate = this.evaluateNode.bind(this)
|
||||
const evaluations = mapObjIndexed(
|
||||
const evaluations: Record<string, EvaluatedNode> = mapObjIndexed(
|
||||
evaluate as any,
|
||||
(node as any).explanation
|
||||
)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* Those are postprocessor functions for the Nearley grammar.ne.
|
||||
The advantage of putting them here is to get prettier's JS formatting, since Nealrey doesn't support it https://github.com/kach/nearley/issues/310 */
|
||||
import { normalizeDateString } from './date'
|
||||
import { parseUnit } from './units'
|
||||
import { parsePeriod } from './temporal'
|
||||
|
||||
export let binaryOperation = operationType => ([A, , operator, , B]) => ({
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import { map } from 'ramda'
|
||||
import { compose, map, mapObjIndexed } from 'ramda'
|
||||
import { ASTNode, EvaluatedNode, NodeKind } from './AST/types'
|
||||
import { evaluationFunctions } from './evaluationFunctions'
|
||||
import { simplifyNodeUnit } from './nodeUnits'
|
||||
import parse from './parse'
|
||||
import parsePublicodes, { disambiguateReference } from './parsePublicodes'
|
||||
import { getReplacements, inlineReplacements, ReplacementNode } from './replacement'
|
||||
import { Rule, RuleNode } from './rule'
|
||||
import * as utils from './ruleUtils'
|
||||
|
||||
|
@ -52,6 +53,7 @@ export type ParsedRules<Name extends string> = Record<
|
|||
export default class Engine<Name extends string = string> {
|
||||
parsedRules: ParsedRules<Name>
|
||||
parsedSituation: Record<string, ASTNode> = {}
|
||||
replacements: Record<string, Array<ReplacementNode>> = {}
|
||||
cache: Cache
|
||||
private warnings: Array<string> = []
|
||||
|
||||
|
@ -73,7 +75,7 @@ export default class Engine<Name extends string = string> {
|
|||
this.parsedRules = parsePublicodes(
|
||||
rules as Record<string, Rule>
|
||||
) as ParsedRules<Name>
|
||||
|
||||
this.replacements = getReplacements(this.parsedRules)
|
||||
}
|
||||
|
||||
private resetCache() {
|
||||
|
@ -84,16 +86,18 @@ export default class Engine<Name extends string = string> {
|
|||
situation: Partial<Record<Name, string | number | object | ASTNode>> = {}
|
||||
) {
|
||||
this.resetCache()
|
||||
this.parsedSituation = map(value => {
|
||||
this.parsedSituation = mapObjIndexed((value, key) => {
|
||||
if (value && typeof value === 'object' && 'nodeKind' in value) {
|
||||
return value as ASTNode
|
||||
}
|
||||
return disambiguateReference(this.parsedRules)(
|
||||
return compose(
|
||||
inlineReplacements(this.replacements),
|
||||
disambiguateReference(this.parsedRules)
|
||||
)(
|
||||
parse(value, {
|
||||
dottedName: "situation'''",
|
||||
dottedName: `situation [${key}]`,
|
||||
parsedRules: {}
|
||||
})
|
||||
)
|
||||
}))
|
||||
}, situation)
|
||||
|
||||
return this
|
||||
|
@ -111,8 +115,10 @@ export default class Engine<Name extends string = string> {
|
|||
originalWarn(warning)
|
||||
}
|
||||
const result = this.evaluateNode(
|
||||
// TODO : No replacement here. Is this what we want ?
|
||||
disambiguateReference(this.parsedRules)(
|
||||
compose(
|
||||
inlineReplacements(this.replacements),
|
||||
disambiguateReference(this.parsedRules)
|
||||
)(
|
||||
parse(expression, {
|
||||
dottedName: "evaluation'''",
|
||||
parsedRules: {}
|
||||
|
|
|
@ -4,7 +4,7 @@ import parse from '../parse'
|
|||
import { InfixMecanism, Mecanism } from '../components/mecanisms/common'
|
||||
import { bonus, makeJsx, mergeMissing } from '../evaluation'
|
||||
import { registerEvaluationFunction } from '../evaluationFunctions'
|
||||
import { ASTNode } from '../AST/types'
|
||||
import { ASTNode, EvaluatedNode } from '../AST/types'
|
||||
|
||||
export type ApplicableSiNode = {
|
||||
explanation: {
|
||||
|
@ -39,7 +39,7 @@ const evaluate: evaluationFunction<'applicable si'> = function(node) {
|
|||
condition.nodeValue == null || condition.nodeValue === false
|
||||
? condition.nodeValue
|
||||
: 'nodeValue' in valeur
|
||||
? valeur.nodeValue
|
||||
? (valeur as EvaluatedNode).nodeValue
|
||||
: null,
|
||||
explanation: { valeur, condition },
|
||||
missingVariables: mergeMissing(
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import { is, map, max, mergeWith, reduce } from 'ramda'
|
||||
import { is, isEmpty, map, max, mergeWith, reduce } from 'ramda'
|
||||
import React from 'react'
|
||||
import { evaluationFunction } from '..'
|
||||
import { Mecanism } from '../components/mecanisms/common'
|
||||
import { ASTNode } from '../AST/types'
|
||||
import { collectNodeMissing, makeJsx } from '../evaluation'
|
||||
import { ASTNode, EvaluatedNode, Evaluation } from '../AST/types'
|
||||
import {
|
||||
collectNodeMissing,
|
||||
makeJsx,
|
||||
mergeAllMissing,
|
||||
mergeMissing
|
||||
} from '../evaluation'
|
||||
import { registerEvaluationFunction } from '../evaluationFunctions'
|
||||
import parse from '../parse'
|
||||
import { InternalError } from '../error'
|
||||
|
||||
export type UneDeCesConditionsNode = {
|
||||
explanation: Array<ASTNode>
|
||||
|
@ -14,24 +20,48 @@ export type UneDeCesConditionsNode = {
|
|||
}
|
||||
|
||||
const evaluate: evaluationFunction<'une de ces conditions'> = function(node) {
|
||||
const explanation = node.explanation.map(child => this.evaluateNode(child))
|
||||
|
||||
const anyTrue = explanation.find(e => e.nodeValue === true)
|
||||
const anyNull = explanation.find(e => e.nodeValue === null)
|
||||
const { nodeValue, missingVariables } = anyTrue ??
|
||||
anyNull ?? {
|
||||
type Calculations = {
|
||||
explanation: Array<ASTNode | EvaluatedNode>
|
||||
nodeValue: Evaluation<boolean>
|
||||
missingVariables: Record<string, number>
|
||||
}
|
||||
const calculations = node.explanation.reduce<Calculations>(
|
||||
(acc, node) => {
|
||||
if (acc.nodeValue === true) {
|
||||
return {
|
||||
...acc,
|
||||
explanation: [...acc.explanation, node]
|
||||
}
|
||||
}
|
||||
if (acc.nodeValue === null || acc.nodeValue === false) {
|
||||
const evaluatedNode = this.evaluateNode(node)
|
||||
return {
|
||||
nodeValue: evaluatedNode.nodeValue
|
||||
? true
|
||||
: evaluatedNode.nodeValue === null
|
||||
? null
|
||||
: acc.nodeValue,
|
||||
missingVariables: evaluatedNode.nodeValue
|
||||
? {}
|
||||
: mergeMissing(
|
||||
acc.missingVariables,
|
||||
evaluatedNode.missingVariables
|
||||
),
|
||||
explanation: [...acc.explanation, evaluatedNode]
|
||||
}
|
||||
}
|
||||
throw new InternalError([node, acc])
|
||||
},
|
||||
{
|
||||
nodeValue: false,
|
||||
// Unlike most other array merges of missing variables this is a "flat" merge
|
||||
// because "one of these conditions" tend to be several tests of the same variable
|
||||
// (e.g. contract type is one of x, y, z)
|
||||
missingVariables: reduce(
|
||||
mergeWith(max),
|
||||
{},
|
||||
map(collectNodeMissing, explanation)
|
||||
)
|
||||
missingVariables: {},
|
||||
explanation: []
|
||||
}
|
||||
|
||||
return { ...node, nodeValue, explanation, missingVariables }
|
||||
)
|
||||
return {
|
||||
...node,
|
||||
...calculations
|
||||
}
|
||||
}
|
||||
|
||||
export const mecanismOneOf = (v, context) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react'
|
||||
import { evaluationFunction } from '..'
|
||||
import { ASTNode } from '../AST/types'
|
||||
import { ASTNode, Unit } from '../AST/types'
|
||||
import { Mecanism } from '../components/mecanisms/common'
|
||||
import { convertToDate, convertToString } from '../date'
|
||||
import {
|
||||
|
@ -10,6 +10,7 @@ import {
|
|||
parseObject
|
||||
} from '../evaluation'
|
||||
import { registerEvaluationFunction } from '../evaluationFunctions'
|
||||
import { parseUnit } from '../units'
|
||||
|
||||
export type DuréeNode = {
|
||||
explanation: {
|
||||
|
@ -17,6 +18,7 @@ export type DuréeNode = {
|
|||
"jusqu'à": ASTNode
|
||||
}
|
||||
jsx: any
|
||||
unit: Unit
|
||||
nodeKind: 'durée'
|
||||
}
|
||||
|
||||
|
@ -75,6 +77,7 @@ export default (v, context) => {
|
|||
return {
|
||||
jsx: MecanismDurée,
|
||||
explanation,
|
||||
unit: parseUnit('jours'),
|
||||
nodeKind: 'durée'
|
||||
} as DuréeNode
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
mapTemporal,
|
||||
temporalAverage
|
||||
} from '../temporal'
|
||||
import { parseUnit } from '../units'
|
||||
|
||||
import {
|
||||
evaluatePlafondUntilActiveTranche,
|
||||
parseTranches,
|
||||
|
|
|
@ -38,15 +38,20 @@ export const evaluateInversion: evaluationFunction<'inversion'> = function(
|
|||
candidate =>
|
||||
this.parsedSituation[candidate.dottedName as string] != undefined
|
||||
)
|
||||
|
||||
if (inversionGoal === undefined) {
|
||||
const missingVariables = {
|
||||
...Object.fromEntries(
|
||||
node.explanation.inversionCandidates.map(candidate => [
|
||||
candidate.dottedName,
|
||||
1
|
||||
])
|
||||
),
|
||||
[node.explanation.ruleToInverse]: 1
|
||||
}
|
||||
return {
|
||||
...node,
|
||||
missingVariables: {
|
||||
...Object.fromEntries(
|
||||
node.explanation.inversionCandidates.map(name => [name, 1])
|
||||
),
|
||||
[node.explanation.ruleToInverse]: 1
|
||||
},
|
||||
missingVariables,
|
||||
nodeValue: null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import { evaluationFunction } from '..'
|
||||
import { InfixMecanism, Mecanism } from '../components/mecanisms/common'
|
||||
import { ASTNode } from '../AST/types'
|
||||
import { ASTNode, EvaluatedNode } from '../AST/types'
|
||||
import { bonus, makeJsx, mergeMissing } from '../evaluation'
|
||||
import { registerEvaluationFunction } from '../evaluationFunctions'
|
||||
import parse from '../parse'
|
||||
|
@ -30,7 +30,7 @@ function MecanismNonApplicable({ explanation }) {
|
|||
const evaluate: evaluationFunction<'non applicable si'> = function(node) {
|
||||
const condition = this.evaluateNode(node.explanation.condition)
|
||||
let valeur = node.explanation.valeur
|
||||
if (condition.nodeValue !== true) {
|
||||
if (condition.nodeValue === false || condition.nodeValue === null) {
|
||||
valeur = this.evaluateNode(valeur)
|
||||
}
|
||||
return {
|
||||
|
@ -38,10 +38,10 @@ const evaluate: evaluationFunction<'non applicable si'> = function(node) {
|
|||
nodeValue:
|
||||
condition.nodeValue === null
|
||||
? null
|
||||
: condition.nodeValue === true
|
||||
: condition.nodeValue !== false
|
||||
? false
|
||||
: 'nodeValue' in valeur
|
||||
? valeur.nodeValue
|
||||
? (valeur as EvaluatedNode).nodeValue
|
||||
: null,
|
||||
explanation: { valeur, condition },
|
||||
missingVariables: mergeMissing(
|
||||
|
|
|
@ -26,8 +26,8 @@ export const mecanismOnePossibility = (v, context: Context) => {
|
|||
jsx: (node: PossibilityNode) => (
|
||||
<Mecanism name="une possibilité parmis" value={null}>
|
||||
<ul>
|
||||
{node.explanation.map(node => (
|
||||
<li>{makeJsx(node)}</li>
|
||||
{node.explanation.map((node, i) => (
|
||||
<li key={i}>{makeJsx(node)}</li>
|
||||
))}
|
||||
</ul>
|
||||
</Mecanism>
|
||||
|
|
|
@ -30,7 +30,10 @@ function ParDéfautComponent({ explanation }) {
|
|||
}
|
||||
|
||||
const evaluate: evaluationFunction<'par défaut'> = function(node) {
|
||||
const explanation = { ...node.explanation }
|
||||
const explanation: {
|
||||
parDéfaut: EvaluatedNode | ASTNode
|
||||
valeur: EvaluatedNode | ASTNode
|
||||
} = { ...node.explanation }
|
||||
let valeur = this.evaluateNode(explanation.valeur)
|
||||
explanation.valeur = valeur
|
||||
if (valeur.nodeValue === null) {
|
||||
|
|
|
@ -40,10 +40,10 @@ const evaluate: evaluationFunction<'plafond'> = function(node) {
|
|||
let nodeValue = valeur.nodeValue
|
||||
let plafond = node.explanation.plafond
|
||||
if (nodeValue !== false) {
|
||||
plafond = this.evaluateNode(plafond)
|
||||
const evaluatedPlafond = this.evaluateNode(plafond)
|
||||
if (valeur.unit) {
|
||||
try {
|
||||
plafond = convertNodeToUnit(valeur.unit, plafond as EvaluatedNode)
|
||||
plafond = convertNodeToUnit(valeur.unit, evaluatedPlafond)
|
||||
} catch (e) {
|
||||
typeWarning(
|
||||
this.cache._meta.contextRule,
|
||||
|
@ -53,7 +53,7 @@ const evaluate: evaluationFunction<'plafond'> = function(node) {
|
|||
}
|
||||
}
|
||||
}
|
||||
plafond
|
||||
|
||||
if (
|
||||
typeof nodeValue === 'number' &&
|
||||
'nodeValue' in plafond &&
|
||||
|
|
|
@ -38,10 +38,10 @@ const evaluate: evaluationFunction<'plancher'> = function(node) {
|
|||
let nodeValue = valeur.nodeValue
|
||||
let plancher = node.explanation.plancher
|
||||
if (nodeValue !== false) {
|
||||
plancher = this.evaluateNode(plancher)
|
||||
const evaluatedPlancher = this.evaluateNode(plancher)
|
||||
if (valeur.unit) {
|
||||
try {
|
||||
plancher = convertNodeToUnit(valeur.unit, plancher as EvaluatedNode)
|
||||
plancher = convertNodeToUnit(valeur.unit, evaluatedPlancher)
|
||||
} catch (e) {
|
||||
typeWarning(
|
||||
this.cache._meta.contextRule,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { isEmpty } from 'ramda'
|
||||
import { EvaluatedRule } from '..'
|
||||
import { ASTNode, EvaluatedNode } from '../AST/types'
|
||||
import { InfixMecanism } from '../components/mecanisms/common'
|
||||
import { makeJsx, mergeAllMissing } from '../evaluation'
|
||||
|
@ -32,7 +33,6 @@ export default function parseSituation(v, context) {
|
|||
situationKey: v[parseSituation.nom],
|
||||
valeur: parse(v.valeur, context)
|
||||
}
|
||||
|
||||
return {
|
||||
jsx: MecanismSituation,
|
||||
nodeKind: parseSituation.nom,
|
||||
|
@ -59,7 +59,9 @@ registerEvaluationFunction(parseSituation.nom, function evaluate(node) {
|
|||
valeur.unit ??
|
||||
('unit' in explanation.valeur ? explanation.valeur.unit : undefined)
|
||||
const missingVariables = mergeAllMissing(
|
||||
[explanation.situationValeur, explanation.valeur].filter(Boolean)
|
||||
[explanation.situationValeur, explanation.valeur].filter(Boolean) as Array<
|
||||
EvaluatedRule
|
||||
>
|
||||
)
|
||||
return {
|
||||
...node,
|
||||
|
|
|
@ -59,7 +59,7 @@ registerEvaluationFunction(parseUnité.nom, function evaluate(node) {
|
|||
} catch (e) {
|
||||
typeWarning(
|
||||
this.cache._meta.contextRule,
|
||||
`Erreur lors de la conversion d'unité explicite`,
|
||||
'Erreur lors de la conversion d\'unité explicite',
|
||||
e
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { or } from 'ramda'
|
||||
import { evaluationFunction } from '..'
|
||||
import Variations from '../components/mecanisms/Variations'
|
||||
import { ASTNode, Unit } from '../AST/types'
|
||||
import { ASTNode, EvaluatedNode, Unit } from '../AST/types'
|
||||
import { typeWarning } from '../error'
|
||||
import { bonus, defaultNode } from '../evaluation'
|
||||
import { registerEvaluationFunction } from '../evaluationFunctions'
|
||||
|
@ -23,7 +23,7 @@ export type VariationNode = {
|
|||
satisfied?: boolean
|
||||
}>
|
||||
nodeKind: 'variations'
|
||||
jsx: Function
|
||||
jsx: (n: any) => unknown
|
||||
}
|
||||
|
||||
export const devariate = (k, v, context): ASTNode => {
|
||||
|
@ -95,7 +95,10 @@ const evaluate: evaluationFunction<'variations'> = function(node) {
|
|||
const evaluatedCondition = this.evaluateNode(condition)
|
||||
const currentCondition = liftTemporal2(
|
||||
(previousCond, currentCond) =>
|
||||
previousCond === null ? previousCond : !previousCond && currentCond,
|
||||
previousCond === null
|
||||
? previousCond
|
||||
: !previousCond &&
|
||||
(currentCond === null ? null : currentCond !== false),
|
||||
previousConditions,
|
||||
evaluatedCondition.temporalValue ??
|
||||
pureTemporal(evaluatedCondition.nodeValue)
|
||||
|
|
|
@ -67,7 +67,10 @@ Utilisez leur contrepartie française : 'oui' / 'non'`
|
|||
|
||||
const compiledGrammar = Grammar.fromCompiled(grammar)
|
||||
|
||||
function parseExpression(rawNode, context: Context): Object | undefined {
|
||||
function parseExpression(
|
||||
rawNode,
|
||||
context: Context
|
||||
): Record<string, unknown> | undefined {
|
||||
/* Strings correspond to infix expressions.
|
||||
* Indeed, a subset of expressions like simple arithmetic operations `3 + (quantity * 2)` or like `salary [month]` are more explicit that their prefixed counterparts.
|
||||
* This function makes them prefixed operations. */
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import yaml from 'yaml'
|
||||
import { ParsedRules } from '.'
|
||||
import { traverseParsedRules, updateAST } from './AST'
|
||||
import parse from './parse'
|
||||
import { inlineReplacements } from './replacement'
|
||||
import {
|
||||
getReplacements,
|
||||
inlineReplacements,
|
||||
ReplacementNode
|
||||
} from './replacement'
|
||||
import { Rule, RuleNode } from './rule'
|
||||
import { disambiguateRuleReference } from './ruleUtils'
|
||||
|
||||
|
@ -13,10 +18,10 @@ export type Context = {
|
|||
type RawRule = Omit<Rule, 'nom'> | string | undefined | number
|
||||
export type RawPublicodes = Record<string, RawRule> | string
|
||||
|
||||
export default function parsePublicodes<Names extends string>(
|
||||
export default function parsePublicodes(
|
||||
rawRules: RawPublicodes,
|
||||
partialContext: Partial<Context> = {}
|
||||
) {
|
||||
): ParsedRules<string> {
|
||||
// STEP 1: parse Yaml
|
||||
let rules =
|
||||
typeof rawRules === 'string'
|
||||
|
@ -41,7 +46,7 @@ export default function parsePublicodes<Names extends string>(
|
|||
}
|
||||
if (typeof rule !== 'object') {
|
||||
rule = {
|
||||
formule: rule
|
||||
formule: '' + rule
|
||||
}
|
||||
}
|
||||
parse({ nom: dottedName, ...rule }, context)
|
||||
|
@ -52,10 +57,14 @@ export default function parsePublicodes<Names extends string>(
|
|||
parsedRules = traverseParsedRules(
|
||||
disambiguateReference(parsedRules),
|
||||
parsedRules
|
||||
) as Record<string, RuleNode>
|
||||
)
|
||||
|
||||
// STEP 5: Inline replacements
|
||||
parsedRules = inlineReplacements(parsedRules)
|
||||
const replacements = getReplacements(parsedRules)
|
||||
parsedRules = traverseParsedRules(
|
||||
inlineReplacements(replacements),
|
||||
parsedRules
|
||||
)
|
||||
|
||||
// TODO STEP 6: check for cycle
|
||||
|
||||
|
@ -73,7 +82,7 @@ function transpileRef(object: Record<string, any> | string | Array<any>) {
|
|||
if (!object || typeof object !== 'object') {
|
||||
return object
|
||||
}
|
||||
object as Record<string, any>
|
||||
object
|
||||
return Object.entries(object).reduce((obj, [key, value]) => {
|
||||
const match = /\[ref( (.+))?\]$/.exec(key)
|
||||
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import { groupBy } from 'ramda'
|
||||
import { AST } from 'yaml'
|
||||
import { traverseParsedRules, updateAST } from './AST'
|
||||
import { updateAST } from './AST'
|
||||
import { ASTNode } from './AST/types'
|
||||
import Variations from './components/mecanisms/Variations'
|
||||
import { InternalError, warning } from './error'
|
||||
import { defaultNode, makeJsx } from './evaluation'
|
||||
import { VariationNode } from './mecanisms/variations'
|
||||
import parse from './parse'
|
||||
import { Context } from './parsePublicodes'
|
||||
import { RuleNode } from './rule'
|
||||
import { Rule } from './rule'
|
||||
import { Rule, RuleNode } from './rule'
|
||||
import { coerceArray } from './utils'
|
||||
|
||||
export type ReplacementNode = {
|
||||
|
@ -36,7 +33,7 @@ export function parseReplacements(
|
|||
}
|
||||
|
||||
const replacedReference = parse(replacement.règle, context)
|
||||
let replacementNode = parse(replacement.par ?? context.dottedName, context)
|
||||
const replacementNode = parse(replacement.par ?? context.dottedName, context)
|
||||
|
||||
const [whiteListedNames, blackListedNames] = [
|
||||
replacement.dans ?? [],
|
||||
|
@ -82,10 +79,10 @@ export function parseRendNonApplicable(
|
|||
)
|
||||
}
|
||||
|
||||
export function inlineReplacements(
|
||||
export function getReplacements(
|
||||
parsedRules: Record<string, RuleNode>
|
||||
): Record<string, RuleNode> {
|
||||
const replacements: Record<string, Array<ReplacementNode>> = groupBy(
|
||||
): Record<string, Array<ReplacementNode>> {
|
||||
return groupBy(
|
||||
(r: ReplacementNode) => {
|
||||
if (!r.replacedReference.dottedName) {
|
||||
throw new InternalError(r)
|
||||
|
@ -94,27 +91,38 @@ export function inlineReplacements(
|
|||
},
|
||||
Object.values(parsedRules).flatMap(rule => rule.replacements)
|
||||
)
|
||||
return traverseParsedRules(
|
||||
updateAST(node => {
|
||||
if (
|
||||
node.nodeKind === 'replacement' ||
|
||||
node.nodeKind === 'inversion' ||
|
||||
node.nodeKind === 'une possibilité' ||
|
||||
node.nodeKind === 'recalcul'
|
||||
) {
|
||||
// We don't want to replace references in replacements...
|
||||
// Nor in ammended situation of recalcul and inversion (for now)
|
||||
return false
|
||||
}
|
||||
if (node.nodeKind === 'reference') {
|
||||
if (!node.dottedName) {
|
||||
throw new InternalError(node)
|
||||
}
|
||||
|
||||
export function inlineReplacements(
|
||||
replacements: Record<string, Array<ReplacementNode>>
|
||||
): (n: ASTNode) => ASTNode {
|
||||
return updateAST((n, fn) => {
|
||||
if (
|
||||
n.nodeKind === 'replacement' ||
|
||||
n.nodeKind === 'inversion' ||
|
||||
n.nodeKind === 'une possibilité'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (n.nodeKind === 'recalcul') {
|
||||
// We don't replace references in recalcul keys
|
||||
return {
|
||||
...n,
|
||||
explanation: {
|
||||
recalcul: fn(n.explanation.recalcul),
|
||||
amendedSituation: n.explanation.amendedSituation.map(
|
||||
([name, value]) => [name, fn(value)]
|
||||
)
|
||||
}
|
||||
return replace(node, replacements[node.dottedName] ?? [])
|
||||
}
|
||||
}),
|
||||
parsedRules
|
||||
) as Record<string, RuleNode>
|
||||
}
|
||||
if (n.nodeKind === 'reference') {
|
||||
if (!n.dottedName) {
|
||||
throw new InternalError(n)
|
||||
}
|
||||
return replace(n, replacements[n.dottedName] ?? [])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function replace(
|
||||
|
@ -145,7 +153,7 @@ function replace(
|
|||
.sort((r1, r2) => {
|
||||
// Replacement with whitelist conditions have precedence over the others
|
||||
const criterion1 =
|
||||
(+!!r2.whiteListedNames.length as number) -
|
||||
(+!!r2.whiteListedNames.length ) -
|
||||
+!!r1.whiteListedNames.length
|
||||
// Replacement with blacklist condition have precedence over the others
|
||||
const criterion2 =
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { filter, mapObjIndexed, pick } from 'ramda'
|
||||
import { ASTNode, EvaluatedNode } from './AST/types'
|
||||
import { bonus, makeJsx, mergeMissing } from './evaluation'
|
||||
import { registerEvaluationFunction } from "./evaluationFunctions"
|
||||
import { registerEvaluationFunction } from './evaluationFunctions'
|
||||
import parse, { mecanismKeys } from './parse'
|
||||
import { Context } from './parsePublicodes'
|
||||
import { ReferenceNode } from './reference'
|
||||
|
@ -10,7 +10,7 @@ import { nameLeaf, ruleParents } from './ruleUtils'
|
|||
import { capitalise0 } from './utils'
|
||||
|
||||
export type Rule = {
|
||||
formule?: Object | string
|
||||
formule?: Record<string, unknown> | string
|
||||
question?: string
|
||||
description?: string
|
||||
unité?: string
|
||||
|
@ -27,14 +27,14 @@ export type Rule = {
|
|||
note?: string
|
||||
remplace?: RendNonApplicable | Array<RendNonApplicable>
|
||||
'rend non applicable'?: Remplace | Array<string>
|
||||
suggestions?: Record<string, string | number | object>
|
||||
suggestions?: Record<string, string | number | Record<string, unknown>>
|
||||
références?: { [source: string]: string }
|
||||
API?: string
|
||||
}
|
||||
|
||||
type Remplace = {
|
||||
règle: string
|
||||
par?: Object | string | number
|
||||
par?: Record<string, unknown> | string | number
|
||||
dans?: Array<string> | string
|
||||
'sauf dans'?: Array<string> | string
|
||||
} | string
|
||||
|
@ -43,10 +43,10 @@ type RendNonApplicable = Exclude<Remplace, {par: any}>
|
|||
export type RuleNode = {
|
||||
dottedName: string
|
||||
title: string
|
||||
nodeKind: "rule"
|
||||
nodeKind: 'rule'
|
||||
jsx: any
|
||||
virtualRule: boolean,
|
||||
rawNode: Rule,
|
||||
virtualRule: boolean
|
||||
rawNode: Rule
|
||||
replacements: Array<ReplacementNode>
|
||||
explanation: {
|
||||
parent: ASTNode | false
|
||||
|
@ -86,12 +86,12 @@ export default function parseRule(
|
|||
context.parsedRules[dottedName] = filter(Boolean, {
|
||||
dottedName,
|
||||
replacements: [
|
||||
...parseRendNonApplicable(rawRule["rend non applicable"], ruleContext),
|
||||
...parseRendNonApplicable(rawRule['rend non applicable'], ruleContext),
|
||||
...parseReplacements(rawRule.remplace, ruleContext),
|
||||
],
|
||||
title: capitalise0(rawRule['titre'] || name),
|
||||
suggestions: mapObjIndexed(node => parse(node, ruleContext), rawRule.suggestions ?? {}),
|
||||
nodeKind: "rule",
|
||||
nodeKind: 'rule',
|
||||
jsx: node => <>
|
||||
<code className="ui__ light-bg">{capitalise0(node.rawNode.nom)}</code>
|
||||
{makeJsx(node.explanation.valeur)}
|
||||
|
|
|
@ -27,7 +27,7 @@ export function ruleParents<Names extends string>(
|
|||
|
||||
export function disambiguateRuleReference<R extends Record<string, RuleNode>>(
|
||||
rules: R,
|
||||
contextName: string = '',
|
||||
contextName = '',
|
||||
partialName: string
|
||||
): keyof R {
|
||||
const possibleDottedName = [
|
||||
|
|
|
@ -51,6 +51,6 @@ describe('Cyclic dependencies detectron 3000 ™', () => {
|
|||
formule: a
|
||||
`
|
||||
const cycles = cyclesInDependenciesGraph(rules)
|
||||
expect(cycles).to.deep.equal([["a", "a . c"]])
|
||||
expect(cycles).to.deep.equal([['a', 'a . c']])
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue