Utiliser les points d'extension client
Utiliser les points d'extension client
Un document « mappé » est créé à partir d'un autre : une facture depuis une commande, un bon de livraison depuis une commande… Le desk appelle frappe.model.open_mapped_doc. Le serveur prépare le nouveau document sans l'enregistrer, puis le desk l'ouvre.
Une garde est une fonction JavaScript appelée entre ces deux étapes. Elle peut empêcher l'ouverture du nouveau document.
Fonctions
| Fonction | Rôle |
|---|---|
frappe.model.add_mapped_doc_guard(fn) | Enregistre une garde. La même fonction n'est enregistrée qu'une fois. |
frappe.model.remove_mapped_doc_guard(fn) | Retire une garde. |
frappe.model.should_open_mapped_doc(mapped_doc, opts) | Exécute les gardes dans l'ordre. Renvoie une promesse de true si aucune ne bloque. |
Une garde reçoit (mapped_doc, opts) :
mapped_doc: le nouveau document, pas encore enregistré. Sonnameest provisoire.opts: les options passées àopen_mapped_doc(method,frm,source_name,args…).
Elle renvoie true (ou une promesse de true) pour laisser ouvrir le document, false pour bloquer.
Déroulement
- La première garde qui renvoie
falsearrête la suite. Le desk reste sur le document source. - Une garde qui lève une erreur est ignorée. L'erreur s'affiche dans la console. Une garde en erreur ne bloque donc jamais la création.
- Pendant l'exécution des gardes, l'écran n'est pas gelé : une garde peut ouvrir une boîte de dialogue. Un nouveau clic sur « Créer » est ignoré jusqu'à la fin des gardes.
- Les gardes ne concernent que
open_mapped_doc. Un document créé avec Nouveau ne passe pas par elles.
Exemple : confirmer avant de créer un deuxième bon de livraison
Placez le code dans un fichier JavaScript chargé par le desk (app_include_js dans le hooks.py de votre application).
frappe.model.add_mapped_doc_guard(async (mapped_doc, opts) => {
if (mapped_doc.doctype !== "Delivery Note" || !opts.frm) return true;
const count = await frappe.db.count("Delivery Note", {
filters: [
["Delivery Note Item", "against_sales_order", "=", opts.frm.doc.name],
["Delivery Note", "docstatus", "!=", 2],
],
});
if (!count) return true;
return new Promise((resolve) => {
frappe.confirm(
__("Un bon de livraison existe déjà pour cette commande. Continuer ?"),
() => resolve(true),
() => resolve(false)
);
});
});
frappe.confirm ne renvoie pas de promesse. Enveloppez-la dans une promesse comme ci-dessus. La fonction de refus est appelée aussi quand l'utilisateur ferme la boîte.
Bonnes pratiques
- Testez
mapped_doc.doctypeen premier : une garde s'applique à tous les mappings. - Une garde ne doit pas modifier
mapped_doc. Pour préremplir des champs, utilisez le script client du document cible (onload,refresh) ou la méthode de mapping côté serveur. - Résolvez toujours la promesse. Sinon, les clics suivants sur « Créer » restent ignorés.