Aller au contenu principal

Formulaire multi-étapes / workflow

Le besoin​

Une note de frais passe par Brouillon → Soumise → Validée / Refusée. Chaque transition revient à un rôle donné ; certains champs n'ont de sens que dans certains états ; une note en attente depuis trop longtemps doit être relancée.

La démarche​

BesoinMécanisme
Une transition qui ne s'applique que depuis le bon étatUne requête d'écriture par transition, avec AND STATUS = '<attendu>' dans sa clause WHERE.
Un bouton par transitionUne action du menu de ligne : une chain avec confirmation, saisie et requête.
Seuls les managers validentLa permission de la requête de transition, accordée au rôle des managers.
Des champs selon l'étatvisible_when, required_when, disabled_when sur les colonnes.
Figé une fois la décision priseLe réglage editable_when de l'écran.
Prévenir les bonnes personnesDes règles de notification sur les écritures de l'écran.
Relancer les notes en attenteUne tâche Nomaflow quotidienne.

La recette​

1. La table​

CREATE TABLE expense_claims (
id INTEGER PRIMARY KEY,
employee VARCHAR(64) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
description VARCHAR(2000),
status VARCHAR(16) NOT NULL DEFAULT 'DRAFT',
submitted_at TIMESTAMP,
decided_by VARCHAR(64),
decided_at TIMESTAMP,
reject_reason VARCHAR(500),
reminded_at TIMESTAMP
);

2. La liste des statuts​

Liberty Next → Construire → Dictionnaire → Énumérations : une énumération CLAIM_STATUS avec les valeurs DRAFT (Brouillon), SUBMITTED (Soumise), APPROVED (Validée), REJECTED (Refusée). L'entrée STATUS reçoit Rules ENUM et Rules values CLAIM_STATUS : la grille affiche les libellés et le dialogue une liste.

3. Une requête par transition​

Dans Liberty Next → Construire → Connecteurs → expenses → Requêtes, trois requêtes d'écriture :

-- submit_claim
UPDATE expense_claims
SET STATUS = 'SUBMITTED', SUBMITTED_AT = {{SYSTIMESTAMP}}
WHERE ID = :ID AND STATUS = 'DRAFT' AND EMPLOYEE = {{LOGIN}}

-- approve_claim
UPDATE expense_claims
SET STATUS = 'APPROVED', DECIDED_BY = {{LOGIN}}, DECIDED_AT = {{SYSTIMESTAMP}}
WHERE ID = :ID AND STATUS = 'SUBMITTED'

-- reject_claim
UPDATE expense_claims
SET STATUS = 'REJECTED', DECIDED_BY = {{LOGIN}}, DECIDED_AT = {{SYSTIMESTAMP}},
REJECT_REASON = :REJECT_REASON
WHERE ID = :ID AND STATUS = 'SUBMITTED'

La garde AND STATUS = … fait qu'une transition depuis un mauvais état ne modifie rien ; EMPLOYEE = {{LOGIN}} limite la soumission aux notes du salarié lui-même ({{LOGIN}} vaut le nom de l'utilisateur en majuscules, forme sous laquelle EMPLOYEE doit être enregistré).

4. Les boutons de transition​

Dans l'éditeur d'écran, onglet Menu de ligne, une entrée par transition :

[[screens.expenses.expense_claims.row_menu]]
type = "chain"
id = "reject"
label = "Refuser"
prompt_title = "Refuser la note"
prompt_fields = [{ name = "REJECT_REASON", label = "Motif", required = true }]
steps = [
{ type = "run_query", id = "do", query = "reject_claim",
param_binds = [{ param = "ID", source = "ID" },
{ param = "REJECT_REASON", source = "INPUT.REJECT_REASON" }] },
{ type = "refresh", id = "reload" },
]

Valider suit le même modèle, avec une étape confirm à la place de la saisie ; Soumettre, avec submit_claim. Pour afficher un message clair quand la note n'est pas dans le bon état, placer les étapes dans un if sur STATUS (equals SUBMITTED) : then_steps exécutent la requête, else_steps un notify. Voir Actions et cycle de vie.

5. Qui peut faire quoi​

Chaque requête a sa propre permission : sql:expenses:submit_claim, sql:expenses:approve_claim, sql:expenses:reject_claim. Dans Liberty Next → Administrer → Accès → Roles, accorder la première aux salariés et les deux autres aux seuls managers : un salarié qui clique sur Valider se voit opposer un refus. Voir Rôles et permissions.

6. Les champs selon l'état​

Sur les colonnes (onglets Edit et Filter de l'inspecteur) :

ColonneRéglage
DESCRIPTION, AMOUNTrequired_when STATUS = DRAFT
SUBMITTED_ATvisible_when STATUS = SUBMITTED, APPROVED, REJECTED ; disabled
DECIDED_BY, DECIDED_ATvisible_when STATUS = APPROVED, REJECTED ; disabled
REJECT_REASONvisible_when STATUS = REJECTED ; disabled

Et dans l'onglet Général, editable_when STATUS = DRAFT : une fois soumise, la note s'ouvre en lecture seule et seules les transitions du menu de ligne la font évoluer. Voir Conditions de formulaire.

7. Les notifications​

Dans Liberty Next → Construire → Notifications, une règle sur l'événement update de l'écran, avec Only when the written row has STATUS = SUBMITTED, canaux portal et email, destinataires role:managers, objet Note {ID} de {EMPLOYEE} à valider. Une seconde règle sur STATUS = REJECTED peut prévenir le demandeur. Voir Notifications.

8. Les relances​

Une tâche Nomaflow, chaque matin, avec une étape sql_query :

UPDATE expense_claims SET REMINDED_AT = CURRENT_TIMESTAMP
WHERE STATUS = 'SUBMITTED' AND SUBMITTED_AT < CURRENT_TIMESTAMP - INTERVAL '5' DAY

et une règle de notification sur l'événement succeeded de cette tâche : {ROWS} notes en attente depuis plus de 5 jours, à role:managers.

Variantes​

BesoinMoyen
Historique de chaque transitionLa table d'audit de l'écran (audit_table) — voir Piste d'audit.
Rouvrir une note refuséeUne requête reopen_claim (STATUS = 'DRAFT' … WHERE STATUS = 'REJECTED') et son entrée de menu de ligne.
Un long formulaire en étapesDes onglets de dialogue, avec hide_on_add / hide_on_edit pour les onglets propres à un mode.

Pour aller plus loin​