Personnalisations

Scripts Python

Écrire un script Python exécuté sur le serveur et déclenché par un événement de document, une planification, une requête d'autorisation ou un appel à l'API.

Scripts Python

Un script Python (« Script Serveur (Python) ») exécute du code sur le serveur sans développer d'application. Le code tourne dans un environnement restreint (RestrictedPython). Seule une sélection de fonctions est disponible.

Prérequis

  • Les scripts Python sont désactivés par défaut. Activez-les pour tout le bench, dans common_site_config.json. La clé server_script_enabled d'un fichier site_config.json n'a pas d'effet.
    bench set-config -g server_script_enabled 1
    
  • Vous avez le rôle Gestionnaire de script. Seul ce rôle peut créer, modifier ou supprimer un script.

Créer un script

  1. Ouvrez la recherche (Ctrl+K) et saisissez « Script Serveur (Python) ».
  2. Cliquez sur Ajouter.
  3. Choisissez le Type de script.
  4. Remplissez les champs propres à ce type (voir le tableau ci-dessous).
  5. Saisissez le code dans le champ Script.
  6. Enregistrez.

À l'enregistrement, Dokos compile le script. Une erreur de syntaxe s'affiche dans une fenêtre « Compilation warning ». Cochez Désactivé pour arrêter un script sans le supprimer.

Types de script

Type de scriptDéclenchementChamps à remplirVariables disponibles
Evénement déclencheurUn événement du cycle de vie d'un documentType de document de référence, Evénement déclencheurdoc
Événement programméLe planificateur, à la fréquence choisieFréquence de l'événement, Format Cron si la fréquence est « Cron »aucune
Requête d'autorisationChaque lecture de liste du type de documentType de document de référenceuser, conditions
APIUn appel HTTP à /api/method/<méthode>Méthode d'API, Autoriser les utilisateurs invités, limite d'usagefrappe.form_dict
Tâche de workflowUne action de workflowaucundoc

Événements de document

Le champ Evénement déclencheur propose ces valeurs :

ValeurMoment
Avant la créationAvant la première insertion en base
Après l'insertionAprès la première insertion
Avant vérificationAvant la validation des données (before_validate)
Avant l'enregistrementAvant chaque enregistrement (validate)
Après l'enregistrementAprès chaque enregistrement
Avant la validation / Après la validationAutour de la validation (soumission) du document
Avant l'annulation / Après l'annulationAutour de l'annulation
Avant l'abandon / Après l'abandonAutour de l'abandon d'un brouillon
Avant la suppression / Après la suppressionAutour de la suppression
Avant le renommage / Après le renommageAutour du renommage
Avant enregistrement (Document validé) / Après enregistrement (Document validé)Mise à jour d'un document déjà validé
Avant l'impressionAvant la génération de l'aperçu ou du PDF
Sur autorisation de paiement, Après la validation du paiement, Lors de l'échec d'un paiement…Événements de paiement propres à Dokos, émis par les passerelles de paiement

Dans un script d'événement, frappe.db.commit() et frappe.db.rollback() ne sont pas disponibles. La transaction du document reste maîtrisée par Dokos.

Scripts planifiés

Le champ Fréquence de l'événement accepte : Tous, Toutes les heures, Quotidien, Hebdomadaire, Mensuel, Annuel, les variantes « - Long » (file d'attente longue) et Cron. À l'enregistrement, Dokos crée ou met à jour la tâche planifiée correspondante. Cocher Désactivé arrête cette tâche.

Scripts API

Le nom saisi dans Méthode d'API devient l'URL /api/method/<méthode>.

  • Sans Autoriser les utilisateurs invités, un visiteur non connecté reçoit une erreur d'autorisation.
  • Activer la limite d'usage limite le nombre d'appels. Par défaut : 5 requêtes (Limite de requêtes) par période de 86 400 secondes (Fenêtre temporelle (Secondes)).
  • Renvoyez la réponse dans frappe.response["message"]. Une valeur placée dans frappe.flags remplace aussi message.

Fonctions disponibles

Les scripts Python ont accès à une version complète des fonctions de lecture et d'écriture. Les principales :

DomaineFonctions
Documentsfrappe.get_doc, frappe.new_doc, frappe.copy_doc, frappe.get_cached_doc, frappe.get_last_doc, frappe.get_mapped_doc, frappe.rename_doc, frappe.delete_doc, frappe.get_meta
Listesfrappe.get_list (avec permissions), frappe.get_all (sans permissions)
Base de donnéesfrappe.db.get_value, frappe.db.set_value, frappe.db.get_single_value, frappe.db.get_list, frappe.db.get_all, frappe.db.exists, frappe.db.count, frappe.db.get_default, frappe.db.escape, frappe.db.sql (lecture seule : SELECT et EXPLAIN), frappe.db.commit, frappe.db.rollback, frappe.qb
Messages et erreursfrappe.msgprint, frappe.throw, frappe.log_error, frappe.bold, les exceptions frappe.ValidationError, frappe.PermissionError…
Emails et impressionfrappe.sendmail, frappe.get_print, frappe.attach_print, frappe.render_template
Tâches de fondfrappe.enqueue, frappe.is_job_queued, frappe.call, run_script
Requêtes HTTPfrappe.make_get_request, frappe.make_post_request, frappe.make_put_request, frappe.make_patch_request, frappe.make_delete_request (HTTP et HTTPS uniquement, adresses internes bloquées), FrappeClient
Sessionfrappe.session.user, frappe.user, frappe.form_dict, frappe.request.path, frappe.response, frappe.flags
Formatagefrappe.format_value, frappe.format_date, frappe.date_format, frappe.time_format, _() (traduction)
Utilitairesfrappe.utils (dates, nombres, URL : getdate, add_days, flt, cint, fmt_money, get_url_to_form…), frappe.get_url, frappe.get_hooks, frappe.get_system_settings, frappe.redirect_to_message, json.loads, json.dumps

frappe.utils n'expose qu'une sélection de fonctions de frappe.utils.data. Les imports (import) sont interdits. Les noms qui commencent par _ sont inaccessibles.

Les modèles Jinja (formats d'impression, modèles d'email) n'ont pas accès à ces fonctions d'écriture. Voir Modèles Jinja.

Exemples

Fermer une tâche selon sa description

  • Type de script : Evénement déclencheur
  • Type de document de référence : ToDo
  • Evénement déclencheur : Avant l'enregistrement
if doc.description and "terminé" in doc.description:
    doc.status = "Closed"

Bloquer l'enregistrement

  • Evénement déclencheur : Avant l'enregistrement
if doc.priority == "High" and not doc.date:
    frappe.throw("Une tâche de priorité haute doit avoir une date d'échéance.")

frappe.throw affiche le message et annule l'enregistrement.

Créer une tâche après l'insertion d'un document

  • Type de document de référence : Note (exemple)
  • Evénement déclencheur : Après l'insertion
frappe.get_doc({
    "doctype": "ToDo",
    "allocated_to": frappe.session.user,
    "description": f"Relire la note : {doc.title}",
    "reference_type": doc.doctype,
    "reference_name": doc.name,
}).insert()

Créer une API

  • Type de script : API
  • Méthode d'API : taches_ouvertes
user = frappe.form_dict.get("user") or frappe.session.user
frappe.response["message"] = frappe.db.count("ToDo", {"allocated_to": user, "status": "Open"})

Appel : GET /api/method/taches_ouvertes?user=jean.dupont@exemple.fr renvoie {"message": 3} (exemple fictif).

Restreindre une liste par une requête d'autorisation

  • Type de script : Requête d'autorisation
  • Type de document de référence : ToDo
if user != "Administrator":
    conditions = f"`tabToDo`.allocated_to = {frappe.db.escape(user)}"

La variable conditions contient un filtre SQL ajouté à chaque lecture de la liste. Ici, chaque utilisateur ne voit que les tâches qui lui sont attribuées.