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

- {evaluateQuestion(engine, engine.getRule(rule.dottedName))} - + {evaluateQuestion(engine, engine.getRule(questionDottedName))} +

{ if (currentQuestion) { @@ -65,12 +65,7 @@ export default function Conversation({ } const onChange = (value: PublicodesExpression | undefined) => { - dispatch( - (value == null ? deleteFromSituation : updateSituation)( - currentQuestion, - value - ) - ) + dispatch(answerQuestion(currentQuestion, value)) } return ( diff --git a/site/source/components/conversation/RuleInput.tsx b/site/source/components/conversation/RuleInput.tsx index 52b4660bf..aedb99b34 100644 --- a/site/source/components/conversation/RuleInput.tsx +++ b/site/source/components/conversation/RuleInput.tsx @@ -119,9 +119,17 @@ export default function RuleInput({ /> ) } + if (rule.rawNode.API && rule.rawNode.API === 'commune') { - return + return ( + commonProps.onChange({ batchUpdate: c })} + value={value as Evaluation} + /> + ) } + if (rule.rawNode.API && rule.rawNode.API.startsWith('pays détachement')) { return ( ({ ) } if (rule.rawNode.API) { - throw new Error("Les seules API implémentées sont 'commune'") + throw new Error( + "Les seules API implémentées sont 'commune' et 'pays détachement'" + ) } if (rule.dottedName === 'établissement . taux ATMP . taux collectif') { diff --git a/site/source/components/conversation/select/SelectCommune.tsx b/site/source/components/conversation/select/SelectCommune.tsx index 390250d2e..6e0962d89 100644 --- a/site/source/components/conversation/select/SelectCommune.tsx +++ b/site/source/components/conversation/select/SelectCommune.tsx @@ -10,10 +10,17 @@ import { debounce } from '@/utils' import { KeyboardEvent, useCallback, useMemo, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' -import { InputProps } from '../RuleInput' function formatCommune(value: SearchCommune) { - return value && `${value.nom} (${value.codePostal})` + return value && `${value.nom} (${value['code postal']})` +} + +type SelectCommuneProps = { + onChange: (c: Commune) => void + value: string | undefined | null + missing?: boolean + id?: string + autoFocus?: boolean } export default function Select({ @@ -22,10 +29,8 @@ export default function Select({ id, missing, autoFocus, -}: InputProps) { - const [name, setName] = useState( - missing ? '' : formatCommune(value as Commune) - ) +}: SelectCommuneProps) { + const [name, setName] = useState(missing ? '' : value ?? undefined) const [searchResults, setSearchResults] = useState>(null) const { t } = useTranslation() @@ -51,15 +56,13 @@ export default function Select({ setName(formatCommune(commune)) try { const communeWithDetails = await fetchCommuneDetails( - commune.code, - commune.codePostal + commune['code commune'], + commune['code postal'] ) if (!communeWithDetails) { return } - onChange({ - objet: communeWithDetails, - }) + onChange(communeWithDetails) } catch (error) { // eslint-disable-next-line no-console console.warn( diff --git a/site/source/components/utils/useNextQuestion.tsx b/site/source/components/utils/useNextQuestion.tsx index 7f96c1e55..44d933a87 100644 --- a/site/source/components/utils/useNextQuestion.tsx +++ b/site/source/components/utils/useNextQuestion.tsx @@ -3,7 +3,7 @@ import { answeredQuestionsSelector, configSelector, currentQuestionSelector, - objectifsSelector, + useMissingVariables, } from '@/selectors/simulationSelectors' import { DottedName } from 'modele-social' import { useContext, useMemo } from 'react' @@ -12,27 +12,6 @@ import { EngineContext } from './EngineContext' type MissingVariables = Partial> -export function getNextSteps( - missingVariables: Array -): Array { - const missingByTotalScore = missingVariables.reduce>( - (acc, mv) => ({ - ...acc, - ...Object.fromEntries( - Object.entries(mv).map(([name, score]) => [ - name, - (acc[name] || 0) + score, - ]) - ), - }), - {} - ) - - return Object.entries(missingByTotalScore) - .sort(([, a], [, b]) => b - a) - .map(([a]) => a) as Array -} - // Max : 1 // Min -> 0 const questionDifference = (ruleA = '', ruleB = '') => { @@ -46,7 +25,7 @@ const questionDifference = (ruleA = '', ruleB = '') => { } export function getNextQuestions( - missingVariables: Array, + missingVariables: MissingVariables, questionConfig: SimulationConfig['questions'] = {}, answeredQuestions: Array = [] ): Array { @@ -56,7 +35,9 @@ export function getNextQuestions( 'liste noire': blacklist = [], } = questionConfig - const nextSteps = getNextSteps(missingVariables) + const nextSteps = Object.entries(missingVariables) + .sort(([, a], [, b]) => b - a) + .map(([a]) => a as DottedName) .filter((name) => !answeredQuestions.includes(name)) .filter( (step) => @@ -82,14 +63,11 @@ export function getNextQuestions( } export const useNextQuestions = function (): Array { - const objectifs = useSelector(objectifsSelector) const answeredQuestions = useSelector(answeredQuestionsSelector) const currentQuestion = useSelector(currentQuestionSelector) const questionsConfig = useSelector(configSelector).questions const engine = useContext(EngineContext) - const missingVariables = objectifs.map( - (objectif) => engine.evaluate(objectif).missingVariables ?? {} - ) + const missingVariables = useMissingVariables() const nextQuestions = useMemo(() => { let next = getNextQuestions( missingVariables, diff --git a/site/source/data/releases.json b/site/source/data/releases.json index fe0a05531..e20cb9cf6 100644 --- a/site/source/data/releases.json +++ b/site/source/data/releases.json @@ -1,7 +1,7 @@ [ { "name": "Juin 2022", - "description": "**En bref**\r\n> - Vous pouvez installer mon-entreprise sur votre téléphone et accéder aux simulateurs même sans connection internet !\r\n> - Accédez à toutes les informations de votre entreprise grâce au lien vers [annuaire-entreprise.data.gouv.fr]\r\n> - Améliorations de l'interface et corrections de bugs\r\n\r\n## Accédez aux simulateurs à tout moment ✈️\r\n\r\nTous les simulateurs de mon-entreprise sont maintenant utilisables en mode hors ligne ! Il vous suffit de vous rendre une fois sur le site, et vous pourrez y revenir à tout moment, même sans accès internet.\r\n\r\nEt ce n'est pas tout : vous pouvez installer les simulateurs directement sur votre téléphone ou votre ordinateur pour y revenir en un clic ! Pour cela il vous suffit de cliquer sur « installer » lors de la visite du site depuis le navigateur. \r\n\r\nhttps://user-images.githubusercontent.com/1775934/181524049-56055bd8-342f-43d8-ad38-5f745e2eb89a.mp4\r\n\r\n## Retrouvez toutes les informations de votre entreprise sur une seule page\r\n\r\nVous ne vous rappelez jamais du SIRET ? Impossible de remettre la main sur votre numéro de TVA intercommunautaire ? Vous pouvez consulter toutes les données publiques de votre entreprise sur [annuaire-entreprise.data.gouv.fr]. Nous avons ajouté un lien en bas du tableau de bord de votre entreprise.\r\n![image](https://user-images.githubusercontent.com/1775934/181525140-3c421884-f772-43ee-9d2f-60540df48dd0.png)\r\n\r\n## Améliorations diverses et corrections de bugs\r\n\r\n- Les taux du versement mobilité ont été actualisés\r\n- La grille des taux neutre de l'impôt sur le revenu a été également mis à jour\r\n- Vous pouvez maintenant déposer un avis sur le simulateur salarié grâce au bouton « Je donne mon avis »\r\n- Nous avons corrigé le calcul de l'impôt sur le revenu pour les parents isolés\r\n- L'abattement sur les dividendes a été corrigé\r\n- Nous avons ajouté davantage de liens vers des pages d'explications derrière le bouton « Info » présent à côté des questions\r\n- Corrections de bug divers " + "description": "**En bref**\r\n> - Vous pouvez installer mon-entreprise sur votre téléphone et accéder aux simulateurs même sans connection internet !\r\n> - Accédez à toutes les informations de votre entreprise grâce au lien vers [annuaire-entreprise.data.gouv.fr]\r\n> - Améliorations de l'interface et corrections de bugs\r\n\r\n## Accédez aux simulateurs à tout moment ✈️\r\n\r\nTous les simulateurs de mon-entreprise sont maintenant utilisables en mode hors ligne ! Il vous suffit de vous rendre une fois sur le site, et vous pourrez y revenir à tout moment, même sans accès internet.\r\n\r\nEt ce n'est pas tout : vous pouvez installer les simulateurs directement sur votre téléphone ou votre ordinateur pour y revenir en un clic ! Pour cela il vous suffit de cliquer sur « installer » lors de la visite du site depuis le navigateur. \r\n\r\nhttps://user-images.githubusercontent.com/1775934/181524049-56055bd8-342f-43d8-ad38-5f745e2eb89a.mp4\r\n\r\n## Retrouvez toutes les informations de votre entreprise sur une seule page\r\n\r\nVous ne vous rappelez jamais du SIRET ? Impossible de remettre la main sur votre numéro de TVA intercommunautaire ? Vous pouvez consulter toutes les données publiques de votre entreprise sur [annuaire-entreprise.data.gouv.fr]. Nous avons ajouté un lien en bas du tableau de bord de votre entreprise.\r\n![image](https://user-images.githubusercontent.com/1775934/181525140-3c421884-f772-43ee-9d2f-60540df48dd0.png)\r\n\r\n## Améliorations diverses et corrections de bugs\r\n\r\n- Les taux versement mobilité ont été actualisés\r\n- La grille des taux neutre de l'impôt sur le revenu a été également mis à jour\r\n- Vous pouvez maintenant déposer un avis sur le simulateur salarié grâce au bouton « Je donne mon avis »\r\n- Nous avons corrigé le calcul de l'impôt sur le revenu pour les parents isolés\r\n- L'abattement sur les dividendes a été corrigé\r\n- Nous avons ajouté davantage de liens vers des pages d'explications derrière le bouton « Info » présent à côté des questions\r\n- Corrections de bug divers " }, { "name": "Avril 2022", @@ -9,7 +9,7 @@ }, { "name": "Janvier 2022", - "description": "> **En bref :**\r\n> - Mise à jour législative au 1er janvier\r\n> - Nouveau moteur de recherche d'entreprise\r\n> - Travail sur les parcours\r\n> - Mise à jour du formulaire de demande de mobilité\r\n\r\n## Mise à jour législative au 1er janvier 2022\r\n\r\nComme tous les ans, certains montants sont revalorisés au 1er janvier. C'est le cas en particulier du SMIC qui vaut désormais 1603 € brut par mois pour un salarié travaillant à temps plein. Le barème de l'impôt sur le revenu a aussi été ajusté pour prendre en compte l'inflation. D'autres éléments ont été mis à jour comme les barèmes de cotisation des caisses de retraite, le taux du versement mobilité, le taux de la cotisation pour les indemnités journalières des indépendants ou encore le montant des titres restaurants exonéré de cotisations.\r\n\r\n## Nouveau moteur de recherche d'entreprise 🔍\r\n\r\nNous avons travaillé avec les équipes de [code du travail numérique] (https://code.travail.gouv.fr/) sur un nouveau moteur de recherche des entreprises. Il vous permet de trouver votre entreprise facilement et de manière plus fiable que ce que nous proposions avant. Ce nouveau moteur permet également d'associer à une entreprise des informations comme sa convention collective si elle en possède une, la localisation de son siège social, sa date de création, etc.\r\n\r\n[![recherche d'entreprise](https://user-images.githubusercontent.com/1730702/149759756-02f30ab4-2531-416c-8438-4cdf96b83523.png)](https://mon-entreprise.urssaf.fr/)\r\n\r\n## Travail sur les parcours\r\n\r\nVous avez désormais la possibilité de renseigner votre entreprise actuelle dès la page d’accueil du site. Grâce à cela nous identifions les bons outils dans votre situation, par exemple un simulateur de revenu pour un auto-entrepreneur, ou bien une aide à la déclaration fiscale pour les indépendants. Grâce au code APE nous pouvons même identifier la nature de certaines activités pour les professions libérales et aller plus loin dans la personnalisation des outils.\r\n\r\n![image](https://user-images.githubusercontent.com/1730702/149761273-fe9fa7fd-8e4d-45ca-868f-f35a5e1bacb7.png)\r\n\r\n## Mise à jour du formulaire de demande de mobilité\r\n\r\nLe formulaire de demande de mobilité gère désormais le cas des salariés ainsi que des praticiens et auxiliaires médicaux. Un nouveau parcour a été crée dans le cas d'un détachement dans un pays avec une convention bilatérale.\r\n\r\n## Détails des changements\r\n\r\n* ✨ Nouvelle page d'accueil - charte urssaf by @bobylito in https://github.com/betagouv/mon-entreprise/pull/1851\r\n* Améliore le style de la landing et de la page gérer by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1867\r\n* Quelques bugfixes by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1876\r\n* Répare la couleur du placeholder sous chrome by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1877\r\n* Répare la comparaison de régime sociaux by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1886\r\n* Petits fix de la recherche by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1887\r\n* Affiche une bannière dans la section dev lors d'un recrutement by @mquandalle in https://github.com/betagouv/mon-entreprise/pull/1884\r\n* Quelques fixes by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1891\r\n* Améliore le style des simulateurs et de la fiche de paie by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1892\r\n* Correction tests CI master by @mquandalle in https://github.com/betagouv/mon-entreprise/pull/1896\r\n* Corrections de bugs par wiinxt by @mquandalle in https://github.com/betagouv/mon-entreprise/pull/1903\r\n* Modification formulaire DLA suite aux retours Urssaf by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1783\r\n* Mise à jour legislative 1er janvier 2022 by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1912\r\n* 🎨 Affiche le simulateur PL adapté à l'entreprise by @lajarre in https://github.com/betagouv/mon-entreprise/pull/1882\r\n* Modif 1er janvier (suite) by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1915\r\n* Fix E2E tests by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1919\r\n* Met à jour pour 2022 les barèmes et cotisations pour les PLR by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1926\r\n* Remplace le moteur de recherche d'entreprise by @bobylito in https://github.com/betagouv/mon-entreprise/pull/1868\r\n" + "description": "> **En bref :**\r\n> - Mise à jour législative au 1er janvier\r\n> - Nouveau moteur de recherche d'entreprise\r\n> - Travail sur les parcours\r\n> - Mise à jour du formulaire de demande de mobilité\r\n\r\n## Mise à jour législative au 1er janvier 2022\r\n\r\nComme tous les ans, certains montants sont revalorisés au 1er janvier. C'est le cas en particulier du SMIC qui vaut désormais 1603 € brut par mois pour un salarié travaillant à temps plein. Le barème de l'impôt sur le revenu a aussi été ajusté pour prendre en compte l'inflation. D'autres éléments ont été mis à jour comme les barèmes de cotisation des caisses de retraite, le taux versement mobilité, le taux de la cotisation pour les indemnités journalières des indépendants ou encore le montant des titres restaurants exonéré de cotisations.\r\n\r\n## Nouveau moteur de recherche d'entreprise 🔍\r\n\r\nNous avons travaillé avec les équipes de [code du travail numérique] (https://code.travail.gouv.fr/) sur un nouveau moteur de recherche des entreprises. Il vous permet de trouver votre entreprise facilement et de manière plus fiable que ce que nous proposions avant. Ce nouveau moteur permet également d'associer à une entreprise des informations comme sa convention collective si elle en possède une, la localisation de son siège social, sa date de création, etc.\r\n\r\n[![recherche d'entreprise](https://user-images.githubusercontent.com/1730702/149759756-02f30ab4-2531-416c-8438-4cdf96b83523.png)](https://mon-entreprise.urssaf.fr/)\r\n\r\n## Travail sur les parcours\r\n\r\nVous avez désormais la possibilité de renseigner votre entreprise actuelle dès la page d’accueil du site. Grâce à cela nous identifions les bons outils dans votre situation, par exemple un simulateur de revenu pour un auto-entrepreneur, ou bien une aide à la déclaration fiscale pour les indépendants. Grâce au code APE nous pouvons même identifier la nature de certaines activités pour les professions libérales et aller plus loin dans la personnalisation des outils.\r\n\r\n![image](https://user-images.githubusercontent.com/1730702/149761273-fe9fa7fd-8e4d-45ca-868f-f35a5e1bacb7.png)\r\n\r\n## Mise à jour du formulaire de demande de mobilité\r\n\r\nLe formulaire de demande de mobilité gère désormais le cas des salariés ainsi que des praticiens et auxiliaires médicaux. Un nouveau parcour a été crée dans le cas d'un détachement dans un pays avec une convention bilatérale.\r\n\r\n## Détails des changements\r\n\r\n* ✨ Nouvelle page d'accueil - charte urssaf by @bobylito in https://github.com/betagouv/mon-entreprise/pull/1851\r\n* Améliore le style de la landing et de la page gérer by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1867\r\n* Quelques bugfixes by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1876\r\n* Répare la couleur du placeholder sous chrome by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1877\r\n* Répare la comparaison de régime sociaux by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1886\r\n* Petits fix de la recherche by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1887\r\n* Affiche une bannière dans la section dev lors d'un recrutement by @mquandalle in https://github.com/betagouv/mon-entreprise/pull/1884\r\n* Quelques fixes by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1891\r\n* Améliore le style des simulateurs et de la fiche de paie by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1892\r\n* Correction tests CI master by @mquandalle in https://github.com/betagouv/mon-entreprise/pull/1896\r\n* Corrections de bugs par wiinxt by @mquandalle in https://github.com/betagouv/mon-entreprise/pull/1903\r\n* Modification formulaire DLA suite aux retours Urssaf by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1783\r\n* Mise à jour legislative 1er janvier 2022 by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1912\r\n* 🎨 Affiche le simulateur PL adapté à l'entreprise by @lajarre in https://github.com/betagouv/mon-entreprise/pull/1882\r\n* Modif 1er janvier (suite) by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1915\r\n* Fix E2E tests by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1919\r\n* Met à jour pour 2022 les barèmes et cotisations pour les PLR by @johangirod in https://github.com/betagouv/mon-entreprise/pull/1926\r\n* Remplace le moteur de recherche d'entreprise by @bobylito in https://github.com/betagouv/mon-entreprise/pull/1868\r\n" }, { "name": "Décembre 2021", diff --git a/site/source/locales/rules-en.yaml b/site/source/locales/rules-en.yaml index 9cd6f29a7..2088305f1 100644 --- a/site/source/locales/rules-en.yaml +++ b/site/source/locales/rules-en.yaml @@ -7720,19 +7720,11 @@ situation personnelle . domiciliation fiscale à l'étranger: établissement . ZFU . durée d'implantation en fin d'année: titre.en: '[automatic] duration of implementation at the end of the year' titre.fr: durée d'implantation en fin d'année -établissement . localisation: - description.en: |- - When a company has more than one establishment, certain contributions are - calculated at the establishment level and are based on local regulations. - description.fr: > - 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: question.en: In which city is the establishment located? question.fr: Dans quelle commune l'établissement est-il implanté ? - titre.en: localisation - titre.fr: localisation + titre.en: '[automatic] ' + titre.fr: commune établissement . taux ATMP: description.en: > [automatic] The rate of the AT/MP contribution is determined for @@ -7769,6 +7761,3 @@ situation personnelle . domiciliation fiscale à l'étranger: question.fr: Quel est le taux de la cotisation AT/MP pour l'établissement ? titre.en: '[automatic] ATMP rate' titre.fr: taux ATMP -établissement . versement mobilité: - titre.en: '[automatic] mobility payment' - titre.fr: versement mobilité diff --git a/site/source/locales/ui-en.yaml b/site/source/locales/ui-en.yaml index 13f41c1e1..e468d1ec0 100644 --- a/site/source/locales/ui-en.yaml +++ b/site/source/locales/ui-en.yaml @@ -1237,15 +1237,16 @@ pages: <3>evaluate<2>Experimental rules also contain a warning in the "Reuse this calculation" section of the documentation.<3><0>Reusing data from external - APIs<1>Some data in the my-company simulators come from external - APIs. You will have to change their value by yourself in the given input - situation.<2>The mobility payment<3><0><0>establishment . - mobility payment<4>In the <2>employee simulator, all you - have to do is enter the municipality and the corresponding mobility - payment rate is automatically determined.<5>You will have to specify - the rate yourself to redo the calculation. You can find it - again:<1><0>By entering your municipality in a simulator, then searching - for the "mobility payment" rule with the "search" button at the top + APIs<1>Some of the data in the my-company simulators come from + external APIs. You will have to retrieve their value yourself to enter + it in the input situation.<2>The mobility + payment<3><0><0>establishment . municipality . mobility payment + rate<4>In the <2>employee simulator, all you have to do + is enter the municipality and the corresponding mobility payment rate is + automatically determined.<5>You will have to specify the rate + yourself to redo the calculation. You can find it again:<1><0>By + entering your municipality in a simulator, then searching for the + "mobility payment" rule with the "search" button at the top right<1>Using the <2>dedicated service on urssaf.fr<6>The collective AT/MP rate<7><0><0>establishment . ATMP rate . collective diff --git a/site/source/locales/ui-fr.yaml b/site/source/locales/ui-fr.yaml index 25d25dc32..c9f975469 100644 --- a/site/source/locales/ui-fr.yaml +++ b/site/source/locales/ui-fr.yaml @@ -1002,15 +1002,16 @@ pages: Réutiliser ce calcul » de la documentation.<3><0>Réutiliser une donnée provenant d'API externes<1>Certaines données des simulateurs de mon-entreprise proviennent d'API externes. Il vous faudra - ainsi changer leur valeur par vous-même dans la situation donnée en - entrée.<2>Le versement mobilité<3><0><0>établissement . - versement mobilité<4>Dans le simulateur <2>salarié, il - suffit de renseigner la commune et le taux du versement mobilité - correspondant est automatiquement déterminé.<5>Il vous faudra - préciser le taux vous-même pour refaire le calcul. Vous pouvez le - retrouver :<1><0>En saisissant votre commune dans un simulateur, puis en - recherchant la règle « versement mobilité » avec le bouton « rechercher - » en haut à droite<1>Grâce au <2>service dédié sur + ainsi récuperer leur valeur par vous-même pour la saisir dans la + situation donnée en entrée.<2>Le versement + mobilité<3><0><0>établissement . commune . taux versement + mobilité<4>Dans le simulateur <2>salarié, il suffit de + renseigner la commune et le taux versement mobilité correspondant est + automatiquement déterminé.<5>Il vous faudra préciser le taux + vous-même pour refaire le calcul. Vous pouvez le retrouver :<1><0>En + saisissant votre commune dans un simulateur, puis en recherchant la + règle « versement mobilité » avec le bouton « rechercher » en haut à + droite<1>Grâce au <2>service dédié sur urssaf.fr<6>Le taux collectif AT/MP<7><0><0>établissement . taux ATMP . taux collectif<8>Ce taux collectif doit être retrouvé diff --git a/site/source/pages/Simulateurs/configs/auto-entrepreneur.yaml b/site/source/pages/Simulateurs/configs/auto-entrepreneur.yaml index a1d2dafa9..b8b84aea0 100644 --- a/site/source/pages/Simulateurs/configs/auto-entrepreneur.yaml +++ b/site/source/pages/Simulateurs/configs/auto-entrepreneur.yaml @@ -18,7 +18,7 @@ questions: - établissement - situation personnelle non prioritaires: - - établissement . localisation + - établissement . commune liste noire: - entreprise . charges - entreprise . chiffre d'affaires diff --git a/site/source/pages/Simulateurs/configs/chômage-partiel.yaml b/site/source/pages/Simulateurs/configs/chômage-partiel.yaml index 9a1a00fc6..3998147f9 100644 --- a/site/source/pages/Simulateurs/configs/chômage-partiel.yaml +++ b/site/source/pages/Simulateurs/configs/chômage-partiel.yaml @@ -9,7 +9,7 @@ questions: liste: - salarié . activité partielle - salarié . temps de travail - - établissement . localisation + - établissement . commune unité par défaut: €/mois diff --git a/site/source/pages/Simulateurs/configs/dirigeant-sasu.yaml b/site/source/pages/Simulateurs/configs/dirigeant-sasu.yaml index 226bc1dec..d45dc3393 100644 --- a/site/source/pages/Simulateurs/configs/dirigeant-sasu.yaml +++ b/site/source/pages/Simulateurs/configs/dirigeant-sasu.yaml @@ -8,7 +8,7 @@ objectifs: questions: à l'affiche: ACRE: entreprise . exonérations . ACRE - Commune: établissement . localisation + Commune: établissement . commune Avantages en nature: salarié . rémunération . avantages en nature Impôt sur le revenu: impôt . méthode de calcul @@ -19,7 +19,7 @@ questions: - entreprise . association non lucrative non prioritaires: - entreprise . TVA - - établissement . localisation + - établissement . commune - situation personnelle . domiciliation fiscale à l'étranger - salarié . régimes spécifiques . impatriés diff --git a/site/source/pages/Simulateurs/configs/salarié.yaml b/site/source/pages/Simulateurs/configs/salarié.yaml index 2644c8473..24c791775 100644 --- a/site/source/pages/Simulateurs/configs/salarié.yaml +++ b/site/source/pages/Simulateurs/configs/salarié.yaml @@ -14,7 +14,7 @@ questions: Heures supplémentaires: salarié . temps de travail . heures supplémentaires Titres-restaurant: salarié . rémunération . frais professionnels . titres-restaurant Impôt: impôt . méthode de calcul - Commune: établissement . localisation + Commune: établissement . commune non prioritaires: - salarié . régimes spécifiques . DFS - entreprise . association non lucrative diff --git a/site/source/pages/gerer/demande-mobilité/FieldsPDF.tsx b/site/source/pages/gerer/demande-mobilité/FieldsPDF.tsx index 5b0455f0f..8d894790f 100644 --- a/site/source/pages/gerer/demande-mobilité/FieldsPDF.tsx +++ b/site/source/pages/gerer/demande-mobilité/FieldsPDF.tsx @@ -1,5 +1,5 @@ -import PDFElement from '@react-pdf/renderer' import { EngineContext } from '@/components/utils/EngineContext' +import PDFElement from '@react-pdf/renderer' import { formatValue, RuleNode } from 'publicodes' import { useContext } from 'react' @@ -33,18 +33,7 @@ export default function FieldsPDF({ fields }: FieldsPDFProps) { - {`${formatValue(engine.evaluate(dottedName)) as string}${ - API === 'commune' - ? ` (${ - ( - engine.evaluate(dottedName).nodeValue as Record< - string, - unknown - > - )?.codePostal as string - })` - : '' - } `} + {formatValue(engine.evaluate(dottedName)) as string} )} diff --git a/site/source/pages/gerer/demande-mobilité/PDFDocument.tsx b/site/source/pages/gerer/demande-mobilité/PDFDocument.tsx index c8679c0ec..ab4b1af61 100644 --- a/site/source/pages/gerer/demande-mobilité/PDFDocument.tsx +++ b/site/source/pages/gerer/demande-mobilité/PDFDocument.tsx @@ -1,5 +1,5 @@ -import PDFElement from '@react-pdf/renderer' import urssafPng from '@/images/destinataires/Urssaf.png' +import PDFElement from '@react-pdf/renderer' import { RuleNode } from 'publicodes' import FieldsPDF, { styles as fieldStyles } from './FieldsPDF' import montserratUrl from './Montserrat-SemiBold.ttf' diff --git a/site/source/pages/gerer/demande-mobilité/demande-mobilité.yaml b/site/source/pages/gerer/demande-mobilité/demande-mobilité.yaml index 461baed32..373a97c58 100644 --- a/site/source/pages/gerer/demande-mobilité/demande-mobilité.yaml +++ b/site/source/pages/gerer/demande-mobilité/demande-mobilité.yaml @@ -221,6 +221,18 @@ données assuré: titre: Commune non applicable si: étranger API: commune + condition: + si: + est non défini: nom + alors: nom + sinon: + texte: | + {{nom}} ({{code postal}}) + avec: + nom: + titre: Commune + code postal: + commune étranger: applicable si: étranger type: texte @@ -281,6 +293,17 @@ entreprise france . adresse: type: texte entreprise france . commune: API: commune + condition: + si: + est non défini: nom + alors: nom + sinon: + texte: | + {{nom}} ({{code postal}}) + avec: + nom: + titre: Commune + code postal: note: 4.4.3 / 4.4.4 entreprise france . organisme urssaf: diff --git a/site/source/pages/gerer/demande-mobilité/index.tsx b/site/source/pages/gerer/demande-mobilité/index.tsx index 47188f89b..5a997a97f 100644 --- a/site/source/pages/gerer/demande-mobilité/index.tsx +++ b/site/source/pages/gerer/demande-mobilité/index.tsx @@ -8,10 +8,16 @@ import { Markdown } from '@/components/utils/markdown' import { usePersistingState } from '@/components/utils/persistState' import useSimulationConfig from '@/components/utils/useSimulationConfig' import { Button } from '@/design-system/buttons' -import { Spacing, Grid } from '@/design-system/layout' +import { Grid, Spacing } from '@/design-system/layout' import { headings } from '@/design-system/typography' import { Intro, SmallBody } from '@/design-system/typography/paragraphs' -import { evaluateQuestion, getMeta, hash, omit } from '@/utils' +import { + buildSituationFromObject, + evaluateQuestion, + getMeta, + hash, + omit, +} from '@/utils' import { DottedName } from 'modele-social' import Engine, { PublicodesExpression } from 'publicodes' import { Fragment, lazy, Suspense, useCallback, useContext } from 'react' @@ -80,6 +86,15 @@ function FormulairePublicodes() { (dottedName, value) => { if (value === undefined) { setSituation((situation) => omit(situation, dottedName)) + } else if (engine.getRule(dottedName).rawNode.API === 'commune') { + const commune = { + nom: value.batchUpdate.nom, + 'code postal': value.batchUpdate['code postal'], + } + setSituation((situation) => ({ + ...buildSituationFromObject(dottedName, commune), + ...situation, + })) } else { setSituation((situation) => ({ ...situation, diff --git a/site/source/pages/integration/_components/CasParticuliers.tsx b/site/source/pages/integration/_components/CasParticuliers.tsx index 6fd4c0cb0..67fa2abad 100644 --- a/site/source/pages/integration/_components/CasParticuliers.tsx +++ b/site/source/pages/integration/_components/CasParticuliers.tsx @@ -81,14 +81,14 @@ export function CasParticuliers() {

Réutiliser une donnée provenant d'API externes

Certaines données des simulateurs de mon-entreprise proviennent d'API - externes. Il vous faudra ainsi changer leur valeur par vous-même dans - la situation donnée en entrée. + externes. Il vous faudra ainsi récuperer leur valeur par vous-même + pour la saisir dans la situation donnée en entrée.

Le versement mobilité

- - établissement . versement mobilité + + établissement . commune . taux versement mobilité @@ -97,7 +97,7 @@ export function CasParticuliers() { salarié - , il suffit de renseigner la commune et le taux du versement mobilité + , il suffit de renseigner la commune et le taux versement mobilité correspondant est automatiquement déterminé. 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