Skip to content

Commit

Permalink
[FIX] l10n_es_aeat_verifactu_pos: Adapt module to chain on create and…
Browse files Browse the repository at this point in the history
… pre-commit stuff
  • Loading branch information
aritzolea committed Feb 25, 2025
1 parent ed9c2b0 commit 72c84e2
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 29 deletions.
16 changes: 15 additions & 1 deletion l10n_es_aeat_verifactu_pos/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,27 @@
class AccountMove(models.Model):
_inherit = "account.move"

def _get_chaining_invoice_dict(self):
def _set_chaining_invoice(self):
"""PoS Config has a different chain for VERI*FACTU"""
if self.pos_order_ids and len(self.pos_order_ids.ids) == 1:
# TODO: use cases
# * The Invoice is created from the PoS
# * The Invoice is created later after some time, in this case
# the PoS order (simplified invoice) is already in the chain
pos_order = self.pos_order_ids
if not pos_order.verifactu_previous_invoice_id:
return pos_order._set_chaining_invoice()
elif len(self.pos_order_ids) > 1:
# TODO: is possible to have multiple PoS orders for the same Invoice?
raise exceptions.UserError(
_("VERI*FACTU: multiple PoS Orders not supported")
)
else:
return super()._set_chaining_invoice()

def _get_chaining_invoice_dict(self):
"""Get the chaining invoice dictionary for POS orders"""
if self.pos_order_ids and len(self.pos_order_ids.ids) == 1:
pos_order = self.pos_order_ids
return pos_order._get_chaining_invoice_dict()
elif len(self.pos_order_ids) > 1:
Expand Down
60 changes: 35 additions & 25 deletions l10n_es_aeat_verifactu_pos/models/pos_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ def _process_order(self, order, draft, existing_order):
pos_order_id = super()._process_order(order, draft, existing_order)
pos_order = self.env["pos.order"].browse(pos_order_id)

if not self._should_send_to_verifactu(pos_order):
if not self._is_verifactu_order(pos_order):
return pos_order_id

# TODO: review retry strategy
# possible scenarios: multiple devices registering invoices
# from the same PoS Config
for attempt in range(SEND_TO_VERIFACTU_MAX_RETRIES):
try:
pos_order.send_verifactu()
pos_order._set_chaining_invoice()
break
except OperationalError:
if attempt == SEND_TO_VERIFACTU_MAX_RETRIES - 1:
Expand All @@ -76,16 +76,26 @@ def _process_order(self, order, draft, existing_order):
pos_order.id,
SEND_TO_VERIFACTU_MAX_RETRIES,
)
raise
else:
sleep(1) # Wait 1 second before next try

if self._should_send_to_verifactu(pos_order):
pos_order.send_verifactu()

return pos_order_id

def _should_send_to_verifactu(self, pos_order):
def _is_verifactu_order(self, pos_order):
return (
not config["test_enable"]
and pos_order.exists()
pos_order.exists()
and not pos_order.to_invoice
and pos_order.verifactu_enabled
)

def _should_send_to_verifactu(self, pos_order):
return (
self._is_verifactu_order(pos_order)
and not config["test_enable"]
and pos_order.state in VERIFACTU_VALID_POS_STATES
)

Expand Down Expand Up @@ -204,9 +214,9 @@ def _get_verifactu_invoice_dict_out(self, cancel=False):
registroAlta.setdefault("RegistroAlta", inv_dict)
return registroAlta

def _get_chaining_invoice_dict(self):
"""Get the chaining invoice dictionary for POS orders"""
inv_dict = {}
def _set_chaining_invoice(self):
"""Set the chaining order"""
prev_order = False
try:
self.config_id.flush_model(["verifactu_last_invoice_id"])
self._cr.execute(
Expand All @@ -218,22 +228,6 @@ def _get_chaining_invoice_dict(self):
prev_order = self.env["pos.order"].browse(result[0]) if result else False
if prev_order and prev_order.exists():
self.verifactu_previous_invoice_id = prev_order
if prev_order.is_invoiced and prev_order.account_move.exists():
prev_inv = prev_order.account_move
else:
prev_inv = prev_order
inv_dict = {
"RegistroAnterior": {
"IDEmisorFactura": prev_inv._get_verifactu_issuer(),
"NumSerieFactura": prev_inv._get_document_serial_number(),
"FechaExpedicionFactura": prev_inv._change_date_format(
prev_inv._get_document_date()
),
"Huella": prev_inv.verifactu_hash,
}
}
else:
inv_dict = {"PrimerRegistro": "S"}
self._cr.execute(
"UPDATE pos_config SET verifactu_last_invoice_id = %s WHERE id = %s",
(self.id, self.config_id.id),
Expand All @@ -248,7 +242,23 @@ def _get_chaining_invoice_dict(self):
self.id,
)
raise
return inv_dict
return prev_order

def _get_chaining_invoice_dict(self):
"""Get the chaining invoice dictionary for POS orders"""
if self.verifactu_previous_invoice_id:
prev_order = self.verifactu_previous_invoice_id
return {
"RegistroAnterior": {
"IDEmisorFactura": prev_order._get_verifactu_issuer(),
"NumSerieFactura": prev_order._get_document_serial_number(),
"FechaExpedicionFactura": prev_order._change_date_format(
prev_order._get_document_date()
),
"Huella": prev_order.verifactu_hash,
}
}
return {"PrimerRegistro": "S"}

def _get_verifactu_taxes_and_total(self):
"""Get the tax breakdown for Verifactu from POS order lines.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,14 @@ def mock_execute(*args, **kwargs):
second_order_data["data"]["name"] = "Order 0002"
second_order_data["data"]["uid"] = str(uuid.uuid4()) # New unique ID
second_order_data["id"] = second_order_data["data"]["uid"]
second_order_ids = self.env["pos.order"].create_from_ui([second_order_data])
second_order = self.env["pos.order"].browse(second_order_ids[0]["id"])

old_execute = self.cr.execute
with self.assertRaises(OperationalError):
with self.cr.savepoint():
self.cr.execute = mock_execute
second_order._get_chaining_invoice_dict()
second_order_ids = self.env["pos.order"].create_from_ui(
[second_order_data]
)
self.cr.execute = old_execute

self.assertEqual(
Expand All @@ -347,6 +347,14 @@ def mock_execute(*args, **kwargs):
"Should not update config's last order reference on error",
)

second_order_ids = self.env["pos.order"].create_from_ui([second_order_data])
second_order = self.env["pos.order"].browse(second_order_ids[0]["id"])
self.assertEqual(
self.pos_config.verifactu_last_invoice_id.id,
second_order.id,
"Should have updates config's last order to second_order",
)

def test_verifactu_chaining_invoiced_pos_order(self):
"""Test that invoiced POS orders are added to POS config chain"""
orders_data = [self._create_ui_order_data()]
Expand Down

0 comments on commit 72c84e2

Please sign in to comment.