Dans cet article, je vous explique via un exemple concret comment vous pouvez créer et imprimer un rapport PDF à partir d'un wizard avec Odoo v13.
Exemple d’application
Imprimer un rapport de production cumulée pour une période précise.
Comment faire pour la réalisation d’un tel rapport ?
-
Analyser la structure du rapport pour voir quels sont les modules et modèles Odoo qui entreront en jeu
-
Préparer le code HTML du rapport
-
Si le rapport doit être imprimé pour une période précise, coder un wizard (fenêtre modale) qui affiche la date de début et la date de fin pour la période voulue. Sinon, il faudra juste lier l’action du rapport à un bouton comme on va le faire avec le bouton Imprimer (Print) du wizard.
-
Coder le rapport proprement dit et l’imprimer
NB: Le wizard peut afficher plusieurs autres champs qui permettront d’imprimer le rapport c’est à dire produit, matricule, nom, etc… Bref, n’importe quel champ qui pourra aider à l’impression du rapport.
Création du rapport par la pratique
1. Analyse du rapport
Le rapport de production cumulé dont il est question est un rapport qui est utilisé en production dans la fabrication de pains dans une boulangerie.
Dans un rapport pareil, on voit très bien qu’il met en jeu un tableau à 9 colonnes et que les produits qui y sont présents sont utilisés en production dans le module frabication. De plus il y’a quelques calculs à faire (Moy. par production, Moy. par Produit).
Résultat de l’analyse: Imprimer ce rapport revient à installer le module de fabrication (nom technique: mrp) puis utiliser les champs move_raw_ids (onglet Composants) et finished_move_line_ids (onglet Produits finis) du modèle mrp.production, ainsi que tout autres champs du modèle qui peut être utilisé dans le rapport.
NB: Les champs ne sont pas toujours figés dans un seul modèle. Il peut arriver que vous utilisiez les champs d’autres modèles soit en appelant ce modèle directement en utilisant self.env[nom_du_modele] ou par relation Many2one, One2many ou Many2many. Par exemple, move_line_ids.product_id permet de récupérer le produit lié au champ One2many move_line_ids.
2. Préparation du code HTML du rapport
Préparer le code HTML du rapport revient à coder en HTML/CSS la structure de ce rapport.
Dans notre cas, il s’agit d’un tableau à 9 colonnes. Généralement, j’utilise le site W3schools pour récupérer le code d’un tableau avant de l’améliorer. Pour celà, il suffit juste de taper sur la barre de recherche Google “html table w3schools” et cliquer sur le lien qui convient, puis aller sur Try it Yourself pour copier le code HTML/CSS du tableau.
3. Wizard pour l’impression du rapport
Dans ce cas ci, le wizard va contenir uniquement 2 champs: date de début et date de fin, puisqu’il s’agit d’un rapport de production pour une période précise. Maintenant, nous allons créer le wizard pas à pas.
Créer un nouveau module ou utiliser un module existant. Dans mon cas, je vais créer le module px_mrp, et mettre les informations nécessaires dans le fichier manifest du module.
Dans le dossier wizard, créer les modèles et vues du wizard en question
-
Modèle Python
https://gist.github.com/nasser-bloopark/24573d971918a60ea83dc7fe1ddff024
- Vue XML
Il faut créer un fichier XML Odoo et y insérer le code suivant:
https://gist.github.com/nasser-bloopark/eb41041028bef4d744e91bb8000fb511
Explication du code
-
Au niveau de la vue, il faut définir le menu à partir duquel sera imprimé le rapport PDF lorsqu’on utilise le wizard. Pour celà, il faut une action et un menu qui va exécuter l’action. Le menu du wizard sera présent au niveau du menu Analyse (external ID: mrp.menu_mrp_reporting) dans le module Fabrication.
-
Les champs du modèle sont présents dans la vue XML grâce au tag
-
Le modèle à partir duquel on veut imprimer le rapport (cumulative.production.wizard) est définie dans la vue XML à partir du tag et au niveau de l’action.
-
print_report() est la fonction python présente dans le modèle. Il est lié au bouton Print et sera exécuté pour imprimer le rapport. Nous allons en parler plus bas.
-
Après avoir importé ces fichiers dans le fichier init (pour le fichier python) et manifest (pour le fichier xml), il faut installer ou mettre à jour le module et le tour est joué. Vous obtiendrez ceci:
4. Codage et impression du rapport proprement dit
Après avoir affiché le wizard pour l’impression du rapport, l’utilisateur n’aura qu’à entrer les dates de début et date de fin, avant de cliquer sur Imprimer (Print). Lorsqu’il clique dessus, tout un ensemble de logique se déclenche comme la récupération des données dans la BD, leur assignation aux variables nécéssaires et l’impression du rapport avec les données récupérées. Toute cette logique doit être codée dans le dossier report du module.
-
Modèle Python
https://gist.github.com/nasser-bloopark/a4cd61a797673c169dd09ff6641ca0bb
Explication du code:
-
Il faut tout d’abord créer une classe python de type models.AbstractModel() dont le nom (_name) sera report.nom_du_module.xml_id_template_du_rapport dans notre cas report.px_mrp.cumulative_production_report avec px_mrp le nom du module, cumulative_production_report l’ID du template XML du rapport
-
La fonction _get_data(self, start_date, end_date) est juste une fonction dans laquelle on définit toute la logique du rapport PDF. Toutes les conditions pour obtenir les données recherchées sont ici. Dans notre cas, cette fonction prend en paramètre les champs start_date et end_date et retourne une liste de données basée sur ces champs.
-
La variable form qui se trouve dans la fonction _get_report_values(self, docids, data) contient toutes les données que l'utilisateur entre dans le formulaire au niveau du wizard. Vous pouvez l'utiliser pour récupérer ces données.
-
Enfin, _get_report_values(self, docids, data) est une fonction sans laquelle le rapport ne peut être imprimé. Cette fonction est obligatoire et retourne un dictionnaire de données. Les arguments de cette fonction sont passées à partir du wizard dans la fonction print_report()
https://gist.github.com/nasser-bloopark/6222c37b5a514a24a00110504a96755b
On se rend compte que la fonction print_report() retourne une action qui prend en paramètre la définition du rapport dans le XML (px_mrp.report_cumulative_production_report, px_mrp étant le nom du module et report_cumulative_production_report, l’ID de la définition du rapport dans le XML de ce rapport)
-
Vue XML
Toujours dans le dossier report, il faut créer un fichier XML et y mettre le code correspondant comme celui-ci
Le template
https://gist.github.com/nasser-bloopark/0d1a60e51de77538156b467a060a610a
Le template doit être exactement comme celui ci, avec pour seule différence la définition de l’ID du template (cumulative_production_report) qui est utilisé dans le nom (_name) du rapport dans le modèle Python (report.px_mrp.cumulative_production_report).
Puis, il faut insérer dans la div "page" le code HTML du rapport. Pour afficher les données, il suffit juste de boucler sur l'objet data retournée par le dictionnaire au niveau de l’AbstractModel dans le return de la fonction:
https://gist.github.com/nasser-bloopark/e37c37626280bb2fada6042759231dd6
Au niveau du XML, vous pouvez voir le t-foreach "data" qui permet de boucler sur data et afficher les données via le span t-esc.
On peut aussi voir span t-esc="print_time" qui permet d’afficher la date d’impression du rapport. Vous pouvez voir que print_time est aussi présent dans le return de la classe.
La définition du rapport
Le rapport est définit par le code
https://gist.github.com/nasser-bloopark/58efab1721152833ab60d72311a6fc9f
C’est l’ID de cette action qui est appelé au niveau du print_report() dans return self.env.ref('px_mrp.report_cumulative_production_report').report_action(self, data=data)
Et voici le résultat, il suffit d’y appliquer du CSS et le tour est joué