From 3d2021ca2140a25ac5a002322ea6157cd1023c38 Mon Sep 17 00:00:00 2001 From: Johan Girod Date: Tue, 17 May 2022 10:45:25 +0200 Subject: [PATCH] =?UTF-8?q?Met=20=C3=A0=20jour=20vers=20la=20derni=C3=A8re?= =?UTF-8?q?=20version=20de=20publicodes=20(1.0.0-beta.38)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exoneration-covid/package.json | 4 +- modele-social/package.json | 4 +- modele-social/règles/dirigeant.yaml | 111 ++++++++++-------- modele-social/règles/profession-libérale.yaml | 68 ++++++----- modele-social/règles/protection-sociale.yaml | 5 +- modele-social/règles/salarié.yaml | 41 +++---- site/package.json | 4 +- site/source/components/EngineValue.tsx | 45 ++----- site/source/components/Feedback/index.tsx | 2 + site/source/components/PaySlip.tsx | 7 +- site/source/components/PaySlipSections.tsx | 45 ++++--- site/source/design-system/global-style.ts | 4 - site/source/design-system/popover/Popover.tsx | 4 + site/source/design-system/typography/link.tsx | 4 +- site/source/pages/Simulateurs/Salarié.tsx | 15 +-- site/test/conversation.test.js | 12 +- .../simulations-salarié.test.ts.snap | 2 +- .../simulations-auto-entrepreneur.test.ts | 10 +- .../regressions/simulations-salarié.test.ts | 28 ++--- site/test/regressions/utils.ts | 10 +- yarn.lock | 43 +++---- 21 files changed, 222 insertions(+), 246 deletions(-) diff --git a/exoneration-covid/package.json b/exoneration-covid/package.json index 490c7b06e..f93b83968 100644 --- a/exoneration-covid/package.json +++ b/exoneration-covid/package.json @@ -19,10 +19,10 @@ "devDependencies": { "js-yaml": "^4.1.0", "onchange": "^7.1.0", - "publicodes": "^1.0.0-beta.32" + "publicodes": "=1.0.0-beta.40" }, "peerDependencies": { - "publicodes": "^1.0.0-beta.32" + "publicodes": "*" }, "scripts": { "build": "node ../scripts/build-rules.js", diff --git a/modele-social/package.json b/modele-social/package.json index d30b944f4..6ee5e75fb 100644 --- a/modele-social/package.json +++ b/modele-social/package.json @@ -20,10 +20,10 @@ "devDependencies": { "js-yaml": "^4.1.0", "onchange": "^7.1.0", - "publicodes": "^1.0.0-beta.32" + "publicodes": "=1.0.0-beta.40" }, "peerDependencies": { - "publicodes": "^1.0.0-beta.32" + "publicodes": "*" }, "scripts": { "build": "node ../scripts/build-rules.js", diff --git a/modele-social/règles/dirigeant.yaml b/modele-social/règles/dirigeant.yaml index 139bcbdc7..568f62393 100644 --- a/modele-social/règles/dirigeant.yaml +++ b/modele-social/règles/dirigeant.yaml @@ -565,14 +565,13 @@ dirigeant . indépendant . cotisations et contributions . PSS proratisé: Le plafond de la sécurité sociale, proratisé par la durée d'activité pendant l'année (dans le cas d'activité crée ou cessée en cours d'année). Utile pour calculer les cotisations forfaitaires de début d'activité ou le montant de l'ACRE - formule: - unité: €/an - produit: - assiette: plafond sécurité sociale temps plein - taux: - valeur: entreprise . durée d'activité . en fin d'année / 1 an - plafond: 100% - arrondi: oui + unité: €/an + produit: + assiette: plafond sécurité sociale temps plein + taux: + valeur: entreprise . durée d'activité . en fin d'année / 1 an + plafond: 100% + arrondi: oui dirigeant . indépendant . cotisations et contributions . exonérations . ACRE . prorata sur l'année: description: | @@ -700,8 +699,7 @@ dirigeant . indépendant . conjoint collaborateur . cotisations . assiette: - si: assiette . pourcentage . moitié alors: taux: 50% - - sinon: oui - # sinon rien ne change + - sinon: {} dirigeant . indépendant . conjoint collaborateur . cotisations: titre: Cotisations conjoint collaborateur @@ -752,27 +750,23 @@ dirigeant . indépendant . conjoint collaborateur . cotisations . retraite compl alors: 4 * plafond sécurité sociale temps plein - sinon: 3 * plafond sécurité sociale temps plein -dirigeant . indépendant . conjoint collaborateur . cotisations . invalidité et décès . assiette: - titre: assiette invalidité et décès - formule: - le maximum de: - - cotisations . assiette - - 20% * plafond sécurité sociale temps plein dirigeant . indépendant . conjoint collaborateur . cotisations . invalidité et décès: titre: invalidité et décès (conjoint collaborateur) - unité: €/an produit: - assiette: assiette + assiette: + unité: €/an + valeur: cotisations . assiette + plancher: 20% * plafond sécurité sociale temps plein + plafond: plafond sécurité sociale temps plein taux: 1.3% - plafond: plafond sécurité sociale temps plein arrondi: oui dirigeant . indépendant . conjoint collaborateur . cotisations . indemnités journalières maladie: titre: indemnités journalières maladie (conjoint collaborateur) produit: assiette: - valeur: 40% * plafond sécurité sociale temps plein unité: €/an + valeur: 40% * plafond sécurité sociale temps plein taux: cotisations et contributions . indemnités journalières maladie . taux arrondi: oui @@ -1028,22 +1022,27 @@ dirigeant . indépendant . cotisations et contributions . début activité: recalcul: règle: cotisations et contributions avec: - maladie . taux progressif . assiette: 40% * plafond sécurité sociale temps plein assiette des cotisations: assiette forfaitaire CSG et CRDS . assiette: assiette forfaitaire dirigeant . indépendant . cotisations facultatives: non + maladie . taux progressif . assiette: assiette forfaitaire maladie + avec: + assiette forfaitaire: + produit: + assiette: PSS proratisé + taux: 19% + arrondi: oui + unité: €/an + références: + Fiche Urssaf: https://www.urssaf.fr/portail/home/independant/mes-cotisations/les-etapes-de-calcul/le-mode-de-calcul/les-cotisations-provisionnelles/debut-dactivite.html + assiette forfaitaire maladie: + valeur: 40% * plafond sécurité sociale temps plein + unité: €/an + arrondi: oui + références: Fiche Urssaf: https://www.urssaf.fr/portail/home/independant/mes-cotisations/les-etapes-de-calcul/le-mode-de-calcul/lajustement-et-la-regularisation.html -dirigeant . indépendant . cotisations et contributions . début activité . assiette forfaitaire: - produit: - assiette: PSS proratisé - taux: 19% - unité: €/an - arrondi: oui - références: - Fiche Urssaf: https://www.urssaf.fr/portail/home/independant/mes-cotisations/les-etapes-de-calcul/le-mode-de-calcul/les-cotisations-provisionnelles/debut-dactivite.html - dirigeant . indépendant . cotisations et contributions . régularisation: titre: Comment fonctionne la régularisation des cotisations provisionnelles description: | @@ -1085,6 +1084,7 @@ dirigeant . indépendant . cotisations et contributions . indemnités journaliè nom: taux valeur: 0.85% arrondi: oui + unité: €/an références: Cotisation minimale: https://www.secu-independants.fr/cotisations/calcul-des-cotisations/cotisations-minimales/ Taux de cotisations: https://www.secu-independants.fr/cotisations/calcul-cotisations/taux-de-cotisations/ @@ -1104,6 +1104,7 @@ dirigeant . indépendant . cotisations et contributions . maladie: plafond: 5 - taux: 6.5% arrondi: oui + unité: €/an références: Articles D621-1 à D621-6 du Code de la sécurité sociale: https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006073189/LEGISCTA000028171649/#LEGISCTA000036475251 taux de cotisations: https://www.secu-independants.fr/cotisations/calcul-cotisations/taux-de-cotisations/ @@ -1182,18 +1183,19 @@ dirigeant . indépendant . cotisations et contributions . retraite complémentai - taux: 8% plafond: 4 * plafond sécurité sociale temps plein arrondi: oui + unité: €/an références: Fiche Urssaf: https://www.urssaf.fr/portail/home/taux-et-baremes/taux-de-cotisations/artisans-commercants-et-professi/bases-de-calcul-et-taux-des-coti.html dirigeant . indépendant . cotisations et contributions . invalidité et décès: - formule: - produit: - assiette: - valeur: assiette des cotisations - plancher: assiette minimale . retraite - plafond: plafond sécurité sociale temps plein - taux: 1.3% - arrondi: oui + produit: + assiette: + valeur: assiette des cotisations + plancher: assiette minimale . retraite + plafond: plafond sécurité sociale temps plein + taux: 1.3% + unité: €/an + arrondi: oui références: Cotisation minimale: https://www.secu-independants.fr/cotisations/calcul-des-cotisations/cotisations-minimales/ @@ -1205,6 +1207,7 @@ dirigeant . indépendant . cotisations et contributions . CSG et CRDS: - attributs: nom: non déductible arrondi: oui + unité: €/an composantes: - taux: nom: taux @@ -1216,6 +1219,7 @@ dirigeant . indépendant . cotisations et contributions . CSG et CRDS: - attributs: nom: déductible arrondi: oui + unité: €/an composantes: - taux: nom: taux @@ -1289,20 +1293,20 @@ dirigeant . indépendant . cotisations et contributions . formation professionne brève Urssaf pour les artisans: https://www.urssaf.fr/portail/home/actualites/toute-lactualite-indépendant/transfert-du-recouvrement-de-la.html dirigeant . indépendant . cotisations et contributions . allocations familiales: - formule: - produit: - assiette: assiette des cotisations - taux: - nom: taux - taux progressif: - assiette: assiette des cotisations - multiplicateur: plafond sécurité sociale temps plein - tranches: - - plafond: 110% - taux: 0% - - plafond: 140% - taux: 3.1% - arrondi: oui + produit: + assiette: assiette des cotisations + taux: + nom: taux + taux progressif: + assiette: assiette des cotisations + multiplicateur: plafond sécurité sociale temps plein + tranches: + - plafond: 110% + taux: 0% + - plafond: 140% + taux: 3.1% + arrondi: oui + unité: €/an dirigeant . indépendant . cotisations et contributions . exonérations: formule: @@ -1478,6 +1482,7 @@ dirigeant . indépendant . cotisations et contributions . exonérations . covid dirigeant . indépendant . cotisations et contributions . exonérations . covid . part cotisations: titre: Part réduction Covid sur cotisations (hors CSG/CRDS) arrondi: oui + unité: €/an résoudre la référence circulaire: oui produit: assiette: montant @@ -1497,6 +1502,7 @@ dirigeant . indépendant . cotisations et contributions . exonérations . covid assiette: part CSG taux: CSG et CRDS . déductible . taux / taux CSG arrondi: oui + unité: €/an dirigeant . indépendant . cotisations et contributions . exonérations . covid . part CSG . non déductible: titre: Part réduction Covid sur CSG/CRDS non déductible @@ -1516,6 +1522,7 @@ dirigeant . indépendant . cotisations et contributions . maladie domiciliation produit: assiette: assiette des cotisations taux: 14.5% + unité: €/an arrondi: oui dirigeant . indépendant . IJSS: diff --git a/modele-social/règles/profession-libérale.yaml b/modele-social/règles/profession-libérale.yaml index 9ac0da33a..142e1aa7b 100644 --- a/modele-social/règles/profession-libérale.yaml +++ b/modele-social/règles/profession-libérale.yaml @@ -493,11 +493,13 @@ dirigeant . indépendant . PL . CNAVPL . retraite: - attributs: nom: tranche T1 arrondi: oui + unité: €/an taux: 8.23% plafond: plafond sécurité sociale temps plein - attributs: nom: tranche T2 arrondi: oui + unité: €/an taux: 1.87% plafond: 5 * plafond sécurité sociale temps plein références: @@ -538,6 +540,7 @@ dirigeant . indépendant . PL . CNAVPL . indemnités journalières maladie: - si: date >= 01/2021 alors: 0.15% arrondi: oui + unité: €/an références: Communiqué de la CNAVPL: https://www.cnavpl.fr/les-pl-indemnises-des-ij/ @@ -588,8 +591,7 @@ dirigeant . indépendant . PL . CNAVPL . conjoint collaborateur . assiette: - si: proportion . quart alors: taux: 25% - - sinon: oui - # sinon rien ne change + - sinon: {} dirigeant . indépendant . PL . CNAVPL . conjoint collaborateur . retraite: titre: Retraite de base (conjoint collaborateur CNAVPL) @@ -704,6 +706,7 @@ dirigeant . indépendant . PL . PAMC . CURPS: - sinon: 0.1% plafond: 0.50% * plafond sécurité sociale temps plein arrondi: oui + unité: €/an références: Fiche Urssaf.fr: https://www.urssaf.fr/portail/home/independant/mes-cotisations/quelles-cotisations/la-contribution-aux-unions-regio/la-base-de-calcul-et-le-taux-de.html @@ -1139,19 +1142,19 @@ dirigeant . indépendant . PL . CARMF . retraite CNAVPL: dirigeant . indépendant . PL . CARMF . retraite CNAVPL . participation CPAM: titre: participation CPAM à la retraite de base - formule: - produit: - assiette: assiette des cotisations - taux: - grille: - assiette: assiette des cotisations - multiplicateur: plafond sécurité sociale temps plein - tranches: - - montant: 2.15% - plafond: 140% - - montant: 1.51% - plafond: 250% - - montant: 1.12% + unité: €/an + produit: + assiette: assiette des cotisations + taux: + grille: + assiette: assiette des cotisations + multiplicateur: plafond sécurité sociale temps plein + tranches: + - montant: 2.15% + plafond: 140% + - montant: 1.51% + plafond: 250% + - montant: 1.12% arrondi: oui références: Avenant 5 à la convention médical: https://www.ameli.fr/sites/default/files/Documents/434342/document/avis_relatif_a_lavenant_ndeg_5_a_la_convention_nationale_organisant_les_rapports_entre_les_medecins_liberaux_et_lassurance_maladie.pdf @@ -1179,7 +1182,7 @@ dirigeant . indépendant . PL . CARMF . retraite complémentaire: assiette: assiette des cotisations plafond: 3.5 * plafond sécurité sociale temps plein taux: 9.80% - + unité: €/an références: Site CARMF: http://www.carmf.fr/page.php?page=cdrom/coti/coti-chiffre.htm @@ -1234,6 +1237,7 @@ dirigeant . indépendant . PL . CARMF . ASV: assiette: PAMC . revenus activité conventionnée plafond: 5 * plafond sécurité sociale temps plein taux: 3.80% + unité: €/an abattement: participation CPAM arrondi: oui références: @@ -1271,6 +1275,7 @@ dirigeant . indépendant . PL . CARCDSF . retraite complémentaire: dirigeant . indépendant . PL . CARCDSF . retraite complémentaire . cotisation proportionnelle: formule: + unité: €/an barème: assiette: assiette des cotisations multiplicateur: plafond sécurité sociale temps plein @@ -1342,22 +1347,22 @@ dirigeant . indépendant . PL . CARCDSF . chirurgien-dentiste . PCV: Cette dispense entraîne l’annulation des droits pour l’année et les points non cotisés ne sont pas rachetables. - formule: - somme: - - forfaitaire - - proportionnelle - arrondi: oui -dirigeant . indépendant . PL . CARCDSF . chirurgien-dentiste . PCV . forfaitaire: - formule: 1440.60 €/an -dirigeant . indépendant . PL . CARCDSF . chirurgien-dentiste . PCV . proportionnelle: - formule: - produit: - assiette: assiette des cotisations - plafond: 5 * plafond sécurité sociale temps plein - taux: 0.725 % - références: - Site CARCDSF: http://www.carcdsf.fr/cotisations-du-praticien/montant-des-cotisations + somme: + - forfaitaire + - proportionnelle + arrondi: oui + avec: + forfaitaire: 1440.60 €/an + proportionnelle: + produit: + assiette: assiette des cotisations + plafond: 5 * plafond sécurité sociale temps plein + taux: 0.725 % + unité: €/an + références: + Site CARCDSF: http://www.carcdsf.fr/cotisations-du-praticien/montant-des-cotisations + dirigeant . indépendant . PL . CARCDSF . chirurgien-dentiste . PCV . participation CPAM: titre: Participation CPAM à la prestation complémentaire vieillesse formule: @@ -1420,6 +1425,7 @@ dirigeant . indépendant . PL . CARCDSF . sage-femme . RID . classe: - A - B - C + dirigeant . indépendant . PL . CARCDSF . sage-femme . RID . classe . A: titre: classe A dirigeant . indépendant . PL . CARCDSF . sage-femme . RID . classe . B: diff --git a/modele-social/règles/protection-sociale.yaml b/modele-social/règles/protection-sociale.yaml index d441e63e2..6a12fb7bd 100644 --- a/modele-social/règles/protection-sociale.yaml +++ b/modele-social/règles/protection-sociale.yaml @@ -109,7 +109,10 @@ protection sociale . retraite . base . trimestres . indépendant: <<: *bareme_trimestre assiette: nom: revenu cotisé - valeur: dirigeant . indépendant . cotisations et contributions . retraite de base / dirigeant . indépendant . cotisations et contributions . retraite de base . taux + condition: + si: dirigeant . indépendant . PL . CNAVPL . exonération incapacité + alors: 0€/an + sinon: dirigeant . indépendant . cotisations et contributions . retraite de base / dirigeant . indépendant . cotisations et contributions . retraite de base . taux références: Article R351-9 du code de la sécurité sociale: https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000028751530/2014-03-21 Article R634-1 du code de la sécurité sociale: https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000038787378 diff --git a/modele-social/règles/salarié.yaml b/modele-social/règles/salarié.yaml index edc57f659..ff20f3926 100644 --- a/modele-social/règles/salarié.yaml +++ b/modele-social/règles/salarié.yaml @@ -2438,17 +2438,14 @@ contrat salarié . réduction générale . coefficient: contrat salarié . réduction générale . T: titre: Coefficient T - unité: '' - formule: - somme: - - T sécurité sociale et chômage - - valeur: retraite complémentaire . employeur . taux tranche 1 - plafond: 4.72% - - valeur: contribution d'équilibre général . employeur . taux tranche 1 - plafond: 1.29% + somme: + - T sécurité sociale et chômage + - valeur: retraite complémentaire . employeur . taux tranche 1 + plafond: 4.72% + - valeur: contribution d'équilibre général . employeur . taux tranche 1 + plafond: 1.29% contrat salarié . réduction générale . T sécurité sociale et chômage: - unité: '' formule: somme: - maladie . taux employeur @@ -3593,25 +3590,25 @@ contrat salarié . lodeom . éligible barème innovation et croissance: Fiche Urssaf: https://www.urssaf.fr/portail/home/outre-mer/employeur/exoneration-de-cotisations-di-1/employeurs-situes-en-guadeloupe/bareme-dit-innovation-et-croissa.html contrat salarié . lodeom . borne inférieure: - formule: - variations: - - si: éligible barème compétitivité - alors: 130% - - sinon: 170% + unité: '' + variations: + - si: éligible barème compétitivité + alors: 130% + - sinon: 170% contrat salarié . lodeom . borne supérieure: unité: '' - formule: - variations: - - si: éligible barème compétitivité - alors: 220% - - si: éligible barème compétitivité renforcée - alors: 270% - - si: éligible barème innovation et croissance - alors: 350% + variations: + - si: éligible barème compétitivité + alors: 220% + - si: éligible barème compétitivité renforcée + alors: 270% + - si: éligible barème innovation et croissance + alors: 350% contrat salarié . lodeom . multiplicateur: note: pour le barème 1 le dénominateur vaut 0,9 + unité: '%' formule: (borne inférieure * paramètre T) / (borne supérieure - borne inférieure) contrat salarié . lodeom . paramètre T: diff --git a/site/package.json b/site/package.json index b485ac6c1..a4aad3d3c 100644 --- a/site/package.json +++ b/site/package.json @@ -81,8 +81,8 @@ "iframe-resizer": "^4.3.2", "markdown-to-jsx": "^7.1.7", "modele-social": "workspace:^", - "publicodes": "=1.0.0-beta.33", - "publicodes-react": "=1.0.0-beta.33", + "publicodes": "=1.0.0-beta.40", + "publicodes-react": "=1.0.0-beta.40", "ramda": "^0.27.0", "react": "^17.0.0", "react-color": "^2.14.0", diff --git a/site/source/components/EngineValue.tsx b/site/source/components/EngineValue.tsx index 070912907..8c88d9eb5 100644 --- a/site/source/components/EngineValue.tsx +++ b/site/source/components/EngineValue.tsx @@ -1,11 +1,5 @@ import { DottedName } from 'modele-social' -import Engine, { - ASTNode, - formatValue, - isNotApplicable, - isNotYetDefined, - PublicodesExpression, -} from 'publicodes' +import Engine, { ASTNode, formatValue, PublicodesExpression } from 'publicodes' import React from 'react' import { useTranslation } from 'react-i18next' import styled, { keyframes } from 'styled-components' @@ -54,7 +48,7 @@ export default function Value({ if (isRule && linkToRule) { const ruleEvaluation = e.evaluate(expression) let dottedName = expression as DottedName - if (ruleEvaluation.visualisationKind === 'replacement') { + if (ruleEvaluation.sourceMap?.mecanismName === 'replacement') { dottedName = ( ruleEvaluation as { @@ -102,33 +96,14 @@ const StyledValue = styled.span<{ $flashOnChange: boolean }>` type ConditionProps = { expression: PublicodesExpression | ASTNode - defaultIfNotYetDefined?: boolean children: React.ReactNode } -export function Condition({ - expression, - defaultIfNotYetDefined = false, - children, -}: ConditionProps) { +export function Condition({ expression, children }: ConditionProps) { const engine = useEngine() - const value = engine.evaluate(expression).nodeValue - const boolValue = isNotYetDefined(value) - ? defaultIfNotYetDefined - : isNotApplicable(value) - ? false - : value + const nodeValue = engine.evaluate({ '!=': [expression, 'non'] }).nodeValue - if (Boolean(boolValue) !== boolValue) { - console.error( - `[ CONDITION NON-BOOLEENNE ] dans le composant Condition: expression=${JSON.stringify( - expression, - null, - 2 - )}` - ) - } - if (!boolValue) { + if (!nodeValue) { return null } @@ -143,7 +118,7 @@ export function WhenApplicable({ children: React.ReactNode }) { const engine = useEngine() - if (engine.evaluate(dottedName).nodeValue === null) { + if (engine.evaluate({ 'est applicable': dottedName }).nodeValue !== true) { return null } @@ -158,7 +133,9 @@ export function WhenNotApplicable({ children: React.ReactNode }) { const engine = useEngine() - if (engine.evaluate(dottedName).nodeValue !== null) { + if ( + engine.evaluate({ 'est non applicable': dottedName }).nodeValue !== true + ) { return null } @@ -173,7 +150,7 @@ export function WhenAlreadyDefined({ children: React.ReactNode }) { const engine = useEngine() - if (isNotYetDefined(engine.evaluate(dottedName).nodeValue)) { + if (engine.evaluate({ 'est non défini': dottedName }).nodeValue) { return null } @@ -188,7 +165,7 @@ export function WhenNotAlreadyDefined({ children: React.ReactNode }) { const engine = useEngine() - if (!isNotYetDefined(engine.evaluate(dottedName).nodeValue)) { + if (engine.evaluate({ 'est défini': dottedName }).nodeValue) { return null } diff --git a/site/source/components/Feedback/index.tsx b/site/source/components/Feedback/index.tsx index 53812d872..d6118ba37 100644 --- a/site/source/components/Feedback/index.tsx +++ b/site/source/components/Feedback/index.tsx @@ -178,6 +178,8 @@ export default function PageFeedback({ customMessage }: PageFeedbackProps) { const EmojiButton = styled.button` font-size: 1.5rem; padding: 0.6rem; + border: none; + background: none; transition: transform 0.05s; will-change: transform; :hover { diff --git a/site/source/components/PaySlip.tsx b/site/source/components/PaySlip.tsx index 6bdbce5e3..e1d2e1c6c 100644 --- a/site/source/components/PaySlip.tsx +++ b/site/source/components/PaySlip.tsx @@ -10,6 +10,7 @@ import { formatValue, ParsedRules, reduceAST, + Rule, RuleNode, } from 'publicodes' import { Fragment, useContext } from 'react' @@ -32,8 +33,10 @@ export const SECTION_ORDER = [ type Section = typeof SECTION_ORDER[number] function getSection(rule: RuleNode): Section { - const section = ('protection sociale . ' + - (rule.rawNode.cotisation?.branche ?? '')) as Section + const section = `protection sociale . ${ + (rule.rawNode as Rule & { cotisation?: { branche?: string } })?.cotisation + ?.branche ?? '' + }` as Section if (SECTION_ORDER.includes(section)) { return section } diff --git a/site/source/components/PaySlipSections.tsx b/site/source/components/PaySlipSections.tsx index 934f06ab7..678f757b9 100644 --- a/site/source/components/PaySlipSections.tsx +++ b/site/source/components/PaySlipSections.tsx @@ -1,10 +1,13 @@ -import Value, { Condition, ValueProps } from '@/components/EngineValue' +import Value, { + Condition, + ValueProps, + WhenAlreadyDefined, + WhenApplicable, +} from '@/components/EngineValue' import RuleLink from '@/components/RuleLink' import { H4 } from '@/design-system/typography/heading' import { DottedName } from 'modele-social' -import { isNotApplicable, isNotYetDefined } from 'publicodes' import { Trans, useTranslation } from 'react-i18next' -import { useEngine } from './utils/EngineContext' export const SalaireBrutSection = () => { return ( @@ -82,28 +85,20 @@ export function Line({ title, ...props }: LineProps) { - const engine = useEngine() - - const evaluatedNode = engine.evaluate(rule) - if ( - isNotYetDefined(evaluatedNode.nodeValue) || - // ⚠️ isNotApplicable is a bad func only here to help with further refactoring: - isNotApplicable(evaluatedNode.nodeValue) || - evaluatedNode.nodeValue === 0 - ) { - return null - } - return ( - 0`}> - {title} - - + + + 0`}> + {title} + + + + ) } diff --git a/site/source/design-system/global-style.ts b/site/source/design-system/global-style.ts index 9cb4eb08c..9e6ba9ecd 100644 --- a/site/source/design-system/global-style.ts +++ b/site/source/design-system/global-style.ts @@ -126,10 +126,6 @@ fieldset { min-width: 0; } -button { - background: none; - border: none; -} button:enabled { cursor: pointer; diff --git a/site/source/design-system/popover/Popover.tsx b/site/source/design-system/popover/Popover.tsx index 03051aaca..38891cdba 100644 --- a/site/source/design-system/popover/Popover.tsx +++ b/site/source/design-system/popover/Popover.tsx @@ -194,6 +194,10 @@ const CloseButtonContainer = styled.div` const CloseButton = styled.button` display: inline-flex; align-items: center; + + background: none; + border: none; + color: ${({ theme }) => theme.colors.bases.primary[700]}; font-family: ${({ theme }) => theme.fonts.main}; font-weight: 700; diff --git a/site/source/design-system/typography/link.tsx b/site/source/design-system/typography/link.tsx index 273a16c9b..885ecf7f8 100644 --- a/site/source/design-system/typography/link.tsx +++ b/site/source/design-system/typography/link.tsx @@ -1,6 +1,6 @@ +import { FocusStyle } from '@/design-system/global-style' import { useButton } from '@react-aria/button' import { AriaButtonProps } from '@react-types/button' -import { FocusStyle } from '@/design-system/global-style' import React, { ComponentPropsWithRef, CSSProperties, @@ -40,6 +40,8 @@ export const StyledLink = styled.a<{ $isDisabled?: boolean }>` font-weight: 700; padding: 0; font-size: inherit; + background: none; + border: none; text-decoration: none; border-radius: ${({ theme }) => theme.box.borderRadius}; &:hover { diff --git a/site/source/pages/Simulateurs/Salarié.tsx b/site/source/pages/Simulateurs/Salarié.tsx index e2d9759e1..a439fdede 100644 --- a/site/source/pages/Simulateurs/Salarié.tsx +++ b/site/source/pages/Simulateurs/Salarié.tsx @@ -11,20 +11,20 @@ import Simulation, { } from '@/components/Simulation' import SalaryExplanation from '@/components/simulationExplanation/SalaryExplanation' import { FromTop } from '@/components/ui/animate' +import BrowserOnly from '@/components/utils/BrowserOnly' import Emoji from '@/components/utils/Emoji' import { useEngine } from '@/components/utils/EngineContext' import { SitePathsContext } from '@/components/utils/SitePathsContext' import { Button } from '@/design-system/buttons' import { Link } from '@/design-system/typography/link' import { Body, SmallBody } from '@/design-system/typography/paragraphs' +import { targetUnitSelector } from '@/selectors/simulationSelectors' import { DottedName } from 'modele-social' -import { reduceAST } from 'publicodes' +import { ASTNode, reduceAST } from 'publicodes' import { useContext } from 'react' import { Trans } from 'react-i18next' import { useSelector } from 'react-redux' -import { targetUnitSelector } from '@/selectors/simulationSelectors' import styled from 'styled-components' -import BrowserOnly from '@/components/utils/BrowserOnly' const ButtonContainer = styled.div` margin: 2rem 1rem; @@ -132,10 +132,11 @@ function AidesGlimpse() { // est une somme des aides qui sont toutes nulle sauf l'aide active. const aideLink = reduceAST( (acc, node) => { - if (node.nodeKind === 'somme') { - const aidesNotNul = node.explanation - .map((n) => engine.evaluate(n)) - .filter(({ nodeValue }) => nodeValue !== false) + if (node.sourceMap?.mecanismName === 'somme') { + const aidesNotNul = + (node.sourceMap?.args.valeur as ASTNode[]) + .map((n) => engine.evaluate(n)) + .filter(({ nodeValue }) => nodeValue !== false) ?? [] if (aidesNotNul.length === 1 && 'dottedName' in aidesNotNul[0]) { return aidesNotNul[0].dottedName as DottedName } else { diff --git a/site/test/conversation.test.js b/site/test/conversation.test.js index ca3974b87..40b73d3cf 100644 --- a/site/test/conversation.test.js +++ b/site/test/conversation.test.js @@ -1,10 +1,10 @@ -import { describe, it, expect } from 'vitest' +import rules from 'modele-social' import Engine from 'publicodes' +import { describe, expect, it } from 'vitest' import { getNextQuestions, getNextSteps, } from '../source/components/utils/useNextQuestion' -import rules from 'modele-social' describe('conversation', function () { it('should start with the first missing variable', function () { @@ -12,12 +12,10 @@ describe('conversation', function () { // TODO - this won't work without the indirection, figure out why top: 'oui', 'top . startHere': { formule: { somme: ['a', 'b'] } }, - 'top . a': { formule: 'aa' }, - 'top . b': { formule: 'bb' }, - 'top . aa': { question: '?', titre: 'a', unité: '€' }, - 'top . bb': { question: '?', titre: 'b', unité: '€' }, + 'top . a': { question: '?', titre: 'a', unité: '€' }, + 'top . b': { question: '?', titre: 'b', unité: '€' }, }).evaluate('top . startHere').missingVariables - expect(getNextQuestions([missingVariables])[0]).to.equal('top . aa') + expect(getNextQuestions([missingVariables])[0]).to.equal('top . a') }) it('should first ask for questions without defaults, then those with defaults', function () { const engine = new Engine({ diff --git a/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap b/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap index ce88b8e76..e6b4ca37f 100644 --- a/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap +++ b/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap @@ -246,7 +246,7 @@ Notifications affichées : contrat salarié . rémunération . contrôle salaire `; exports[`calculate simulations-salarié > impôt sur le revenu - quotient familial 12`] = ` -"[28342,0,20000,15969,11996] +"[28342,0,20000,15969,11030] Notifications affichées : contrat salarié . rémunération . contrôle salaire élevé" `; diff --git a/site/test/regressions/simulations-auto-entrepreneur.test.ts b/site/test/regressions/simulations-auto-entrepreneur.test.ts index 0562f4314..f0029be04 100644 --- a/site/test/regressions/simulations-auto-entrepreneur.test.ts +++ b/site/test/regressions/simulations-auto-entrepreneur.test.ts @@ -21,14 +21,14 @@ it('calculate simulations-auto-entrepreneur', () => { ) ).toMatchInlineSnapshot(` [ - "entreprise . activité . mixte", - "entreprise . activité", - "entreprise . activité . service ou vente", - "impôt . foyer fiscal . enfants à charge", "dirigeant . auto-entrepreneur . impôt . versement libératoire", - "impôt . foyer fiscal . situation de famille", + "entreprise . activité", + "entreprise . activité . mixte", + "entreprise . activité . service ou vente", "entreprise . date de création", + "impôt . foyer fiscal . enfants à charge", "impôt . foyer fiscal . revenu imposable . autres revenus imposables", + "impôt . foyer fiscal . situation de famille", "impôt . méthode de calcul", ] `) diff --git a/site/test/regressions/simulations-salarié.test.ts b/site/test/regressions/simulations-salarié.test.ts index 5e0f0e64d..9cdecd8b5 100644 --- a/site/test/regressions/simulations-salarié.test.ts +++ b/site/test/regressions/simulations-salarié.test.ts @@ -22,24 +22,24 @@ it('calculate simulations-salarié', () => { ).toMatchInlineSnapshot(` [ "contrat salarié", - "contrat salarié . convention collective", - "contrat salarié . temps de travail . temps partiel", - "contrat salarié . rémunération . primes . activité . base", - "contrat salarié . temps de travail . heures supplémentaires", - "contrat salarié . frais professionnels . abonnement transports publics . montant", - "contrat salarié . frais professionnels . transports personnels . carburant faible émission . montant", - "contrat salarié . déduction forfaitaire spécifique", - "contrat salarié . frais professionnels . titres-restaurant", - "contrat salarié . frais professionnels . transports personnels . forfait mobilités durables . montant", - "contrat salarié . rémunération . avantages en nature", - "contrat salarié . rémunération . primes . fin d'année . treizième mois", "contrat salarié . complémentaire santé . forfait", "contrat salarié . complémentaire santé . part employeur", - "situation personnelle . domiciliation fiscale à l'étranger", - "contrat salarié . statut cadre", + "contrat salarié . convention collective", + "contrat salarié . déduction forfaitaire spécifique", + "contrat salarié . frais professionnels . abonnement transports publics . montant", + "contrat salarié . frais professionnels . titres-restaurant", + "contrat salarié . frais professionnels . transports personnels . carburant faible émission . montant", + "contrat salarié . frais professionnels . transports personnels . forfait mobilités durables . montant", "contrat salarié . régime des impatriés", - "établissement . localisation", + "contrat salarié . rémunération . avantages en nature", + "contrat salarié . rémunération . primes . activité . base", + "contrat salarié . rémunération . primes . fin d'année . treizième mois", + "contrat salarié . statut cadre", + "contrat salarié . temps de travail . heures supplémentaires", + "contrat salarié . temps de travail . temps partiel", "impôt . méthode de calcul", + "situation personnelle . domiciliation fiscale à l'étranger", + "établissement . localisation", ] `) }) diff --git a/site/test/regressions/utils.ts b/site/test/regressions/utils.ts index c59e626ea..b8a339397 100644 --- a/site/test/regressions/utils.ts +++ b/site/test/regressions/utils.ts @@ -6,6 +6,7 @@ // renamed the test configuration may be adapted but the persisted snapshot will remain unchanged). import rules, { DottedName } from 'modele-social' +import { EvaluatedNode } from 'publicodes' import { expect } from 'vitest' import { engineFactory } from '../../source/components/utils/EngineContext' import { Simulation } from '../../source/reducers/rootReducer' @@ -61,9 +62,6 @@ export const runSimulations = ( }) ) -export const getMissingVariables = ( - evaluatedNode: ReturnType -) => - Object.entries(evaluatedNode.missingVariables) - .sort(([, scoreA], [, scoreB]) => scoreB - scoreA) - .map(([name]) => name) +export function getMissingVariables(node: EvaluatedNode) { + return Object.keys(node.missingVariables).sort() +} diff --git a/yarn.lock b/yarn.lock index a8bff5be1..1ad505be2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11289,9 +11289,9 @@ __metadata: dependencies: js-yaml: ^4.1.0 onchange: ^7.1.0 - publicodes: ^1.0.0-beta.32 + publicodes: =1.0.0-beta.40 peerDependencies: - publicodes: ^1.0.0-beta.32 + publicodes: "*" languageName: unknown linkType: soft @@ -15099,9 +15099,9 @@ __metadata: dependencies: js-yaml: ^4.1.0 onchange: ^7.1.0 - publicodes: ^1.0.0-beta.32 + publicodes: =1.0.0-beta.40 peerDependencies: - publicodes: ^1.0.0-beta.32 + publicodes: "*" languageName: unknown linkType: soft @@ -16625,41 +16625,28 @@ __metadata: languageName: node linkType: hard -"publicodes-react@npm:=1.0.0-beta.33": - version: 1.0.0-beta.33 - resolution: "publicodes-react@npm:1.0.0-beta.33" +"publicodes-react@npm:=1.0.0-beta.40": + version: 1.0.0-beta.40 + resolution: "publicodes-react@npm:1.0.0-beta.40" dependencies: styled-components: ^5.1.0 peerDependencies: - publicodes: 1.0.0-beta.33 + publicodes: 1.0.0-beta.40 react: ^17.0.2 - checksum: f455b85579191eda86599ea0cf97f7523f0e03cd1d5b1063031734458cfd022706664138deb74d85d06e6bd1672c0ab71a3e1034fa1647bb0f6b292d5bf9381a + checksum: 0840973921cab75b27475491d56bae3ff84c80c288d8eb9a0f3fbd4f464ea608b31e5907c55b06b5b46645b63a3bf342115587730bf9c04722edba17ac106556 languageName: node linkType: hard -"publicodes@npm:=1.0.0-beta.33": - version: 1.0.0-beta.33 - resolution: "publicodes@npm:1.0.0-beta.33" +"publicodes@npm:=1.0.0-beta.40": + version: 1.0.0-beta.40 + resolution: "publicodes@npm:1.0.0-beta.40" dependencies: moo: ^0.5.1 nearley: ^2.19.2 yaml: ^1.9.2 peerDependencies: "@types/mocha": ^9.0.0 - checksum: 065fd94d2b639c0ae9d5ae52effa2998fa1e9e94c02177e97b467c55ac3f8658310b494eedefd2b0ccc58de3829529709080d8d2aad800cdfb496b7cf62fc8f7 - languageName: node - linkType: hard - -"publicodes@npm:^1.0.0-beta.32": - version: 1.0.0-beta.34 - resolution: "publicodes@npm:1.0.0-beta.34" - dependencies: - moo: ^0.5.1 - nearley: ^2.19.2 - yaml: ^1.9.2 - peerDependencies: - "@types/mocha": ^9.0.0 - checksum: 8904460eb095f37fc38a5f16756e4315b2f26cf3f0d02300dfe87a63cfa37da45e72b19550fec7d977361c830d9010f5663937b98d3c36c3d8a6a1d6592daacd + checksum: 5bfd4d157332d319f2a7b958e0df165756dd94c63f39d47e4f834ff491e8a6311636676ba5f800f48499658a0ea614e2f85c70a3af4fe675918aca6ab3ed7443 languageName: node linkType: hard @@ -18511,8 +18498,8 @@ __metadata: isomorphic-fetch: ^2.2.1 markdown-to-jsx: ^7.1.7 modele-social: "workspace:^" - publicodes: =1.0.0-beta.33 - publicodes-react: =1.0.0-beta.33 + publicodes: =1.0.0-beta.40 + publicodes-react: =1.0.0-beta.40 ramda: ^0.27.0 react: ^17.0.0 react-color: ^2.14.0