Les métadonnées permettent d'attacher des propriétés structurées personnalisées aux documents : numéro de facture, date d'expiration, fournisseur, statut, etc. Le système est entièrement configurable : types de données, validation, transformation automatique, valeurs par défaut, listes de choix.
Le système repose sur trois modèles distincts :
MetadataType ← définition globale (une fois pour tout le système)
│
├── DocumentTypeMetadataType ← liaison à un type de document
│ └── required (bool) ← obligatoire ou optionnel pour ce type
│
└── DocumentMetadata ← valeur effective sur un document
└── value (str)
Exemple concret :
MetadataType : "Numéro de facture" (name=invoice_number)
│
├── DocumentTypeMetadataType : Factures ↔ invoice_number (required=True)
└── DocumentTypeMetadataType : Bons de commande ↔ invoice_number (required=False)
DocumentMetadata : Document #42 → invoice_number = "FAC-2024-001"
DocumentMetadata : Document #43 → invoice_number = "FAC-2024-002"
Un MetadataType est une définition globale réutilisable sur plusieurs types de documents. Il se crée dans Administration > Métadonnées > Types de métadonnées.
| Propriété | Requis | Description |
|---|---|---|
Nom (name) |
Oui | Identifiant technique unique, sans espaces ni mots réservés. Utilisé dans les templates : {{ document.metadata_value_of.invoice_number }} |
Label (label) |
Oui | Libellé affiché à l'utilisateur dans l'interface |
Valeur par défaut (default) |
Non | Valeur pré-remplie — supporte les templates Django |
Lookup (lookup) |
Non | Template générant une liste de choix CSV |
Validateur (validation) |
Non | Classe de validation à appliquer |
Arguments validateur (validation_arguments) |
Non | Paramètres YAML du validateur |
Parseur (parser) |
Non | Classe de transformation à appliquer après validation |
Arguments parseur (parser_arguments) |
Non | Paramètres YAML du parseur |
Mayan ajoute une propriété dynamique sur chaque Document :
{# Dans un template workflow ou index #}
{{ workflow_instance.document.metadata_value_of.invoice_number }}
{{ workflow_instance.document.metadata_value_of.expiration_date }}
# En Python
document.metadata_value_of.invoice_number # → "FAC-2024-001" ou None
Un type de métadonnée doit être associé à un type de document avant de pouvoir être utilisé sur des documents de ce type.
Administration > Types de documents > [Type] > Types de métadonnées
ou
Administration > Métadonnées > Types de métadonnées > [Type] > Types de documents
| Propriété | Description |
|---|---|
| Optionnel | La métadonnée peut être vide |
| Requis | La métadonnée doit avoir une valeur — impossible de laisser le document sans cette valeur |
Quand on marque une métadonnée comme requise pour un type de document :
→ La métadonnée est automatiquement ajoutée à tous les documents existants de ce type (tâche asynchrone), avec valeur vide (ou valeur par défaut si configurée).
Quand on supprime une association :
→ Tous les DocumentMetadata de ce type sont supprimés de tous les documents du type concerné (tâche asynchrone).
Quand un document change de type :
Un DocumentMetadata est l'instance d'une valeur de métadonnée sur un document précis.
| Propriété | Description |
|---|---|
document |
Le document |
metadata_type |
Le type de métadonnée |
value |
La valeur stockée (toujours une chaîne de caractères) |
DocumentMetadata par combinaison (document, metadata_type) — on ne peut pas avoir deux valeurs du même type sur le même documentenforce_required=False)Le champ default supporte le moteur de templates Django. Il est évalué au moment où la métadonnée est ajoutée au document.
Valeur du champ default |
Résultat |
|---|---|
Brouillon |
Valeur littérale "Brouillon" |
{{ now\|date:"Y-m-d" }} |
Date du jour au format ISO |
{{ now\|date:"Y" }} |
Année courante |
{{ document.document_type.label }} |
Label du type de document |
defaultLes variables de contexte standard des templates Mayan sont disponibles, notamment now (date/heure actuelle) et document.
Le champ lookup génère une liste déroulante dans le formulaire d'édition. Il doit produire une chaîne CSV de valeurs séparées par des virgules.
Brouillon,En révision,Approuvé,Rejeté,Archivé
Le champ lookup est un template Django avec accès aux variables groups (tous les groupes) et users (tous les utilisateurs).
Exemple — liste des groupes :
{% for group in groups %}{{ group.name }},{% endfor %}
Exemple — liste d'années (5 dernières) :
{% for y in "0,1,2,3,4"|split:"," %}{{ now.year|add:"-"|add:y }},{% endfor %}
lookup est défini, la valeur doit être dans la liste — toute valeur hors liste est rejetéeLes validateurs vérifient que la valeur saisie respecte un format ou une contrainte. Ils sont appliqués après la vérification du lookup.
DateValidator — Validation de dateVérifie que la valeur est une date valide et la convertit au format ISO.
Chemin : mayan.apps.metadata.metadata_validators.DateValidator
Arguments : (aucun)
Exemple entrée : "15/01/2024" ou "2024-01-15"
Exemple sortie : validation OK ou erreur
DateAndTimeValidator — Validation date + heureVérifie qu'une valeur est une date et heure valide.
Chemin : mayan.apps.metadata.metadata_validators.DateAndTimeValidator
Arguments : (aucun)
Exemple entrée : "2024-01-15 14:30"
TimeValidator — Validation d'heureVérifie qu'une valeur est une heure valide.
Chemin : mayan.apps.metadata.metadata_validators.TimeValidator
Arguments : (aucun)
Exemple entrée : "14:30"
RegularExpressionValidator — Validation par expression régulièreVérifie que la valeur correspond à un motif regex.
Chemin : mayan.apps.metadata.metadata_validators.RegularExpressionValidator
Arguments : (YAML)
pattern: "^[A-Z]{3}-[0-9]{4}-[0-9]{3}$"
Exemples de patterns utiles :
| Usage | Pattern |
|---|---|
Code facture FAC-2024-001 |
^FAC-[0-9]{4}-[0-9]{3}$ |
| SIRET | ^[0-9]{14}$ |
| Code postal français | ^[0-9]{5}$ |
^[^@]+@[^@]+\.[^@]+$ |
|
| Montant décimal | ^[0-9]+(\.[0-9]{1,2})?$ |
Les parseurs transforment la valeur après validation. La valeur stockée dans la base de données est la valeur après parsing.
DateParser — Normalisation de dateConvertit une date saisie en format ISO YYYY-MM-DD.
Chemin : mayan.apps.metadata.metadata_parsers.DateParser
Arguments : (aucun)
Entrée : "15/01/2024" ou "15-01-2024" ou "2024-01-15"
Sortie : "2024-01-15"
DateAndTimeParser — Normalisation date + heureChemin : mayan.apps.metadata.metadata_parsers.DateAndTimeParser
Arguments : (aucun)
Entrée : "15/01/2024 14:30"
Sortie : "2024-01-15T14:30:00"
TimeParser — Normalisation d'heureChemin : mayan.apps.metadata.metadata_parsers.TimeParser
Arguments : (aucun)
Entrée : "14h30" ou "14:30"
Sortie : "14:30:00"
RegularExpressionParser — Transformation par regexApplique une substitution regex sur la valeur.
Chemin : mayan.apps.metadata.metadata_parsers.RegularExpressionParser
Arguments : (YAML)
pattern: "[^a-zA-Z0-9]"
replacement: ""
Exemples d'usage :
| Objectif | pattern | replacement |
|---|---|---|
| Supprimer espaces | \s+ |
`` (vide) |
| Mettre en majuscules | (impossible seul — utiliser avec validateur) | |
| Supprimer caractères spéciaux | [^a-zA-Z0-9\-] |
`` |
| Normaliser séparateur de date | [/\.] |
- |
| Extraire les chiffres uniquement | [^0-9] |
`` |
Note : Validateur et parseur peuvent être combinés sur le même type. La validation s'applique en premier, puis le parseur transforme la valeur validée.
Voici l'ordre exact de traitement d'une valeur soumise :
Valeur saisie par l'utilisateur
│
▼
[1] Valeur vide + default défini ?
→ Appliquer la valeur par défaut (rendu du template)
│
▼
[2] Valeur toujours vide + métadonnée requise ?
→ Lever une erreur de validation
│
▼
[3] lookup défini ?
→ La valeur doit être dans la liste générée
→ Sinon : ValidationError
│
▼
[4] validator défini ?
→ Instancier le validateur avec validation_arguments (YAML)
→ Appeler validate(value) — peut lever ValidationError
│
▼
[5] parser défini ?
→ Instancier le parseur avec parser_arguments (YAML)
→ Appeler parse(value) → valeur transformée
│
▼
Valeur finale stockée en base
Quand required=True est défini sur une association DocumentTypeMetadataType :
task_add_required_metadata_type) ajoute cette métadonnée à tous les documents existants du typeQuand une association DocumentTypeMetadataType est supprimée :
task_remove_metadata_type) supprime toutes les valeurs de cette métadonnée sur les documents du typeQuand un MetadataType est supprimé :
DocumentTypeMetadataType associés sont supprimés → déclenchent leurs handlers de suppressionDocumentMetadata sont supprimés avec émission d'événementsHandler handler_post_document_type_change_metadata :
| Permission | Description |
|---|---|
permission_document_metadata_view |
Voir les métadonnées d'un document |
permission_document_metadata_add |
Ajouter des types de métadonnées à un document |
permission_document_metadata_edit |
Modifier les valeurs de métadonnées |
permission_document_metadata_remove |
Supprimer des métadonnées d'un document |
permission_metadata_type_create |
Créer de nouveaux types de métadonnées |
permission_metadata_type_view |
Voir la configuration des types |
permission_metadata_type_edit |
Modifier un type (validateurs, parseurs, etc.) |
permission_metadata_type_delete |
Supprimer un type |
| Événement | Cible | Déclencheur |
|---|---|---|
event_metadata_type_created |
MetadataType | Création d'un type |
event_metadata_type_edited |
MetadataType | Modification d'un type |
event_document_metadata_added |
Document + MetadataType | Ajout d'une métadonnée à un document |
event_document_metadata_edited |
Document + MetadataType | Modification d'une valeur |
event_document_metadata_removed |
Document + MetadataType | Suppression d'une métadonnée |
event_metadata_type_relationship_updated |
DocumentType + MetadataType | Création, modification ou suppression d'une association |
Ces événements peuvent être utilisés comme triggers de workflow — voir Intégration workflows.
| Endpoint | Méthodes | Description |
|---|---|---|
/api/v4/metadata/metadata-types/ |
GET, POST | Lister / créer des types |
/api/v4/metadata/metadata-types/{id}/ |
GET, PATCH, PUT, DELETE | Détail / modifier / supprimer |
Champs exposés : id, name, label, default, lookup, parser, parser_arguments, validation, validation_arguments, url
| Endpoint | Méthodes | Description |
|---|---|---|
/api/v4/documents/{id}/metadata/ |
GET, POST | Lister / ajouter |
/api/v4/documents/{id}/metadata/{metadata_id}/ |
GET, PATCH, PUT, DELETE | Détail / modifier / supprimer |
Champs exposés : id, document, metadata_type, metadata_type_id (write-only), value, url
| Endpoint | Méthodes | Description |
|---|---|---|
/api/v4/documents/types/{id}/metadata-types/ |
GET, POST | Lister / associer |
/api/v4/documents/types/{id}/metadata-types/{id}/ |
GET, PATCH, PUT, DELETE | Détail / modifier |
Champs exposés : id, document_type, metadata_type, metadata_type_id (write-only), required, url
# Lister les types de métadonnées
curl -u admin:password http://mayan/api/v4/metadata/metadata-types/
# Créer un type de métadonnée
curl -u admin:password -X POST http://mayan/api/v4/metadata/metadata-types/ \
-H "Content-Type: application/json" \
-d '{"name": "invoice_number", "label": "Numéro de facture"}'
# Ajouter une valeur de métadonnée sur un document
curl -u admin:password -X POST http://mayan/api/v4/documents/42/metadata/ \
-H "Content-Type: application/json" \
-d '{"metadata_type_id": 3, "value": "FAC-2024-001"}'
# Modifier une valeur
curl -u admin:password -X PATCH http://mayan/api/v4/documents/42/metadata/7/ \
-H "Content-Type: application/json" \
-d '{"value": "FAC-2024-002"}'
Add metadata — Ajouter des types de métadonnéesAjoute des types de métadonnées au document (sans valeur initiale).
| Champ | Requis | Description |
|---|---|---|
metadata_types |
Oui | Sélection multiple des types à ajouter |
Edit metadata — Modifier une valeur de métadonnéeDéfinit ou met à jour la valeur d'une métadonnée. Supporte les templates Django pour la valeur.
| Champ | Requis | Description |
|---|---|---|
metadata_type |
Oui | Le type de métadonnée à modifier |
value |
Oui | Nouvelle valeur — template Django avec accès au contexte workflow |
Exemples de valeurs template :
{# Date du jour #}
{{ now|date:"Y-m-d" }}
{# Valeur d'un champ de transition #}
{{ workflow_instance_context.motif_validation }}
{# Label de l'état courant #}
{{ workflow_instance.state_active.label }}
{# Concaténation #}
APPROUVÉ - {{ workflow_instance.document.label }}
Remove metadata — Supprimer des métadonnées| Champ | Requis | Description |
|---|---|---|
metadata_types |
Oui | Types à supprimer |
Ces événements peuvent déclencher automatiquement une transition de workflow :
| Trigger | Quand |
|---|---|
document_metadata_added |
Une métadonnée est ajoutée au document |
document_metadata_edited |
Une valeur de métadonnée change |
document_metadata_removed |
Une métadonnée est retirée |
{# Condition : approuver seulement si le statut est "Validé" #}
{% for m in workflow_instance.document.metadata.all %}
{% if m.metadata_type.name == "status" %}
{% if m.value == "Validé" %}True{% endif %}
{% endif %}
{% endfor %}
{# Ou via la propriété directe #}
{% if workflow_instance.document.metadata_value_of.status == "Validé" %}True{% endif %}
Les champs de métadonnées sont indexés pour la recherche :
| Champ de recherche | Description |
|---|---|
metadata__metadata_type__name |
Recherche par nom de type |
metadata__value |
Recherche dans les valeurs |
Syntaxe de recherche avancée :
# Trouver tous les documents avec la métadonnée "fournisseur" = "Acme"
metadata_type__name:fournisseur metadata_value:Acme
# Chercher par valeur partielle
metadata_value:FAC-2024
Le modèle DocumentMetadataSearchResult (proxy) est également indexé, permettant une recherche directe sur les métadonnées :
| Champ | Description |
|---|---|
metadata_type__name |
Nom du type |
value |
Valeur |
document__document_type__label |
Type de document |
Configuration :
invoice_numberNuméro de factureRegularExpressionValidatorpattern: "^FAC-[0-9]{4}-[0-9]{3,6}$"
Résultat : Le système accepte uniquement FAC-2024-001, FAC-2024-12345, etc.
Configuration :
expiration_dateDate d'expirationDateValidatorDateParserRésultat : L'utilisateur peut saisir 15/01/2025, 15-01-2025, ou 2025-01-15 — la valeur est toujours stockée comme 2025-01-15.
Configuration :
document_statusStatutBrouillon,En révision,Approuvé,Rejeté,ArchivéRésultat : L'utilisateur voit un menu déroulant. Toute valeur hors liste est rejetée.
Configuration :
invoice_amountMontant HT (€)RegularExpressionValidator — pattern: "^[0-9]+([.,][0-9]{1,2})?$" (après parsing)RegularExpressionParserpattern: "[^0-9,.]"
replacement: ""
Résultat : 1 234,56 € → parseur retire espaces et € → 1234,56.
Configuration :
responsible_teamÉquipe responsable{% for group in groups %}{{ group.name }},{% endfor %}
Résultat : La liste déroulante affiche tous les groupes Mayan — se met à jour automatiquement quand les groupes changent.
Action Edit metadata sur l'état "Approuvé" (on entry) :
metadata_type : approval_date
value : {{ now|date:"Y-m-d" }}
Action Edit metadata — enregistrer le validateur :
metadata_type : approved_by
value : {{ workflow_instance.document.metadata_value_of.submitted_by }}
Transition "Approuver" disponible seulement si le montant est inférieur à 10 000 :
{% with amount=workflow_instance.document.metadata_value_of.invoice_amount %}
{% if amount %}
{% if amount|add:"0" < 10000 %}True{% endif %}
{% endif %}
{% endwith %}
Administration > Métadonnées > Types de métadonnées > Créer
Pour chaque métadonnée à gérer :
Administration > Types de documents > [Type] > Types de métadonnées
Pour chaque association :
Attribuer aux rôles appropriés :
permission_document_metadata_view — lecteurspermission_document_metadata_add / edit — contributeurspermission_metadata_type_create / edit — administrateurs[Document] > Métadonnées| Label | Chemin | Arguments YAML |
|---|---|---|
| Date validator | mayan.apps.metadata.metadata_validators.DateValidator |
(aucun) |
| Date and time validator | mayan.apps.metadata.metadata_validators.DateAndTimeValidator |
(aucun) |
| Time validator | mayan.apps.metadata.metadata_validators.TimeValidator |
(aucun) |
| Regular expression validator | mayan.apps.metadata.metadata_validators.RegularExpressionValidator |
pattern: "regex" |
| Label | Chemin | Arguments YAML |
|---|---|---|
| Date parser | mayan.apps.metadata.metadata_parsers.DateParser |
(aucun) |
| Date and time parser | mayan.apps.metadata.metadata_parsers.DateAndTimeParser |
(aucun) |
| Time parser | mayan.apps.metadata.metadata_parsers.TimeParser |
(aucun) |
| Regular expression parser | mayan.apps.metadata.metadata_parsers.RegularExpressionParser |
pattern: "regex" replacement: "str" |
{# Valeur directe (None si non définie) #}
{{ document.metadata_value_of.nom_du_type }}
{# Itérer toutes les métadonnées #}
{% for m in document.metadata.all %}
{{ m.metadata_type.label }} : {{ m.value }}
{% endfor %}
{# Vérifier une valeur en condition #}
{% if document.metadata_value_of.status == "Approuvé" %}...{% endif %}
{# Dans un contexte workflow #}
{{ workflow_instance.document.metadata_value_of.invoice_number }}
valeur → [défaut si vide] → [requis ?] → [lookup ?] → [validateur ?] → [parseur] → stockage
Généré le 2026-04-30 — Fork 4.11.1+egyptian.1, branche egyptian.
Sources : mayan/apps/metadata/ — modèles, formulaires, validateurs, parseurs, API.