Modèle de données
Modèle de données
Dans Dodock, tout est Document. Cette abstraction uniforme simplifie le développement, l'extension et la maintenance des applications.
Concepts fondamentaux
DocType et Document
Un DocType est la définition d'un type de document : il décrit les champs, les comportements et les permissions. Un Document est une instance de ce DocType, c'est-à-dire un enregistrement en base de données.
Analogie avec les bases de données
| Concept Dodock | Équivalent SQL | Description |
|---|---|---|
| DocType | Table + Schéma | Définition de la structure |
| Document | Ligne (row) | Enregistrement de données |
| DocField | Colonne | Champ du document |
| Link | Clé étrangère | Référence vers un autre DocType |
| Table | Table enfant | Relation 1-N intégrée |
Types de champs (DocField)
Chaque champ d'un DocType est défini par :
- fieldname : Nom technique (snake_case)
- fieldtype : Type de données
- label : Libellé affiché
- reqd : Obligatoire ou non
Types de champs disponibles
| Type | Description | Exemple |
|---|---|---|
| Data | Texte court | Nom, référence |
| Text | Texte long | Description |
| Int | Nombre entier | Quantité |
| Float | Nombre décimal | Taux |
| Currency | Montant monétaire | Prix, total |
| Date | Date | Date de facturation |
| Datetime | Date et heure | Horodatage |
| Check | Case à cocher | Actif/Inactif |
| Select | Liste déroulante | Statut |
| Link | Référence vers un DocType | Client, Article |
| Table | Table enfant | Lignes de facture |
| Attach | Fichier joint | Document PDF |
Champs de mise en page
| Type | Description |
|---|---|
| Section Break | Nouvelle section |
| Column Break | Nouvelle colonne |
| Tab Break | Nouvel onglet |
| HTML | Contenu HTML personnalisé |
Champs standards
Tous les documents possèdent automatiquement ces champs de métadonnées :
| Champ | Type | Description |
|---|---|---|
name | Data | Identifiant unique du document |
owner | Link (User) | Utilisateur créateur |
creation | Datetime | Date de création |
modified | Datetime | Date de dernière modification |
modified_by | Link (User) | Dernier utilisateur modificateur |
docstatus | Int | État du document |
idx | Int | Position de la ligne, pour une table enfant |
parent, parenttype, parentfield | Data | Document parent, type du parent et champ Table, pour une ligne de table enfant |
États du document (docstatus)
Pour les DocTypes soumissibles (option « Est soumissible ») :
| Valeur | État | Description |
|---|---|---|
| 0 | Brouillon | Modifiable, non validé |
| 1 | Validé | Non modifiable, sauf les champs « Autoriser les modifications après validation » |
| 2 | Annulé | Annulé après validation. Le bouton Modifier crée une copie en brouillon |
Nommage des documents
Le champ name est l'identifiant unique de chaque document. La propriété « Règle de nommage » du DocType choisit la méthode. Elle remplit la propriété autoname :
| Règle | Valeur de autoname | Exemple de nom |
|---|---|---|
Par série (champ naming_series) | naming_series: | ACC-SINV-2026-00001 |
| Par nom de champ | field:customer_name | Maison Verte SARL |
| Expression | format:INT-{customer}-{####} | INT-Maison Verte SARL-0001 |
| Aléatoire | hash | a1b2c3d4e5 |
| Auto-incrément | autoincrement | 42 |
| UUID | UUID | 0192f0e6-… |
| Défini par l'utilisateur | prompt | Saisie manuelle |
Le contrôleur peut aussi définir une méthode autoname(self) qui calcule self.name.
Exemple de série
Avec la règle « Par série », l'utilisateur choisit la série dans le champ naming_series du document. Une série comme FACT-.YYYY.-.##### donne FACT-2026-00001. .YYYY. est remplacé par l'année et ##### par un compteur sur 5 chiffres.
Lire ou modifier le compteur d'une série depuis le code
La classe NamingSeries de frappe.model.naming donne accès au compteur d'une série. Le compteur est stocké dans le DocType Series, sous une clé qui est le préfixe calculé de la série : FACT-2026- pour FACT-.YYYY.-.#####.
| Méthode | Rôle |
|---|---|
get_prefix(doc=None) | Retourne le préfixe, c'est-à-dire la clé du compteur. |
get_current_value(doc=None) | Retourne la valeur actuelle du compteur (entier). Lit la ligne avec un verrou (for_update). |
update_counter(new_count, doc=None) | Écrit new_count dans le compteur. Crée la ligne du compteur si elle n'existe pas. |
get_preview(doc=None) | Retourne trois exemples de noms (compteur 1, 2 et 3), sans lire ni modifier le compteur. |
generate_next_name(doc, *, ignore_validate=False) | Retourne le prochain nom de la série. |
Quand la série contient une partie {nom_du_champ}, le préfixe dépend de la valeur de ce champ. Passez alors le document en argument doc : sans lui, la partie n'est pas remplacée et le préfixe garde le texte littéral {nom_du_champ}. Les trois méthodes qui lisent ou écrivent le compteur (get_prefix, get_current_value, update_counter) acceptent ce paramètre facultatif. Un appel sans doc se comporte comme avant.
Exemple : avec un document Webhook dont le champ webhook_docevent vaut on_update :
from frappe.model.naming import NamingSeries
webhook = frappe.new_doc("Webhook")
webhook.webhook_docevent = "on_update"
series = NamingSeries("KOOH-.{webhook_docevent}.-.####")
series.get_prefix() # "KOOH-{webhook_docevent}-"
series.get_prefix(webhook) # "KOOH-on_update-"
series.update_counter(7, webhook)
series.get_current_value(webhook) # 7
update_counter écrit la valeur sans autre contrôle. Une valeur trop basse peut produire des noms en double. Voir Reprendre un compteur pour la même opération depuis l'interface.Relations entre DocTypes
Link (relation 1-1 ou N-1)
Un champ Link crée une référence vers un autre DocType.
Table (relation 1-N)
Un champ Table intègre une table enfant directement dans le document parent.
Exemple concret :
| Facture de vente | Client A |
|---|---|
| Date | 2024-01-15 |
| Articles | |
| ART-001 | 5 × 100 € = 500 € |
| ART-002 | 3 × 100 € = 300 € |
| Total | 800 € |
Cycle de vie d'un document
Événements disponibles
| Événement | Moment | Usage typique |
|---|---|---|
before_insert | Avant la création | Valeurs par défaut |
before_validate | Avant validate | Compléter des valeurs avant les contrôles |
validate | Avant chaque enregistrement | Validations métier |
before_save | Après validate, avant l'écriture | Calculs automatiques |
after_insert | Après la création | Notifications |
on_update | Après chaque enregistrement | Actions après l'enregistrement |
before_submit, on_submit | Avant et après la validation (docstatus 1) | Écritures comptables, mouvements de stock |
before_cancel, on_cancel | Avant et après l'annulation (docstatus 2) | Contre-passations |
before_update_after_submit, on_update_after_submit | Modification d'un document validé | Contrôle des champs modifiables |
on_change | Après tout changement enregistré | Mise à jour de documents liés |
on_trash, after_delete | Avant et après la suppression | Nettoyage |
Une application peut aussi réagir à ces événements sans modifier le contrôleur, avec le hook doc_events. Voir Référence des hooks.