Une formule est un champ qui permet d'afficher une valeur définie par une fonction javascript personnalisée.
Les différents points seront abordés au cours de cet article :
Règle de calcul
Il est possible de choisir l'une des trois règles de calcul suivante :
Manuel: les utilisateurs doivent cliquer sur un bouton afin que la formule se calcule.
Automatique : la formule se calcule automatiquement à chaque fois que c'est pertinent (quand un champ utilisé est modifié, quand la fiche est enregistrée...)
Une seule fois : cette nouvelle méthode se comporte comme le mode automatique mais une fois que le résultat est calculé il ne change plus (même si un champ lié est modifié)
Types de donnée
Pour paramétrer une formule, vous devez d'abord spécifier le type de donnée qu'elle va retourner.Voici les types disponibles :
Texte
Nombre
Booléen
Durée
Date
Liste
Pour chacun de ces types de données vous avez une ou deux options pour l'affichage de la donnée.
Écriture de la formule
La formule doit s'écrire en javascript. Elle doit inclure un « return » pour renvoyer l’information souhaitée.
Quelques cas à prendre en compte :
Type Date :
Renvoie un Unix timestamp (le nombre de secondes entre la date souhaitée et le 1er janvier 1970 minuit UTC)
Exemple, pour le 26 mars 2020 10h (UTC) :
return 1585216800;
Par défaut, les dates sont traitées avec la timezone système de votre appareil. Il est possible de contourner cela et d'imposer l'heure UTC. Exemple :
var date = new Date();return (date.getTime() + date.getTimezoneOffset()*60*1000)/1000;
Type Durée :
Renvoie un entier avec le nombre de secondes
Exemple pour 58 min 26 sec :
return (58 * 60) + 26;
Type Liste :
Renvoie un tableau d'objets liste complets. Pour le formatage il est fortement recommandé de passer par la fonction searchList détaillée juste après.
Il ne faut pas utiliser de caractère spéciaux dans l'external id d'un élément de liste (exemple : l'underscore "_")
Exemple :
return services.searchList({ type: "id", value : 427459});
Accéder aux listes (searchlist)
En appelant services.searchList(); vous pouvez accéder directement aux éléments d'une liste liée à votre formule.
Elle prend un objet en paramètre qui peut avoir 3 valeurs :
type (obligatoire) : vous avez le choix du mode de recherche parmi "name", "external_id" ou "id"
value (obligatoire) : à vous de renseigner le nom cherché (ou l'id ou l'external_id en fonction du type) ; attention, dans le cas de l'external_id, la valeur doit être de type String ;
parent (facultatif) : vous pouvez renseigner l'id du noeud dans votre liste arborescente auquel vous souhaitez restreindre la recherche.
La fonction searchList renvoie un tableau d'objets liste complets :
[ {
"id": 123,
"external_id": null,
"caption": "Nom de l'élément de liste",
"color":null,
"imageId": "504d4a60-0db2-4bed-b234-a6d75e9950f4"
},{
"id": 124,
"external_id": "456,
"caption": "Autre nom de l'élément de liste",
"color": null, "imageId": null
}]
Récupération d'une valeur dans un champ simple
On utilise la même manière de récupérer les informations de la fiche courante pour la plupart des éléments d’un formulaire :
Texte
Nombre
Booléen
Date
Durée
Email
Téléphone
Formule d'un type mentionné dans cette liste
On utilise pour cela le nom système du champ concerné.
items['nom_systeme']
Par exemple, si on veut calculer un prix TTC en se basant sur un prix HT :
return items['prix_ht'] * ( 1 + 20/100);
NB : si le champ n'est pas encore renseigné, il n'est pas forcément présent dans l'objet items. Il peut donc être intéressant d'inclure une vérification pour afficher une information cohérente :
if(items['prix_ht']){
return items['prix_ht'] * ( 1 + 20/100);} else {
return 0; }
Récupération des données système de la fiche
Il est possible d'accéder aux données système de la fiche en utilisant l'objet javascript metadata :
number permet de récupérer un nombre unique permettant d'identifier la fiche
uuid est également un identifiant permettant de retrouver la fiche
number_in_structure permet de connaitre le numéro de la fiche dans son formulaire
created_at permet d'avoir la date de création de fiche (Unix timestamp)
user permet d'avoir des informations sur l'utilisateur ayant créé la fiche. Il s'agit d'un objet avec les informations email, prénom et nom de famille.
Voici la structure de l'objet :
{
"number": 63930,
"number_in_structure" : 12,
"uuid": "38c6d76e-5442-4cbd-baef-cb9e5d6c4daa",
"created_at": 1550242752,
"user": {
"email": "toto@gmail.com",
"last_name": "Toto",
"first_name": "Toto"
}}
Voici un exemple :
return metadata['number'];
NB : number, number_in_structure et created_at ne sont disponibles qu'après le premier enregistrement de la fiche sur le web.
Récupération des données d'un champ localisation
Un champ localisation est composé d'une adresse textuelle (ex : 21A boulevard Guist'hau, 44 000 Nantes, France) et de cordonnées géographiques (ex : lat 47.2165879, long -1.566951)
Pour récupérer ces informations, il faut donc préciser la donnée souhaitée. Voici un exemple pour un champ localisation dont le nom système est "adresse" (formule de type texte) :
var result = "";if(items['adresse']){
if(items['adresse'].address){
result = "Adresse : "+ items['adresse'].address ;
}
if(items['adresse'].lat && items['adresse'].lng){
result = result + "\nlat: " + items['adresse'].lat;
result = result + ", long: " +items['adresse'].lng;
}}
return result;
Résultat :
Adresse : 21A boulevard Guist'hau, 44 000 Nantes, France
lat: 47.2165879, long: -1.566951
Attention, les formules localisation ne sont pas compatibles avec l'application Android V1.
Récupération des données d’un champ liste
Une liste peut avoir plusieurs éléments sélectionnés. Nous avons donc mis en place une méthode plus complète pour accéder à ces informations.
Utilisons un exemple avec des animaux :
Animal
Félin
Chat (external_id : cat)
Tigre
Oiseau
Mouette
Pigeon
Parmi ces choix, on va imaginer que "Chat" et "Mouette" sont sélectionnés.
items[‘liste_animal’] sera alors un tableau d’objets :
Pour obtenir le nom du premier élément sélectionné :
items['liste_animal'][0].caption
Réponse : Chat
Pour obtenir l’identifiant externe du premier élément sélectionné :
items['liste_animal'][0].external_id
Réponse : cat
Pour obtenir le parent le plus proche de la souche :
items['liste_animal'][0].parents[0].caption
Réponse : Animal
Pour obtenir le parent direct :
items['liste_animal'][0].parents[ items['liste_animal'][0].parents.length – 1 ].caption
Réponse : Félin
Exemple complet pour liste l’ensemble des choix sélectionnes :
if(items['liste_animal']){
return items['liste_animal'].reduce(function(result,element){
return result + " - " + element.caption + ".";
},"");} else {
return "Aucun élément sélectionné dans la liste.";}
Réponse : " - Chat. - Mouette."
Récupération des données d’une relation
Il est également possible de chercher des informations dans les fiches qui sont en relations avec la fiche courante.
Pour cela, on peut chercher ces fiches en relation à l’aide de l’objet javascript relations.
Fiches enfants
Si la relation est définie dans la fiche courante avec le nom système ‘nom_systeme’, on peut accéder aux fiches avec :
relations.children.nom_systeme.submissions
Du coup pour récupérer le champ ‘titre’ de la première fiche en relation :
relations.children.nom_systeme.submissions[0].items['titre'];
Fiches parentes
Si la relation est définie dans un formulaire parent, la syntaxe est similaire, mais en utilisant ‘parents’ à la place de ‘children’ :
relations.parents.nom_systeme.submissions[0].items['titre'];
Donc pour lister l’ensemble des titres des fiches qui ont établi une relation vers la fiche courante avec la relation ‘nom_relation’ (il faut donc que ces fiches aient un champ dont le nom système soit titre) :
if(relations.parents.nom_relation &&relations.parents.nom_relation.submissions){ return relations.parents.nom_relation.submissions.reduce(function(result,element){
return result + " - " + element.items['titre'] + ".";
},"");} else {
return "Aucune fiche parente trouvée";}
Relations quantifiables
Certaines relations comme les relations quantifiables possèdent des attributs qu'il peut être utile d'utiliser dans des formules.
Pour accéder aux attributs d'une relation, il faut utiliser l'attribut relationProperties à la place de itemsdans la fiche en relation. Du coup, si la relation a pour nom système produits et que l'on cherche la quantité associée (paramètre "count"), cela donne :
relations.children.produits.submissions.relationProperties.count
Cas pratique : La fiche parente est une commande avec les produits entrés au sein d'une relation quantifiable (nom système : "produit"). Le prix de chaque produit apparait dans le champ "prix" des produits. Si je cherche à obtenir le prix total de ma commande, je peux faire :
var prix = 0;
if(relations && relations.children && relations.children.produits && relations.children.produits.submissions && relations.children.produits.submissions.length > 0){ relations.children.produits.submissions.forEach(function(prod){
var quant = 1;
if(prod.relationProperties.count && prod.relationProperties.count){ quant = prod.relationProperties.count
}
if (prod.items && prod.items['prix']){
prix += prod.items['prix'] * quant;
} });}
return prix;
Récupération des données d'un champ utilisateur
Comme pour les listes, un champ utilisateur peut avoir plusieurs éléments sélectionnés. Nous avons donc mis en place une méthode similaire pour accéder à ces informations.
return items['user_field_system_name'][0]['propriété_utilisateur'];
Exemple, pour récupérer l'adresse mail de l'utilisateur
return items['user_field_system_name'][0]['email'];
Renvoie un tableau d'utilisateurs.
Ensuite, voici les différentes propriétés d'un utilisateur :
email
first_name
last_name
Donc pour afficher les noms et prénoms d'un utilisateur dans un champ utilisateur non multiple, cela donne :
if(items['user_field_system_name'] &&items['user_field_system_name'].length > 0){ return items['user_field_system_name'][0].first_name + ' ' +items['user_field_system_name'][0].last_name;} else {
return "Pas d'utilisateur sélectionné";}
Remarque de syntaxe
Lorsqu'une formule est mise en place dans un formulaire, Daxium-Air vient lire la formule pour en déduire les champs qui sont nécessaires au calcul de cette dernière. Pour cela, nous parsons le javascript à la recherche de items['nom_systeme']. Il est donc important de bien laisser cette syntaxe dans l'écriture de vos formules.
Voici deux exemples qui ne fonctionnent pas :
Exemple 1
return items.number * 2 ;
On pourrait s'imaginer que les valeurs des champs de la fiche sont directement incluses dans l'objet items et que donc la syntaxe items['number'] est identique à items.number. Or dans certains cas, l'objet items est créé dynamiquement pour la formule en question.
Exemple 2
var total = 0 ;for(var i=1 ; i<10; i++){
if(items['number'+i]){
total += items['number'+i]; }}
return total;
A partir du moment où les champs sont bien formatés, on a envie de se faciliter la vie avec des formules qui viennent chercher les champs dynamiquement. Mais pour les raisons évoquées plus haut, cette formule ne fonctionnera pas correctement dans la plupart des cas.