From 36684faf5d1ac3126164219e932b1e169f1e56fc Mon Sep 17 00:00:00 2001 From: fkantelberg Date: Thu, 4 Apr 2024 08:59:22 +0200 Subject: [PATCH] [IMP] datev_export_xml: Allow previous validation to see all errors on invoices. Fix some edge cases like fully discounted lines --- datev_export_xml/models/account_move.py | 1 + datev_export_xml/models/datev_export.py | 39 +++++++++++++++++-- .../models/datev_xml_generator.py | 10 ++++- .../views/account_invoice_view.xml | 12 ++++++ datev_export_xml/views/datev_export_views.xml | 20 ++++++++++ datev_export_xml/views/templates.xml | 28 +++++++++++-- 6 files changed, 102 insertions(+), 8 deletions(-) diff --git a/datev_export_xml/models/account_move.py b/datev_export_xml/models/account_move.py index ec0f2b8d..9fa12f92 100644 --- a/datev_export_xml/models/account_move.py +++ b/datev_export_xml/models/account_move.py @@ -43,6 +43,7 @@ class AccountMove(models.Model): help="When finishing a datev export the processed invoices are marked as exported.\n" "If you need to export the invoices again, set this field to False.", ) + datev_validation = fields.Text() def datev_format_total(self, value, prec=2): self.ensure_one() diff --git a/datev_export_xml/models/datev_export.py b/datev_export_xml/models/datev_export.py index 6aab9bd1..00e2f0aa 100644 --- a/datev_export_xml/models/datev_export.py +++ b/datev_export_xml/models/datev_export.py @@ -122,6 +122,9 @@ def name_get(self): compute="_compute_datev_filesize", ) + problematic_invoices_count = fields.Integer( + compute="_compute_problematic_invoices_count" + ) invoice_ids = fields.Many2many(comodel_name="account.move", string="Invoices") invoices_count = fields.Integer(compute="_compute_invoices_count", store=True) @@ -148,6 +151,13 @@ def _compute_datev_filesize(self): for r in self: r.datev_filesize = human_size(r.attachment_id.file_size) + @api.depends("invoice_ids") + def _compute_problematic_invoices_count(self): + for r in self: + r.problematic_invoices_count = len( + r.invoice_ids.filtered("datev_validation") + ) + @api.depends("invoice_ids") def _compute_invoices_count(self): for r in self: @@ -256,6 +266,8 @@ def get_zip(self): self.write({"exception_info": msg, "state": "failed"}) _logger.exception(e) + self._compute_problematic_invoices_count() + @api.model def cron_run_pending_export(self): """ @@ -351,6 +363,16 @@ def _create_activity(self): } ) + def action_validate(self): + generator = self.env["datev.xml.generator"] + for invoice in self.invoice_ids: + try: + generator.generate_xml_invoice(invoice) + except UserError: + pass + + self._compute_problematic_invoices_count() + def action_done(self): self.filtered(lambda r: r.state in ["running", "failed"]).write( { @@ -391,10 +413,21 @@ def action_draft(self): ) r.write({"state": "draft"}) + def action_show_invalid_invoices_view(self): + tree_view = self.env.ref("datev_export_xml.view_move_datev_validation") + return { + "type": "ir.actions.act_window", + "view_mode": "tree,form", + "views": [[tree_view.id, "tree"], [False, "form"]], + "res_model": "account.move", + "target": "current", + "name": _("Problematic Invoices"), + "domain": [("id", "in", self.invoice_ids.filtered("datev_validation").ids)], + } + def action_show_related_invoices_view(self): return { "type": "ir.actions.act_window", - "view_type": "form", "view_mode": "tree,kanban,form", "res_model": "account.move", "target": "current", @@ -409,7 +442,7 @@ def unlink(self): return res def write(self, vals): - super().write(vals) + res = super().write(vals) if any( r in vals for r in [ @@ -426,7 +459,7 @@ def write(self, vals): super(DatevExport, r).write( {"invoice_ids": [(6, 0, r.get_invoices().ids)]} ) - return True + return res @api.model def create(self, vals): diff --git a/datev_export_xml/models/datev_xml_generator.py b/datev_export_xml/models/datev_xml_generator.py index 9c733bde..407a6a59 100644 --- a/datev_export_xml/models/datev_xml_generator.py +++ b/datev_export_xml/models/datev_xml_generator.py @@ -24,16 +24,23 @@ class DatevXmlGenerator(models.AbstractModel): _description = "DATEV XML Generator" @api.model - def check_xml_file(self, doc_name, root, xsd=None): + def check_xml_file(self, doc_name, root, xsd=None, invoice=None): if not xsd: xsd = "Document_v050.xsd" schema = tools.file_open(f"datev_export_xml/xsd_files/{xsd}") try: + if invoice: + invoice.datev_validation = False + schema = etree.XMLSchema(etree.parse(schema)) schema.assertValid(root) except (etree.DocumentInvalid, etree.XMLSyntaxError) as e: _logger.warning(etree.tostring(root)) + + if invoice: + invoice.datev_validation = str(e) + raise UserError( _( "Wrong Data in XML file!\nTry to solve the problem with " @@ -96,6 +103,7 @@ def generate_xml_invoice(self, invoice, check_xsd=True): doc_name, root, "Belegverwaltung_online_invoice_v050.xsd", + invoice=invoice, ) return doc_name, etree.tostring(root) diff --git a/datev_export_xml/views/account_invoice_view.xml b/datev_export_xml/views/account_invoice_view.xml index c86ac245..417ee5df 100644 --- a/datev_export_xml/views/account_invoice_view.xml +++ b/datev_export_xml/views/account_invoice_view.xml @@ -13,6 +13,18 @@ + + account.move + primary + 800 + + + + + + + + account.move diff --git a/datev_export_xml/views/datev_export_views.xml b/datev_export_xml/views/datev_export_views.xml index 59265b73..137ac7b2 100644 --- a/datev_export_xml/views/datev_export_views.xml +++ b/datev_export_xml/views/datev_export_views.xml @@ -85,6 +85,12 @@ attrs="{'invisible': ['|', ('state', 'not in', ['done', 'pending', 'failed']), ('manually_document_selection', '=', True)]}" confirm="Do you really want to set the export to draft?" /> + + diff --git a/datev_export_xml/views/templates.xml b/datev_export_xml/views/templates.xml index c6856d79..46ab9073 100644 --- a/datev_export_xml/views/templates.xml +++ b/datev_export_xml/views/templates.xml @@ -3,7 +3,7 @@