diff --git a/l10n_br_mdfe/__init__.py b/l10n_br_mdfe/__init__.py index cc6b6354ad8f..ee3b8ee6dfd6 100644 --- a/l10n_br_mdfe/__init__.py +++ b/l10n_br_mdfe/__init__.py @@ -1,2 +1,3 @@ -from . import models from .hooks import post_init_hook +from . import models +from . import report diff --git a/l10n_br_mdfe/__manifest__.py b/l10n_br_mdfe/__manifest__.py index 2901b17eda10..54f2dd37a91e 100644 --- a/l10n_br_mdfe/__manifest__.py +++ b/l10n_br_mdfe/__manifest__.py @@ -18,8 +18,11 @@ "spec_driven_model", ], "data": [ - "security/ir.model.access.csv", + # Data "data/ir_config_parameter.xml", + # Security + "security/ir.model.access.csv", + # Views "views/document.xml", "views/mdfe_action.xml", "views/mdfe_menu.xml", @@ -30,6 +33,10 @@ "views/modal/modal_aquaviario.xml", "views/modal/modal_rodoviario.xml", "views/modal/modal_ferroviario.xml", + # Report + "report/reports.xml", + "report/damdfe_mdfe.xml", + "report/damdfe_report.xml", ], "demo": [ "demo/fiscal_document_demo.xml", diff --git a/l10n_br_mdfe/models/document.py b/l10n_br_mdfe/models/document.py index 268dc2cf06c5..c5ac54095d2b 100644 --- a/l10n_br_mdfe/models/document.py +++ b/l10n_br_mdfe/models/document.py @@ -1,6 +1,7 @@ # Copyright 2023 KMEE # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import base64 import re import string from enum import Enum @@ -914,3 +915,23 @@ def _validate_xml(self, xml_file): erros = Mdfe.schema_validation(xml_file) erros = "\n".join(erros) self.write({"xml_error_message": erros or False}) + + def make_pdf(self): + if not self.filtered(filtered_processador_edoc_mdfe): + return super().make_pdf() + + attachment_data = { + "name": self.document_key + ".pdf", + "res_model": self._name, + "res_id": self.id, + "mimetype": "application/pdf", + "type": "binary", + } + report = self.env.ref("l10n_br_mdfe.report_damdfe") + pdf_data = report._render_qweb_pdf(self.fiscal_line_ids.document_id.ids) + attachment_data["datas"] = base64.b64encode(pdf_data[0]) + file_pdf = self.file_report_id + self.file_report_id = False + file_pdf.unlink() + + self.file_report_id = self.env["ir.attachment"].create(attachment_data) diff --git a/l10n_br_mdfe/report/__init__.py b/l10n_br_mdfe/report/__init__.py new file mode 100644 index 000000000000..a248cf2162f5 --- /dev/null +++ b/l10n_br_mdfe/report/__init__.py @@ -0,0 +1 @@ +from . import ir_actions_report diff --git a/l10n_br_mdfe/report/damdfe_mdfe.xml b/l10n_br_mdfe/report/damdfe_mdfe.xml new file mode 100644 index 000000000000..adb936eb8a41 --- /dev/null +++ b/l10n_br_mdfe/report/damdfe_mdfe.xml @@ -0,0 +1,165 @@ + + + + diff --git a/l10n_br_mdfe/report/damdfe_report.xml b/l10n_br_mdfe/report/damdfe_report.xml new file mode 100644 index 000000000000..03312f4c60bf --- /dev/null +++ b/l10n_br_mdfe/report/damdfe_report.xml @@ -0,0 +1,12 @@ + + + DAMDFE + l10n_br_fiscal.document + qweb-pdf + main_template_damdfe + main_template_damdfe + '%s' % (object.document_key) + + report + + diff --git a/l10n_br_mdfe/report/ir_actions_report.py b/l10n_br_mdfe/report/ir_actions_report.py new file mode 100644 index 000000000000..a6ff27ffe7dd --- /dev/null +++ b/l10n_br_mdfe/report/ir_actions_report.py @@ -0,0 +1,111 @@ +# Copyright 2024 Engenere.one +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import base64 +import logging +from io import BytesIO + +from brazilfiscalreport.dacte import Dacte, DacteConfig, Margins +from erpbrasil.edoc.pdf import base +from lxml import etree + +from odoo import _, api, models +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + + +class IrActionsReport(models.Model): + _inherit = "ir.actions.report" + + def temp_xml_autorizacao(self, xml_string): + """TODO: Migrate-me to erpbrasil.edoc.pdf ASAP""" + root = etree.fromstring(xml_string) + ns = {None: "http://www.portalfiscal.inf.br/cte"} + new_root = etree.Element("cteProc", nsmap=ns) + + protCTe_node = etree.Element("protCTe") + infProt = etree.SubElement(protCTe_node, "infProt") + etree.SubElement(infProt, "tpAmb").text = "2" + etree.SubElement(infProt, "verAplic").text = "" + etree.SubElement(infProt, "dhRecbto").text = None + etree.SubElement(infProt, "nProt").text = "" + etree.SubElement(infProt, "digVal").text = "" + etree.SubElement(infProt, "cStat").text = "" + etree.SubElement(infProt, "xMotivo").text = "" + + new_root.append(root) + new_root.append(protCTe_node) + return etree.tostring(new_root) + + def _render_qweb_html(self, res_ids, data=None): + if self.report_name == "main_template_dacte": + return + + return super()._render_qweb_html(res_ids, data=data) + + def _render_qweb_pdf(self, res_ids, data=None): + if self.report_name not in ["main_template_dacte"]: + return super()._render_qweb_pdf(res_ids, data=data) + + cte = self.env["l10n_br_fiscal.document"].search([("id", "in", res_ids)]) + + return self._render_dacte(cte) + + def _render_dacte(self, cte): + if cte.document_type != "57": + raise UserError(_("You can only print a DACTE of a NFe(57).")) + + cte_xml = False + if cte.authorization_file_id: + cte_xml = base64.b64decode(cte.authorization_file_id.datas) + elif cte.send_file_id: + cte_xml = base64.b64decode(cte.send_file_id.datas) + + if not cte_xml: + raise UserError(_("No xml file was found.")) + + return self.render_dacte_brazilfiscalreport(cte, cte_xml) + + def render_dacte_brazilfiscalreport(self, cte, cte_xml): + logo = False + if cte.issuer == "company" and cte.company_id.logo: + logo = base64.b64decode(cte.company_id.logo) + elif cte.issuer != "company" and cte.company_id.logo_web: + logo = base64.b64decode(cte.company_id.logo_web) + + if logo: + tmpLogo = BytesIO() + tmpLogo.write(logo) + tmpLogo.seek(0) + else: + tmpLogo = False + config = self._get_dacte_config(tmpLogo, cte.company_id) + + dacte = Dacte(xml=cte_xml, config=config) + + tmpDacte = BytesIO() + dacte.output(tmpDacte) + dacte_file = tmpDacte.getvalue() + tmpDacte.close() + + return dacte_file, "pdf" + + @api.model + def _get_dacte_config(self, tmpLogo, company): + margins = Margins( + top=company.dacte_margin_top, + right=company.dacte_margin_right, + bottom=company.dacte_margin_bottom, + left=company.dacte_margin_left, + ) + dacte_config = { + "logo": tmpLogo, + "margins": margins, + } + return DacteConfig(**dacte_config) + + def render_dacte_erpbrasil(self, cte_xml): + pdf = base.ImprimirXml.imprimir( + string_xml=cte_xml, + ) + return pdf, "pdf" diff --git a/l10n_br_mdfe/report/reports.xml b/l10n_br_mdfe/report/reports.xml new file mode 100644 index 000000000000..60c8aa1a9948 --- /dev/null +++ b/l10n_br_mdfe/report/reports.xml @@ -0,0 +1,29 @@ + + + + + DAMDFE MDFE-e qweb paper format + + custom + 297 + 56 + Portrait + 0.5 + 0.5 + 0.5 + 0.5 + + 10 + 110 + + + + DAMDFE MDF-e + account.move + qweb-html + l10n_br_mdfe.report_damdfe_mdfe + l10n_br_mdfe.damdfe_mdfe + + + +