Merge pull request #945 from betagouv/publicode-doc
Améliore la documentation publicodepull/940/head
commit
0215db0038
|
@ -52,6 +52,7 @@
|
|||
"react-redux": "^7.0.3",
|
||||
"react-router": "^5.1.1",
|
||||
"react-router-dom": "^5.1.1",
|
||||
"react-router-hash-link": "^1.2.2",
|
||||
"react-spring": "=8.0.27",
|
||||
"react-syntax-highlighter": "^10.1.1",
|
||||
"react-to-print": "^2.5.1",
|
||||
|
|
|
@ -159,6 +159,8 @@ brut:
|
|||
somme:
|
||||
- 2000 €/mois | du 01/01/2020 | au 31/05/2020
|
||||
- 4000 €/mois | du 01/06/2020 | au 31/12/2020
|
||||
plafond:
|
||||
formule: 3000 €/mois
|
||||
|
||||
cotisation:
|
||||
formule:
|
||||
|
@ -166,13 +168,17 @@ cotisation:
|
|||
règle:
|
||||
produit:
|
||||
assiette: brut
|
||||
plafond: 3000€/mois
|
||||
plafond: plafond
|
||||
taux: 10%
|
||||
valeurs cumulées:
|
||||
- brut
|
||||
- plafond
|
||||
|
||||
cotisation en 2020:
|
||||
formule: cotisation | du 01/01/2020 | au 31/12/2020
|
||||
cotisation en mai:
|
||||
formule: cotisation | du 01/05/2020 | au 30/05/2020
|
||||
|
||||
cotisation en juin:
|
||||
formule: cotisation | du 01/05/2020 | au 30/05/2020
|
||||
```
|
||||
|
||||
[Lancer le calcul](https://publi.codes/studio?code=brut%3A%0A%20%20formule%3A%0A%20%20%20%20somme%3A%0A%20%20%20%20%20%20-%202000%20%E2%82%AC%2Fmois%20%7C%20du%2001%2F01%2F2020%20%7C%20au%2031%2F05%2F2020%0A%20%20%20%20%20%20-%204000%20%E2%82%AC%2Fmois%20%7C%20du%2001%2F06%2F2020%20%7C%20au%2031%2F12%2F2020%0A%0Acotisation%3A%0A%20%20formule%3A%20%0A%20%20%20%20r%C3%A9gularisation%3A%0A%20%20%20%20%20%20r%C3%A8gle%3A%0A%20%20%20%20%20%20%20%20produit%3A%0A%20%20%20%20%20%20%20%20%20%20assiette%3A%20brut%0A%20%20%20%20%20%20%20%20%20%20plafond%3A%203000%E2%82%AC%2Fmois%0A%20%20%20%20%20%20%20%20%20%20taux%3A%2010%25%0A%20%20%20%20%20%20valeurs%20cumul%C3%A9es%3A%0A%20%20%20%20%20%20%20%20-%20brut%0A%0Acotisation%20en%202020%3A%0A%20%20formule%3A%0A%20%20%20%20cotisation%20%7C%20du%2001%2F01%2F2020%20%7C%20au%2031%2F12%2F2020%0A)
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
// Page listing the engine's currently implemented mecanisms and their tests
|
||||
import knownMecanims from 'Engine/known-mecanisms.yaml'
|
||||
import { fromPairs, has, toPairs } from 'ramda'
|
||||
import React from 'react'
|
||||
import './Mecanisms.css'
|
||||
|
||||
let directoryLoader = require.context('../../test/mécanismes/', true, /.yaml$/),
|
||||
suites = fromPairs(
|
||||
directoryLoader
|
||||
.keys()
|
||||
.map(key => [
|
||||
key.replace(/\/|\.|(yaml)/g, '').replace(/-/g, ' '),
|
||||
directoryLoader(key)
|
||||
])
|
||||
)
|
||||
|
||||
export default function Mecanisms() {
|
||||
return (
|
||||
<div style={{ margin: '1em auto', maxWidth: '45em' }}>
|
||||
<p>
|
||||
Cette page liste les mécanismes et indique en rouge ceux qui n'ont pas
|
||||
de tests. La commande "yarn test" permet de voir ceux qui passent. Ce
|
||||
serait bien de pouvoir les faire tourner dans le navigateur en
|
||||
partageant le code de mecanisms.test.js
|
||||
</p>
|
||||
<ul id="mecanisms">
|
||||
{toPairs(knownMecanims).map(([name, data]) => (
|
||||
<li key={name}>
|
||||
{name}
|
||||
{suites[name] == null ? (
|
||||
<p className="warning">Pas de tests !</p>
|
||||
) : (
|
||||
<Tests name={name} suites={suites} />
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Tests({ suites, name }) {
|
||||
let suite = suites[name],
|
||||
tests = suite.filter(has('test'))
|
||||
|
||||
return (
|
||||
<p>
|
||||
{tests.length} {tests.length == 1 ? 'test' : 'tests'}
|
||||
</p>
|
||||
)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import React from 'react'
|
||||
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
|
||||
import yaml from 'react-syntax-highlighter/dist/cjs/languages/hljs/yaml'
|
||||
import style from 'react-syntax-highlighter/dist/cjs/styles/hljs/tomorrow'
|
||||
SyntaxHighlighter.registerLanguage('yaml', yaml)
|
||||
|
||||
export default ({ source }) => (
|
||||
<SyntaxHighlighter language="yaml" style={style}>
|
||||
{source}
|
||||
</SyntaxHighlighter>
|
||||
)
|
|
@ -1,7 +1,7 @@
|
|||
import { ThemeColorsContext } from 'Components/utils/colors'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import Value from 'Components/Value'
|
||||
import knownMecanisms from 'Engine/known-mecanisms.yaml'
|
||||
import mecanisms from 'Engine/mecanisms.yaml'
|
||||
import { findRuleByDottedName, findRuleByNamespace } from 'Engine/rules'
|
||||
import { isEmpty } from 'ramda'
|
||||
import React, { Suspense, useContext, useState } from 'react'
|
||||
|
@ -28,7 +28,7 @@ import './Rule.css'
|
|||
|
||||
let LazySource = React.lazy(() => import('./RuleSource'))
|
||||
|
||||
export default AttachDictionary(knownMecanisms)(function Rule({ dottedName }) {
|
||||
export default AttachDictionary(mecanisms)(function Rule({ dottedName }) {
|
||||
const currentExample = useSelector(state => state.currentExample)
|
||||
const flatRules = useSelector(flatRulesSelector)
|
||||
const valuesToShow = !useSelector(noUserInputSelector)
|
||||
|
|
|
@ -3,7 +3,7 @@ import rules from 'Publicode/rules'
|
|||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Rule } from 'Types/rule'
|
||||
import ColoredYaml from './ColoredYaml'
|
||||
import PublicodeHighlighter from '../ui/PublicodeHighlighter'
|
||||
|
||||
type RuleSourceProps = Pick<Rule, 'dottedName'>
|
||||
|
||||
|
@ -17,7 +17,7 @@ export default function RuleSource({ dottedName }: RuleSourceProps) {
|
|||
Code source <br />
|
||||
<code>{dottedName}</code>
|
||||
</h2>
|
||||
<ColoredYaml source={safeDump(source)} />
|
||||
<PublicodeHighlighter source={safeDump(source)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter'
|
||||
import yaml from 'react-syntax-highlighter/dist/esm/languages/prism/yaml'
|
||||
import style from 'react-syntax-highlighter/dist/esm/styles/prism/atom-dark'
|
||||
|
||||
SyntaxHighlighter.registerLanguage('yaml', yaml)
|
||||
|
||||
export default ({ source }) => (
|
||||
<div css="position: relative; margin-bottom: 1rem">
|
||||
<SyntaxHighlighter language="yaml" style={style}>
|
||||
{source}
|
||||
</SyntaxHighlighter>
|
||||
<a
|
||||
href={`https://publi.codes/studio?code=${encodeURIComponent(source)}`}
|
||||
css="position: absolute; bottom: 5px; right: 10px; color: white !important;"
|
||||
>
|
||||
{emoji('⚡')} Lancer le calcul
|
||||
</a>
|
||||
</div>
|
||||
)
|
|
@ -31,10 +31,11 @@ button {
|
|||
|
||||
blockquote {
|
||||
background: var(--lighterColor);
|
||||
border-radius: 0.6em;
|
||||
padding: 1.2em 1em 0.4em;
|
||||
margin: 0.6em;
|
||||
color: #333;
|
||||
border-radius: 0.3rem;
|
||||
padding: 1rem;
|
||||
padding-bottom: 0.6rem;
|
||||
margin: 1rem 0;
|
||||
color: var(--darkerColor);
|
||||
}
|
||||
|
||||
.ui__.answer-group {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import PublicodeHighlighter from 'Components/ui/PublicodeHighlighter'
|
||||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown'
|
||||
|
@ -31,6 +32,15 @@ type MarkdownProps = ReactMarkdownProps & {
|
|||
className?: string
|
||||
}
|
||||
|
||||
const CodeBlock = ({ value, language }) =>
|
||||
language === 'yaml' ? (
|
||||
<PublicodeHighlighter source={value} />
|
||||
) : (
|
||||
<pre>
|
||||
<code>{value}</code>
|
||||
</pre>
|
||||
)
|
||||
|
||||
export const Markdown = ({
|
||||
source,
|
||||
className = '',
|
||||
|
@ -40,7 +50,12 @@ export const Markdown = ({
|
|||
<ReactMarkdown
|
||||
source={source}
|
||||
className={`markdown ${className}`}
|
||||
renderers={{ link: LinkRenderer, text: TextRenderer, ...renderers }}
|
||||
renderers={{
|
||||
link: LinkRenderer,
|
||||
text: TextRenderer,
|
||||
code: CodeBlock,
|
||||
...renderers
|
||||
}}
|
||||
{...otherProps}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -1,16 +1,29 @@
|
|||
# Publicode
|
||||
|
||||
Publicode est un langage déclaratif pour encoder les algorithmes d'intérêt
|
||||
public. Il permet de réaliser des calculs généraux tout en fournissant une
|
||||
explication permettant de comprendre et de documenter ces calculs.
|
||||
|
||||
Publicode est adapté pour modéliser des domaines métiers complexes pouvant être
|
||||
décomposés en règles élémentaires simples (comme la législation socio-fiscale,
|
||||
un bilan carbone, un estimateur de rendement locatif, etc.). Il permet de
|
||||
décomposés en règles élémentaires simples (comme la [législation socio-fiscale](https://github.com/betagouv/mon-entreprise/tree/master/publicode),
|
||||
[un bilan carbone](https://github.com/laem/futureco-data/blob/master/co2.yaml),
|
||||
un estimateur de rendement locatif, etc.).
|
||||
|
||||
Il permet de
|
||||
générer facilement des simulateurs web interactifs où l'on peut affiner
|
||||
progressivement le résultat affiché, et explorer une documentation du calcul.
|
||||
|
||||
## Formule basiques
|
||||
## Projets phares
|
||||
|
||||
- [mon-entreprise.fr](https://mon-entreprise.fr/simulateurs) : utilise publicode
|
||||
pour spécifier l'ensemble des calculs relatifs à la législation socio-fiscale
|
||||
en France. Le site permet entre autre de simuler une fiche de paie complète,
|
||||
de calculer les cotisations sociales pour un indépendant ou encore connaître
|
||||
le montant du chômage partiel. Les règles sont publiées sous la forme d'une
|
||||
[bibliothèque de calcul autonome](https://mon-entreprise.fr/intégration/bibliothèque-de-calcul), libre de droit.
|
||||
|
||||
- [futur.eco](https://futur.eco/) utilise publicode pour calculer les bilans
|
||||
carbone d'un grand nombre d'activités, plats, transports ou biens.
|
||||
|
||||
## Principe de base
|
||||
|
||||
La syntaxe de Publicode est basée sur le langage
|
||||
[Yaml](https://en.wikipedia.org/wiki/YAML). Un fichier Publicode contient une
|
||||
|
@ -18,7 +31,7 @@ liste de règles identifiées par leur nom et possédant une formule de calcul :
|
|||
|
||||
```yaml
|
||||
prix d'un repas:
|
||||
formule: 10
|
||||
formule: 10 €
|
||||
```
|
||||
|
||||
Une formule de calcul peut référencer d'autres variables. Dans l'exemple suivant
|
||||
|
@ -26,14 +39,12 @@ la règle `prix total` aura pour valeur 50 (= 5 \* 10)
|
|||
|
||||
```yaml
|
||||
prix d'un repas:
|
||||
formule: 10
|
||||
formule: 10 €
|
||||
|
||||
prix total:
|
||||
formule: 5 * prix d'un repas
|
||||
```
|
||||
|
||||
> [Lancer le calcul](https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%0A%0Aprix%20total%3A%0A%20%20formule%3A%205%20*%20prix%20d'un%20repas)
|
||||
|
||||
Il s'agit d'un langage déclaratif : comme dans une formule d'un tableur le `prix total` sera recalculé automatiquement si le prix d'un repas change. L'ordre de
|
||||
définition des règles n'a pas d'importance.
|
||||
|
||||
|
@ -53,12 +64,12 @@ prix total:
|
|||
formule: nombre de repas * prix d'un repas
|
||||
```
|
||||
|
||||
> [Lancer le calcul](https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%20%E2%82%AC%2Frepas%0A%0Anombre%20de%20repas%3A%0A%20%20formule%3A%205%20repas%0A%0Aprix%20total%3A%0A%20%20formule%3A%20nombre%20de%20repas%20*%20prix%20d'un%20repas)
|
||||
|
||||
Le calcul est inchangé mais on a indiqué que le "prix d'un repas" s'exprime en
|
||||
`€/repas` et que le "nombre de repas" est un nombre de `repas`. L'unité du prix
|
||||
total est inférée automatiquement comme étant en `€`. (`€/repas` \* `repas` =
|
||||
`€`) Ce système d'unité permet de typer les formules de calcul et de rejeter
|
||||
`€`)
|
||||
|
||||
Ce système d'unité permet de typer les formules de calcul et de rejeter
|
||||
automatiquement des formules incohérentes :
|
||||
|
||||
```yaml
|
||||
|
@ -77,8 +88,6 @@ prix total:
|
|||
# La formule de "prix total" est invalide.
|
||||
```
|
||||
|
||||
> [Lancer le calcul](https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%20%E2%82%AC%2Frepas%0A%0Anombre%20de%20repas%3A%0A%20%20formule%3A%205%20repas%0A%0Afrais%20de%20r%C3%A9servation%3A%0A%20%20formule%3A%201%20%E2%82%AC%2Frepas%0A%0Aprix%20total%3A%0A%20%20formule%3A%20nombre%20de%20repas%20*%20prix%20d'un%20repas%20%2B%20frais%20de%20r%C3%A9servation)
|
||||
|
||||
Dans l'exemple ci-dessus Publicode détecte une erreur car les termes de
|
||||
l'addition ont des unités incompatibles : d'un côté on a des `€` et de l'autre
|
||||
des `€/repas`. Comme dans les formules de Physique, cette incohérence d'unité
|
||||
|
@ -90,10 +99,37 @@ prix total:
|
|||
formule: nombre de repas * (prix d'un repas + frais de réservation)
|
||||
```
|
||||
|
||||
> [Lancer le calcul](<https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%20%E2%82%AC%2Frepas%0A%0Anombre%20de%20repas%3A%0A%20%20formule%3A%205%20repas%0A%0Afrais%20de%20r%C3%A9servation%3A%0A%20%20formule%3A%201%20%E2%82%AC%2Frepas%0A%0Aprix%20total%3A%0A%20%20formule%3A%20nombre%20de%20repas%20*%20(prix%20d'un%20repas%20%2B%20frais%20de%20r%C3%A9servation)>)
|
||||
> **Attention :** Il ne faut pas insérer d'espace autour de la barre oblique dans
|
||||
> les unités, l'unité `€ / mois` doit être notée `€/mois`
|
||||
|
||||
> **Attention:** Il ne faut pas insérer d'espace autour de la barre oblique dans
|
||||
> les unités, l'unité ~`€ / mois`~ doit être notée `€/mois`
|
||||
### Conversion
|
||||
|
||||
Publicode convertit automatiquement les unités si besoin.
|
||||
|
||||
```yaml
|
||||
salaire:
|
||||
formule: 1500 €/mois
|
||||
|
||||
prime faible salaire:
|
||||
applicable si: salaire < 20 k€/an
|
||||
formule: 300€
|
||||
```
|
||||
|
||||
On peut forcer la conversion des unités via la propriété `unité`, ou la notation suffixé `[...]`
|
||||
|
||||
```yaml
|
||||
salaire:
|
||||
unité: €/mois
|
||||
formule: 3200
|
||||
|
||||
salaire annuel:
|
||||
formule: salaire [k€/an]
|
||||
```
|
||||
|
||||
**Conversions disponibles :**
|
||||
|
||||
- `mois` / `année` / `jour`
|
||||
- `€` / `k€`
|
||||
|
||||
## Titre, description et références
|
||||
|
||||
|
@ -149,25 +185,34 @@ spécifique par mécanisme.
|
|||
Par exemple on a un mécanisme `barème`:
|
||||
|
||||
```yaml
|
||||
revenu imposable:
|
||||
formule: 54126 €
|
||||
|
||||
impôt sur le revenu:
|
||||
formule:
|
||||
barème:
|
||||
assiette: revenu imposable
|
||||
tranches:
|
||||
- taux: 0%
|
||||
plafond: 9807
|
||||
plafond: 9807 €
|
||||
- taux: 14%
|
||||
plafond: 27086
|
||||
plafond: 27086 €
|
||||
- taux: 30%
|
||||
plafond: 72617
|
||||
plafond: 72617 €
|
||||
- taux: 41%
|
||||
plafond: 153783
|
||||
plafond: 153783 €
|
||||
- taux: 45%
|
||||
```
|
||||
|
||||
La syntaxe hiérarchique de Yaml permet d'imbriquer les mécanismes :
|
||||
|
||||
```yaml
|
||||
prime . fixe:
|
||||
formule: 1000€
|
||||
|
||||
prime . taux du bonus:
|
||||
formule: 20%
|
||||
|
||||
prime:
|
||||
formule:
|
||||
somme:
|
||||
|
@ -175,15 +220,9 @@ prime:
|
|||
- produit:
|
||||
assiette: fixe
|
||||
taux: taux du bonus
|
||||
|
||||
prime . fixe:
|
||||
formule: 1000€
|
||||
|
||||
prime . taux du bonus:
|
||||
formule: 20%
|
||||
```
|
||||
|
||||
**[Voir la liste des mécanismes](https://github.com/betagouv/mon-entreprise/blob/master/publicode/mecanism.md)**
|
||||
> **[Aller à la liste des mécanismes existants](./mécanismes)**
|
||||
|
||||
## Applicabilité
|
||||
|
||||
|
@ -204,8 +243,6 @@ prime de vacances:
|
|||
formule: 200€
|
||||
```
|
||||
|
||||
> [Lancer le calcul](https://publi.codes/studio?code=date%20de%20d%C3%A9but%3A%20%0A%20%20formule%3A%2012%2F02%2F2020%0A%20%20%0Aanciennet%C3%A9%20en%20fin%20d'ann%C3%A9e%3A%0A%20%20formule%3A%20%0A%20%20%20%20dur%C3%A9e%3A%0A%20%20%20%20%20%20%20depuis%3A%20date%20de%20d%C3%A9but%0A%20%20%20%20%20%20%20jusqu'%C3%A0%3A%2031%2F12%2F2020%0A%0Aprime%20de%20vacances%3A%0A%20%20applicable%20si%3A%20anciennet%C3%A9%20en%20fin%20d'ann%C3%A9e%20%3E%201%20an%0A%20%20formule%3A%20200%E2%82%AC)
|
||||
|
||||
Ici si l'ancienneté est inférieure à un an la prime de vacances ne sera pas
|
||||
applicable. Les variables non applicables sont ignorées au niveau des mécanismes
|
||||
(par exemple le mécanisme `somme` comptera une prime non applicable comme valant
|
|
@ -1,219 +0,0 @@
|
|||
# Liste et description des différents mécanismes compris par le moteur.
|
||||
# La description peut être rédigée en markdown :-)
|
||||
|
||||
une possibilité:
|
||||
type: enum
|
||||
|
||||
inversion numérique:
|
||||
type: numeric
|
||||
description: |
|
||||
La formule de calcul de cette variable n'est pas connue, souvent elle n'a même pas de sens. Mais le mécanisme `inversion` indique qu'elle peut être _estimée_ à partir de l'un des _objectifs_ listés sous l'attribut `avec`. Il faut alors renseigner une valeur cible pour cet objectif.
|
||||
|
||||
Voilà comment ça marche : on va donner à la variable une valeur au hasard, calculer _l'objectif_, puis grâce à des calculs savants améliorer notre choix jusqu'à ce que l'écart entre le calcul et la valeur cible devienne satisfaisant.
|
||||
|
||||
Concrètement, si l'on demande au moteur (même indirectement) la valeur d'une variable qui a pour formule une inversion, il va vérifier qu'une des possibilités d'inversion a bien une valeur calculée ou saisie, et procéder à l'inversion décrite plus haut à partir de celle-ci. Sinon, ces possibilités d'inversions seront listées comme manquantes.
|
||||
|
||||
une de ces conditions:
|
||||
type: boolean
|
||||
description: |
|
||||
C'est un `ou` logique.
|
||||
|
||||
Contient une liste de conditions.
|
||||
|
||||
Renvoie vrai si l'une des conditions est vraie.
|
||||
toutes ces conditions:
|
||||
type: boolean
|
||||
description: |
|
||||
C'est un `et` logique.
|
||||
|
||||
Contient une liste de conditions.
|
||||
|
||||
Renvoie vrai si toutes les conditions vraies.
|
||||
|
||||
variations:
|
||||
type: numeric
|
||||
description: |
|
||||
Contient une liste de conditions (`si`) et leurs conséquences associées (`alors`).
|
||||
|
||||
Pour la première condition vraie dans la liste, on retient la valeur qui lui est associée.
|
||||
|
||||
Si aucune condition n'est vraie, alors ce mécanisme renvoie implicitement `non applicable`
|
||||
|
||||
|
||||
Exemple:
|
||||
```
|
||||
- si: age < 18 ans
|
||||
alors: 'mineur'
|
||||
- sinon: 'majeur'
|
||||
```
|
||||
|
||||
Ce mécanisme peut aussi être utilisé au sein d'un mécanisme compatible, tel que la produit ou le barème.
|
||||
|
||||
Exemple (TVA):
|
||||
```
|
||||
produit:
|
||||
assiette: total hors taxe
|
||||
variations:
|
||||
- si: restauration
|
||||
alors:
|
||||
taux: 10%
|
||||
- sinon:
|
||||
taux: 20%
|
||||
```
|
||||
|
||||
produit:
|
||||
type: numeric
|
||||
description: |
|
||||
C'est une multiplication un peu améliorée, très utile pour exprimer les cotisations.
|
||||
|
||||
Sa propriété `assiette` est multipliée par un pourcentage, `taux`, ou par un `facteur` quand ce nom est plus approprié.
|
||||
|
||||
La multiplication peut être plafonnée : ce plafond sépare l'assiette en deux, et la partie au-dessus du plafond est tout simplement ignorée. Dans ce cas, elle se comporte comme une barème en taux marginaux à deux tranches, la deuxième au taux nul et allant de `plafond` à l'infini.
|
||||
|
||||
le maximum de:
|
||||
type: numeric
|
||||
description: |
|
||||
Renvoie la valeur numérique de la liste de propositions fournie qui est la plus grande.
|
||||
|
||||
Il est conseillé de renseigner une description de chaque proposition par exemple quand elles représentent des méthodes de calcul alternatives.
|
||||
|
||||
le minimum de:
|
||||
type: numeric
|
||||
description: |
|
||||
Renvoie l'élément de la liste de propositions fournie qui a la plus petite valeur.
|
||||
|
||||
Ces propositions doivent avoir un mécanisme de calcul ou être une valeur numérique.
|
||||
|
||||
Il est conseillé de renseigner une description de chaque proposition par exemple quand elles représentent des méthodes de calcul alternatives parmi lesquelles il faut en choisir une.
|
||||
|
||||
somme:
|
||||
type: numeric
|
||||
description: |
|
||||
C'est tout simplement la somme de chaque terme de la liste.
|
||||
|
||||
arrondi:
|
||||
type: numeric
|
||||
description: |
|
||||
On arrondi à l'euro le plus proche
|
||||
|
||||
recalcul:
|
||||
type: numeric
|
||||
description: >-
|
||||
Relance le calcul d'une règle dans une situation différente de la situation
|
||||
courante. Permet par exemple de calculer le montant des cotisations au
|
||||
niveau du SMIC, même si le salaire est plus élevé dans la situation
|
||||
actuelle.
|
||||
|
||||
##########################################
|
||||
# Ce qu'on appelle aujourd'hui des RuleProp
|
||||
# Et qui deviendront des mécanismes classiques normalement par la suite #TODO
|
||||
|
||||
formule:
|
||||
description: |
|
||||
C'est la formule de calcul d'une variable. Elle renvoie une valeur numérique ou un 'non', exprimant le fait que la variable n'est pas applicable, ce qui vaut implicitement 0.
|
||||
|
||||
Cette doit faire appel à fera appel à des mécanismes de calcul : par exemple `produit`, le plus commun pour les variables de type `Cotisation`.
|
||||
|
||||
applicable si:
|
||||
description: |
|
||||
Décide si la règle est applicable pour la situation saisie.
|
||||
|
||||
> Une cotisation sociale peut ne concerner que les salariés au statut cadre. Elle ne sera pas à verser pour un non cadre
|
||||
|
||||
La formule de calcul peut donc être ignorée, quel que soit son montant.
|
||||
|
||||
Peut être accompagnée du mécanisme 'non applicable si'.
|
||||
|
||||
non applicable si:
|
||||
description: |
|
||||
Décide si la règle n'est applicable pour la situation saisie.
|
||||
|
||||
> Un contrat CDD peut entraîner une majoration spécifique. Cette majoration est 'non applicable si' le contrat est un CDI.
|
||||
|
||||
La formule de calcul peut donc être ignorée, quel que soit son montant.
|
||||
|
||||
Peut être accompagnée du mécanisme 'applicable si'.
|
||||
|
||||
rend non applicable:
|
||||
description: |
|
||||
Permet de désactiver l'application de certaines règles pour la situation saisie.
|
||||
|
||||
> Ce mécanisme est utile pour encoder les régimes d'exceptions (par exemple le [régime des impatriés](/documentation/contrat-salarié/régime-des-impatriés)) sans avoir à modifier la définition des règles de base.
|
||||
|
||||
barème:
|
||||
type: numeric
|
||||
description: >-
|
||||
C'est un barème en taux marginaux, mécanisme de calcul connu son utilisation
|
||||
dans le calcul de l'impôt sur le revenu.
|
||||
|
||||
L'assiette est décomposée en plusieurs tranches, qui sont multipliées par un
|
||||
taux spécifique.
|
||||
|
||||
Les tranches sont souvent exprimées sous forme de facteurs d'une variable
|
||||
que l'on appelle `multiplicateur`, par exemple `1 x le plafond de la
|
||||
sécurité sociale`.
|
||||
|
||||
grille:
|
||||
type: numeric
|
||||
description: >-
|
||||
C'est un barème sous la forme d'une grille de correspondance. C'est le
|
||||
mécanisme de calcul de l'impôt neutre, aussi appelé impôt non personnalisé.
|
||||
|
||||
Il est composé de tranches qui se suivent. Il suffit de trouver l'assiette
|
||||
qui correspond à la tranche, et de selectionner le montant associé à
|
||||
l'assiette.
|
||||
|
||||
taux progressif:
|
||||
type: numeric
|
||||
description: >-
|
||||
Ce mécanisme permet de calculer un taux progressif. On spécifie pour chaque
|
||||
tranche le plafond et le taux associé. Le taux effectif renvoyé est calculé
|
||||
en lissant la différence de taux entre la borne inférieure et supérieure de
|
||||
l'assiette
|
||||
|
||||
> Par exemple, si nous nous avons les tranches suivantes :
|
||||
- taux: 50% / plafond: 0
|
||||
- taux: 100% / plafond: 1000
|
||||
|
||||
> Pour une assiette de 500, le taux retourné sera 75%, car il correspond au
|
||||
taux situé à la moitié de la tranche correspondante.
|
||||
|
||||
composantes:
|
||||
type: numeric
|
||||
description: |
|
||||
Beaucoup de cotisations sont composées de deux parties qui partagent la méthode de calcul mais diffèrent par des paramètres différents.
|
||||
|
||||
Pour ne pas définir deux variables presque redondantes, on utilise le mécanisme de composante. Il se comportera comme une somme dans les calculs, mais son affichage sur les pages /règle sera adapté.
|
||||
|
||||
Il est même possible, pour les mécanismes `barème` et `produit` de garder en commun un paramètre comme l'assiette, puis de déclarer des composantes pour le taux.
|
||||
|
||||
> L'exemple le plus courant de composantes, c'est la distinction part employeur, part salarié (ex. retraite AGIRC).
|
||||
|
||||
allègement:
|
||||
type: numeric
|
||||
description: |
|
||||
Permet de réduire le montant d'une variable.
|
||||
Très utilisé dans le contexte des impôts.
|
||||
|
||||
encadrement:
|
||||
type: numeric
|
||||
description: |
|
||||
Permet d'ajouter un plafond et/ou un plancher à une valeur.
|
||||
|
||||
durée:
|
||||
type: numeric
|
||||
description: |
|
||||
Permet d'obtenir le nombre de jours entre deux dates
|
||||
|
||||
synchronisation:
|
||||
type: object
|
||||
description: |
|
||||
Pour éviter trop de saisies à l'utilisateur, certaines informations sont
|
||||
récupérées à partir de ce que l'on appelle des API. Ce sont des services
|
||||
auxquels ont fait appel pour obtenir des informations sur un sujet précis.
|
||||
Par exemple, l'État français fournit gratuitement l'API géo, qui permet à
|
||||
partir du nom d'une ville, d'obtenir son code postal, son département, la
|
||||
population etc.
|
||||
|
||||
Ce mécanismes `synchronisation` permet de faire le lien entre les règles de
|
||||
notre système et les réponses de ces API.
|
|
@ -2,33 +2,11 @@ import { decompose } from 'Engine/mecanisms/utils'
|
|||
import variations from 'Engine/mecanisms/variations'
|
||||
import { convertNodeToUnit } from 'Engine/nodeUnits'
|
||||
import { inferUnit, isPercentUnit } from 'Engine/units'
|
||||
import {
|
||||
any,
|
||||
equals,
|
||||
evolve,
|
||||
is,
|
||||
map,
|
||||
max,
|
||||
mergeWith,
|
||||
min,
|
||||
path,
|
||||
pluck,
|
||||
reduce,
|
||||
toPairs
|
||||
} from 'ramda'
|
||||
import { any, equals, evolve, is, map, max, mergeWith, min, path, pluck, reduce, toPairs } from 'ramda'
|
||||
import React from 'react'
|
||||
import 'react-virtualized/styles.css'
|
||||
import { typeWarning } from './error'
|
||||
import {
|
||||
collectNodeMissing,
|
||||
defaultNode,
|
||||
evaluateArray,
|
||||
evaluateNode,
|
||||
evaluateObject,
|
||||
makeJsx,
|
||||
mergeAllMissing,
|
||||
parseObject
|
||||
} from './evaluation'
|
||||
import { collectNodeMissing, defaultNode, evaluateArray, evaluateNode, evaluateObject, makeJsx, mergeAllMissing, parseObject } from './evaluation'
|
||||
import Allègement from './mecanismViews/Allègement'
|
||||
import { Node, SimpleRuleLink } from './mecanismViews/common'
|
||||
import InversionNumérique from './mecanismViews/InversionNumérique'
|
||||
|
@ -463,7 +441,7 @@ export let mecanismReduction = (recurse, k, v) => {
|
|||
|
||||
export let mecanismProduct = (recurse, k, v) => {
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
//mécanisme de composantes. Voir mécanismes.md/composantes
|
||||
return decompose(recurse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
|
|
|
@ -0,0 +1,437 @@
|
|||
une de ces conditions:
|
||||
description: >-
|
||||
C'est un `ou` logique.
|
||||
Contient une liste de conditions.
|
||||
Renvoie `oui` si l'une des conditions est applicable.
|
||||
retourne: Booléen
|
||||
exemples:
|
||||
base: >-
|
||||
âge:
|
||||
formule: 17 ans
|
||||
|
||||
mineur émancipé:
|
||||
formule: oui
|
||||
|
||||
peut voter:
|
||||
formule:
|
||||
une de ces conditions:
|
||||
- âge > 18 ans
|
||||
- mineur émancipé
|
||||
|
||||
toutes ces conditions:
|
||||
description: >-
|
||||
C'est un `et` logique.
|
||||
Contient une liste de conditions.
|
||||
Renvoie `oui` si toutes les conditions sont applicables.
|
||||
argument:
|
||||
- '*'
|
||||
- ...
|
||||
exemples:
|
||||
base: >-
|
||||
âge:
|
||||
formule: 17 ans
|
||||
|
||||
citoyenneté française:
|
||||
formule: oui
|
||||
|
||||
peut voter:
|
||||
formule:
|
||||
toutes ces conditions:
|
||||
- citoyenneté française
|
||||
- âge > 18 ans
|
||||
|
||||
produit:
|
||||
description: >-
|
||||
C'est une multiplication un peu améliorée, très utile pour exprimer les
|
||||
cotisations.
|
||||
|
||||
Sa propriété `assiette` est multipliée par un pourcentage, `taux`, ou par un
|
||||
`facteur` quand ce nom est plus approprié.
|
||||
|
||||
La multiplication peut être plafonnée : ce plafond sépare l'assiette en
|
||||
deux, et la partie au-dessus du plafond est tout simplement ignorée. Dans ce
|
||||
cas, elle se comporte comme une barème en taux marginaux à deux tranches, la
|
||||
deuxième au taux nul et allant de `plafond` à l'infini.
|
||||
argument:
|
||||
assiette: Valeur à multiplier
|
||||
taux: Taux à appliquer
|
||||
facteur: Facteur multiplicatif
|
||||
plafond: Plafond au dessus duquel le taux appliqué est nul
|
||||
|
||||
exemples:
|
||||
base: >-
|
||||
cotisation:
|
||||
formule:
|
||||
produit:
|
||||
assiette: 2000 €/mois
|
||||
taux: 5%
|
||||
|
||||
assiette plafonnée: >-
|
||||
plafond sécurité sociale:
|
||||
formule: 3000 €/mois
|
||||
|
||||
assiette cotisation:
|
||||
formule: 15000 €/mois
|
||||
|
||||
chômage:
|
||||
formule:
|
||||
produit:
|
||||
assiette: assiette cotisation
|
||||
plafond: 400% * plafond sécurité sociale
|
||||
taux: 4%
|
||||
|
||||
variations:
|
||||
description: >-
|
||||
Contient une liste de conditions (`si`) et leurs conséquences associées
|
||||
(`alors`).
|
||||
|
||||
Pour la première condition vraie dans la liste, on retient la valeur qui lui
|
||||
est associée.
|
||||
|
||||
Si aucune condition n'est vraie, alors ce mécanisme renvoie implicitement
|
||||
`non applicable`
|
||||
|
||||
Ce mécanisme peut aussi être utilisé au sein d'un mécanisme compatible, tel qu'un produit ou un barème.
|
||||
arguments:
|
||||
- si: condition à vérifier
|
||||
alors: consequence évaluée si la condition est vrai
|
||||
- ...
|
||||
- sinon: consequence évaluée si aucune des conditions précédente n'était applicable
|
||||
exemples:
|
||||
base: >-
|
||||
taux réduit:
|
||||
formule: oui
|
||||
|
||||
taux allocation familiales:
|
||||
formule:
|
||||
variations:
|
||||
- si: taux réduit
|
||||
alors: 3.45%
|
||||
- sinon: 5.25%
|
||||
|
||||
dans un produit: >-
|
||||
assiette cotisation:
|
||||
formule: 2300 €/mois
|
||||
|
||||
taux réduit:
|
||||
formule: oui
|
||||
|
||||
allocation familiales:
|
||||
formule:
|
||||
produit:
|
||||
assiette: assiette cotisation
|
||||
variations:
|
||||
- si: taux réduit
|
||||
alors:
|
||||
taux: 3.45%
|
||||
- sinon:
|
||||
taux: 5.25%
|
||||
|
||||
somme:
|
||||
description: >-
|
||||
C'est tout simplement la somme de chaque terme de la liste. Si un des terme
|
||||
n'est pas applicable, il vaut zéro.
|
||||
|
||||
On peut aussi retrancher des valeurs avec l'opérateur unaire `-`
|
||||
arguments:
|
||||
- '*'
|
||||
- ...
|
||||
|
||||
exemples:
|
||||
base: >-
|
||||
somme:
|
||||
- 15.89 €
|
||||
- 12% * 14 €
|
||||
- (-30 €)
|
||||
terme non applicable: >-
|
||||
a:
|
||||
formule: 50 €
|
||||
|
||||
b:
|
||||
applicable si: non
|
||||
formule: 20 €
|
||||
|
||||
somme:
|
||||
formule:
|
||||
somme:
|
||||
- a
|
||||
- b
|
||||
- 40 €
|
||||
|
||||
le maximum de:
|
||||
description: >-
|
||||
Renvoie la valeur numérique de la liste de propositions fournie qui est la
|
||||
plus grande.
|
||||
|
||||
Pour ajouter un plancher à une valeur, préférer l'utilisation du
|
||||
mécanisme `encadrement`.
|
||||
exemples:
|
||||
base: >-
|
||||
max:
|
||||
formule:
|
||||
le maximum de:
|
||||
- 50
|
||||
- 100
|
||||
|
||||
le minimum de:
|
||||
description: >-
|
||||
Renvoie la valeur numérique de la liste de propositions fournie qui est la
|
||||
plus petite.
|
||||
|
||||
Pour plafonner une valeur, préférer l'utilisation du mécanisme `encadrement`.
|
||||
exemples:
|
||||
base: >-
|
||||
min:
|
||||
formule:
|
||||
le minimum de:
|
||||
- 50
|
||||
- 100
|
||||
|
||||
arrondi:
|
||||
description: >-
|
||||
Arrondi à l'entier le plus proche, ou à une précision donnée.
|
||||
exemples:
|
||||
base: >-
|
||||
arrondi:
|
||||
formule:
|
||||
arrondi:
|
||||
valeur: 12.45
|
||||
décimales: 1
|
||||
|
||||
régularisation:
|
||||
description: >-
|
||||
Permet de régulariser progressivement un calcul de cotisation en fonction de
|
||||
variables numérique mensuelle cumulée.
|
||||
|
||||
Ce mécanisme spécifique est utilisé pour le calcul des cotisations
|
||||
mensuelles.
|
||||
|
||||
arguments:
|
||||
règle: règle à régulariser
|
||||
valeurs cumulées:
|
||||
- liste de variables cumulée mensuellement pour calculer la régularisation. Doit être
|
||||
numérique, et avoir une unité `/mois`
|
||||
|
||||
exemples:
|
||||
base: >-
|
||||
brut:
|
||||
formule:
|
||||
somme:
|
||||
- 2000 €/mois | du 01/01/2020 | au 31/05/2020
|
||||
- 4000 €/mois | du 01/06/2020 | au 31/12/2020
|
||||
plafond:
|
||||
formule: 3000 €/mois
|
||||
|
||||
cotisation:
|
||||
formule:
|
||||
régularisation:
|
||||
règle:
|
||||
produit:
|
||||
assiette: brut
|
||||
plafond: plafond
|
||||
taux: 10%
|
||||
valeurs cumulées:
|
||||
- brut
|
||||
- plafond
|
||||
|
||||
cotisation en mai:
|
||||
formule: cotisation | du 01/05/2020 | au 31/05/2020
|
||||
|
||||
cotisation en juin:
|
||||
formule: cotisation | du 01/06/2020 | au 30/06/2020
|
||||
|
||||
cotisation en novembre:
|
||||
formule: cotisation | du 01/11/2020 | au 30/11/2020
|
||||
|
||||
recalcul:
|
||||
description: >-
|
||||
Relance le calcul d'une règle dans une situation différente de la situation
|
||||
courante. Permet par exemple de calculer le montant des cotisations au niveau du
|
||||
SMIC, même si le salaire est plus élevé dans la situation actuelle.
|
||||
|
||||
exemples:
|
||||
base: >-
|
||||
brut:
|
||||
formule: 2000€
|
||||
|
||||
cotisations:
|
||||
formule:
|
||||
produit:
|
||||
assiette: brut
|
||||
taux: 20%
|
||||
|
||||
cotisations pour un SMIC:
|
||||
recalcul:
|
||||
règle: cotisations
|
||||
avec:
|
||||
- brut: 1500 €
|
||||
|
||||
barème:
|
||||
description: C'est un barème en taux marginaux, mécanisme de calcul connu son utilisation
|
||||
dans le calcul de l'impôt sur le revenu.
|
||||
|
||||
L'assiette est décomposée en plusieurs tranches, qui sont multipliées par un
|
||||
taux spécifique.
|
||||
|
||||
Les tranches sont souvent exprimées sous forme de facteurs d'une variable
|
||||
que l'on appelle `multiplicateur`, par exemple `1 x le plafond de la
|
||||
sécurité sociale`.
|
||||
exemples:
|
||||
base: >-
|
||||
revenu imposable:
|
||||
formule: 54126 €
|
||||
|
||||
impôt sur le revenu:
|
||||
formule:
|
||||
barème:
|
||||
assiette: revenu imposable
|
||||
tranches:
|
||||
- taux: 0%
|
||||
plafond: 9807 €
|
||||
- taux: 14%
|
||||
plafond: 27086 €
|
||||
- taux: 30%
|
||||
plafond: 72617 €
|
||||
- taux: 41%
|
||||
plafond: 153783 €
|
||||
- taux: 45%
|
||||
|
||||
grille:
|
||||
description: >-
|
||||
C'est un barème sous la forme d'une grille de correspondance. C'est le
|
||||
mécanisme de calcul de l'impôt neutre, aussi appelé impôt non personnalisé.
|
||||
|
||||
Il est composé de tranches qui se suivent. Il suffit de trouver l'assiette
|
||||
qui correspond à la tranche, et de selectionner le montant associé à
|
||||
l'assiette.
|
||||
exemples:
|
||||
grille avec multiplicateur et unité: >-
|
||||
SMIC horaire:
|
||||
formule: 10 €/heure
|
||||
|
||||
revenu moyen:
|
||||
formule:
|
||||
2000 €/mois
|
||||
|
||||
trimestres validés:
|
||||
formule:
|
||||
grille:
|
||||
unité: trimestres validés/an
|
||||
assiette: revenu moyen
|
||||
multiplicateur: SMIC horaire
|
||||
tranches:
|
||||
- montant: 0
|
||||
plafond: 150 heures/an
|
||||
- montant: 1
|
||||
plafond: 300 heures/an
|
||||
- montant: 2
|
||||
plafond: 450 heures/an
|
||||
- montant: 3
|
||||
plafond: 600 heures/an
|
||||
- montant: 4
|
||||
|
||||
taux progressif:
|
||||
description: >-
|
||||
Ce mécanisme permet de calculer un taux progressif. On spécifie pour chaque
|
||||
tranche le plafond et le taux associé. Le taux effectif renvoyé est calculé
|
||||
en lissant la différence de taux entre la borne inférieure et supérieure de
|
||||
l'assiette
|
||||
|
||||
> Par exemple, si nous nous avons les tranches suivantes :
|
||||
|
||||
- taux: 50% / plafond: 0
|
||||
- taux: 100% / plafond: 1000
|
||||
|
||||
> Pour une assiette de 500, le taux retourné sera 75%, car il correspond au
|
||||
> taux situé à la moitié de la tranche correspondante.
|
||||
exemples:
|
||||
base: >-
|
||||
chiffre d'affaires:
|
||||
formule: 30000 €/an
|
||||
|
||||
plafond:
|
||||
formule: 3000 €/mois
|
||||
|
||||
taux réduction de cotisation:
|
||||
formule:
|
||||
taux progressif:
|
||||
assiette: chiffre d'affaires
|
||||
multiplicateur: plafond
|
||||
tranches:
|
||||
- taux: 100%
|
||||
plafond: 75%
|
||||
- taux: 0%
|
||||
plafond: 100%
|
||||
composantes:
|
||||
description: >-
|
||||
Beaucoup de cotisations sont composées de deux parties qui partagent la
|
||||
méthode de calcul mais diffèrent par des paramètres différents.
|
||||
|
||||
Pour ne pas définir deux variables presque redondantes, on utilise le
|
||||
mécanisme de composante. Il se comportera comme une somme dans les calculs,
|
||||
mais son affichage sur les pages /règle sera adapté.
|
||||
|
||||
Il est même possible, pour les mécanismes `barème` et `produit` de garder en
|
||||
commun un paramètre comme l'assiette, puis de déclarer des composantes pour
|
||||
le taux.
|
||||
|
||||
> L'exemple le plus courant de composantes, c'est la distinction part
|
||||
employeur, part salarié (ex. retraite AGIRC).
|
||||
|
||||
allègement:
|
||||
description: >-
|
||||
Permet de réduire le montant d'une variable.
|
||||
Très utilisé dans le contexte des impôts.
|
||||
|
||||
encadrement:
|
||||
description: Permet d'ajouter un plafond et/ou un plancher à une valeur.
|
||||
exemples:
|
||||
base: >-
|
||||
assiette plafonnée:
|
||||
formule:
|
||||
encadrement:
|
||||
plancher: 0 €
|
||||
valeur: 2000 €
|
||||
plafond: 1500 €
|
||||
|
||||
durée:
|
||||
description: Permet d'obtenir le nombre de jours entre deux dates
|
||||
exemples:
|
||||
base: >-
|
||||
date d'embauche: 14/04/2008
|
||||
|
||||
ancienneté en fin d'année:
|
||||
unité: an
|
||||
formule:
|
||||
durée:
|
||||
depuis: date d'embauche
|
||||
jusqu'à: 31/12/2020
|
||||
|
||||
synchronisation:
|
||||
description: Pour éviter trop de saisies à l'utilisateur, certaines informations sont
|
||||
récupérées à partir de ce que l'on appelle des API. Ce sont des services
|
||||
auxquels ont fait appel pour obtenir des informations sur un sujet précis.
|
||||
Par exemple, l'État français fournit gratuitement l'API géo, qui permet à
|
||||
partir du nom d'une ville, d'obtenir son code postal, son département, la
|
||||
population etc.
|
||||
|
||||
Ce mécanismes `synchronisation` permet de faire le lien entre les règles de
|
||||
notre système et les réponses de ces API.
|
||||
|
||||
inversion numérique:
|
||||
description: >-
|
||||
La formule de calcul de cette variable n'est pas connue, souvent elle n'a
|
||||
même pas de sens. Mais le mécanisme `inversion` indique qu'elle peut être
|
||||
_estimée_ à partir de l'un des _objectifs_ listés sous l'attribut `avec`. Il
|
||||
faut alors renseigner une valeur cible pour cet objectif.
|
||||
|
||||
Voilà comment ça marche : on va donner à la variable une valeur au hasard,
|
||||
calculer _l'objectif_, puis grâce à des calculs savants améliorer notre
|
||||
choix jusqu'à ce que l'écart entre le calcul et la valeur cible devienne
|
||||
satisfaisant.
|
||||
|
||||
Concrètement, si l'on demande au moteur (même indirectement) la valeur d'une
|
||||
variable qui a pour formule une inversion, il va vérifier qu'une des
|
||||
possibilités d'inversion a bien une valeur calculée ou saisie, et procéder à
|
||||
l'inversion décrite plus haut à partir de celle-ci. Sinon, ces possibilités
|
||||
d'inversions seront listées comme manquantes.
|
|
@ -20,7 +20,7 @@ export default function parse(parse, k, v) {
|
|||
// Barème en taux marginaux.
|
||||
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
//mécanisme de composantes. Voir mécanismes.md/composantes
|
||||
return decompose(parse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
|
||||
export default function parse(parse, k, v) {
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
//mécanisme de composantes. Voir mécanismes.md/composantes
|
||||
return decompose(parse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
Evaluation,
|
||||
groupByYear,
|
||||
liftTemporal2,
|
||||
pureTemporal,
|
||||
Temporal,
|
||||
temporalAverage,
|
||||
temporalCumul
|
||||
|
@ -95,17 +96,17 @@ function evaluate(
|
|||
const cumulatedVariables = node.explanation.variables.reduce(
|
||||
(acc, parsedVariable) => {
|
||||
const evaluation = evaluate(parsedVariable)
|
||||
if (!evaluation.temporalValue) {
|
||||
if (!evaluation.unit.denominators.some(unit => unit === 'mois')) {
|
||||
evaluationError(
|
||||
cache._meta.contextRule,
|
||||
`Dans le mécanisme régularisation, la valeur annuelle ${parsedVariable.name} n'est pas une variables temporelle`
|
||||
`Dans le mécanisme régularisation, la valeur cumulée '${parsedVariable.name}' n'est pas une variable numérique définie sur le mois`
|
||||
)
|
||||
}
|
||||
return {
|
||||
...acc,
|
||||
[parsedVariable.dottedName]: getMonthlyCumulatedValuesOverYear(
|
||||
currentYear,
|
||||
evaluation.temporalValue,
|
||||
evaluation.temporalValue ?? pureTemporal(evaluation.nodeValue),
|
||||
evaluation.unit
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
|
||||
export default function parse(parse, k, v) {
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
//mécanisme de composantes. Voir mécanismes.md/composantes
|
||||
return decompose(parse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import { getSessionStorage } from '../../utils'
|
|||
import redirects from '../mon-entreprise.fr/redirects'
|
||||
import Landing from './Landing'
|
||||
import Studio from './LazyStudio'
|
||||
import Mécanismes from './Mécanismes'
|
||||
|
||||
function Router({ language }) {
|
||||
useEffect(() => {
|
||||
|
@ -38,7 +39,8 @@ let RouterSwitch = () => {
|
|||
<>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Landing} />
|
||||
<Route exact path="/Studio" component={Studio} />
|
||||
<Route exact path="/studio" component={Studio} />
|
||||
<Route exact path="/mécanismes" component={Mécanismes} />
|
||||
<Route component={App} />
|
||||
</Switch>
|
||||
</>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
export const Header = ({ noSubtitle, sectionName = '' }) => (
|
||||
export const Header = ({ noSubtitle = false, sectionName = '' }) => (
|
||||
<header css="text-align: center; a {text-decoration: none}">
|
||||
<Link to="/">
|
||||
<h1>
|
||||
|
@ -19,7 +19,7 @@ export const Header = ({ noSubtitle, sectionName = '' }) => (
|
|||
</Link>
|
||||
{!noSubtitle && (
|
||||
<p css="max-width: 28rem; margin: 0 auto; font-size: 120%">
|
||||
Un nouveau langage pour les algorithmes d'intérêt public.
|
||||
Le langage pour les algorithmes d'intérêt public.
|
||||
</p>
|
||||
)}
|
||||
</header>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import exemple1 from '!!raw-loader!./exemples/bareme-ir.yaml'
|
||||
import exemple2 from '!!raw-loader!./exemples/douche.yaml'
|
||||
import ColoredYaml from 'Components/rule/ColoredYaml'
|
||||
import { Markdown } from 'Components/utils/markdown'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import publicodeReadme from 'Engine/README.md'
|
||||
import React, { useEffect } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Header } from './Header'
|
||||
|
||||
export default function Landing() {
|
||||
|
@ -21,67 +19,12 @@ export default function Landing() {
|
|||
document.body.appendChild(css)
|
||||
})
|
||||
return (
|
||||
<div className="app-content ui__ container" css="margin-bottom: 2rem">
|
||||
<div className="app-content ui__ container" css="margin: 2rem 0">
|
||||
<ScrollToTop />
|
||||
<Header />
|
||||
<h2>Pourquoi ?</h2>
|
||||
<p>
|
||||
Certains algorithmes sont bien trop importants pour être maintenus dans
|
||||
une boîte noire, souvent privée, que seuls les développeurs expérimentés
|
||||
peuvent comprendre.
|
||||
</p>
|
||||
<p>
|
||||
{' '}
|
||||
C'est notamment le cas d'une bonne partie de la loi, qui spécifie en
|
||||
français des règles... et charge à d'autres de les implémenter
|
||||
librement.
|
||||
</p>
|
||||
<p>
|
||||
La plateforme <em>publicodes</em> fusionne documentation et
|
||||
implémentation en partant d'un code simple. Ajouter une règle de calcul,
|
||||
c'est déployer sans effort sur le Web la page de documentation
|
||||
correspondante, lisible par tout citoyen.
|
||||
</p>
|
||||
<br />
|
||||
<p>Pour aller plus loin:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/betagouv/publicodes/wiki">
|
||||
{emoji('📖 ')} Lire la documentation
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/studio">⚡ Essayer le langage </Link>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Projets phares</h2>
|
||||
<h3>
|
||||
La sécurité sociale et les impôts -{' '}
|
||||
<a href="https://mon-entreprise.fr">mon-entreprise.fr</a>
|
||||
</h3>
|
||||
<div className="ui__ card">
|
||||
<ColoredYaml source={exemple1} />
|
||||
</div>
|
||||
<Link to="/studio?exemple=bareme-ir" className="ui__ button small">
|
||||
Lancer le calcul ⚡
|
||||
</Link>
|
||||
<p>
|
||||
En plus du site Web, Mon-entreprise est disponible comme une{' '}
|
||||
<a href="https://mon-entreprise.fr/intégration/bibliothèque-de-calcul">
|
||||
bibliothèque de calcul autonome
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<h3>
|
||||
L'impact climatique de nos gestes du quotidien -
|
||||
<a href="https://futur.eco">futur.eco</a>
|
||||
</h3>
|
||||
<div className="ui__ card">
|
||||
<ColoredYaml source={exemple2} />
|
||||
</div>
|
||||
<Link to="/studio?exemple=douche" className="ui__ button small">
|
||||
Lancer le calcul ⚡
|
||||
</Link>
|
||||
<br />
|
||||
<Markdown source={publicodeReadme} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
import { Markdown } from 'Components/utils/markdown'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import mecanisms from 'Engine/mecanisms.yaml'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useLocation } from 'react-router'
|
||||
import { HashLink as Link } from 'react-router-hash-link'
|
||||
import { capitalise0 } from '../../utils'
|
||||
import { Header } from './Header'
|
||||
|
||||
type MecanismProp = {
|
||||
exemples: { base: string }
|
||||
description: string
|
||||
name: string
|
||||
}
|
||||
const Mecanism = ({ name, description, exemples }: MecanismProp) => (
|
||||
<React.Fragment key={name}>
|
||||
<h2 id={name}>
|
||||
<pre>{name}</pre>
|
||||
</h2>
|
||||
<Markdown source={description} />
|
||||
{exemples && (
|
||||
<>
|
||||
{Object.entries(exemples).map(([name, exemple]) => (
|
||||
<React.Fragment key={name}>
|
||||
<h3>{name === 'base' ? 'Exemple' : capitalise0(name)}</h3>
|
||||
<Markdown source={`\`\`\`yaml\n${exemple}\n\`\`\``} />
|
||||
</React.Fragment>
|
||||
))}{' '}
|
||||
</>
|
||||
)}
|
||||
<Link to={useLocation().pathname + '#top'}>Retour à la liste</Link>
|
||||
</React.Fragment>
|
||||
)
|
||||
export default function Landing() {
|
||||
useEffect(() => {
|
||||
var css = document.createElement('style')
|
||||
css.type = 'text/css'
|
||||
css.innerHTML = `
|
||||
#js {
|
||||
animation: appear 0.5s;
|
||||
opacity: 1;
|
||||
}
|
||||
#loading {
|
||||
display: none !important;
|
||||
}`
|
||||
document.body.appendChild(css)
|
||||
})
|
||||
return (
|
||||
<div className="app-content ui__ container" css="margin: 2rem 0">
|
||||
<ScrollToTop />
|
||||
<Header />
|
||||
<h1 id="top">Mécanismes existants</h1>
|
||||
<ul>
|
||||
{Object.keys(mecanisms).map(name => (
|
||||
<li key={name}>
|
||||
<Link to={useLocation().pathname + '#' + name}>{name}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{Object.entries(mecanisms).map(([name, data]) => (
|
||||
<Mecanism {...(data as any)} name={name} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
import baremeIr from '!!raw-loader!./exemples/bareme-ir.yaml'
|
||||
import douche from '!!raw-loader!./exemples/douche.yaml'
|
||||
import { ControlledEditor } from '@monaco-editor/react'
|
||||
import Engine from 'Engine/react'
|
||||
import { safeLoad } from 'js-yaml'
|
||||
|
@ -10,11 +8,6 @@ import { useLocation } from 'react-router'
|
|||
import styled from 'styled-components'
|
||||
import { Header } from './Header'
|
||||
|
||||
let examples = {
|
||||
'bareme-ir': baremeIr,
|
||||
douche
|
||||
}
|
||||
|
||||
let initialInput = `a:
|
||||
formule: 10€
|
||||
b:
|
||||
|
@ -30,15 +23,8 @@ d:
|
|||
|
||||
export default function Studio() {
|
||||
const search = new URLSearchParams(useLocation().search ?? '')
|
||||
const currentExample = search.get('exemple')
|
||||
const code = search.get('code')
|
||||
const [editorValue, setEditorValue] = useState(
|
||||
code
|
||||
? code
|
||||
: currentExample && Object.keys(examples).includes(currentExample)
|
||||
? examples[currentExample]
|
||||
: initialInput
|
||||
)
|
||||
const [editorValue, setEditorValue] = useState(code ? code : initialInput)
|
||||
const [targets, setTargets] = useState<string[]>([])
|
||||
const [rules, setRules] = useState(editorValue)
|
||||
const handleShare = useCallback(() => {
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
revenu imposable:
|
||||
formule: 18000 €
|
||||
|
||||
revenu abattu:
|
||||
formule:
|
||||
allègement:
|
||||
assiette: revenu imposable
|
||||
abattement: 10%
|
||||
|
||||
impôt sur le revenu:
|
||||
formule:
|
||||
barème:
|
||||
assiette: revenu abattu
|
||||
tranches:
|
||||
- taux: 0%
|
||||
plafond: 9807€
|
||||
- taux: 14%
|
||||
plafond: 27086€
|
||||
- taux: 30%
|
||||
plafond: 72617€
|
||||
- taux: 41%
|
||||
plafond: 153783€
|
||||
- taux: 45%
|
|
@ -1,96 +0,0 @@
|
|||
douche:
|
||||
icônes: 🚿
|
||||
|
||||
douche . impact par douche:
|
||||
titre: Une douche
|
||||
formule: impact par litre * litres d'eau
|
||||
|
||||
douche . impact par litre:
|
||||
formule: eau . impact par litre froid + chauffage . impact par litre
|
||||
|
||||
douche . litres d'eau:
|
||||
formule: durée de la douche * litres par minute
|
||||
|
||||
douche . litres par minute:
|
||||
unité: l/minute
|
||||
formule:
|
||||
variations:
|
||||
- si: pomme de douche économe
|
||||
alors: 9
|
||||
- sinon: 18
|
||||
références:
|
||||
- https://www.jeconomiseleau.org/index.php/particuliers/economies-par-usage/la-douche-et-le-bain
|
||||
|
||||
douche . pomme de douche économe:
|
||||
question: Utilisez-vous une pomme de douche économe ?
|
||||
par défaut: non
|
||||
|
||||
douche . durée de la douche:
|
||||
question: Combien de temps dure votre douche en général (en minutes) ?
|
||||
par défaut: 5
|
||||
unité: minute
|
||||
suggestions:
|
||||
expresse: 5
|
||||
moyenne: 10
|
||||
lente: 20
|
||||
|
||||
chauffage:
|
||||
icônes: 🔥
|
||||
|
||||
chauffage . type:
|
||||
question: Votre eau est chauffée comment ?
|
||||
formule:
|
||||
une possibilité:
|
||||
choix obligatoire: oui
|
||||
possibilités:
|
||||
- gaz
|
||||
- fioul
|
||||
- électricité
|
||||
par défaut: gaz
|
||||
|
||||
chauffage . impact par kWh:
|
||||
unité: kgCO₂e/kWh
|
||||
formule:
|
||||
variations:
|
||||
- si: type = 'gaz'
|
||||
alors: 0.227
|
||||
- si: type = 'fioul'
|
||||
alors: 0.324
|
||||
- si: type = 'électricité'
|
||||
alors: 0.059
|
||||
|
||||
note: |
|
||||
La base carbone de l'ADEME ne permet malheureusement pas de faire des liens profonds vers les chiffres utilisés.
|
||||
Pour l'électricité, nous retenons le chiffre de l'ADEME "Electricité - 2016 - usage : Eau Chaude Sanitaire - consommation".
|
||||
références:
|
||||
- http://www.bilans-ges.ademe.fr/fr/accueil
|
||||
- https://www.electricitymap.org/?page=country&solar=false&remote=true&wind=false&countryCode=FR
|
||||
- https://decrypterlenergie.org/decryptage-quel-est-le-contenu-en-co2-du-kwh-electrique
|
||||
|
||||
chauffage . énergie consommée par litre:
|
||||
formule: 0.0325
|
||||
unité: kWh
|
||||
références:
|
||||
- https://www.econologie.com/forums/plomberie-et-sanitaire/prix-reel-d-un-bain-ou-d-une-douche-pour-l-eau-et-chauffage-t12727.html
|
||||
|
||||
chauffage . impact par litre:
|
||||
titre: impact par litre chauffé
|
||||
formule: impact par kWh * énergie consommée par litre
|
||||
|
||||
eau:
|
||||
icônes: 🌊
|
||||
|
||||
eau . impact par litre froid:
|
||||
unité: kgCO₂e/l
|
||||
formule: eau potable + traitement eau usée
|
||||
références:
|
||||
- >-
|
||||
http://www.bilans-ges.ademe.fr/documentation/UPLOAD_DOC_FR/index.htm?boissons.htm
|
||||
|
||||
eau . impact par litre froid . eau potable:
|
||||
unité: kgCO₂e/l
|
||||
formule: 0.000132
|
||||
|
||||
eau . impact par litre froid . traitement eau usée:
|
||||
unité: kgCO₂e/l
|
||||
formule: 0.000262
|
|
@ -134,6 +134,10 @@ module.exports.commonLoaders = ({ legacy = false } = {}) => {
|
|||
{
|
||||
test: /\.ne$/,
|
||||
use: [babelLoader, 'nearley-loader']
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
use: ['raw-loader']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9365,6 +9365,13 @@ react-router-dom@^5.1.1:
|
|||
tiny-invariant "^1.0.2"
|
||||
tiny-warning "^1.0.0"
|
||||
|
||||
react-router-hash-link@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/react-router-hash-link/-/react-router-hash-link-1.2.2.tgz#7a0ad5e925d49596d19554de8bc6c554ce4f8099"
|
||||
integrity sha512-LBthLVHdqPeKDVt3+cFRhy15Z7veikOvdKRZRfyBR2vjqIE7rxn+tKLjb6DOmLm6JpoQVemVDnxQ35RVnEHdQA==
|
||||
dependencies:
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-router@5.1.2, react-router@^5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418"
|
||||
|
|
Loading…
Reference in New Issue