Principes de base

La syntaxe de Publicodes est basée sur le langage Yaml.

Un modèle Publicodes est un dossier contenant des fichiers avec l’extension .publicodes. Un fichier Publicodes contient une liste de règles identifiées par leur nom et possédant une valeur :

Loading editor...

prix d'un repas: 10 €

Une formule de calcul peut faire référence à d’autres règles provenant du même modèle. Dans l’exemple suivant la règle prix total aura pour valeur 50 (= 5 * 10)

Loading editor...

prix d'un repas: 10 €
prix total: 5 * prix d'un repas

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.

Il est possible de préciser des unités pour les valeurs littérales. Ici, prix d’un repas a pour unité €. Les unités sont propagées dans les calculs, et les incohérences d’unités sont détectées automatiquement.

En savoir plus sur les unités

Mécanismes

Il existe une autre manière d’écrire des formules de calcul : les mécanismes. Au lieu de définir la formule sur une ligne, celle-ci prend la forme d’un objet sur plusieurs lignes.

Par exemple, la formule suivante :

Loading editor...

prix total: 5 repas * 9 €/repas

peut également s’écrire en utilisant le mécanisme produit :

Loading editor...

prix total:
  produit:
    - 9 €/repas
    - 5 repas

Un des avantages de cette écriture est que la syntaxe hiérarchique de Yaml permet d’imbriquer les mécanismes :

Loading editor...

nombre de repas: 12 repas
prix total:
  somme:
    - 7 cafés * 1.5 €/cafés
    - produit:
        - nombre de repas
        - 12 €/repas

En savoir plus sur les mécanismes

Pages d’explications

L’explication des calculs est un des objectifs fondamentaux de Publicodes. Un utilitaire permet de générer automatiquement une documentation explorable à partir des règles définies.

Sur ce site, vous pouvez afficher la documentation d’un exemple en cliquant sur le bouton en haut à droite.

Loading editor...

ticket resto:
  titre: Prise en charge des titres-restaurants
  formule: 4 €/repas
  description: |
    L'employeur peut remettre des titres restaurants sous plusieurs formats: ticket papier, carte à puce
    ou appli mobile
  note: |
    La valeur a été revalorisée en 2022 pour faire face à l'inflation.

En savoir plus sur les pages d’explication

Types

En plus des nombres, publicodes supporte différents types de valeurs :

Loading editor...

# Chaine de caractères
nationalité: "'française'"
# Date
date de naissance: 11/01/2000
# Booléen
majeur: oui

En savoir plus sur les types de base

Applicabilité

On peut définir des conditions d’applicabilité pour des valeurs :

Loading editor...

date de début: 12/02/2020

ancienneté en fin d'année:
  durée:
    depuis: date de début
    jusqu'à: 31/12/2020

prime de vacances:
  applicable si: ancienneté en fin d'année > 1 an
  valeur: 200€

Ici, si l’ancienneté est inférieure à un an, alors la prime de vacances sera non applicable.

Les variables non applicable sont prise en compte différement au niveau des mécanismes numériques. Par exemple le mécanisme somme comptera une prime non applicable comme valant zéro. Un plafond non applicable n’aura pas d’incidence sur la valeur retournée (même chose pour un abattement ou un plancher par exemple).

Tester l’applicabilité

On peut tester si une variable est applicable ou non applicable avec les mécanismes est applicable et est non applicable.

Rend non applicable

Il est également possible de rendre une règle non applicable depuis une autre règle :

Loading editor...

nouveau salarié:
  valeur: oui
  rend non applicable: prime de vacances

prime de vacances: 200€

primes:
  somme:
    - prime de vacances
    - 150€

Si on change la valeur de la règle nouveau salarié à non, alors la référence à prime de vacances redevient applicable.

Espace de nom

Les espaces de noms sont utiles pour organiser un grand nombre de règles. On utilise le . pour exprimer la hiérarchie des noms.

Loading editor...

prime de vacances: taux * 1000 €
prime de vacances . taux: 6%

Ici, prime de vacances est à la fois une règle et un espace de noms. La variable taux est définie dans cet espace de noms et c’est elle qui est référencée dans la formule de calcul de la règle prime de vacances.

La règle prime de vacances est elle-même définie dans l’espace de nom racine.

On pourrait avoir une autre variable taux dans un espace de nom différent, sans que cela entre en conflit :

Loading editor...

prime de vacances: taux * 1000 €
prime de vacances . taux: 6%

# Ceci n'entre pas dans le calcul de `prime de vacances` définie plus haut
autre prime:
autre prime . taux: 19%

On dit que la règle prime de vacances fait référence à la règle prime de vacances . taux via le nom raccourci taux.

Pour faire référence à une règle hors de son espace de nom, on peut écrire le nom complet de cette règle:

Loading editor...

a:
a . b: 10
c: a . b

Désactivation de branche

Il est possible de désactiver l’ensemble des règles définies dans un espace de nom, en l’indiquant avec applicabilité étendue à l'espace de nom:

Loading editor...

CDD:
  valeur: non
  applicabilité étendue à l'espace de nom: oui
CDD . indemnité de précarité: 1500€ # non applicable

indemnités:
  somme:
    - 100 €
    - CDD . indemnité de précarité

Loading editor...

région: '"Centre"'

aides occitanie:
  applicable si: région = 'Occitanie'
  applicabilité étendue à l'espace de nom: oui
aides occitanie . subvention vélo : 500 €

Remplacement

Les remplacements sont un moyen de simplifier l’expression d’exceptions. Modifier une règle pour lui ajouter des conditions, avec par exemple une variation, va la complexifier, l’alourdir, et poser des problèmes de maintenabilité.

Publicodes dispose d’un mécanisme de remplacement qui permet d’amender n’importe quelle règle existante, sans avoir besoin de la modifier. Dans cet exemple, toutes les références à la règle frais de repas seront remplacées par des références à cafés-restaurants . frais de repas :

Loading editor...

frais de repas: 5 €/repas

cafés-restaurants: oui

cafés-restaurants . frais de repas:
  remplace: frais de repas
  valeur: 6 €/repas

montant repas mensuels: 20 repas * frais de repas

Il est possible de restreindre le remplacement à une règle précise :

Loading editor...

foo: 0

foo remplacé dans résultat 1:
  remplace:
    références à: foo
    dans: résultat 1
  valeur: 2

foo remplacé dans autres résultats:
  remplace:
    références à: foo
    sauf dans: résultat 1
  valeur: 3

résultat 1: foo # vaut 2
résultat 2: foo # vaut 3
résultat 3: foo # vaut 3

Remplacement non applicable

Le remplacement est ignoré si la règle est non applicable. Cela permet de conditionner le remplacement :

Loading editor...

a: 1

b:
  applicable si: non
  remplace: a
  valeur: 5

résultat: a # vaut 1 car b est non applicable

Remplacements exclusifs

Lorsque plusieurs remplacements sont applicables pour une même référence, alors il faut qu’ils soient exclusifs. Alternativement, il faudra utiliser les remplacement chainés.

Il est necessaire de préciser que les remplacements sont exclusifs avec l’attribut exclusif: oui :

Loading editor...

a: 1
b:
  non applicable si:
    est défini: c
  remplace:
    références à: a
    exclusif: oui
  valeur: 5
c:
  remplace:
    références à: a
    exclusif: oui
  valeur: 10

résultat: a
# est remplacé par `c` car `c` est défini rendant `b` non applicable.

Une erreur sera levée à l’execution si l’exclusivité n’est pas vérifié :

Loading editor...

a: 1

b:
  remplace:
    références à: a
    exclusif: oui
  valeur: 5

c:
  remplace:
    références à: a
    exclusif: oui
  valeur: 10

# Ce cas produit une erreur.

Remplacements chainés

Lorsque les remplacements ne sont pas exclusifs, alors il faut indiquer lesquels sont prioritaires sur les autres. Il faut pour se faire utiliser les remplacements chainés, ou transitifs :

Loading editor...

a: 1
b:
  remplace: a
  valeur: 5
c:
  remplace: b
  valeur: 10

résultat: a
# est remplacé par `b` puis par `c`, donc vaut 10

Définir des règles imbriquées

Loading editor...

prix final:
   valeur: 157 € * (100% - 20%)

Dans cet exemple, si l’on veut extraire le prix et la promotion dans des variables séparées, on est obligé de les définir à côté de la règle prix final :

Loading editor...

prix final:
   valeur: prix de base * (100% - réduction)
prix final . prix de base: 157€
prix final . réduction: 20%

Pour alléger cette écriture, on peut utiliser la notation avec qui permet de définir des règles enfants directement depuis une règle parente :

Loading editor...

# Equivalent à l'exemple précédent

prix final:
   valeur: prix de base * (100% - réduction)
   avec:
     prix de base: 157 €
     réduction: 20%

Règles non définie

Il est possible de laisser certaines règles vide pour être saisie par l’utilisateur par exemple. Lors de l’évaluation, les variables dont les valeurs ne sont pas renseignées sont remontées.

Loading editor...

salaire brut:
  unité: €/mois

salaire net: salaire brut - 20 %

Il est possible de donner une valeur par défaut. Les variables manquantes seront quand même remontées, et le moteur utilisera la valeur par défaut pour le calcul.

Loading editor...

durée:
  par défaut: 2 mois

salaire brut:
  par défaut: 1500 €/mois

indemnité de CDD: 10 % * salaire brut * durée

Cycle

Publicodes détecte les cycles dans les règles au runtime. Si un cycle est détecté, un warning est affiché et la règle est évaluée à non défini.

Loading editor...

a: b + 2
b: c + 3
c: a + 4
  • Avertissement ➡️ Dans la règle "a" ⚠️ Un cycle a été détecté lors de l'évaluation de cette règle: a → b → c → a Cela vient probablement d'une erreur dans votre modèle. Si le cycle est voulu, vous pouvez indiquer au moteur de résoudre la référence circulaire en trouvant le point fixe de la fonction. Pour cela, ajoutez l'attribut suivant niveau de la règle : a: résoudre la référence circulaire: oui" ...

Pour lever une exception plutôt qu’un warning, on peut utiliser l’option noCycleRuntime

Il est possible de résoudre une référence circulaire avec le mécanisme résoudre la référence circulaire.