From ba852367adeeb050218d1c3b0f4cb2c5b0618de1 Mon Sep 17 00:00:00 2001 From: almumu Date: Fri, 27 Jun 2025 14:57:37 +0200 Subject: [PATCH] =?UTF-8?q?a=C3=B1adido=20compatibilidad=20y=20herencia=20?= =?UTF-8?q?que=20faltaba=20con=20aeat.mixin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- l10n_es_verifactu/models/account_move.py | 49 ++----------- l10n_es_verifactu/models/verifactu_mixin.py | 67 +----------------- .../models/verifactu_send_queue.py | 34 +++++++++- l10n_es_verifactu/views/account_move_view.xml | 68 ++++++++++++++----- 4 files changed, 90 insertions(+), 128 deletions(-) diff --git a/l10n_es_verifactu/models/account_move.py b/l10n_es_verifactu/models/account_move.py index 415a5241e4b..3ce85ad1327 100644 --- a/l10n_es_verifactu/models/account_move.py +++ b/l10n_es_verifactu/models/account_move.py @@ -319,7 +319,8 @@ def _get_verifactu_invoice_dict_out(self, cancel=False): "Huella": self.verifactu_hash, } ) - if self.verifactu_send_state in ["incorrect", "accepted_with_errors"]: + if self.aeat_state == "sent_w_errors": + # en caso de subsanación, debe generar un nuevo hash en la factura inv_dict.update( { "Subsanacion": "S", @@ -526,7 +527,7 @@ def _get_verifactu_qr_values(self): def _post(self, soft=True): res = super()._post(soft=soft) for record in self: - if record.verifactu_enabled and record.verifactu_send_state == "not_sent": + if record.verifactu_enabled and record.aeat_state == "not_sent": record._check_verifactu_configuration() record.verifactu_registration_date = datetime.now() record._generate_verifactu_chaining() @@ -636,7 +637,7 @@ def cancel_verifactu(self): def write(self, vals): for invoice in self.filtered( - lambda x: x.is_invoice() and x.verifactu_send_state != "not_sent" + lambda x: x.is_invoice() and x.aeat_state != "not_sent" ): if invoice.move_type in ["out_invoice", "out_refund"]: if "invoice_date" in vals: @@ -647,21 +648,9 @@ def write(self, vals): self._raise_exception_verifactu(_("invoice number")) return super().write(vals) - def _compute_verifactu_send_state(self): - for rec in self: - rec.verifactu_send_state = "not_sent" - # Check the state from the last - send_queue = ( - rec.verifactu_send_queue_ids - and rec.verifactu_send_queue_ids[0] - or False - ) - if send_queue: - rec.verifactu_send_state = send_queue.send_state - def button_cancel(self): invoices_sent = self.filtered( - lambda inv: inv.verifactu_enabled and inv.verifactu_send_state != "not_sent" + lambda inv: inv.verifactu_enabled and inv.aeat_state != "not_sent" ) if invoices_sent: raise UserError(_("You can not cancel invoices sent to verifactu")) @@ -669,38 +658,12 @@ def button_cancel(self): def button_draft(self): invoices_sent = self.filtered( - lambda inv: inv.verifactu_enabled and inv.verifactu_send_state != "not_sent" + lambda inv: inv.verifactu_enabled and inv.aeat_state != "not_sent" ) if invoices_sent: raise UserError(_("You can not set to draft invoices sent to verifactu")) return super().button_draft() - def _compute_verifactu_csv(self): - for rec in self: - rec.verifactu_csv = "" - # Check the state from the last - send_queue = ( - rec.verifactu_send_queue_ids - and rec.verifactu_send_queue_ids[0] - or False - ) - if send_queue: - last_response = send_queue.response_ids and send_queue.response_ids[0] - rec.verifactu_csv = last_response.verifactu_csv - - def _search_verifactu_send_state(self, operator, value): - queue_recs = self.env["verifactu.send.queue"].search( - [ - ("send_state", operator, value), - ("move_id", "!=", False), - ] - ) - if (operator == "=" and value) or (operator == "!=" and not value): - new_operator = "in" - else: - new_operator = "not in" - return [("id", new_operator, queue_recs.mapped("move_id").ids)] - def resend_verifactu(self): for rec in self: rec.verifactu_send_queue_ids.write({"correction": True}) diff --git a/l10n_es_verifactu/models/verifactu_mixin.py b/l10n_es_verifactu/models/verifactu_mixin.py index 59ae6002d68..bdff155b0a9 100644 --- a/l10n_es_verifactu/models/verifactu_mixin.py +++ b/l10n_es_verifactu/models/verifactu_mixin.py @@ -21,13 +21,6 @@ qrcode = None _logger.error(err) -VERIFACTU_SEND_STATES = [ - ("not_sent", "Not sent"), - ("correct", "Sent and Correct"), - ("incorrect", "Sent and Incorrect"), - ("accepted_with_errors", "Sent and accepted with errors"), -] - ########################################### # revisar los imports que no hagan falta # cuando funcione bien el _connect_aeat sin tener que poner @@ -44,6 +37,7 @@ class VerifactuMixin(models.AbstractModel): _name = "verifactu.mixin" + _inherit = "aeat.mixin" _description = "Verifactu Mixin" verifactu_enabled = fields.Boolean( @@ -71,6 +65,7 @@ class VerifactuMixin(models.AbstractModel): "greater o equal to 100 000 000,00 euros.", compute="_compute_verifactu_macrodata", ) + verifactu_csv = fields.Char(copy=False, readonly=True) verifactu_return = fields.Text(copy=False, readonly=True) verifactu_registration_date = fields.Datetime(copy=False) verifactu_registration_key = fields.Many2one( @@ -98,32 +93,6 @@ class VerifactuMixin(models.AbstractModel): copy=False, ) verifactu_send_date = fields.Datetime(index=True, copy=False) - verifactu_send_state = fields.Selection( - selection=VERIFACTU_SEND_STATES, - string="Verifactu send state", - compute="_compute_verifactu_send_state", - search="_search_verifactu_send_state", - readonly=True, - copy=False, - help="Indicates the state of this document in relation with the " - "presentation to Verifactu.", - ) - verifactu_csv = fields.Char( - string="Verifactu CSV", - compute="_compute_verifactu_csv", - readonly=True, - copy=False, - help="Indicates the CSV of the latest verifactu response.", - ) - - def _compute_verifactu_send_state(self): - raise NotImplementedError - - def _search_verifactu_send_state(self, operator, value): - raise NotImplementedError - - def _compute_verifactu_csv(self): - raise NotImplementedError @api.model def _selection_verifactu_reference_models(self): @@ -219,38 +188,6 @@ def _connect_verifactu_params_aeat(self, mapping_key): agency = self.env.ref("l10n_es_aeat.aeat_tax_agency_spain") return agency._connect_params_verifactu(self.company_id) - def _get_verifactu_aeat_header(self, tipo_comunicacion=False, cancellation=False): - """Builds VERIFACTU send header - - :param tipo_comunicacion String 'A0': new reg, 'A1': modification - :param cancellation Bool True when the communitacion es for document - cancellation - :return Dict with header data depending on cancellation - """ - self.ensure_one() - if not self.company_id.vat: - raise UserError( - _("No VAT configured for the company '{}'").format(self.company_id.name) - ) - header = { - "ObligadoEmision": { - "NombreRazon": self.company_id.name[0:120], - "NIF": self.company_id.partner_id._parse_aeat_vat_info()[2], - }, - } - registration_date = self.verifactu_registration_date - # Si han pasado más de 120 segundos de la fecha y hora de emisión de la factura - # devuelve error 2004: El valor del campo FechaHoraHusoGenRegistro debe ser - # la fecha actual del sistema de la AEAT. - # Debe enviarse como incidencia - if ( - self.verifactu_send_state == "incorrect" - and registration_date < fields.Datetime.now() - and self.aeat_send_error[:4] == "2004" - ): - header.update({"RemisionVoluntaria": {"Incidencia": "S"}}) - return header - def _get_verifactu_invoice_dict(self): self.ensure_one() inv_dict = {} diff --git a/l10n_es_verifactu/models/verifactu_send_queue.py b/l10n_es_verifactu/models/verifactu_send_queue.py index 00dd417bd58..79348908727 100644 --- a/l10n_es_verifactu/models/verifactu_send_queue.py +++ b/l10n_es_verifactu/models/verifactu_send_queue.py @@ -201,18 +201,48 @@ def _send_documents_to_verifactu(self): [("move_id", "=", invoice.id)], limit=1 ) send_queue.correction = False - estadoregistro = linea["EstadoRegistro"] + estado_registro = linea["EstadoRegistro"] self.env["verifactu.send.response.line"].sudo().create( { "send_queue_id": send_queue.id, "response": linea, "send_response_id": response.id, - "send_state": VERIFACTU_STATE_MAPPING[estadoregistro], + "send_state": VERIFACTU_STATE_MAPPING[estado_registro], "error_code": "CodigoErrorRegistro" in linea and str(linea["CodigoErrorRegistro"]) or "", } ) + doc_vals = { + "aeat_header_sent": json.dumps(header, indent=4), + } + if estado_registro == "Correcto": + doc_vals.update( + { + "aeat_state": "sent", + "verifactu_csv": res["CSV"], + "aeat_send_failed": False, + } + ) + elif estado_registro == "AceptadoConErrores": + doc_vals.update( + { + "aeat_state": "sent_w_errors", + "verifactu_csv": res["CSV"], + "aeat_send_failed": True, + } + ) + else: + doc_vals["aeat_send_failed"] = True + doc_vals["verifactu_return"] = linea + send_error = False + if linea["CodigoErrorRegistro"]: + send_error = "{} | {}".format( + str(linea["CodigoErrorRegistro"]), + str(linea["DescripcionErrorRegistro"]), + ) + doc_vals["aeat_send_error"] = send_error + send_queue.move_id.write(doc_vals) return True @api.depends("response_ids", "response_ids.send_state") diff --git a/l10n_es_verifactu/views/account_move_view.xml b/l10n_es_verifactu/views/account_move_view.xml index 9930c04c9b8..623d6d19d0c 100644 --- a/l10n_es_verifactu/views/account_move_view.xml +++ b/l10n_es_verifactu/views/account_move_view.xml @@ -14,7 +14,7 @@ string="Re-send to Verifactu" name="resend_verifactu" groups="l10n_es_aeat.group_account_aeat" - attrs="{'invisible': ['|','|',('verifactu_enabled', '=', False), ('state', 'not in', ['posted']), ('verifactu_send_state','not in',['incorrect','accepted_with_errors'])]}" + attrs="{'invisible': ['|','|',('verifactu_enabled', '=', False), ('state', 'not in', ['posted']), ('aeat_state','not in',['sent','sent_w_errors'])]}" /> @@ -28,7 +28,7 @@ name="group_aeat_information" > - + - + + + + + + + + + @@ -113,30 +129,46 @@ + + + + + +