> For the complete documentation index, see [llms.txt](https://documentation.efalia.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.efalia.com/documentations/efalia-process/administration/administration-fonctionnelle/langages-process.md).

# Langages Process

Efalia Process met à disposition deux langages complémentaires pour enrichir le comportement des processus et des formulaires :

* **STalk** — langage d'expression côté serveur, utilisé dans le Designer pour calculer des valeurs, définir des règles d'opérations automatiques, des sujets de documents ou des colonnes de vues.
* **WKYJS** — bibliothèque JavaScript côté client, utilisée dans les formulaires pour manipuler les champs, réagir aux événements utilisateur et personnaliser l'interface.

***

## STalk

### Principe

STalk est un langage d'expression typé, évalué **côté serveur** par Efalia Process. Il opère toujours dans le contexte d'un **document de référence** (source implicite), dont il peut lire les champs et les métadonnées.

STalk ne permet pas de déclarer des structures répétitives (`while`, `for`) : il est conçu pour des **expressions de calcul**, pas pour un script généraliste.

### Contextes d'utilisation

| Contexte                          | Où le configurer                        | Description                                         |
| --------------------------------- | --------------------------------------- | --------------------------------------------------- |
| **Valeur initiale d'un champ**    | Propriétés du champ, onglet Calcul      | Valeur affectée à la création du document           |
| **Valeur calculée d'un champ**    | Propriétés du champ, onglet Calcul      | Recalculée à chaque ouverture du document           |
| **Sujet du document**             | Propriétés du document                  | Titre affiché dans les vues et notifications        |
| **Règle d'opération automatique** | Propriétés de l'opération               | Condition déclenchant automatiquement une opération |
| **Colonne de vue**                | Propriétés de la colonne (codage STalk) | Valeur affichée dans chaque cellule d'une vue       |
| **Règle de dictionnaire**         | Propriétés du domaine de valeur         | Filtre dynamique des valeurs proposées              |

***

### Types

STalk est un langage **fortement typé**. Les types sont déduits automatiquement à partir de la déclaration des champs dans le Designer.

| Type STalk  | Équivalent   | Description                                 |
| ----------- | ------------ | ------------------------------------------- |
| `WKString`  | Texte        | Chaîne de caractères                        |
| `WKInteger` | Entier court | Entier 32 bits                              |
| `WKLong`    | Entier long  | Entier 64 bits                              |
| `WKFloat`   | Décimal      | Nombre à virgule flottante simple précision |
| `WKDouble`  | Décimal long | Nombre à virgule flottante double précision |
| `WKDate`    | Date/heure   | Date et heure avec fuseau horaire           |
| `WKBoolean` | Booléen      | `true` ou `false`                           |

Un champ peut être **mono-valué** (valeur unique) ou **multi-valué** (conteneur de plusieurs valeurs, noté `WKString[]`, `WKLong[]`, etc.).

***

### Opérateurs

#### Arithmétiques

| Opérateur | Signification            | Exemple                   |
| --------- | ------------------------ | ------------------------- |
| `+`       | Addition / concaténation | `Montant_HT + TVA`        |
| `-`       | Soustraction             | `Prix - Remise`           |
| `*`       | Multiplication           | `Quantite * PrixUnitaire` |
| `/`       | Division                 | `Total / Nombre`          |

#### Relationnels

| Opérateur   | Signification      |
| ----------- | ------------------ |
| `>`         | Plus grand que     |
| `<`         | Plus petit que     |
| `=` ou `==` | Égal               |
| `!=`        | Différent          |
| `>=`        | Plus grand ou égal |
| `<=`        | Plus petit ou égal |

Le résultat d'une expression relationnelle est toujours de type `WKBoolean`.

#### Logiques

| Opérateur      | Signification | Exemple                                    |
| -------------- | ------------- | ------------------------------------------ |
| `and` ou `&&`  | Et logique    | `(Montant > 1000) and (Statut = "valide")` |
| `or` ou `\|\|` | Ou logique    | `(Pays = "FR") or (Pays = "BE")`           |
| `!`            | Négation      | `!(Statut = "annule")`                     |

#### Ensemblistes (champs multi-valués)

| Opérateur | Signification           | Exemple                 |
| --------- | ----------------------- | ----------------------- |
| `union`   | Union de deux ensembles | `Liste1 union Liste2`   |
| `inter`   | Intersection            | `Tags inter TagsCibles` |
| `minus`   | Différence              | `Tous minus Exclus`     |
| `in`      | Appartenance            | `"urgent" in Tags`      |

***

### Conditionnelle if/else

```
if ( condition ) valeur_si_vrai else valeur_si_faux
```

Les conditionnelles peuvent être imbriquées :

```
if ( Priorite = "haute" ) "red.png"
else if ( Priorite = "normale" ) "orange.png"
else "green.png"
```

***

### Fonctions principales

#### Fonctions de document

| Fonction                      | Retour        | Description                               |
| ----------------------------- | ------------- | ----------------------------------------- |
| `createTime()`                | `WKDate`      | Date de création du document courant      |
| `documentType()`              | `WKString`    | Nom interne du type de document           |
| `documentTypeName()`          | `WKString`    | Nom localisé du type de document          |
| `authorId()`                  | `WKString`    | Identifiant de l'auteur du document       |
| `fatherId()`                  | `WKLong`      | Identifiant du document père              |
| `now()`                       | `WKDate`      | Date et heure courantes                   |
| `state()`                     | `WKString`    | Nom interne de l'état courant du document |
| `documentState(ids)`          | `WKString`    | État courant d'un ou plusieurs documents  |
| `countChildren()`             | `WKInteger`   | Nombre de documents fils                  |
| `countTypedChildren(doctype)` | `WKInteger`   | Nombre de fils d'un type donné            |
| `childrenIds(type)`           | `WKInteger[]` | Identifiants des documents fils d'un type |

#### Fonctions d'acteur

| Fonction             | Retour       | Description                                             |
| -------------------- | ------------ | ------------------------------------------------------- |
| `activeWriters()`    | `WKLong[]`   | Acteurs pouvant écrire sur le document courant          |
| `actorsHistory()`    | `WKString[]` | Acteurs ayant interagi avec le document (sans doublons) |
| `actorsRoles(roles)` | `WKLong[]`   | Acteurs appartenant aux rôles spécifiés                 |
| `actorsUnits(units)` | `WKString[]` | Acteurs appartenant aux unités spécifiées               |
| `actorUnits(actor)`  | `WKString[]` | Unités auxquelles appartient un acteur                  |

#### Fonctions de texte

| Fonction           | Retour      | Description                                       |
| ------------------ | ----------- | ------------------------------------------------- |
| `concat(m, s)`     | `WKString`  | Concatène un champ multi-valué avec un séparateur |
| `count(exp)`       | `WKInteger` | Nombre de valeurs d'une expression                |
| `element(name, i)` | `WKObject`  | Nième élément d'un champ multi-valué              |

#### Fonctions de date

| Fonction                | Retour   | Description                                                   |
| ----------------------- | -------- | ------------------------------------------------------------- |
| `addDay(d, i)`          | `WKDate` | Ajoute `i` jours à une date                                   |
| `addHour(d, i)`         | `WKDate` | Ajoute `i` heures à une date                                  |
| `addMinute(d, i)`       | `WKDate` | Ajoute `i` minutes à une date                                 |
| `addMonth(d, i)`        | `WKDate` | Ajoute `i` mois à une date                                    |
| `addYear(d, i)`         | `WKDate` | Ajoute `i` années à une date                                  |
| `addWeekDay(d, i)`      | `WKDate` | Ajoute `i` jours de semaine à une date                        |
| `addBusinessDay(d, i)`  | `WKDate` | Ajoute `i` jours ouvrables (lun–ven, hors jours fériés fixes) |
| `addBusinessHour(d, i)` | `WKDate` | Ajoute `i` heures ouvrables (8h–18h)                          |

#### Fonctions de formatage

| Fonction                       | Retour     | Description                                                |
| ------------------------------ | ---------- | ---------------------------------------------------------- |
| `text(val, format)`            | `WKString` | Formate une valeur selon un format donné (dates, acteurs…) |
| `timeFormat(duration, format)` | `WKString` | Formate une durée selon un pattern                         |

**Formats courants pour `text()` :**

```
text(Date_echeance, "dd/MM/yyyy")           → "25/12/2025"
text(Date_echeance, "dd/MM/yyyy HH:mm")     → "25/12/2025 14:30"
text(authorId(), "shortLdapName")           → "j.dupont"
text(authorId(), "fullLdapName")            → "Jean Dupont"
```

**Format pour `timeFormat()` :**

```
timeFormat(now() - createTime(), "d' jours 'H' heures'")
→ "3 jours 2 heures"
```

#### Fonctions d'agrégation (champs multi-valués)

| Fonction         | Retour    | Description         |
| ---------------- | --------- | ------------------- |
| `sum(champ)`     | numérique | Somme des valeurs   |
| `product(champ)` | numérique | Produit des valeurs |
| `minima(champ)`  | numérique | Valeur minimale     |
| `maxima(champ)`  | numérique | Valeur maximale     |

#### Débogage

| Fonction         | Description                                                        |
| ---------------- | ------------------------------------------------------------------ |
| `debugText(str)` | Écrit un message dans les journaux serveur (diagnostic uniquement) |

***

### Exemples pratiques STalk

**Sujet de document dynamique :**

```
"Contrat #" + Reference + " – " + text(authorId(), "fullLdapName")
```

**Valeur calculée avec TVA :**

```
Montant_HT * 1.20
```

**Délai d'échéance automatique (15 jours ouvrables) :**

```
addBusinessDay(createTime(), 15)
```

**Règle d'opération automatique (passage si montant validé) :**

```
(Montant > 0) and (Statut_validation = "ok")
```

**Durée depuis la création (pour colonne de vue) :**

```
timeFormat(now() - createTime(), "d' jours'")
```

**Icône de statut colorée (pour colonne de vue) :**

```
if ( Priorite = "haute" ) "red.png"
else if ( Priorite = "normale" ) "orange.png"
else "green.png"
```

**Concaténation de valeurs multiples :**

```
concat(Tags, ", ")
```

{% hint style="warning" %}
⚠️ **Sensibilité à la casse**

Les noms de champs dans STalk respectent strictement les majuscules et minuscules tels que définis dans le Designer (`Montant_HT` ≠ `montant_ht`).
{% endhint %}

***

## WKYJS

### Principe

**WKYJS** est une bibliothèque JavaScript fournie par Efalia Process, disponible automatiquement dans tous les formulaires. Elle permet d'interagir avec le formulaire côté client : lire/écrire des valeurs, réagir aux actions utilisateur, afficher ou masquer des champs, naviguer entre états.

### Insérer du JavaScript dans un formulaire

Pour utiliser WKYJS, ajoutez un composant **Script JS** dans votre formulaire depuis le panneau du Designer HTML. Ce champ n'est pas visible par l'utilisateur final ; il contient uniquement le code JavaScript à exécuter.

📸 **CAPTURE : admin-fonct-langages-01-script-js.png**

> Panneau Designer avec un composant Script JS dans le formulaire, son nom interne et son contenu JavaScript

{% hint style="info" %}
💡 Il peut y avoir **plusieurs champs Script JS** dans un même formulaire. Ils sont exécutés dans l'ordre d'apparition.
{% endhint %}

***

### Méthodes d'action

Ces méthodes déclenchent une action sur le document.

| Méthode                                                   | Description                                                |
| --------------------------------------------------------- | ---------------------------------------------------------- |
| `WKYJS.submitDoc()`                                       | Soumet le document vers le prochain état sélectionné       |
| `WKYJS.saveDoc()`                                         | Sauvegarde le document sans le soumettre                   |
| `WKYJS.cancel()`                                          | Annule les modifications et ferme le formulaire            |
| `WKYJS.refreshDoc()`                                      | Rafraîchit le formulaire (recalcule les valeurs calculées) |
| `WKYJS.takeInCharge()`                                    | Prend en charge le document                                |
| `WKYJS.releaseTakeInCharge()`                             | Libère la prise en charge                                  |
| `WKYJS.deleteDraft()`                                     | Supprime le brouillon courant                              |
| `WKYJS.selectStateByOperationNameAndStateName(op, state)` | Sélectionne un état cible avant soumission                 |
| `WKYJS.reopenDocAfterCreation()`                          | Rouvre le document immédiatement après sa création         |

***

### Écouteurs d'événements

Utilisez ces écouteurs dans un bloc `WKYJS.onLoad()` ou directement dans le champ Script JS.

| Méthode                           | Déclenchement                                 |
| --------------------------------- | --------------------------------------------- |
| `WKYJS.onLoad(fn)`                | Au chargement du formulaire                   |
| `WKYJS.onSubmit(fn)`              | Avant la soumission du document               |
| `WKYJS.onSave(fn)`                | Avant la sauvegarde du document               |
| `WKYJS.onCancel(fn)`              | Avant l'annulation                            |
| `WKYJS.onRefresh(fn)`             | Avant le rafraîchissement                     |
| `WKYJS.onChangeState(fn)`         | Quand l'utilisateur change l'état sélectionné |
| `WKYJS.onTakeInCharge(fn)`        | Avant la prise en charge                      |
| `WKYJS.onReleaseTakeInCharge(fn)` | Avant la libération de prise en charge        |
| `WKYJS.onDeleteDraft(fn)`         | Avant la suppression du brouillon             |

**Exemple :**

```javascript
WKYJS.onLoad(function() {
    // Code exécuté au chargement du formulaire
    if (WKYJS.getFieldValue("Statut") === "urgent") {
        WKYJS.showField("Motif_urgence");
    }
});

WKYJS.onSubmit(function() {
    // Validation avant soumission
    if (!WKYJS.getFieldValue("Email")) {
        WKYJS.errorBox("L'adresse email est obligatoire.");
        return false; // Annule la soumission
    }
});
```

***

### Méthodes de contexte

Ces méthodes lisent les métadonnées du document affiché.

| Méthode                           | Retour     | Description                             |
| --------------------------------- | ---------- | --------------------------------------- |
| `WKYJS.getWorkeyDocumentId()`     | `string`   | Identifiant du document                 |
| `WKYJS.getWorkeyDocumentType()`   | `string`   | Nom interne du type de document         |
| `WKYJS.getWorkeyDocumentState()`  | `string`   | Nom interne de l'état courant           |
| `WKYJS.getWorkeyProcessType()`    | `string`   | Nom interne du processus                |
| `WKYJS.getWorkeyProcessVersion()` | `string`   | Version du processus                    |
| `WKYJS.getWorkeyForm()`           | `string`   | Nom interne du formulaire               |
| `WKYJS.getWorkeyRole()`           | `string`   | Nom interne du rôle de l'utilisateur    |
| `WKYJS.getWorkeyNextStates()`     | `string[]` | Tableau des prochains états disponibles |
| `WKYJS.getWorkeySelectedState()`  | `string`   | Prochain état actuellement sélectionné  |
| `WKYJS.getWorkeyUserLanguage()`   | `string`   | Langue d'affichage                      |

***

### Méthodes d'interface du formulaire

#### Barre de boutons personnalisée

`WKYJS.addButtonBar(options)` remplace la barre d'actions standard par une barre de boutons entièrement personnalisée.

```javascript
WKYJS.onLoad(function() {
    WKYJS.hideStates();
    WKYJS.addButtonBar({
        "buttons": [
            {
                "label": "Approuver",
                "type": "success",
                "action": function() {
                    WKYJS.selectStateByOperationNameAndStateName("valider", "approuve");
                    WKYJS.submitDoc();
                }
            },
            {
                "label": "Rejeter",
                "type": "danger",
                "bgColor": "#8B0000",
                "txtColor": "#FFFFFF",
                "action": function() {
                    WKYJS.selectStateByOperationNameAndStateName("rejeter", "rejete");
                    WKYJS.submitDoc();
                }
            }
        ],
        "cancelable": true,
        "savable": false
    });
});
```

**Propriétés d'un bouton :**

| Propriété  | Description                                                                                  |
| ---------- | -------------------------------------------------------------------------------------------- |
| `label`    | Texte affiché sur le bouton                                                                  |
| `type`     | Style prédéfini : `"success"`, `"danger"`, `"primary"`, `"secondary"`, `"info"`, `"warning"` |
| `bgColor`  | Couleur de fond personnalisée (surcharge `type`)                                             |
| `txtColor` | Couleur du texte personnalisée                                                               |
| `action`   | Fonction JavaScript exécutée au clic                                                         |

**Options de la barre :**

| Option            | Par défaut | Description                              |
| ----------------- | ---------- | ---------------------------------------- |
| `cancelable`      | `true`     | Affiche le bouton Annuler                |
| `savable`         | `true`     | Affiche le bouton Sauvegarder            |
| `takeInChargable` | `false`    | Affiche le bouton Prendre en charge      |
| `releasable`      | `false`    | Affiche le bouton Libérer                |
| `discardable`     | `false`    | Affiche le bouton Supprimer le brouillon |

#### Contrôle de visibilité des boutons natifs

| Méthode                              | Description                                       |
| ------------------------------------ | ------------------------------------------------- |
| `WKYJS.hideStates()`                 | Masque la section "Prochain état"                 |
| `WKYJS.showStates()`                 | Affiche la section "Prochain état"                |
| `WKYJS.hideSaveButton()`             | Masque le bouton Sauvegarder                      |
| `WKYJS.hideCancelButton()`           | Masque le bouton Annuler                          |
| `WKYJS.showButtonInButtonBar(index)` | Affiche le bouton à la position `index` (0-based) |
| `WKYJS.hideButtonInButtonBar(index)` | Masque le bouton à la position `index` (0-based)  |

#### Bouton de soumission simple

```javascript
WKYJS.addSubmitButton({
    "vertical": true,
    "horizontal": false,
    "text": "Envoyer",
    "cancelable": true,
    "savable": false
});
```

***

### Méthodes de section

| Méthode                       | Description                                                          |
| ----------------------------- | -------------------------------------------------------------------- |
| `WKYJS.showSection(name)`     | Affiche une section                                                  |
| `WKYJS.hideSection(name)`     | Masque une section                                                   |
| `WKYJS.collapseSection(name)` | Replie une section                                                   |
| `WKYJS.expandSection(name)`   | Déplie une section                                                   |
| `WKYJS.enabled(name, bool)`   | Active (`true`) ou désactive (`false`) tous les champs d'une section |

***

### Méthodes de champ

#### Lecture et écriture

| Méthode                            | Description                                                        |
| ---------------------------------- | ------------------------------------------------------------------ |
| `WKYJS.getFieldValue(name)`        | Retourne la valeur du champ (tableau pour les champs multi-valués) |
| `WKYJS.setFieldValue(name, value)` | Affecte une valeur au champ                                        |

```javascript
// Champ simple
WKYJS.setFieldValue("Nom", "Jean-Pierre");

// Champ multi-valué (liste de choix)
WKYJS.setFieldValue("Villes", ["Paris", "Lyon"]);
WKYJS.setFieldValue("Villes", []); // Vide la liste
```

#### Visibilité et état

| Méthode                            | Description                                                          |
| ---------------------------------- | -------------------------------------------------------------------- |
| `WKYJS.showField(name)`            | Affiche un champ                                                     |
| `WKYJS.hideField(name)`            | Masque un champ                                                      |
| `WKYJS.error(name, bool)`          | Applique (`true`) ou retire (`false`) le style d'erreur sur un champ |
| `WKYJS.setPlaceholder(name, text)` | Définit le texte placeholder d'un champ de saisie                    |

#### Réactivité aux changements

| Méthode                                            | Description                                                                     |
| -------------------------------------------------- | ------------------------------------------------------------------------------- |
| `WKYJS.onChange(name, fn)`                         | Exécute `fn` quand la valeur du champ change                                    |
| `WKYJS.refreshOnChange(name, [targets], scrollTo)` | Rafraîchit le document quand le champ change (utile pour les listes en cascade) |
| `WKYJS.showOrHideElements(name, values, targets)`  | Affiche les cibles si la valeur est dans `values`, les masque sinon             |
| `WKYJS.hideOrShowElements(name, values, targets)`  | Masque les cibles si la valeur est dans `values`, les affiche sinon             |

**Exemple de liste en cascade :**

```javascript
WKYJS.refreshOnChange("Choix_marque");
```

**Exemple d'affichage conditionnel :**

```javascript
// Si abonnement expert ou premium → afficher la section détails
WKYJS.showOrHideElements(
    "Type_abonnement",
    ["expert", "premium"],
    ["section_details_premium"]
);
```

***

### Requêtes SQL depuis un formulaire

`WKYJS.sqlRequest()` permet d'interroger une source de données définie dans l'administration (section *Requêtes SQL*).

```javascript
WKYJS.sqlRequest({
    "sqlName": "rechercheClient",
    "parameters": [WKYJS.getFieldValue("Code_client")],
    "parametersType": ["VARCHAR"],
    "done": function(data) {
        // data est un tableau d'objets JSON
        if (data.length > 0) {
            WKYJS.setFieldValue("Nom_client", data[0].Nom);
            WKYJS.setFieldValue("Ville", data[0].Ville);
        }
    }
});
```

| Attribut         | Obligatoire | Description                                                                    |
| ---------------- | ----------- | ------------------------------------------------------------------------------ |
| `sqlName`        | ✅           | Nom de la requête définie dans l'administration                                |
| `parameters`     | ❌           | Tableau des valeurs des paramètres (`?` dans la requête SQL)                   |
| `parametersType` | ❌           | Types SQL des paramètres (ex : `"VARCHAR"`, `"BIGINT"`) — `VARCHAR` par défaut |
| `done`           | ✅           | Callback recevant `data` : tableau d'objets JSON (colonnes = attributs)        |

***

### Méthodes de messages et validation

#### Afficher des messages

| Méthode                      | Description                               |
| ---------------------------- | ----------------------------------------- |
| `WKYJS.msg(text)`            | Affiche un message éphémère à l'écran     |
| `WKYJS.informationBox(text)` | Affiche une boîte de dialogue informative |
| `WKYJS.errorBox(text)`       | Affiche une boîte de dialogue d'erreur    |

#### Valider des valeurs

| Méthode                                | Retour    | Description                                               |
| -------------------------------------- | --------- | --------------------------------------------------------- |
| `WKYJS.isEmailValid(value)`            | `boolean` | Valide une adresse email                                  |
| `WKYJS.isPhoneNumberValid(value)`      | `boolean` | Valide un numéro de téléphone                             |
| `WKYJS.isFieldValueValid(name, regex)` | `boolean` | Valide la valeur d'un champ avec une expression régulière |

```javascript
WKYJS.onSubmit(function() {
    if (!WKYJS.isEmailValid(WKYJS.getFieldValue("Email_contact"))) {
        WKYJS.error("Email_contact", true);
        WKYJS.errorBox("Veuillez saisir une adresse email valide.");
        return false;
    }
    WKYJS.error("Email_contact", false);
});
```

***

### Fil de Discussion (Chat) dans les Formulaires

Efalia Process propose un composant **fil de discussion** intégrable dans les formulaires, permettant aux utilisateurs d'échanger des messages contextuels directement dans le document.

#### Activer le chat dans un formulaire

{% stepper %}
{% step %}

#### Ajouter le composant dans le Designer

Dans le panneau gauche du Designer HTML, ajoutez un composant **Script JS** au formulaire et collez le code d'initialisation du fil de discussion.
{% endstep %}

{% step %}

#### Configurer le fil de discussion

Le fil de discussion est initialisé via WKYJS avec les paramètres de rôles et de contexte :

```javascript
WKYJS.onLoad(function() {
    // Initialisation du fil de discussion
    WKYJS.showDiscussionThread({
        "container": "discussion_container",
        "roles": ["role_validateur", "role_demandeur"]
    });
});
```

{% endstep %}

{% step %}

#### Vérifier l'affichage

Une fois le formulaire déployé, les utilisateurs ayant les rôles configurés verront le fil de discussion dans le formulaire. Les messages sont persistés avec le document.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
💡 Le fil de discussion est lié au document : chaque message est horodaté, nominatif, et consultable dans l'historique du document. Il ne constitue pas une messagerie instantanée générale mais un espace de commentaires contextuels sur le dossier en cours.
{% endhint %}

***

## Bonnes Pratiques

{% hint style="success" %}
**✅ À faire :**

* Utiliser **STalk** pour toute logique serveur (calculs, règles, sujets) — plus performant que JavaScript pour ces usages
* Centraliser le code WKYJS dans **un seul champ Script JS** par formulaire pour faciliter la maintenance
* Utiliser `WKYJS.onLoad()` pour initialiser les comportements au chargement
* Retourner `false` dans `WKYJS.onSubmit()` pour bloquer la soumission en cas d'erreur de validation
* Utiliser `WKYJS.refreshOnChange()` pour les listes en cascade plutôt qu'un `onChange` manuel
* Tester les expressions STalk dans le Designer via la vérification de cohérence
  {% endhint %}

{% hint style="danger" %}
**❌ À éviter :**

* Expressions STalk complexes dans les colonnes de vues (exécutées pour chaque ligne — impact performances)
* Appels `sqlRequest` dans une boucle dans WKYJS (risque de surcharge serveur)
* Modifier la base de données Efalia Process directement depuis un script externe
* Utiliser des noms de champs sensibles à la casse de manière inconsistante dans STalk
* Code JavaScript trop volumineux dans un formulaire (temps de chargement, maintenabilité)
  {% endhint %}

***

## Questions Fréquentes

<details>

<summary>Quelle est la différence entre valeur initiale et valeur calculée dans STalk ?</summary>

* **Valeur initiale** : évaluée **une seule fois** à la **création** du document. Elle peut ensuite être modifiée par l'utilisateur.
* **Valeur calculée** : réévaluée à **chaque ouverture** du document. L'utilisateur ne peut pas la modifier directement car elle est recalculée automatiquement.

Utilisez la valeur initiale pour pré-remplir un champ modifiable (ex : date du jour à la création). Utilisez la valeur calculée pour un champ dont la valeur doit toujours refléter une expression (ex : total HT × TVA).

</details>

<details>

<summary>Peut-on utiliser STalk dans une règle de filtrage de domaine de valeurs ?</summary>

Oui. Les **règles de dictionnaire** (ou règles de filtre sur un domaine de valeurs) acceptent une expression STalk. Cette expression est évaluée pour chaque valeur du domaine et retourne `true` si la valeur doit être proposée à l'utilisateur, `false` sinon.

Exemple pour n'afficher que les services de la même région que le demandeur :

```
Region_service = Region_demandeur
```

</details>

<details>

<summary>Comment déboguer une expression STalk qui ne fonctionne pas ?</summary>

Plusieurs approches :

1. Utilisez la **vérification de cohérence** dans le Designer pour détecter les erreurs de syntaxe et de types.
2. Utilisez la fonction `debugText(monExpression)` pour écrire la valeur dans les logs Tomcat. Consultez `catalina.out` pour la visualiser.
3. Simplifiez l'expression pour identifier la partie problématique : commencez par tester chaque sous-expression séparément.

</details>

<details>

<summary>WKYJS est-il disponible dans les formulaires d'archivage ?</summary>

Non. Les **formulaires d'archivage** ne supportent pas les composants **Script JS**. Cela signifie que WKYJS n'est pas disponible dans ce contexte. Concevez les formulaires d'archivage sans logique JavaScript.

</details>

<details>

<summary>Comment empêcher la soumission d'un formulaire depuis WKYJS si une condition n'est pas remplie ?</summary>

Utilisez l'écouteur `WKYJS.onSubmit()` et retournez `false` pour bloquer la soumission :

```javascript
WKYJS.onSubmit(function() {
    if (WKYJS.getFieldValue("Montant") <= 0) {
        WKYJS.error("Montant", true);
        WKYJS.errorBox("Le montant doit être supérieur à 0.");
        return false; // Bloque la soumission
    }
});
```

</details>

<details>

<summary>Peut-on appeler l'API REST Efalia Process depuis du code WKYJS ?</summary>

Techniquement oui, via des appels AJAX (`fetch` ou `XMLHttpRequest`). Cependant, cette approche doit être utilisée avec précaution : les appels API depuis le formulaire s'exécutent avec les droits de l'utilisateur connecté. Pour les intégrations complexes, préférez les connecteurs côté serveur (Java, SQL) ou les agents planifiés.

</details>

***

Pour aller plus loin :

* [Tableaux de Bord et Vues](/documentations/efalia-process/administration/administration-fonctionnelle/tableaux-bord-vues.md)
* [Designer HTML – Fonctionnalités Avancées](/documentations/efalia-process/administration/administration-fonctionnelle/designer-html.md)
* [Modélisation avec le Designer](/documentations/efalia-process/administration/administration-fonctionnelle/modelisation-designer.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.efalia.com/documentations/efalia-process/administration/administration-fonctionnelle/langages-process.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
