From 860d7b4cf4d520495924a43265f11e6bfd6123f3 Mon Sep 17 00:00:00 2001
From: Johan Girod
Date: Fri, 23 Sep 2022 14:45:48 +0200
Subject: [PATCH] =?UTF-8?q?Supprime=20l'utilisation=20du=20m=C3=A9canisme?=
=?UTF-8?q?=20synchronisation=20pour=20la=20commune=20de=20localisation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Renomme `localisation` en `commune`
- Déplace la logique de `getNextStep` dans un hook `useMissingVariables`
---
.vscode/settings.json | 11 +-
api/README.md | 6 +
api/package.json | 4 +-
api/source/openapi.yaml | 14 +-
.../test-e2e/__snapshots__/index.test.ts.snap | 140 +++++++++++++-----
exoneration-covid/package.json | 4 +-
modele-social/CHANGELOG.md | 23 ++-
modele-social/package.json | 6 +-
modele-social/règles/base.yaml | 2 +-
.../charges-sociales-formulaire.yaml | 1 +
modele-social/règles/dirigeant.yaml | 8 +-
.../règles/entreprise/entreprise.yaml | 4 +-
.../règles/entreprise/établissement.yaml | 105 +++++--------
modele-social/règles/impôt.yaml | 7 +-
.../règles/salarié/activité-partielle.yaml | 2 +-
.../spectacle-vivant.yaml | 4 +-
modele-social/règles/salarié/cotisations.yaml | 18 +--
modele-social/règles/salarié/salarié.yaml | 12 +-
site/package.json | 4 +-
site/source/actions/actions.ts | 25 +++-
site/source/api/commune.ts | 40 +++--
.../ChiffreAffairesActivitéMixte.tsx | 8 +-
site/source/components/company/Details.tsx | 2 +-
.../components/conversation/AnswerList.tsx | 34 +++--
.../components/conversation/Conversation.tsx | 13 +-
.../components/conversation/RuleInput.tsx | 14 +-
.../conversation/select/SelectCommune.tsx | 25 ++--
.../components/utils/useNextQuestion.tsx | 34 +----
site/source/data/releases.json | 4 +-
site/source/locales/rules-en.yaml | 17 +--
site/source/locales/ui-en.yaml | 19 +--
site/source/locales/ui-fr.yaml | 19 +--
.../configs/auto-entrepreneur.yaml | 2 +-
.../Simulateurs/configs/chômage-partiel.yaml | 2 +-
.../Simulateurs/configs/dirigeant-sasu.yaml | 4 +-
.../pages/Simulateurs/configs/salarié.yaml | 2 +-
.../gerer/demande-mobilité/FieldsPDF.tsx | 15 +-
.../gerer/demande-mobilité/PDFDocument.tsx | 2 +-
.../demande-mobilité/demande-mobilité.yaml | 23 +++
.../pages/gerer/demande-mobilité/index.tsx | 19 ++-
.../_components/CasParticuliers.tsx | 10 +-
.../reducers/companySituationReducer.ts | 4 +-
site/source/reducers/rootReducer.ts | 5 +-
site/source/selectors/simulationSelectors.ts | 40 +++++
site/source/utils.ts | 16 ++
...versation.test.js => conversation.test.ts} | 32 +---
.../simulations-salarié.test.ts.snap | 14 +-
.../regressions/simulations-salarié.test.ts | 4 +-
.../test/regressions/simulations-salarié.yaml | 16 +-
yarn.lock | 40 ++---
50 files changed, 517 insertions(+), 362 deletions(-)
rename site/test/{conversation.test.js => conversation.test.ts} (70%)
diff --git a/.vscode/settings.json b/.vscode/settings.json
index e4116c589..c138feb09 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,13 @@
{
- "spellright.language": ["fr", "en"],
- "spellright.documentTypes": ["yaml", "git-commit", "markdown"],
+ "spellright.language": [
+ "fr",
+ "en"
+ ],
+ "spellright.documentTypes": [
+ "yaml",
+ "git-commit",
+ "markdown"
+ ],
"typescript.tsdk": "node_modules/typescript/lib",
"editor.tabSize": 2,
"cSpell.words": ["mycompanyinfrance", "smarttag"],
diff --git a/api/README.md b/api/README.md
index 2626424ed..9f935c74c 100644
--- a/api/README.md
+++ b/api/README.md
@@ -1 +1,7 @@
# Mon-entreprise API
+
+Vous pouvez réutiliser les calculs de mon-entreprise sur votre site ou service très facilement grâce à notre API REST ouverte et sans authentification.
+
+**[👉️ Voir la documentation sur mon-entreprise](https://mon-entreprise.urssaf.fr/d%C3%A9veloppeur/api)**
+
+**[📊 Voir les statistiques d’utilisation](https://mon-entreprise.urssaf.fr/stats?module=api-rest)**
diff --git a/api/package.json b/api/package.json
index c4833a5c3..5ea0c4cc4 100644
--- a/api/package.json
+++ b/api/package.json
@@ -30,7 +30,7 @@
"@apidevtools/swagger-cli": "^4.0.4",
"@koa/cors": "^3.3.0",
"@koa/router": "^10.1.1",
- "@publicodes/api": "^1.0.0-beta.54",
+ "@publicodes/api": "^1.0.0-beta.55",
"@sentry/node": "^7.1.1",
"@sentry/tracing": "^7.1.1",
"got": "^12.4.1",
@@ -40,7 +40,7 @@
"koa-static": "^5.0.0",
"modele-social": "workspace:^",
"nodemon": "^2.0.16",
- "publicodes": "^1.0.0-beta.54",
+ "publicodes": "^1.0.0-beta.55",
"rate-limiter-flexible": "^2.3.8",
"swagger-ui-dist": "^4.11.1"
},
diff --git a/api/source/openapi.yaml b/api/source/openapi.yaml
index 382e31456..7c14982e1 100644
--- a/api/source/openapi.yaml
+++ b/api/source/openapi.yaml
@@ -1,12 +1,12 @@
-openapi: 3.0.0
+openapi: 3.1.0
info:
title: Mon-entreprise API
- version: beta
+ version: v1
description: |
- Cet API expose les règles Publicodes de [mon-entreprise](https://mon-entreprise.urssaf.fr/).
+ Cet API expose les calculs des simulateurs de [mon-entreprise](https://mon-entreprise.urssaf.fr/).
- Pour plus d'informations, consultez [notre documentation](/d%C3%A9veloppeur/api).
+ **[📒 Voir la documentation](https://mon-entreprise.urssaf.fr/d%C3%A9veloppeur/api)**
servers:
- url: /api/v1/
@@ -18,7 +18,7 @@ paths:
content:
application/json:
examples:
- SalaireBrutEnNet:
+ 'Salaire brut en net':
value:
{
'situation':
@@ -30,7 +30,7 @@ paths:
'expressions':
['salarié . rémunération . net . à payer avant impôt'],
}
- MicroEntreprise:
+ 'Auto-entrepreneur':
value:
{
situation:
@@ -57,7 +57,7 @@ paths:
get:
parameters:
- examples:
- SalaireNet:
+ 'Salaire net':
value: 'salarié . rémunération . net . à payer avant impôt'
Impot:
value: 'impôt . méthode de calcul'
diff --git a/api/source/test-e2e/__snapshots__/index.test.ts.snap b/api/source/test-e2e/__snapshots__/index.test.ts.snap
index e75e0be81..ff656ef08 100644
--- a/api/source/test-e2e/__snapshots__/index.test.ts.snap
+++ b/api/source/test-e2e/__snapshots__/index.test.ts.snap
@@ -15,6 +15,7 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
"salarié . cotisations . prévoyances . santé . montant": 2320,
"salarié . cotisations . prévoyances . santé . taux employeur": 2320,
"salarié . régimes spécifiques . DFS": 1624,
+ "salarié . régimes spécifiques . alsace moselle": 352,
"salarié . rémunération . avantages en nature": 23027,
"salarié . rémunération . frais professionnels . titres-restaurant": 25347,
"salarié . rémunération . frais professionnels . trajets domicile travail . forfait mobilités durables . montant": 59450,
@@ -24,7 +25,8 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
"salarié . rémunération . primes . fin d'année": 23026,
"salarié . temps de travail . heures supplémentaires": 46922,
"situation personnelle . domiciliation fiscale à l'étranger": 580,
- "établissement . localisation": 880,
+ "établissement . commune . département": 2458,
+ "établissement . commune . département . outre-mer": 992,
},
"nodeValue": 2749.50805,
"traversedVariables": [
@@ -154,8 +156,7 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
"salarié . cotisations . maladie . salarié",
"salarié . cotisations . maladie . salarié . taux",
"salarié . régimes spécifiques . alsace moselle",
- "établissement . localisation . département",
- "établissement . localisation",
+ "établissement . commune . département",
"salarié . cotisations . retraite complémentaire . salarié",
"salarié . cotisations . retraite complémentaire",
"salarié . cotisations . retraite complémentaire . employeur",
@@ -178,6 +179,8 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
"salarié . cotisations . chômage . employeur . taux",
"salarié . cotisations . CSG-CRDS",
"salarié . cotisations . CSG-CRDS . CSG",
+ "établissement . commune . département . outre-mer . Mayotte",
+ "établissement . commune . département . outre-mer",
"salarié . cotisations . CSG-CRDS . CSG . déductible",
"salarié . cotisations . CSG-CRDS . CSG . déductible . taux",
"salarié . cotisations . CSG-CRDS . assiette de base",
@@ -257,32 +260,34 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
},
{
"missingVariables": {
- "dirigeant . gérant minoritaire": 814757,
+ "dirigeant . gérant minoritaire": 798729,
"entreprise . TVA": 5,
"entreprise . association non lucrative": 11,
- "entreprise . catégorie juridique": 5865649,
+ "entreprise . catégorie juridique": 5750669,
"entreprise . salariés . effectif . seuil": 515,
- "salarié . activité partielle": 24705,
- "salarié . contrat": 197257,
+ "salarié . activité partielle": 24153,
+ "salarié . contrat": 193409,
"salarié . contrat . statut cadre": 811,
- "salarié . contrat . temps de travail . temps partiel": 41573,
- "salarié . convention collective": 49065,
+ "salarié . contrat . temps de travail . temps partiel": 40733,
+ "salarié . convention collective": 47961,
"salarié . cotisations . ATMP . taux fonctions support": 11,
- "salarié . cotisations . exonérations . JEI": 611,
- "salarié . cotisations . exonérations . lodeom": 111,
+ "salarié . cotisations . exonérations . JEI": 539,
+ "salarié . cotisations . exonérations . lodeom . zone un": 111,
"salarié . cotisations . prévoyances . santé . montant": 591,
"salarié . cotisations . prévoyances . santé . taux employeur": 591,
"salarié . coût total employeur . aides . emploi franc . éligible": 45,
- "salarié . régimes spécifiques . DFS": 1051,
- "salarié . rémunération . avantages en nature": 5121,
- "salarié . rémunération . frais professionnels . titres-restaurant": 5537,
- "salarié . rémunération . frais professionnels . trajets domicile travail . forfait mobilités durables . montant": 12537,
- "salarié . rémunération . frais professionnels . trajets domicile travail . prime de transport . montant": 14201,
- "salarié . rémunération . frais professionnels . trajets domicile travail . transports publics . montant": 36865,
- "salarié . rémunération . primes . activité . base": 5121,
- "salarié . rémunération . primes . fin d'année": 5121,
- "salarié . temps de travail . heures supplémentaires": 7821,
- "établissement . localisation": 631,
+ "salarié . régimes spécifiques . DFS": 1059,
+ "salarié . régimes spécifiques . alsace moselle": 27,
+ "salarié . rémunération . avantages en nature": 4953,
+ "salarié . rémunération . frais professionnels . titres-restaurant": 5369,
+ "salarié . rémunération . frais professionnels . trajets domicile travail . forfait mobilités durables . montant": 12273,
+ "salarié . rémunération . frais professionnels . trajets domicile travail . prime de transport . montant": 13937,
+ "salarié . rémunération . frais professionnels . trajets domicile travail . transports publics . montant": 36313,
+ "salarié . rémunération . primes . activité . base": 4953,
+ "salarié . rémunération . primes . fin d'année": 4953,
+ "salarié . temps de travail . heures supplémentaires": 7605,
+ "établissement . commune . département": 2023,
+ "établissement . commune . département . outre-mer": 967,
"établissement . taux ATMP": 11,
"établissement . taux ATMP . taux collectif": 7,
},
@@ -441,8 +446,7 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
"entreprise . association non lucrative",
"salarié . cotisations . taxe d'apprentissage",
"salarié . régimes spécifiques . alsace moselle",
- "établissement . localisation . département",
- "établissement . localisation",
+ "établissement . commune . département",
"salarié . cotisations . CPF CDD",
"salarié . cotisations . forfait social",
"salarié . cotisations . exonérations . employeur",
@@ -457,6 +461,8 @@ exports[`e2e test mon-entreprise api > Test evaluate brut => net + super brut 2`
"salarié . cotisations . maladie . employeur . taux réduit",
"salarié . temps de travail . SMIC",
"SMIC . horaire",
+ "établissement . commune . département . outre-mer . Mayotte",
+ "établissement . commune . département . outre-mer",
"date",
"salarié . cotisations . allocations familiales . taux",
"salarié . cotisations . allocations familiales . taux réduit",
@@ -592,7 +598,8 @@ exports[`e2e test mon-entreprise api > Test evaluate micro entreprise 2`] = `
{
"missingVariables": {
"entreprise . activité . mixte": 278,
- "établissement . localisation": 12,
+ "établissement . commune . département": 18,
+ "établissement . commune . département . outre-mer": 7,
},
"nodeValue": 1469,
"traversedVariables": [
@@ -607,9 +614,10 @@ exports[`e2e test mon-entreprise api > Test evaluate micro entreprise 2`] = `
"impôt . méthode de calcul",
"impôt . taux neutre d'impôt sur le revenu . barème Guadeloupe Réunion Martinique",
"impôt . taux neutre d'impôt sur le revenu . barème Guyane Mayotte",
- "établissement . localisation . outre-mer . Guadeloupe Réunion Martinique",
- "établissement . localisation . département",
- "établissement . localisation",
+ "établissement . commune . département . outre-mer . Guadeloupe Réunion Martinique",
+ "établissement . commune . département . outre-mer",
+ "établissement . commune . département",
+ "établissement . commune . département . outre-mer . Mayotte",
"impôt . taux neutre d'impôt sur le revenu",
"date",
"impôt . revenu imposable",
@@ -655,7 +663,8 @@ exports[`e2e test mon-entreprise api > Test evaluate micro entreprise 2`] = `
{
"missingVariables": {
"entreprise . activité . mixte": 344,
- "établissement . localisation": 12,
+ "établissement . commune . département": 18,
+ "établissement . commune . département . outre-mer": 7,
},
"nodeValue": 31207,
"traversedVariables": [
@@ -718,9 +727,10 @@ exports[`e2e test mon-entreprise api > Test evaluate micro entreprise 2`] = `
"impôt . méthode de calcul",
"impôt . taux neutre d'impôt sur le revenu . barème Guadeloupe Réunion Martinique",
"impôt . taux neutre d'impôt sur le revenu . barème Guyane Mayotte",
- "établissement . localisation . outre-mer . Guadeloupe Réunion Martinique",
- "établissement . localisation . département",
- "établissement . localisation",
+ "établissement . commune . département . outre-mer . Guadeloupe Réunion Martinique",
+ "établissement . commune . département . outre-mer",
+ "établissement . commune . département",
+ "établissement . commune . département . outre-mer . Mayotte",
"impôt . taux neutre d'impôt sur le revenu",
"impôt . revenu imposable",
"dirigeant . rémunération . net . imposable",
@@ -744,6 +754,60 @@ exports[`e2e test mon-entreprise api > Test evaluate micro entreprise 2`] = `
{
"message": "
[ Avertissement ]
+➡️ Dans la règle \\"déclaration charge sociales . nature de l'activité\\"
+⚠️ Cette règle est tagguée comme experimentale.
+
+Cela veut dire qu'elle peut être modifiée, renommée, ou supprimée sans qu'il n'y ait de changement de version majeure dans l'API.
+",
+ },
+ {
+ "message": "
+[ Avertissement ]
+➡️ Dans la règle \\"déclaration charge sociales . nature de l'activité\\"
+⚠️ Cette règle est tagguée comme experimentale.
+
+Cela veut dire qu'elle peut être modifiée, renommée, ou supprimée sans qu'il n'y ait de changement de version majeure dans l'API.
+",
+ },
+ {
+ "message": "
+[ Avertissement ]
+➡️ Dans la règle \\"déclaration charge sociales . nature de l'activité\\"
+⚠️ Cette règle est tagguée comme experimentale.
+
+Cela veut dire qu'elle peut être modifiée, renommée, ou supprimée sans qu'il n'y ait de changement de version majeure dans l'API.
+",
+ },
+ {
+ "message": "
+[ Avertissement ]
+➡️ Dans la règle \\"déclaration charge sociales . nature de l'activité . libérale\\"
+⚠️ Cette règle est tagguée comme experimentale.
+
+Cela veut dire qu'elle peut être modifiée, renommée, ou supprimée sans qu'il n'y ait de changement de version majeure dans l'API.
+",
+ },
+ {
+ "message": "
+[ Avertissement ]
+➡️ Dans la règle \\"déclaration charge sociales . nature de l'activité\\"
+⚠️ Cette règle est tagguée comme experimentale.
+
+Cela veut dire qu'elle peut être modifiée, renommée, ou supprimée sans qu'il n'y ait de changement de version majeure dans l'API.
+",
+ },
+ {
+ "message": "
+[ Avertissement ]
+➡️ Dans la règle \\"déclaration charge sociales . nature de l'activité\\"
+⚠️ Cette règle est tagguée comme experimentale.
+
+Cela veut dire qu'elle peut être modifiée, renommée, ou supprimée sans qu'il n'y ait de changement de version majeure dans l'API.
+",
+ },
+ {
+ "message": "
+[ Avertissement ]
➡️ Dans la règle \\"impôt . méthode de calcul\\"
⚠️ Cette règle est tagguée comme experimentale.
@@ -987,14 +1051,14 @@ exports[`e2e test mon-entreprise api > Test openapi.json endpoint 2`] = `
},
},
"info": {
- "description": "Cet API expose les règles Publicodes de [mon-entreprise](https://mon-entreprise.urssaf.fr/).
+ "description": "Cet API expose les calculs des simulateurs de [mon-entreprise](https://mon-entreprise.urssaf.fr/).
-Pour plus d'informations, consultez [notre documentation](/d%C3%A9veloppeur/api).
+**[📒 Voir la documentation](https://mon-entreprise.urssaf.fr/d%C3%A9veloppeur/api)**
",
"title": "Mon-entreprise API",
- "version": "beta",
+ "version": "v1",
},
- "openapi": "3.0.0",
+ "openapi": "3.1.0",
"paths": {
"/evaluate": {
"post": {
@@ -1003,7 +1067,7 @@ Pour plus d'informations, consultez [notre documentation](/d%C3%A9veloppeur/api)
"content": {
"application/json": {
"examples": {
- "MicroEntreprise": {
+ "Auto-entrepreneur": {
"value": {
"expressions": [
{
@@ -1024,7 +1088,7 @@ Pour plus d'informations, consultez [notre documentation](/d%C3%A9veloppeur/api)
},
},
},
- "SalaireBrutEnNet": {
+ "Salaire brut en net": {
"value": {
"expressions": [
"salarié . rémunération . net . à payer avant impôt",
@@ -1115,7 +1179,7 @@ Pour plus d'informations, consultez [notre documentation](/d%C3%A9veloppeur/api)
"Impot": {
"value": "impôt . méthode de calcul",
},
- "SalaireNet": {
+ "Salaire net": {
"value": "salarié . rémunération . net . à payer avant impôt",
},
},
diff --git a/exoneration-covid/package.json b/exoneration-covid/package.json
index c9b335d14..16f3eb3e6 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.54"
+ "publicodes": "=1.0.0-beta.55"
},
"peerDependencies": {
- "publicodes": "^1.0.0-beta.54"
+ "publicodes": "^1.0.0-beta.55"
},
"scripts": {
"build": "node ../scripts/build-rules.js",
diff --git a/modele-social/CHANGELOG.md b/modele-social/CHANGELOG.md
index 81cba9770..d9a01ea87 100644
--- a/modele-social/CHANGELOG.md
+++ b/modele-social/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 1.0.0-beta.2
+
+- Réecrit les règles de la cotisation AT/MP
+- Supprime le recours au mécanisme synchronisation pour la localisation de l’établissement
+- Ajoute le tag experimental à de nouvelles règles
+
+
## 1.0.0-beta.1
- Passage du paquet en semver (voir le README)
@@ -6,26 +13,26 @@
Les changements suivants sont cassants :
-- renomme l'espace de nom `contrat salarié` en `salarié`
+- renomme l’espace de nom `contrat salarié` en `salarié`
- réécrit les règles liées au remboursement des frais domicile/travail
- réécrit les règles liées aux CDD
-- déplace les éléments relatif au contrat dans `salarié . contrat`. Il s'agit de `temps partiel`, `salaire brut` ou encore le `statut cadre`
+- déplace les éléments relatif au contrat dans `salarié . contrat`. Il s’agit de `temps partiel`, `salaire brut` ou encore le `statut cadre`
- tous les éléments relatifs à la rémunération sont déplacés dans `salarié . rémunération`
- `salarié . régimes spécifiques` : les règles liées aux régimes spéciaux (DFS, cadre, impatriés, etc)
- `plafond sécurité sociale temps plein` devient `plafond sécurité sociale`
-- toutes les cotisations sont déplacées dans l'espace de nom `salarié . cotisations`, et utilisent les acronymes comme nom tant que possible.
+- toutes les cotisations sont déplacées dans l’espace de nom `salarié . cotisations`, et utilisent les acronymes comme nom tant que possible.
**Corrections de bugs**
- Ajoute la limite de déduction sur la part employeur des prévoyances
-- Enlève la CSA de l'exonération JEI
+- Enlève la CSA de l’exonération JEI
- Réecrit les règles de déductions des frais de transport domicile / travail pour coller à la réglementation
- Réecrit les règles sur le CDD pour une meilleure expérience question par question
-- Précise le calcul de l'assiette de la CSG
+- Précise le calcul de l’assiette de la CSG
- Corrige le calcul de la rémunération brut avec prévoyance
-**Note sur l'upgrade**
-Pour les utilisateur des version précédente, la mise à jour risque d'être longue et fastidieuse. Nous nous en excusons. Le but de cette refacto est de prévenir les changement cassants au maximum à l'avenir.
+**Note sur l’upgrade**
+Pour les utilisateur des version précédente, la mise à jour risque d’être longue et fastidieuse. Nous nous en excusons. Le but de cette refacto est de prévenir les changement cassants au maximum à l’avenir.
Vous pouvez utiliser la fonction recherche de la documentation, et utiliser le nouveau menu de navigation des règles pour plus facilement trouver les nouvelles versions des règles utilisées.
@@ -40,4 +47,4 @@ Ajout des déclarations de type dans le paquet
## 0.6.0
-Publication du paquet sous forme d'ES modules.
+Publication du paquet sous forme d’ES modules.
diff --git a/modele-social/package.json b/modele-social/package.json
index fbf58fbd8..2b7e6c4d8 100644
--- a/modele-social/package.json
+++ b/modele-social/package.json
@@ -1,6 +1,6 @@
{
"name": "modele-social",
- "version": "1.0.0-beta.1",
+ "version": "1.0.0-beta.2",
"description": "Les règles publicodes du système social français",
"type": "module",
"main": "./dist/index.js",
@@ -21,10 +21,10 @@
"devDependencies": {
"js-yaml": "^4.1.0",
"onchange": "^7.1.0",
- "publicodes": "^1.0.0-beta.54"
+ "publicodes": "^1.0.0-beta.55"
},
"peerDependencies": {
- "publicodes": "^1.0.0-beta.54"
+ "publicodes": "^1.0.0-beta.55"
},
"scripts": {
"build": "node ../scripts/build-rules.js",
diff --git a/modele-social/règles/base.yaml b/modele-social/règles/base.yaml
index 11a31980a..9f7d0f7c0 100644
--- a/modele-social/règles/base.yaml
+++ b/modele-social/règles/base.yaml
@@ -45,7 +45,7 @@ SMIC . net imposable:
SMIC . horaire:
titre global: SMIC horaire
variations:
- - si: établissement . localisation . département = 'Mayotte'
+ - si: établissement . commune . département . outre-mer . Mayotte
alors:
variations:
- si: date >= 01/08/2022
diff --git a/modele-social/règles/declarations-indépendant/charges-sociales-formulaire.yaml b/modele-social/règles/declarations-indépendant/charges-sociales-formulaire.yaml
index 75509d95f..d93c9da4d 100644
--- a/modele-social/règles/declarations-indépendant/charges-sociales-formulaire.yaml
+++ b/modele-social/règles/declarations-indépendant/charges-sociales-formulaire.yaml
@@ -1,4 +1,5 @@
déclaration charge sociales:
+ experimental: oui
description: >-
Ces règles calculent les montants des charges sociales à reporter dans la déclaration de revenu
des indépendants et dans les déclaration de résultats.
diff --git a/modele-social/règles/dirigeant.yaml b/modele-social/règles/dirigeant.yaml
index aa1d57edc..09b37fb27 100644
--- a/modele-social/règles/dirigeant.yaml
+++ b/modele-social/règles/dirigeant.yaml
@@ -260,9 +260,10 @@ dirigeant . auto-entrepreneur . cotisations et contributions . TFC . métiers .
par: 0.65%
- règle: taux vente
par: 0.29%
+ par défaut: non
une de ces conditions:
- - établissement . localisation . département = 'Bas-Rhin'
- - établissement . localisation . département = 'Haut-Rhin'
+ - établissement . commune . département = 'Bas-Rhin'
+ - établissement . commune . département = 'Haut-Rhin'
références:
service-public.fr: https://www.service-public.fr/professionnels-entreprises/vosdroits/F32847
@@ -272,7 +273,8 @@ dirigeant . auto-entrepreneur . cotisations et contributions . TFC . métiers .
par: 0.83%
- règle: taux vente
par: 0.37%
- valeur: établissement . localisation . département = 'Moselle'
+ par défaut: non
+ valeur: établissement . commune . département = 'Moselle'
références:
service-public.fr: https://www.service-public.fr/professionnels-entreprises/vosdroits/F32847
diff --git a/modele-social/règles/entreprise/entreprise.yaml b/modele-social/règles/entreprise/entreprise.yaml
index 99dfcd32e..7866644ee 100644
--- a/modele-social/règles/entreprise/entreprise.yaml
+++ b/modele-social/règles/entreprise/entreprise.yaml
@@ -189,7 +189,7 @@ entreprise . TVA . franchise de TVA: oui
entreprise . TVA . franchise de TVA . seuil vente:
variations:
- - si: établissement . localisation . outre-mer . Guadeloupe Réunion Martinique
+ - si: établissement . commune . département . outre-mer . Guadeloupe Réunion Martinique
alors: 110000 €/an
- sinon: 94300 €/an
références:
@@ -197,7 +197,7 @@ entreprise . TVA . franchise de TVA . seuil vente:
entreprise . TVA . franchise de TVA . seuil service:
variations:
- - si: établissement . localisation . outre-mer . Guadeloupe Réunion Martinique
+ - si: établissement . commune . département . outre-mer . Guadeloupe Réunion Martinique
alors: 60000 €/an
- si: dirigeant . indépendant . PL . métier = 'avocat'
alors: 44500 €
diff --git a/modele-social/règles/entreprise/établissement.yaml b/modele-social/règles/entreprise/établissement.yaml
index 9db9dbbcc..6ad23e9fb 100644
--- a/modele-social/règles/entreprise/établissement.yaml
+++ b/modele-social/règles/entreprise/établissement.yaml
@@ -4,75 +4,40 @@
type: texte
applicable si: entreprise . SIREN
-établissement . localisation:
- experimental: oui
- icônes: 🌍
- description: |
- Lorsqu'une entreprise dispose de plusieurs établissements, certaines cotisations sont
- calculées à l'échelle de l'établissement et sont fonction de règlementations locales.
+établissement . commune:
+ icônes: 📍
question: Dans quelle commune l'établissement est-il implanté ?
API: commune
- # TODO : transform to texte
- par défaut:
- objet:
- code: 29019
- nom: Non renseignée
- departement:
- nom: Non renseigné
- taux du versement mobilité: 1.8
+ variations:
+ - si:
+ est défini: nom
+ alors:
+ texte: '{{ nom }} ({{ code postal }})'
+ - sinon: nom
avec:
- code commune:
- synchronisation:
- data: localisation
- chemin: code
-
- commune:
- description: |
- Lorsqu'une entreprise dispose de plusieurs établissements, certaines cotisations sont
- calculées à l'échelle de l'établissement et sont fonction de règlementations locales.
- synchronisation:
- data: localisation
- chemin: nom
-
+ nom:
+ taux versement mobilité:
+ par défaut: 0
+ unité: '%'
+ code postal:
département:
- synchronisation:
- data: localisation
- chemin: departement . nom
+ avec:
+ outre-mer:
+ par défaut: non
+ une de ces conditions:
+ - département = 'Guadeloupe'
+ - département = 'Martinique'
+ - département = 'Guyane'
+ - département = 'La Réunion'
+ - département . outre-mer . Mayotte
- outre-mer:
- applicable si:
- une de ces conditions:
- - département = 'Guadeloupe'
- - département = 'Martinique'
- - département = 'Guyane'
- - département = 'La Réunion'
- - département = 'Mayotte'
-
- outre-mer . Guadeloupe Réunion Martinique:
- une de ces conditions:
- - département = 'Guadeloupe'
- - département = 'Martinique'
- - département = 'La Réunion'
-
-établissement . versement mobilité:
- experimental: oui
- unité: '%'
- par défaut: oui
- synchronisation:
- data: localisation
- chemin: taux du versement mobilité
-
-établissement . ZFU:
- experimental: oui
- applicable si: entreprise . date de création < 01/2015
- question: Votre établissement bénéficie-t-il du dispositif zone franche urbaine (ZFU) ?
- par défaut: non
-
-établissement . ZFU . durée d'implantation en fin d'année:
- formule:
- durée:
- depuis: entreprise . date de création
- jusqu'à: 31/12/2019
+ avec:
+ Guadeloupe Réunion Martinique:
+ une de ces conditions:
+ - département = 'Guadeloupe'
+ - département = 'Martinique'
+ - département = 'La Réunion'
+ Mayotte: département = 'Mayotte'
établissement . taux ATMP:
description: |
@@ -106,3 +71,15 @@
si: taux ATMP < salarié . cotisations . ATMP . taux minimum
niveau: avertissement
description: Le taux renseigné est inférieur au taux minimum légal
+
+établissement . ZFU:
+ experimental: oui
+ applicable si: entreprise . date de création < 01/2015
+ question: Votre établissement bénéficie-t-il du dispositif zone franche urbaine (ZFU) ?
+ par défaut: non
+
+établissement . ZFU . durée d'implantation en fin d'année:
+ formule:
+ durée:
+ depuis: entreprise . date de création
+ jusqu'à: 31/12/2019
diff --git a/modele-social/règles/impôt.yaml b/modele-social/règles/impôt.yaml
index 85468849b..a739b6bad 100644
--- a/modele-social/règles/impôt.yaml
+++ b/modele-social/règles/impôt.yaml
@@ -97,7 +97,7 @@ impôt . revenu imposable . abattement contrat court:
impôt . taux neutre d'impôt sur le revenu . barème Guadeloupe Réunion Martinique:
icônes: 🇬🇵🇷🇪 🇲🇶
- applicable si: établissement . localisation . outre-mer . Guadeloupe Réunion Martinique
+ applicable si: établissement . commune . département . outre-mer . Guadeloupe Réunion Martinique
remplace: taux neutre d'impôt sur le revenu
grille:
assiette: revenu imposable
@@ -189,9 +189,10 @@ impôt . taux neutre d'impôt sur le revenu . barème Guadeloupe Réunion Martin
impôt . taux neutre d'impôt sur le revenu . barème Guyane Mayotte:
icônes: 🇬🇾 🇾🇹
applicable si:
+ par défaut: non
une de ces conditions:
- - établissement . localisation . département = 'Guyane'
- - établissement . localisation . département = 'Mayotte'
+ - établissement . commune . département = 'Guyane'
+ - établissement . commune . département = 'Mayotte'
remplace: taux neutre d'impôt sur le revenu
grille:
assiette: revenu imposable
diff --git a/modele-social/règles/salarié/activité-partielle.yaml b/modele-social/règles/salarié/activité-partielle.yaml
index ef7e5ed01..1b86dbc68 100644
--- a/modele-social/règles/salarié/activité-partielle.yaml
+++ b/modele-social/règles/salarié/activité-partielle.yaml
@@ -29,7 +29,7 @@ salarié . rémunération . revenus de remplacement:
assiette: revenus de remplacement
taux:
variations:
- - si: établissement . localisation . département = 'Mayotte'
+ - si: établissement . commune . département . outre-mer . Mayotte
alors: 2.35%
- si: régimes spécifiques . alsace moselle
alors: 1.5%
diff --git a/modele-social/règles/salarié/conventions-collectives/spectacle-vivant.yaml b/modele-social/règles/salarié/conventions-collectives/spectacle-vivant.yaml
index ab1943a57..df742e6a6 100644
--- a/modele-social/règles/salarié/conventions-collectives/spectacle-vivant.yaml
+++ b/modele-social/règles/salarié/conventions-collectives/spectacle-vivant.yaml
@@ -184,8 +184,8 @@ salarié . régimes spécifiques . intermittents du spectacle . artiste . réduc
par: cotisations . vieillesse . salarié . déplafonnée . taux * réduction de taux
- règle: cotisations . allocations familiales . taux
par: cotisations . allocations familiales . taux * réduction de taux
- - règle: établissement . versement mobilité
- par: établissement . versement mobilité * réduction de taux
+ - règle: cotisations . versement mobilité
+ par: cotisations . versement mobilité * réduction de taux
- règle: cotisations . FNAL . taux
par: cotisations . FNAL . taux * réduction de taux
formule: 70%
diff --git a/modele-social/règles/salarié/cotisations.yaml b/modele-social/règles/salarié/cotisations.yaml
index 65d69b0d7..7292a4369 100644
--- a/modele-social/règles/salarié/cotisations.yaml
+++ b/modele-social/règles/salarié/cotisations.yaml
@@ -99,18 +99,18 @@ salarié . cotisations . exonérations . heures supplémentaires:
urssaf.fr: https://www.urssaf.fr/portail/home/employeur/beneficier-dune-exoneration/exonerations-generales/la-deduction-forfaitaire-patrona/employeurs-concernes.html
salarié . cotisations . exonérations . lodeom:
- beta: oui
- valeur: oui
+ experimental: oui
applicable si:
+ par défaut: non
nom: zone un
titre: Zone géographique 1 (Guadeloupe, Martinique, La Réunion, Guyane)
références:
fiche Urssaf: https://www.urssaf.fr/portail/home/outre-mer/employeur/exoneration-de-cotisations-di-1/employeurs-situes-en-guadeloupe.html
une de ces conditions:
- - établissement . localisation . département = 'Guadeloupe'
- - établissement . localisation . département = 'La Réunion'
- - établissement . localisation . département = 'Martinique'
- - établissement . localisation . département = 'Guyane'
+ - établissement . commune . département = 'Guadeloupe'
+ - établissement . commune . département = 'La Réunion'
+ - établissement . commune . département = 'Martinique'
+ - établissement . commune . département = 'Guyane'
# TODO : ajouter la zone 2
description: |
Un ensemble assez complexe de réductions de cotisation est disponible pour les salariés d'outre-mer.
@@ -697,7 +697,7 @@ salarié . cotisations . CSG-CRDS . non déductible:
- revenus de remplacement . CRDS
salarié . cotisations . CSG-CRDS . CSG:
- non applicable si: établissement . localisation . département = 'Mayotte'
+ non applicable si: établissement . commune . département . outre-mer . Mayotte
description: >-
La contribution sociale généralisée (CSG) est un impôt destiné à participer
au financement de la protection sociale.
@@ -1092,7 +1092,7 @@ salarié . cotisations . taxe d'apprentissage:
valeur: cotisations . assiette
abattement:
variations:
- - si: établissement . localisation . outre-mer
+ - si: établissement . commune . département . outre-mer
alors: 20% * temps de travail . SMIC
- sinon: 11% * temps de travail . SMIC
- sinon: cotisations . assiette
@@ -1142,7 +1142,7 @@ salarié . cotisations . versement mobilité:
branche: transport
produit:
assiette: cotisations . assiette
- taux: établissement . versement mobilité
+ taux: établissement . commune . taux versement mobilité
références:
Recherchez le taux de versement mobilité applicable dans votre ville: https://www.urssaf.fr/portail/home/taux-et-baremes/versement-mobilite.html
diff --git a/modele-social/règles/salarié/salarié.yaml b/modele-social/règles/salarié/salarié.yaml
index 11e831ccb..0e814d123 100644
--- a/modele-social/règles/salarié/salarié.yaml
+++ b/modele-social/règles/salarié/salarié.yaml
@@ -38,11 +38,11 @@ salarié . régimes spécifiques . alsace moselle:
Nous considérons qu'un salarié est affilié au régime Alsace-Moselle quand l'établissement dans lequel il travaille est situé dans ces départements.
Attention : c'est une **simplification** : l'affiliation est plus compliquée que celà, voir les conditions exactes [sur le site du régime](http://regime-local.fr/salaries/).
-
+ par défaut: non
une de ces conditions:
- - établissement . localisation . département = 'Bas-Rhin'
- - établissement . localisation . département = 'Haut-Rhin'
- - établissement . localisation . département = 'Moselle'
+ - établissement . commune . département = 'Bas-Rhin'
+ - établissement . commune . département = 'Haut-Rhin'
+ - établissement . commune . département = 'Moselle'
salarié . régimes spécifiques . alsace moselle . ATMP:
avec:
@@ -188,8 +188,8 @@ salarié . régimes spécifiques . DFS . profession . journaliste . réduction d
- règle: cotisations . allocations familiales . taux
par: cotisations . allocations familiales . taux * réduction de taux
- - règle: établissement . versement mobilité
- par: établissement . versement mobilité * réduction de taux
+ - règle: cotisations . versement mobilité
+ par: cotisations . versement mobilité * réduction de taux
- règle: cotisations . ATMP . taux
par: cotisations . ATMP . taux * réduction de taux
- règle: cotisations . ATMP . taux minimum
diff --git a/site/package.json b/site/package.json
index 966d37168..b0dc1625f 100644
--- a/site/package.json
+++ b/site/package.json
@@ -79,8 +79,8 @@
"isbot": "^3.5.0",
"markdown-to-jsx": "^7.1.7",
"modele-social": "workspace:^",
- "publicodes": "^1.0.0-beta.54",
- "publicodes-react": "^1.0.0-beta.54",
+ "publicodes": "^1.0.0-beta.55",
+ "publicodes-react": "^1.0.0-beta.55",
"react": "^17.0.0",
"react-colorful": "^5.5.1",
"react-dom": "^17.0.0",
diff --git a/site/source/actions/actions.ts b/site/source/actions/actions.ts
index fe75e2b58..746094459 100644
--- a/site/source/actions/actions.ts
+++ b/site/source/actions/actions.ts
@@ -1,6 +1,7 @@
import { SimulationConfig } from '@/reducers/rootReducer'
+import { buildSituationFromObject } from '@/utils'
import { DottedName } from 'modele-social'
-import Engine from 'publicodes'
+import Engine, { PublicodesExpression } from 'publicodes'
import { CompanyActions } from './companyActions'
import { CompanyCreationAction } from './companyCreationChecklistActions'
import { CompanyStatusAction } from './companyStatusActions'
@@ -110,3 +111,25 @@ export const updateShouldFocusField = (shouldFocusField: boolean) =>
type: 'UPDATE_SHOULD_FOCUS_FIELD',
shouldFocusField,
} as const)
+
+export const answerQuestion = (
+ dottedName: DottedName,
+ value:
+ | PublicodesExpression
+ | undefined
+ | { batchUpdate: Record }
+) => {
+ if (value && typeof value === 'object' && 'batchUpdate' in value) {
+ return batchUpdateSituation(
+ buildSituationFromObject(
+ dottedName,
+ value.batchUpdate as Record
+ )
+ )
+ }
+
+ return (value == null ? deleteFromSituation : updateSituation)(
+ dottedName,
+ value
+ )
+}
diff --git a/site/source/api/commune.ts b/site/source/api/commune.ts
index 08bda8a40..90e367eb0 100644
--- a/site/source/api/commune.ts
+++ b/site/source/api/commune.ts
@@ -14,13 +14,14 @@ export type ApiCommuneJson = {
}
export type SearchCommune = {
- code: string
- codePostal: string
+ 'code commune': string
+ 'code postal': string
nom: string
+ département: string
}
-export type Commune = SearchCommune & {
- 'taux du versement mobilité': number
+export type Commune = Omit & {
+ 'taux versement mobilité': number
}
export async function searchCommunes(
@@ -42,8 +43,15 @@ export async function searchCommunes(
.flatMap(({ codesPostaux, ...commune }) =>
codesPostaux
.sort()
- .map((codePostal) => ({ ...commune, codePostal }))
- .filter(({ codePostal }) => codePostal.startsWith(number))
+ .map((codePostal) => ({
+ 'code commune': commune.code,
+ nom: commune.nom,
+ 'code postal': codePostal,
+ département: commune.departement.nom,
+ }))
+ .filter(({ 'code postal': codePostal }) =>
+ codePostal.startsWith(number)
+ )
)
.slice(0, 10)
}
@@ -64,36 +72,38 @@ export async function fetchCommuneDetails(
'Le code postal et le code commune fournis sont incompatibles'
)
}
- const commune: SearchCommune = { ...apiCommune, codePostal }
- const taux = await tauxVersementTransport(commune)
+
+ const taux = await tauxVersementTransport(apiCommune.code, codePostal)
if (taux === null) {
return null
}
return {
- ...commune,
- 'taux du versement mobilité': taux,
+ 'taux versement mobilité': taux,
+ nom: apiCommune.nom,
+ 'code postal': codePostal,
+ département: apiCommune.departement.nom,
}
}
async function tauxVersementTransport(
- commune: SearchCommune
+ codeCommune: string,
+ codePostal: string
): Promise {
- let codeCommune = commune.code
// 1. Si c'est une commune à arrondissement, on récupère le bon code correspondant à l'arrondissement.
// Comme il n'y a pas d'API facile pour faire ça, on le fait à la mano
// 1. a : PARIS
if (codeCommune === '75056') {
- codeCommune = '751' + commune.codePostal.slice(-2)
+ codeCommune = '751' + codePostal.slice(-2)
}
// 1. b : LYON
if (codeCommune === '69123') {
- codeCommune = '6938' + commune.codePostal.slice(-1)
+ codeCommune = '6938' + codePostal.slice(-1)
}
// 1. c : MARSEILLE
if (codeCommune === '13055') {
- codeCommune = '132' + commune.codePostal.slice(-2)
+ codeCommune = '132' + codePostal.slice(-2)
}
// 2. On récupère le versement transport associé
const response = await fetch('/data/versement-mobilité.json')
diff --git a/site/source/components/ChiffreAffairesActivitéMixte.tsx b/site/source/components/ChiffreAffairesActivitéMixte.tsx
index c63547881..2afffd6d6 100644
--- a/site/source/components/ChiffreAffairesActivitéMixte.tsx
+++ b/site/source/components/ChiffreAffairesActivitéMixte.tsx
@@ -1,18 +1,16 @@
import { batchUpdateSituation } from '@/actions/actions'
-import ButtonHelp from '@/design-system/buttons/ButtonHelp'
+import { Switch } from '@/design-system/switch'
+import { situationSelector } from '@/selectors/simulationSelectors'
import { DottedName } from 'modele-social'
import { serializeEvaluation } from 'publicodes'
import { useCallback } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
-import { situationSelector } from '@/selectors/simulationSelectors'
import styled from 'styled-components'
+import { ExplicableRule } from './conversation/Explicable'
import { Condition } from './EngineValue'
import { SimulationGoal } from './Simulation'
import { useEngine } from './utils/EngineContext'
-import { Markdown } from './utils/markdown'
-import { Switch } from '@/design-system/switch'
-import { ExplicableRule } from './conversation/Explicable'
const proportions = {
'entreprise . activité . mixte . proportions . service BIC':
diff --git a/site/source/components/company/Details.tsx b/site/source/components/company/Details.tsx
index 12597a428..9f2b689a7 100644
--- a/site/source/components/company/Details.tsx
+++ b/site/source/components/company/Details.tsx
@@ -41,7 +41,7 @@ export function CompanyDetails({
et domiciliée à{' '}
diff --git a/site/source/components/conversation/AnswerList.tsx b/site/source/components/conversation/AnswerList.tsx
index 8bf13aa39..afb919bc4 100644
--- a/site/source/components/conversation/AnswerList.tsx
+++ b/site/source/components/conversation/AnswerList.tsx
@@ -1,4 +1,4 @@
-import { resetSimulation, updateSituation } from '@/actions/actions'
+import { answerQuestion, resetSimulation } from '@/actions/actions'
import { resetCompany } from '@/actions/companyActions'
import Emoji from '@/components/utils/Emoji'
import { EvaluatedRule, useEngine } from '@/components/utils/EngineContext'
@@ -10,6 +10,8 @@ import { H2, H3 } from '@/design-system/typography/heading'
import { Link } from '@/design-system/typography/link'
import { Body } from '@/design-system/typography/paragraphs'
import { CurrentSimulatorDataContext } from '@/pages/Simulateurs/metadata'
+import { utils } from 'publicodes'
+
import {
answeredQuestionsSelector,
companySituationSelector,
@@ -196,17 +198,23 @@ function StepsTable({
function AnswerElement(rule: EvaluatedRule) {
const dispatch = useDispatch()
-
- const dottedName = rule.dottedName
- const handleChange = useCallback(
- (value) => {
- dispatch(updateSituation(dottedName, value))
- },
- [dispatch, dottedName]
- )
const engine = useEngine()
- return rule.rawNode.question ? (
+ const parentDottedName = utils.ruleParent(rule.dottedName) as DottedName
+ const questionDottedName = rule.rawNode.question
+ ? rule.dottedName
+ : parentDottedName && engine.getRule(parentDottedName).rawNode.API
+ ? parentDottedName
+ : undefined
+
+ const handleChange = useCallback(
+ (value) => {
+ questionDottedName && dispatch(answerQuestion(questionDottedName, value))
+ },
+ [dispatch, questionDottedName]
+ )
+
+ return questionDottedName ? (
(
@@ -222,11 +230,11 @@ function AnswerElement(rule: EvaluatedRule) {
<>
diff --git a/site/source/reducers/companySituationReducer.ts b/site/source/reducers/companySituationReducer.ts
index 29f9107e3..791e9ff16 100644
--- a/site/source/reducers/companySituationReducer.ts
+++ b/site/source/reducers/companySituationReducer.ts
@@ -1,7 +1,7 @@
import { DottedName } from '@/../../modele-social'
import { Action } from '@/actions/actions'
import { FabriqueSocialEntreprise } from '@/api/fabrique-social'
-import { omit } from '@/utils'
+import { buildSituationFromObject, omit } from '@/utils'
import { Situation } from './rootReducer'
const SAVED_NAMESPACES = [
@@ -53,7 +53,7 @@ export function companySituation(state: Situation = {}, action: Action) {
case 'COMPANY::ADD_COMMUNE_DETAILS':
return {
...state,
- 'établissement . localisation': { objet: action.details },
+ ...buildSituationFromObject('établissement . commune', action.details),
}
case 'COMPANY::SET_BÉNÉFICE_TYPE':
return {
diff --git a/site/source/reducers/rootReducer.ts b/site/source/reducers/rootReducer.ts
index f8b6cd5c7..722abf074 100644
--- a/site/source/reducers/rootReducer.ts
+++ b/site/source/reducers/rootReducer.ts
@@ -1,7 +1,7 @@
import { Action } from '@/actions/actions'
-import { Commune } from '@/api/commune'
import { PreviousSimulation } from '@/selectors/previousSimulationSelectors'
import { DottedName } from 'modele-social'
+import { PublicodesExpression } from 'publicodes'
import reduceReducers from 'reduce-reducers'
import { combineReducers, Reducer } from 'redux'
import { objectifsSelector } from '../selectors/simulationSelectors'
@@ -56,9 +56,8 @@ type Overwrite = { [P in keyof Omit]: T[P] } & U
export type Situation = Partial<
Overwrite<
- Record,
+ Record,
{
- 'établissement . localisation': { objet: Commune }
'entreprise . imposition': string
année: number
}
diff --git a/site/source/selectors/simulationSelectors.ts b/site/source/selectors/simulationSelectors.ts
index ecaaa0e0c..d563487d2 100644
--- a/site/source/selectors/simulationSelectors.ts
+++ b/site/source/selectors/simulationSelectors.ts
@@ -1,5 +1,8 @@
+import { useEngine } from '@/components/utils/EngineContext'
import { RootState, SimulationConfig, Situation } from '@/reducers/rootReducer'
import { DottedName } from 'modele-social'
+import Engine, { utils } from 'publicodes'
+import { useSelector } from 'react-redux'
export const configSelector = (state: RootState): Partial =>
state.simulation?.config ?? {}
@@ -19,6 +22,17 @@ export const objectifsSelector = (state: RootState) => {
const emptySituation: Situation = {}
+export const useMissingVariables = (): Partial> => {
+ const objectifs = useSelector(objectifsSelector)
+ const engine = useEngine()
+
+ return mergeObjectifsMissingVariable(
+ objectifs.map(
+ (objectif) => engine.evaluate(objectif).missingVariables ?? {}
+ ),
+ engine
+ )
+}
export const situationSelector = (state: RootState) =>
state.simulation?.situation ?? emptySituation
@@ -50,3 +64,29 @@ export const answeredQuestionsSelector = (state: RootState) =>
export const shouldFocusFieldSelector = (state: RootState) =>
state.simulation?.shouldFocusField ?? false
+
+/**
+ * Merge objectifs missings that depends on the same input field.
+ *
+ * For instance, the commune field (API) will fill `commune . nom` `commune . taux versement transport`, `commune . département`, etc.
+ */
+function mergeObjectifsMissingVariable(
+ missingVariables: Array>>,
+ engine: Engine
+): Partial> {
+ return (
+ missingVariables.flatMap((missings) => Object.entries(missings)) as Array<
+ [Name, number]
+ >
+ ).reduce((missings, [name, value]: [Name, number]) => {
+ const parentName = utils.ruleParent(name) as Name
+ if (parentName && engine.getRule(parentName).rawNode.API) {
+ missings[parentName] = (missings[parentName] ?? 0) + value
+
+ return missings
+ }
+ missings[name] = value
+
+ return missings
+ }, {} as Partial>)
+}
diff --git a/site/source/utils.ts b/site/source/utils.ts
index cbefceec9..1356b6c88 100644
--- a/site/source/utils.ts
+++ b/site/source/utils.ts
@@ -1,9 +1,11 @@
+import { DottedName } from 'modele-social'
import Engine, {
formatValue,
PublicodesExpression,
Rule,
RuleNode,
} from 'publicodes'
+import { Situation } from './reducers/rootReducer'
export function capitalise0(name: undefined): undefined
export function capitalise0(name: string): string
@@ -240,3 +242,17 @@ export function evaluateQuestion(
return question
}
+
+export function buildSituationFromObject(
+ contextDottedName: Names,
+ situationObject: Record
+): Situation {
+ return Object.fromEntries(
+ Object.entries(situationObject).map(
+ ([key, value]: [string, PublicodesExpression]) => [
+ `${contextDottedName} . ${key}` as Names,
+ typeof value === 'string' ? `'${value}'` : value,
+ ]
+ )
+ )
+}
diff --git a/site/test/conversation.test.js b/site/test/conversation.test.ts
similarity index 70%
rename from site/test/conversation.test.js
rename to site/test/conversation.test.ts
index edd974c91..19c1fc231 100644
--- a/site/test/conversation.test.js
+++ b/site/test/conversation.test.ts
@@ -1,10 +1,7 @@
import rules from 'modele-social'
import Engine from 'publicodes'
import { describe, expect, it } from 'vitest'
-import {
- getNextQuestions,
- getNextSteps,
-} from '../source/components/utils/useNextQuestion'
+import { getNextQuestions } from '../source/components/utils/useNextQuestion'
describe('conversation', function () {
it('should start with the first missing variable', function () {
@@ -15,7 +12,7 @@ describe('conversation', function () {
'top . a': { question: '?', titre: 'a', unité: '€' },
'top . b': { question: '?', titre: 'b', unité: '€' },
}).evaluate('top . startHere').missingVariables
- expect(getNextQuestions([missingVariables])[0]).to.equal('top . a')
+ 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({
@@ -46,12 +43,11 @@ describe('conversation', function () {
},
cadre: {
question: 'Est-ce un cadre ?',
- 'par défaut': 'non',
},
})
expect(
- getNextQuestions([engine.evaluate('net').missingVariables])[0]
+ getNextQuestions(engine.evaluate('net').missingVariables)[0]
).to.equal('brut')
engine.setSituation({
@@ -59,7 +55,7 @@ describe('conversation', function () {
})
expect(
- getNextQuestions([engine.evaluate('net').missingVariables])[0]
+ getNextQuestions(engine.evaluate('net').missingVariables)[0]
).to.equal('cadre')
})
@@ -78,23 +74,3 @@ describe('conversation', function () {
expect(result).to.include('salarié . contrat . CDD . motif')
})
})
-
-describe('getNextSteps', function () {
- it('should give priority to questions by total weight when advancing the same target count', function () {
- let missingVariablesByTarget = [
- {
- effectif: 24.01,
- cadre: 30,
- },
- {
- effectif: 24.01,
- cadre: 10.1,
- },
- {},
- ]
-
- let result = getNextSteps(missingVariablesByTarget)
-
- expect(result[0]).to.equal('effectif')
- })
-})
diff --git a/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap b/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap
index d65dcb8a3..520592a5e 100644
--- a/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap
+++ b/site/test/regressions/__snapshots__/simulations-salarié.test.ts.snap
@@ -1,5 +1,11 @@
// Vitest Snapshot v1
+exports[`calculate simulations-salarié > ATMP 1`] = `"[2370,0,2000,1561,1527]"`;
+
+exports[`calculate simulations-salarié > ATMP 2`] = `"[2312,0,2000,1561,1527]"`;
+
+exports[`calculate simulations-salarié > ATMP 3`] = `"[2326,0,2000,1561,1527]"`;
+
exports[`calculate simulations-salarié > CCN HCR 1`] = `
"[3480,0,2500,1983,1872]
Notifications affichées : salarié . convention collective . contrôle décharge"
@@ -131,11 +137,11 @@ exports[`calculate simulations-salarié > contrat pro 2`] = `"[1566,0,1500,1165,
exports[`calculate simulations-salarié > effectif 1`] = `"[2354,0,2000,1561,1527]"`;
-exports[`calculate simulations-salarié > effectif 2`] = `"[2401,0,2000,1561,1527]"`;
+exports[`calculate simulations-salarié > effectif 2`] = `"[2365,0,2000,1561,1527]"`;
-exports[`calculate simulations-salarié > effectif 3`] = `"[2413,0,2000,1561,1527]"`;
+exports[`calculate simulations-salarié > effectif 3`] = `"[2377,0,2000,1561,1527]"`;
-exports[`calculate simulations-salarié > effectif 4`] = `"[2413,0,2000,1561,1527]"`;
+exports[`calculate simulations-salarié > effectif 4`] = `"[2377,0,2000,1561,1527]"`;
exports[`calculate simulations-salarié > frais pro - DFS 1`] = `"[2078,0,2000,1622,1622]"`;
@@ -187,7 +193,7 @@ exports[`calculate simulations-salarié > heures supplémentaires et complément
exports[`calculate simulations-salarié > heures supplémentaires et complémentaires 2`] = `"[2415,0,2000,1606,1572]"`;
-exports[`calculate simulations-salarié > heures supplémentaires et complémentaires 3`] = `"[2524,0,2000,1636,1601]"`;
+exports[`calculate simulations-salarié > heures supplémentaires et complémentaires 3`] = `"[2486,0,2000,1636,1601]"`;
exports[`calculate simulations-salarié > heures supplémentaires et complémentaires 4`] = `
"[2454,0,2000,1616,1581]
diff --git a/site/test/regressions/simulations-salarié.test.ts b/site/test/regressions/simulations-salarié.test.ts
index 63d91c46a..11420ee35 100644
--- a/site/test/regressions/simulations-salarié.test.ts
+++ b/site/test/regressions/simulations-salarié.test.ts
@@ -29,6 +29,7 @@ it('calculate simulations-salarié', () => {
"salarié . cotisations . prévoyances . santé . montant",
"salarié . cotisations . prévoyances . santé . taux employeur",
"salarié . régimes spécifiques . DFS",
+ "salarié . régimes spécifiques . alsace moselle",
"salarié . régimes spécifiques . impatriés",
"salarié . rémunération . avantages en nature",
"salarié . rémunération . frais professionnels . titres-restaurant",
@@ -39,7 +40,8 @@ it('calculate simulations-salarié', () => {
"salarié . rémunération . primes . fin d'année",
"salarié . temps de travail . heures supplémentaires",
"situation personnelle . domiciliation fiscale à l'étranger",
- "établissement . localisation",
+ "établissement . commune . département",
+ "établissement . commune . département . outre-mer",
]
`)
})
diff --git a/site/test/regressions/simulations-salarié.yaml b/site/test/regressions/simulations-salarié.yaml
index 3c9ed9a57..83ada1182 100644
--- a/site/test/regressions/simulations-salarié.yaml
+++ b/site/test/regressions/simulations-salarié.yaml
@@ -45,6 +45,14 @@ apprentissage:
salarié . contrat . apprentissage . diplôme préparé: "'niveau bac ou moins'"
salarié . contrat . apprentissage . ancienneté: "'moins de deux ans'"
+ATMP:
+ - salarié . contrat . salaire brut: 2000 €/mois
+ établissement . taux ATMP: '3 %'
+ - salarié . contrat . salaire brut: 2000 €/mois
+ établissement . taux ATMP: '0.1 %'
+ - salarié . contrat . salaire brut: 2000 €/mois
+ salarié . cotisations . ATMP . taux fonctions support: oui
+
contrat pro:
- salarié . contrat: "'professionnalisation'"
salarié . contrat . date d'embauche: 01/10/2020
@@ -132,16 +140,16 @@ impôt sur le revenu:
impôt . méthode de calcul: "'taux neutre'"
- salarié . contrat . salaire brut: 3000 €/mois
impôt . méthode de calcul: "'taux neutre'"
- établissement . localisation . département: "'Guadeloupe'"
+ établissement . commune . département: "'Guadeloupe'"
- salarié . contrat . salaire brut: 30000 €/mois
impôt . méthode de calcul: "'taux neutre'"
- établissement . localisation . département: "'Guadeloupe'"
+ établissement . commune . département: "'Guadeloupe'"
- salarié . contrat . salaire brut: 3000 €/mois
impôt . méthode de calcul: "'taux neutre'"
- établissement . localisation . département: "'Mayotte'"
+ établissement . commune . département: "'Mayotte'"
- salarié . contrat . salaire brut: 30000 €/mois
impôt . méthode de calcul: "'taux neutre'"
- établissement . localisation . département: "'Mayotte'"
+ établissement . commune . département: "'Mayotte'"
- salarié . contrat . salaire brut: 3000 €/mois
impôt . méthode de calcul: "'taux personnalisé'"
impôt . taux personnalisé: 10%
diff --git a/yarn.lock b/yarn.lock
index 895ec7694..c31fa0292 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4714,9 +4714,9 @@ __metadata:
languageName: node
linkType: hard
-"@publicodes/api@npm:^1.0.0-beta.54":
- version: 1.0.0-beta.54
- resolution: "@publicodes/api@npm:1.0.0-beta.54"
+"@publicodes/api@npm:^1.0.0-beta.55":
+ version: 1.0.0-beta.55
+ resolution: "@publicodes/api@npm:1.0.0-beta.55"
dependencies:
"@koa/cors": ^3.3.0
"@koa/router": ^10.1.1
@@ -4725,7 +4725,7 @@ __metadata:
openapi-validator-middleware: ^3.2.6
peerDependencies:
publicodes: ^1.0.0-beta.47
- checksum: 8383c05d90b638db49b951dda470adf361ec103ecb43b6b3a4e3a0da84d9f62083391ba46c1927cb0bcd1c90dd66b7b20a8e7a6df3b2e592df88fba56c6af79a
+ checksum: 82bcc777c5b5b644b3ae7fdb9d5b9c0d76c3a940411856e443db94ea9e6f756d2630bbbb90514cc256c6959a7e863b20a8eb778d27c5219bf2e0af9dc36d75cf
languageName: node
linkType: hard
@@ -10036,7 +10036,7 @@ __metadata:
"@apidevtools/swagger-cli": ^4.0.4
"@koa/cors": ^3.3.0
"@koa/router": ^10.1.1
- "@publicodes/api": ^1.0.0-beta.54
+ "@publicodes/api": ^1.0.0-beta.55
"@sentry/node": ^7.1.1
"@sentry/tracing": ^7.1.1
"@types/koa": ^2.13.4
@@ -10053,7 +10053,7 @@ __metadata:
koa-static: ^5.0.0
modele-social: "workspace:^"
nodemon: ^2.0.16
- publicodes: ^1.0.0-beta.54
+ publicodes: ^1.0.0-beta.55
rate-limiter-flexible: ^2.3.8
rimraf: ^3.0.2
swagger-ui-dist: ^4.11.1
@@ -15664,9 +15664,9 @@ __metadata:
dependencies:
js-yaml: ^4.1.0
onchange: ^7.1.0
- publicodes: =1.0.0-beta.54
+ publicodes: =1.0.0-beta.55
peerDependencies:
- publicodes: ^1.0.0-beta.54
+ publicodes: ^1.0.0-beta.55
languageName: unknown
linkType: soft
@@ -21278,9 +21278,9 @@ __metadata:
dependencies:
js-yaml: ^4.1.0
onchange: ^7.1.0
- publicodes: ^1.0.0-beta.54
+ publicodes: ^1.0.0-beta.55
peerDependencies:
- publicodes: ^1.0.0-beta.54
+ publicodes: ^1.0.0-beta.55
languageName: unknown
linkType: soft
@@ -23665,28 +23665,28 @@ __metadata:
languageName: node
linkType: hard
-"publicodes-react@npm:^1.0.0-beta.54":
- version: 1.0.0-beta.54
- resolution: "publicodes-react@npm:1.0.0-beta.54"
+"publicodes-react@npm:^1.0.0-beta.55":
+ version: 1.0.0-beta.55
+ resolution: "publicodes-react@npm:1.0.0-beta.55"
dependencies:
styled-components: ^5.1.0
peerDependencies:
publicodes: 1.0.0-beta.40
react: ^17 || ^18
react-dom: ^17 || ^18
- checksum: 104e489dabdd865f50110348ea778bfd896817b27497803115fe04e95b91c9f59fc1ab11bb54b1af5f6e9a093721ca2720f086f501a1c00acfac6987202ce2d1
+ checksum: c5472d2c71834ce021ecb6e107fb45663c786dcc947d3e5a1768638cddc61fd475925e8c54aaa41b4ebd3fc9e27bd4ad538ea4b28fd27cecff2db36bee8cb10d
languageName: node
linkType: hard
-"publicodes@npm:=1.0.0-beta.54, publicodes@npm:^1.0.0-beta.54":
- version: 1.0.0-beta.54
- resolution: "publicodes@npm:1.0.0-beta.54"
+"publicodes@npm:=1.0.0-beta.55, publicodes@npm:^1.0.0-beta.55":
+ version: 1.0.0-beta.55
+ resolution: "publicodes@npm:1.0.0-beta.55"
dependencies:
moo: ^0.5.1
nearley: ^2.19.2
peerDependencies:
"@types/mocha": ^9.0.0
- checksum: 2a02cfa9e21e1aeb757c757f597ca3ece6d2c22fa863a3cf95b85c14238ff801e8d1a1357dcec03961b517da3154aedfe9ddeb58761c468c31aec6ae692f2e29
+ checksum: 280ea364ccde2a12e74357d300bf5a86d55f6d7acbf9ad38b6b82ef2ae86f4fad24d4ce167d1897a53f6d86b229a4b01ab4c9aeb3e2a8c5c4643c16fe12e52ee
languageName: node
linkType: hard
@@ -25783,8 +25783,8 @@ __metadata:
markdown-to-jsx: ^7.1.7
modele-social: "workspace:^"
netlify-cli: ^10.6.3
- publicodes: ^1.0.0-beta.54
- publicodes-react: ^1.0.0-beta.54
+ publicodes: ^1.0.0-beta.55
+ publicodes-react: ^1.0.0-beta.55
react: ^17.0.0
react-colorful: ^5.5.1
react-dom: ^17.0.0