myFAB Tracabilité documentaire
Le module myFAB Traçabilité documentaire permet de composer une liasse à partir d'un enregistrement Open-Prod et des enregistrements qui lui sont liés.
Une liasse peut contenir :
- des documents Open-Prod déjà présents dans la GED ;
- des rapports Jasper, Excel, QWeb ou tout autre rapport exposé par
ir.actions.report; - une autre liasse documentaire, pour construire des liasses imbriquées.
La liasse peut ensuite être :
- stockée dans un champ GED du document métier ;
- imprimée sur une imprimante Open-Prod ;
- stockée et imprimée en une seule exécution ;
- téléchargée au format PDF fusionné ou ZIP ;
- exécutée manuellement ou automatiquement par une action serveur.
Exemple depuis un bon de livraison : récupérer les documents des articles et des étiquettes, imprimer les ordres de fabrication et ajouter les documents de contrôle qualité dans une liasse stockée sur le BL.
Note attention en v9 toutes les fonctionnalités ne sont pas disponibles
myFAB Tracabilité documentaire
1. Présentation
Le module myFAB Traçabilité documentaire permet de composer une liasse à partir d'un enregistrement Open-Prod et des enregistrements qui lui sont liés.
Une liasse peut contenir :
- des documents Open-Prod déjà présents dans la GED ;
- des rapports Jasper, Excel, QWeb ou tout autre rapport exposé par
ir.actions.report; - une autre liasse documentaire, pour construire des liasses imbriquées.
La liasse peut ensuite être :
- stockée dans un champ GED du document métier ;
- imprimée sur une imprimante Open-Prod ;
- stockée et imprimée en une seule exécution ;
- téléchargée au format PDF fusionné ou ZIP ;
- exécutée manuellement ou automatiquement par une action serveur.
Exemple depuis un bon de livraison : récupérer les documents des articles et des étiquettes, imprimer les ordres de fabrication et ajouter les documents de contrôle qualité dans une liasse stockée sur le BL.
3. Créer une configuration
3.1 Paramètres généraux
| Paramètre | Description |
|---|---|
| Nom | Nom de la configuration et de l'action serveur générée. |
| Modèle | Modèle Open-Prod sur lequel la liasse peut être exécutée, par exemple stock.picking ou mrp.manufacturingorder. |
| Mode de génération | Stockage, Impression ou Stockage + impression. |
| Désactiver mise à jour | Empêche les mises à jour de documents lors des traitements SQL qui le prévoient. |
| Exécution automatique | Exécute la liasse directement sans ouvrir l'assistant. |
3.2 Stockage GED
Ces paramètres sont disponibles pour les modes Stockage et Stockage + impression.
| Paramètre | Description |
|---|---|
| Champ | Champ many2many de type document.openprod dans lequel les documents générés sont ajoutés. |
| Type de génération | Fusion PDF, ZIP ou Documents séparés. |
| Nom du fichier généré | Expression Python utilisée pour calculer le nom du PDF ou du ZIP. |
| Répertoire GED | Répertoire document.directory utilisé pour les documents créés. La valeur par défaut reste le répertoire 1. |
| Type | Type GED affecté au PDF ou au ZIP créé. |
| Tags | Tags GED affectés au PDF ou au ZIP créé. |
L'expression de nommage dispose des variables object et time :
object.display_name + " - " + time.strftime("%d-%m-%Y %H:%M")
Par défaut, le nom reprend le libellé de l'objet, suivi de la date et de l'heure. Les caractères / et \\ sont remplacés pour produire un nom de fichier valide.
3.3 Impression
Ces paramètres sont disponibles pour les modes Impression et Stockage + impression.
- Type d'imprimante : permet de retrouver l'imprimante par la configuration de l'utilisateur ;
- Imprimante : imprimante précise à utiliser.
Une imprimante ou un type d'imprimante est obligatoire pour une configuration qui imprime. Une imprimante peut aussi être définie sur chaque ligne de la liasse. La configuration de ligne est prioritaire.
3.4 Liste des documents
Chaque ligne définit une source de contenu.
| Type | Utilisation |
|---|---|
| Récupérer un document Open-Prod | Récupère les documents dont les identifiants sont renvoyés par la source. |
| Imprimer un rapport | Génère un rapport pour les enregistrements renvoyés par la source. L'option Un document par enregistrement permet de produire un fichier par enregistrement. |
| Générer une sous-liasse | Exécute une autre configuration de liasse pour chaque enregistrement renvoyé. |
Une source peut être basée sur :
- une requête SQL ;
- une expression Python évaluée pour chaque objet sélectionné.
4. Sources SQL et Python
4.1 Requête SQL
La requête doit retourner les identifiants des documents ou des enregistrements du rapport. Deux variables sont disponibles :
%object_idpour un seul enregistrement ;%object_idspour plusieurs enregistrements, sous la forme d'un tuple SQL.
Exemple :
select doc.id
from stock_picking as bl
join stock_move as sm on sm.picking_id = bl.id
join internal_plan_document_openprod_rel as rel on rel.product_id = sm.product_id
join document_openprod as doc on rel.document_id = doc.id
where bl.id = %object_id
Équivalent Python :
object.move_ids.product_id.internal_plan_ids
Pour une source de rapport, la requête doit retourner les identifiants du modèle porté par le rapport. Pour une source de document, elle doit retourner des identifiants document.openprod.
4.2 Expression Python
L'expression est évaluée pour chaque enregistrement source. Les variables disponibles sont :
object: l'enregistrement courant ;env: l'environnement Open-Prod permettant d'accéder aux modèles et à leur contexte.
L'expression doit retourner des enregistrements du modèle attendu. Elle doit rester une expression unique : les affectations comme documents = ... ne sont pas autorisées.
Exemples :
object.move_ids.product_id.internal_plan_ids
object.move_ids.product_id.internal_plan_ids.filtered(
lambda document: document.state != 'obsolete'
)
Exemple d'accès à un modèle avec env :
env['traceability.link'].search([
('in_uc_label_id', 'in', object.move_ids.move_traceability_ids.uc_label_id.ids),
]).mapped('mo_id')
Les chemins one2many et many2many peuvent retourner plusieurs enregistrements. Le type retourné est contrôlé avant la génération afin d'éviter d'utiliser une expression sur un modèle incompatible.
5. Exécuter une liasse
Depuis le modèle configuré, l'action serveur associée est disponible dans les actions du document.
5.1 Assistant
L'assistant permet de :
- choisir le mode et le format de génération ;
- décocher les sources qui ne doivent pas être exécutées ;
- cliquer sur Charger pour calculer les documents et rapports ;
- décocher individuellement les résultats à exclure ;
- télécharger le PDF fusionné ou le ZIP ;
- imprimer les résultats sélectionnés ;
- valider pour stocker les documents dans le champ configuré.
Le chargement est facultatif : si l'utilisateur valide directement, les résultats sont chargés automatiquement.
5.2 Formats de sortie
- Fusion PDF : convertit les documents compatibles et les rapports en un seul PDF ;
- ZIP : regroupe les documents et rapports dans une archive ;
- Documents séparés : ajoute chaque document ou rapport individuellement au champ GED.
La fusion PDF nécessite que chaque contenu puisse être converti en PDF. Les conversions des formats bureautiques utilisent le module d'impression et, si disponible, LibreOffice ou soffice.
Attention : La génération d'un ZIP ou PDF fusionné présente l'avantage de figer les données dans le système à un instant T. Elle a cependant pour effet de dupliquer les documents GED : une fois à leur emplacement d'origine et une fois dans le ZIP/PDF. Il faut donc surveiller l'espace disque du serveur hébergeant la GED et son filestore.
5.3 Doublons GED
Lorsqu'un nouveau fichier est créé dans la GED, son nom est rendu unique dans le répertoire et pour la même extension. En cas de doublon, le module ajoute un suffixe numérique avant l'extension :
Liasse BL.pdf
Liasse BL (1).pdf
Liasse BL (2).pdf
Les documents marqués comme obsolètes ne bloquent pas la réutilisation du nom.
Les documents Open-Prod déjà existants sont réutilisés en mode Documents séparés. Les rapports nouvellement générés reçoivent un document GED avec le répertoire configuré.
6. Sous-liasses
Une ligne de type Générer une sous-liasse permet de réutiliser une configuration existante pour les enregistrements retournés par la source.
Les sous-liasses peuvent produire des documents séparés, un PDF ou un ZIP. Les références circulaires sont refusées. Une sous-liasse en mode impression peut imprimer son propre contenu sans l'ajouter au résultat stocké de la liasse parente.
Une liasse PDF ne peut pas contenir une sous-liasse ZIP, car une archive ne peut pas être intégrée dans un PDF fusionné.
7. Action serveur et exécution automatique
Le bouton Ajouter l'action crée une action serveur sur le modèle choisi. Le bouton Supprimer l'action retire l'action associée.
L'option Exécution automatique permet désormais de lancer directement la liasse depuis son action serveur. Il n'est donc plus nécessaire de créer manuellement le wizard ni de reconstruire son contexte.
Exemple de choix dynamique depuis le partenaire
bundle = object.partner_id.x_liasse_doc_partenaire_id or env['mf.docu.bundle'].browse(1)
action = bundle.mf_execute_action(objects)
La méthode mf_execute_action(objects) utilise la configuration sélectionnée et retourne l'action de l'assistant. Si Exécution automatique est activée, elle exécute directement la liasse et retourne False.
8. Exemple de configuration BL
La configuration livrée avec le module, Liasse documentaire BL, est basée sur stock.picking et peut inclure :
- les documents des articles du BL ;
- les documents des étiquettes tracées ;
- les documents des étiquettes consommées ;
- les documents des contrôles qualité terminés ;
- les ordres de fabrication liés, imprimés un par un.
La configuration peut être adaptée en remplaçant les requêtes SQL par des expressions Python lorsque les relations Open-Prod sont accessibles directement depuis l'objet.
8.1 Bibliothèque de requêtes SQL
Les requêtes doivent retourner une seule colonne contenant les identifiants attendus par la ligne de liasse. Le placeholder %object_id est remplacé par l'identifiant du BL ou de l'OF en cours de traitement.
Documents liés aux étiquettes du BL
Type de ligne : Récupérer un document Open-Prod.
select distinct doc.id
from stock_picking as bl
join stock_move as sm on sm.picking_id = bl.id
join stock_move_traceability as smt on sm.id = smt.move_id
join stock_label as sl on sl.id = smt.uc_label_id
join document_openprod_stock_label_rel as rel
on rel.stock_label_id = smt.uc_label_id
join document_openprod as doc on rel.document_openprod_id = doc.id
where bl.id = %object_id
Équivalent Python :
object.move_ids.move_traceability_ids.uc_label_id.document_ids
Ordres de fabrication liés aux étiquettes du BL
Type de ligne : Imprimer un rapport. La ligne peut être configurée avec Un document par enregistrement.
select distinct tl.mo_id
from stock_picking as bl
join stock_move as sm on sm.picking_id = bl.id
join stock_move_traceability as smt on sm.id = smt.move_id
join stock_label as sl on sl.id = smt.uc_label_id
join traceability_link as tl on tl.in_uc_label_id = sl.id
where bl.id = %object_id
Équivalent Python :
env['traceability.link'].search([
('in_uc_label_id', 'in', object.move_ids.move_traceability_ids.uc_label_id.ids),
]).mapped('mo_id')
Documents des étiquettes consommées dans les OF du BL
Type de ligne : Récupérer un document Open-Prod.
select distinct doc.id
from stock_picking as bl
join stock_move as sm on sm.picking_id = bl.id
join stock_move_traceability as smt on sm.id = smt.move_id
join stock_label as sl on sl.id = smt.uc_label_id
join traceability_link as tl on tl.in_uc_label_id = sl.id
join document_openprod_stock_label_rel as rel
on rel.stock_label_id = tl.out_uc_label_id
join document_openprod as doc on rel.document_openprod_id = doc.id
where bl.id = %object_id
Équivalent Python :
env['traceability.link'].search([
('in_uc_label_id', 'in', object.move_ids.move_traceability_ids.uc_label_id.ids),
]).mapped('out_uc_label_id.document_ids')
Documents des contrôles qualité terminés du BL
Type de ligne : Récupérer un document Open-Prod.
select distinct doc.id
from stock_picking as bl
join stock_move as sm on sm.picking_id = bl.id
join stock_move_traceability as smt on sm.id = smt.move_id
join stock_label as sl on sl.id = smt.uc_label_id
join traceability_link as tl on tl.in_uc_label_id = sl.id
join mrp_workorder as wo on tl.mo_id = wo.mo_id
join quality_control_declaration as qcd
on qcd.wo_id = wo.id and qcd.state = 'done'
join quality_control_document_openprod_rel as rel on qcd.id = rel.qcd_id
join document_openprod as doc on rel.document_id = doc.id
where bl.id = %object_id
Équivalent Python :
env['quality.control.declaration'].search([
('wo_id', 'in', env['mrp.workorder'].search([
('mo_id', 'in', env['traceability.link'].search([
('in_uc_label_id', 'in', object.move_ids.move_traceability_ids.uc_label_id.ids),
]).mapped('mo_id').ids),
]).ids),
('state', '=', 'done'),
]).mapped('document_ids')
Contrôles qualité terminés d'un OF
Type de ligne : Imprimer un rapport. La requête retourne les identifiants du modèle porté par le rapport.
select distinct qcd.id
from mrp_workorder as wo
join quality_control_declaration as qcd
on qcd.wo_id = wo.id and qcd.state = 'done'
where wo.mo_id = %object_id
Équivalent Python :
env['quality.control.declaration'].search([('wo_id', 'in', env['mrp.workorder'].search([('mo_id', '=', object.id),]).ids),('state', '=', 'done'),])
Documents d'un OF filtrés par tag
Type de ligne : Récupérer un document Open-Prod. Cette variante est utile lorsque les documents de l'OF sont classés par tag GED.
select distinct docrel.document_id
from mrp_manufacturingorder as mo
join mo_document_openprod_rel as docrel on docrel.mo_id = mo.id
join document_openprod as doc on doc.id = docrel.document_id
join document_tag_rel as tag_rel on tag_rel.document_id = doc.id
join tracker_tag as tag on tag.id = tag_rel.tag_id
where mo.id = %object_id
and tag.name = 'CLIENT'
Équivalent Python :
object.internal_plan_ids.filtered(lambda document: 'CLIENT' in document.tag_ids.mapped('name'))
9. Bonnes pratiques
- Choisir un répertoire GED dédié aux fichiers générés afin de faciliter leur classement et leur archivage.
- Utiliser des tags et un type GED pour retrouver les PDF et ZIP produits.
- Préférer le mode Documents séparés lorsque les documents doivent rester réutilisables individuellement.
- Utiliser le PDF fusionné ou le ZIP lorsque l'objectif est de figer une liasse à un instant donné.
- Tester les expressions Python sur un petit jeu de données avant de les activer automatiquement.
- Vérifier l'espace disponible du filestore lorsque des ZIP ou des PDF fusionnés sont conservés.
- Configurer une imprimante ou un type d'imprimante avant d'activer un mode d'impression.
- Éviter les références circulaires entre sous-liasses.