DeltiaAide

Calculer une valeur avec une formule

Le marqueur de formule, les fonctions de calcul sûres pour les montants et l'écriture dans un champ crédit

À quoi ça sert

Une variable recopie une valeur telle quelle. Une formule en calcule une : retrancher un montant à un solde de crédits, multiplier une quantité par un prix unitaire, additionner les prix des produits liés à une fiche, choisir une valeur selon une condition.

Une formule s'écrit dans les paramètres d'une action, entre {{= et }}. Elle peut occuper toute la valeur — elle rend alors un nombre, un texte ou un oui/non selon son résultat — ou être insérée dans une phrase, auquel cas son résultat est converti en texte.

Sur une règle au déclencheur « Date », une formule ne peut lire aucune racine : record, before, after, actor et related n'existent pas, faute de fiche déclencheuse. Un calcul qui ne lit rien, par exemple {{= round(1.5) }}, reste utilisable.

Concepts clés

  • Marqueur de formule — la paire {{= et }}. Sans elle, le contenu est pris pour du texte.
  • Racines — les mêmes que dans une condition : record, before, after et actor. Une formule les lit sans le préfixe trigger. : on écrit record.credits, pas {{trigger.record.credits}}.
  • llm — une racine de plus, réservée aux formules des paramètres d'une action qui a un pré-traitement IA : llm.clé lit une valeur renvoyée par le modèle, par exemple {{= mul(llm.seats, 2) }}. Voir Pré-traiter une action avec l'IA.
  • analysis — la racine des valeurs renvoyées par l'analyse IA de la règle, lisible dans les formules des paramètres de toutes les actions : {{= mul(analysis.seats, 2) }}. La règle doit porter une analyse qui déclare la clé.
  • Fonctions de calcul sûres — add, sub, mul, div, round et sum. Elles doivent être employées pour tout ce qui touche à de l'argent.
  • Fonctions de date — formatDateTime et formatTime écrivent une date ou une heure lisible, à l'heure locale ; addMonths et addDays décalent une date.
  • Fonction de liste — range fabrique une suite de nombres entiers, pour répéter une action (voir Répéter une action sur une liste).
  • related — les enregistrements liés à l'objet déclencheur, chargés au moment du déclenchement. Accessible dans une formule et, pour le contrat d'une tâche, dans une condition écrite en expression.
  • actor — la personne à l'origine de l'évènement : actor.id et actor.name. Les deux valent null quand aucune personne n'a déclenché la règle.

Comment faire

Calculer un montant

  1. Dans les paramètres de l'action, écrivez la valeur sous forme de formule.
  2. Utilisez add, sub, mul ou div plutôt que +, -, * ou /.
  3. Arrondissez le résultat final avec round.

Exemple, pour décrémenter un solde de crédits du montant de la facture :

{{= round(sub(record.credits, record.totalTtc), 2) }}

Les opérateurs natifs +, -, * et / restent acceptés, mais ils font un calcul à virgule flottante imprécis : ne les utilisez jamais pour un montant.

Choisir une valeur selon une condition

  1. Écrivez une expression conditionnelle dans la formule.

Exemple :

{{= record.amount > 1000 ? "gold" : "standard" }}

Insérer un résultat dans une phrase

  1. Écrivez la formule au milieu du texte.

Exemple :

Solde restant : {{= sub(record.credits, record.totalTtc) }} €

Le résultat est converti en texte à l'endroit de la formule. Le reste de la phrase est conservé tel quel.

Additionner les données liées à une fiche

  1. Vérifiez que le champ à agréger est un champ de relation ou un champ catalogue de la fiche déclencheuse.
  2. Écrivez la formule avec related, map et sum.

Exemple, pour écrire dans un champ CRM la somme des prix de vente des produits liés :

{{= round(sum(related.produits.map(p, p.sellingPrice)), 2) }}

Remplacez produits par le nom technique de votre champ. Seuls les champs réellement cités par une formule sont chargés.

Écrire une date ou une heure lisible

  1. Passez la date par formatDateTime, ou par formatTime pour l'heure seule.
  2. Indiquez si besoin un fuseau horaire en second argument.

Exemple, pour écrire une ligne d'historique datée :

{{= formatDateTime(record.updatedAt) }} - Démarré

Avec un fuseau : {{= formatTime(record.updatedAt, "America/Martinique") }}. Sans fuseau, l'heure est celle de Paris. La date doit être un instant complet, avec son fuseau (2026-10-19T15:02:00Z) : une date seule comme 2026-10-19 est refusée.

Décaler une date

  1. Passez la date par addMonths(date, n) pour un nombre de mois, ou addDays(date, n) pour un nombre de jours. Un nombre négatif recule.
  2. Le résultat garde la forme de la date de départ : une date seule (2026-11-01) donne une date seule, un instant complet (2026-11-01T10:00:00Z) donne un instant complet.

Exemple : {{= addMonths(record.startDate, 6) }} donne 2027-05-01 pour une date de départ au 2026-11-01. Quand le mois d'arrivée est plus court, le jour est ramené à sa fin : addMonths("2026-01-31", 1) donne 2026-02-28.

Le nombre doit être entier. Un nombre lu sur la fiche est décimal pour la formule : écrivez 12.0 / record.visits et non 12 / record.visits. Une date absente, illisible, impossible (2026-02-30) ou sans fuseau pour un instant (2026-11-01T10:00:00) fait échouer l'action.

Fabriquer une liste de nombres

range(n) donne la liste 0, 1, …, n-1, avec n entier de 0 à 50. Combinée à map, elle produit une liste de dates à répéter : range(record.visits).map(k, addMonths(record.startDate, k * 6)). Voir Répéter une action sur une liste.

Citer la personne à l'origine de l'évènement

  1. Écrivez actor.name dans la formule, ou {{trigger.actor.name}} dans un texte.
  2. Testez-le d'abord quand la règle peut partir sans personne : actor.name vaut alors null.

Exemple : {{= actor.name != null ? actor.name : "le système" }}.

Lire le contrat d'une tâche et ses minutes consommées

Sur une règle déclenchée par une tâche, related.contract donne le contrat auquel la tâche est liée. Voir le tableau « Contenu de related » ci-dessous.

Alimenter un champ crédit

  1. Écrivez la valeur comme un montant signé à ajouter, jamais comme le solde visé.
  2. Renseignez un objet contenant le montant et sa note.

Exemple, pour débiter le montant d'une facture :

{
  "Crédits": {
    "amount": "{{= round(mul(record.totalTtc, -1), 2) }}",
    "note": "facture"
  }
}

Un champ crédit fonctionne comme un cahier auquel on ajoute des écritures : la valeur écrite s'ajoute au solde, elle ne le remplace pas. Quand l'information complémentaire du champ est une liste, la note doit être une des valeurs configurées. Voir Champ crédit.

Référence

Fonctions disponibles

FonctionEffet
add(a, b)Addition sûre de deux montants
sub(a, b)Soustraction sûre
mul(a, b)Multiplication sûre : quantité par prix unitaire
div(a, b)Division sûre. Échoue si le diviseur vaut zéro
round(valeur) ou round(valeur, décimales)Arrondit à N décimales, zéro par défaut. À appliquer sur le résultat monétaire final
sum(liste)Somme sûre d'une liste de nombres, typiquement les prix des enregistrements liés
size(valeur)Taille d'une chaîne ou d'une liste
has(champ)Teste la présence d'une clé
formatDateTime(date) ou formatDateTime(date, fuseau)Écrit la date et l'heure au format jj/mm/aaaa hh:mm, en heure de Paris par défaut
formatTime(date) ou formatTime(date, fuseau)Écrit l'heure au format hh:mm, sur 24 h, en heure de Paris par défaut
addMonths(date, n)Décale la date de n mois (n entier, négatif pour reculer) ; le jour est ramené à la fin du mois d'arrivée s'il n'existe pas
addDays(date, n)Décale la date de n jours (n entier, négatif pour reculer)
range(n)Liste 0 à n-1, avec n entier de 0 à 50

Cette liste est complète : aucune autre fonction ne peut être appelée. Les opérations sur les listes — map, filter, all, exists — s'écrivent attachées à la liste, comme dans related.produits.map(p, p.sellingPrice).

Type de champ de la ficheCe que related contient
Champ catalogue à valeurs multiplesUn objet par produit avec id, name, sellingPrice, vatRate et unit
Champ de relation CRMUn objet par enregistrement lié, avec ses champs
Champ utilisateurUn objet par utilisateur, avec id, name et email

Les objets auxquels vous n'avez pas accès sont absents de la liste : un total calculé avec sum les exclut. Sur un enregistrement lié, les champs réservés à un périmètre, à leur auteur ou masqués aux automatisations n'apparaissent pas dans l'objet, même quand vous avez accès à l'enregistrement lui-même.

Pour un déclencheur de type tâche, ce sont les champs personnalisés du type de tâche qui sont chargés selon les mêmes règles.

Pour un déclencheur de type tâche, related.contract donne aussi le contrat lié à la tâche :

CléContenu
related.contract.templateIdLe modèle du contrat
related.contract.fieldValues.<champ>La valeur d'un champ du modèle : un nombre pour un champ nombre ou montant, un texte pour les autres, vide si non renseigné
related.contract.ticketMinutesLes minutes consommées. Si le contrat suit une unité dont le libellé est « minute » ou « minutes », c'est la quantité consommée de cette unité, ajustements et frais d'accès déduits (plusieurs unités de ce nom s'additionnent ; une unité jamais consommée vaut 0). Sinon, c'est la somme des durées saisies à la clôture des tickets liés au contrat, 0 sans ticket clôturé

related.contract n'existe pas quand la tâche n'a pas de contrat : commencez la condition par has(related.contract), sinon l'exécution échoue. Le ticket en cours de création compte 0 minute, la lecture ignore les groupes de l'utilisateur, et l'aperçu de la règle ne la remplit pas. Les conditions guidées ne la savent pas écrire : choisissez « Expression (CEL) » dans le bloc « Condition ». Une règle dont le déclencheur n'est pas une tâche ne peut pas la lire.

Refus à l'enregistrement

Une formule est contrôlée au moment de l'enregistrement de la règle.

MessageCause
« Une règle planifiée n'a pas de déclencheur à lire : « <référence> » ne peut pas être utilisé. »La règle a le déclencheur « Date » et une formule d'action lit malgré tout une racine
« L'expression de la règle d'automatisation est invalide. »La formule ne s'analyse pas
« <racine> n'existe pas dans le contexte de la règle. Racines disponibles : record, before, after, related, actor. »La formule lit une racine inconnue
« <référence> n'existe pas : record, before, after, related, actor sont des racines de premier niveau. Écrivez <champ> sans préfixe. »Une racine a été imbriquée dans une autre
« Le champ <champ> n'existe pas sur <entité>, ou n'est pas accessible aux automatisations. »Faute de frappe sur un nom de champ
« Fonction <nom> inconnue dans la formule. Fonctions autorisées : has, size, add, sub, mul, div, round. »Une fonction hors de la liste autorisée est appelée

Erreurs à l'exécution

SituationConséquence
Une opérande n'est pas un nombre : champ vide, texte non numériqueL'action passe en erreur. Aucune valeur n'est écrite
Une division par zéroL'action passe en erreur
Une formule référence related alors qu'aucune donnée liée n'a pu être chargéeL'action passe en erreur
Une date n'est pas une date valide, un fuseau n'est pas un fuseau reconnu (par exemple europe/paris)L'action passe en erreur. Une date vide donne un texte vide

Une formule ne fabrique jamais de valeur par défaut : plutôt qu'écrire zéro ou une valeur approchée, elle fait échouer l'action, visible dans l'onglet « Exécutions ».

Limite d'écriture

Une formule ne peut pas contenir la séquence }} autrement que pour se fermer. Si votre calcul en a besoin, placez la formule seule dans la valeur plutôt que de l'insérer dans une phrase.

Questions fréquentes

Puis-je utiliser une formule dans une condition ?

Non. Le marqueur {{= }} n'est reconnu que dans les paramètres d'une action, et les fonctions de date n'y existent pas. Une condition s'écrit directement en expression, sans marqueur, et les fonctions de calcul n'y sont pas disponibles. Voir Restreindre une règle par une condition.

Pourquoi ne pas écrire simplement record.credits - record.totalTtc ?

Parce que la soustraction native est un calcul à virgule flottante : sur des montants, elle produit des résultats faux au centime près. sub fait le calcul exact.

Puis-je additionner les montants de plusieurs fiches liées ?

Oui, si elles sont liées par un champ de relation de la fiche déclencheuse : {{= sum(related.<champ>.map(f, f.<montant>)) }}. Les fiches hors de votre périmètre d'accès sont exclues du total.

Une formule peut-elle rendre autre chose qu'un nombre ?

Oui. Seule dans la valeur, elle rend son résultat avec son type : nombre, texte ou oui/non. Insérée dans une phrase, elle rend toujours du texte.

Sur cette page