{"id":650,"date":"2025-07-22T12:48:16","date_gmt":"2025-07-22T12:48:16","guid":{"rendered":"https:\/\/sienna-manatee-218967.hostingersite.com\/blogs\/tipos-personalizados-de-reportes-2\/"},"modified":"2026-05-04T03:59:33","modified_gmt":"2026-05-04T03:59:33","slug":"tipos-personalizados-de-reportes","status":"publish","type":"post","link":"https:\/\/exdoo.mx\/blogs\/tipos-personalizados-de-reportes\/","title":{"rendered":"Tipos personalizados de reportes"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/reportes-b2-ALpPyK8wkPFbbJLV-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<p class=\"body\" dir=\"auto\"><span><em><u>\u00bfQu\u00e9 es <a href=\"http:\/\/ir.actions.report\" class=\"qbe-widget\" rel=\"noopener noreferrer\" target=\"_blank\">ir.actions.report<\/a>?<\/u><\/em><\/span><\/p>\n<div style=\"background:linear-gradient(135deg,#0A7099 0%,#0d8db8 100%);color:#fff;padding:28px 26px;border-radius:16px;margin:0 0 28px;box-shadow:0 4px 16px rgba(10,112,153,.2);\">\n<div style=\"display:inline-block;background:rgba(255,255,255,.18);padding:6px 14px;border-radius:20px;font-size:12px;font-weight:700;letter-spacing:.5px;margin-bottom:12px;color:#fff;\">\ud83d\udcd8 ART\u00cdCULO T\u00c9CNICO<\/div>\n<p style=\"font-size:16px;line-height:1.6;margin:0;color:#fff;opacity:.95;\">En Odoo, ir.actions.report es un modelo (model) que define acciones de reporte.<\/p>\n<\/div>\n<p class=\"body\" dir=\"auto\"><span>Sirve para configurar y ejecutar la generaci\u00f3n de reportes (PDF, HTML, XML, etc.). Cuando creas un reporte en Odoo (por ejemplo, una factura en PDF), este se representa como un registro en <a href=\"http:\/\/ir.actions.report\" class=\"qbe-widget\" rel=\"noopener noreferrer\" target=\"_blank\">ir.actions.report<\/a>.<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span><em><u>\u00bfQu\u00e9 son los \u201chandlers\u201d?<\/u><\/em><\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>Los handlers de <a href=\"http:\/\/ir.actions.report\" class=\"qbe-widget\" rel=\"noopener noreferrer\" target=\"_blank\">ir.actions.report<\/a> son m\u00e9todos que procesan la generaci\u00f3n del reporte.<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>Son los controladores que se encargan de renderizar el contenido final.<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>Por ejemplo:<\/span><\/p>\n<ul style=\"padding-left:22px;line-height:1.9;\">\n<li><span>Si el report_type es qweb-pdf: Se invoca el handler para convertir la plantilla QWeb en PDF.<\/span><\/li>\n<li><span>Si es qweb-html: El handler renderiza HTML.<\/span><\/li>\n<li><span>Si es controller: Se usa una URL y un controlador HTTP para generar el contenido din\u00e1mico.<\/span><\/li>\n<li><span>Si es py o report_py: Se llama a un m\u00e9todo Python personalizado.<\/span><\/li>\n<\/ul>\n<p class=\"body\" dir=\"auto\"><span><em><u>\u00bfPara qu\u00e9 se usan?<\/u><\/em><\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>Los handlers hacen posible que<\/span><\/p>\n<ul style=\"padding-left:22px;line-height:1.9;\">\n<li><span>El usuario pueda imprimir o descargar un PDF (facturas, pedidos, cotizaciones, etc.).<\/span><\/li>\n<li><span>Los reportes puedan ser convertidos a diferentes formatos seg\u00fan la l\u00f3gica definida.<\/span><\/li>\n<li><span>Se puedan extender o reemplazar: por ejemplo, puedes heredar <a href=\"http:\/\/ir.actions.report\" class=\"qbe-widget\" rel=\"noopener noreferrer\" target=\"_blank\">ir.actions.report<\/a> y definir un handler Python propio para personalizar la salida.<\/span><\/li>\n<li><span>Declarar un nuevo tipo de reporte a descargar.<\/span><\/li>\n<\/ul>\n<p class=\"body\" dir=\"auto\"><span><strong>Ejemplo de creaci\u00f3n de un nuevo tipo de reportes<\/strong><\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>Heredamos la vista lista de las cotizaciones (modelo sale.order) y a\u00f1adimos un bot\u00f3n que acciona una funci\u00f3n dentro del elemento &lt;header&gt; de la siguiente manera:<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/1-YNq2QGNJ1gcoGjNL-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span>El bot\u00f3n anterior acciona la funci\u00f3n action_csv_test, misma que definimos dentro del modelo sale.order de la siguiente manera:<\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/2-YNq2QGrW7Wu2aQND-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span>Hasta aqu\u00ed tenemos lo siguiente:<\/span><\/h3>\n<ul style=\"padding-left:22px;line-height:1.9;\">\n<li><span>Cuando seleccionamos uno o m\u00e1s registros del modelo de cotizaciones desde la vista lista, se muestra un bot\u00f3n llamado \u2018Imprimir reporte CSV\u2019, el cual ejecuta la funci\u00f3n action_csv_test definida desde el modelo sale.order.<\/span><\/li>\n<li><span>La funci\u00f3n action_csv_test devuelve un registro del modelo \u2018<a href=\"http:\/\/ir.actions.report\" class=\"qbe-widget\" rel=\"noopener noreferrer\" target=\"_blank\">ir.actions.report<\/a>\u2019, mismos que definen acciones de reporte. Son configuraciones que enlazan una plantilla de reporte (PDF, HTML, XML, etc.) con un modelo.<\/span><\/li>\n<li><span>Dentro de los datos a enviar tenemos:<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>&nbsp;-Nombre del modelo (sale.order).<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>&nbsp;-Opciones, dentro de las cuales agregamos los IDs de los registros sale.order de los que generaremos el reporte.<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>&nbsp;-Formato de salida, el cual ser\u00e1 \u2018csv_test\u2019. Este no es un formato de archivo, simplemente se utiliza como identificador para validar el formato correcto a utilizar.<\/span><\/p>\n<p class=\"body\" dir=\"auto\"><span>&nbsp; -Nombre del reporte, el cual ser\u00e1 \u2018Venta_CSV\u2019 m\u00e1s la extensi\u00f3n del archivo.<\/span><\/li>\n<li><span>Agregamos \u2018csv_test\u2019 en el campo \u2018report_type\u2019. En este campo pudimos haber agregado cualquier nombre que quisi\u00e9ramos, ya que ese nombre lo declararemos como un nuevo tipo de reportes a utilizar. En este caso, el nuevo tipo de reporte se llamar\u00e1 \u2018csv_test\u2019.<\/span><\/li>\n<\/ul>\n<p class=\"body\" dir=\"auto\"><span>Al tener los anteriores archivos mapeados dentro del m\u00f3dulo, creamos desde un archivo JavaScript el nuevo tipo de reporte. La estructura del c\u00f3digo es la siguiente:<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/3-Yyv0grOR4xIjqBXg-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span>Desde este archivo se est\u00e1 declarando el nuevo tipo de reportes llamado \u2018csv_test\u2019. Lo que har\u00e1 es, que cuando se genere un reporte de este tipo, llamar\u00e1 a la URL \/csv_test_report de un controlador, y el resultado lo descargar\u00e1. Este archivo se debe declarar desde los assets \u2018web.assets_backend\u2019 dentro del m\u00f3dulo.<\/span><\/h3>\n<p class=\"body\" dir=\"auto\"><span>Ahora que sabemos que el nuevo tipo de reporte llamar\u00e1 a una URL de un controlador, es hora de declararla. Creamos el siguiente controlador dentro de un archivo mapeado en la carpeta controladores del m\u00f3dulo, de la siguiente manera:<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/4-AoPJgXrza9UM9LG5-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<ul style=\"padding-left:22px;line-height:1.9;\">\n<li>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span>Declaramos el controlador CSVTestController, donde su URL \/csv_test_report es la que generar\u00e1 el reporte.<\/span><\/h3>\n<\/li>\n<li><span>A trav\u00e9s de los par\u00e1metros, obtenemos el modelo y los ids de los registros de los cuales generaremos el reporte. En este caso, generamos un reporte CSV donde la primer columna, ID, ser\u00e1 el id del registro, lo mismo con las columnas orden y partner, que ser\u00e1n la segunda y tercera, respectivamente.<\/span><\/li>\n<li><span>Validamos el par\u00e1metro output_format y si es igual a \u2018csv_test\u2019 descargamos el archivo CSV.<\/span><\/li>\n<\/ul>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span>Al tener los anteriores archivos mapeados dentro del m\u00f3dulo, generamos el reporte de la siguiente manera: seleccionamos varias ventas, se muestra el bot\u00f3n \u2018Imprimir reporte CSV\u2019, lo presionamos y se descarga el reporte.<\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/5-Aq2Jg9RE7lhX451J-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span>El cual se ve de la siguiente manera (al abrirlo desde libreoffice y desde un editor de texto plano):<\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/6-mePJq79wKyu52jOY-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><br \/>\n<img decoding=\"async\" src=\"https:\/\/exdoo.mx\/blogs\/wp-content\/uploads\/2026\/05\/6.1-YBgb9aDqRaiRGwVv-2.png\" alt=\"\"  style=\"max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 8px rgba(0,0,0,0.12);display:block;margin:14px auto;\" \/><\/p>\n<h3 style=\"color:#0A7099;margin-top:24px;\"><span><strong>Consejos r\u00e1pidos:<\/strong><\/span><\/h3>\n<ul style=\"padding-left:22px;line-height:1.9;\">\n<li><span>Define claramente si necesitas qweb-pdf, qweb-html o un controller especial. Usa qweb-pdf para documentos que se descargar\u00e1n en PDF.<\/span><\/li>\n<li><span>Si necesitas cambiar la forma de renderizar un reporte existente, hereda la clase <a href=\"http:\/\/ir.actions.report\" class=\"qbe-widget\" rel=\"noopener noreferrer\" target=\"_blank\">ir.actions.report<\/a> y redefine solo lo necesario.<\/span><\/li>\n<li><span>Aunque el uso principal de los handlers dentro de Odoo es para declarar nuevos tipos de reportes, existen m\u00f3dulos que los utilizan para llamar m\u00e9todos JavaScript y extender cierta funcionalidad. Entre ellos, est\u00e1n los m\u00f3dulos iot o pos_iot.<\/span><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u00bfQu\u00e9 es ir.actions.report? \ud83d\udcd8 ART\u00cdCULO T\u00c9CNICO En Odoo, ir.actions.report es un modelo (model) que define acciones de reporte. Sirve para configurar y ejecutar la generaci\u00f3n de reportes (PDF,\u2026<\/p>\n","protected":false},"author":4,"featured_media":641,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[],"class_list":["post-650","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"_links":{"self":[{"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/posts\/650","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/comments?post=650"}],"version-history":[{"count":3,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/posts\/650\/revisions"}],"predecessor-version":[{"id":1975,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/posts\/650\/revisions\/1975"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/media\/641"}],"wp:attachment":[{"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/media?parent=650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/categories?post=650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/exdoo.mx\/blogs\/wp-json\/wp\/v2\/tags?post=650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}