[FIX] account_edi: better locking of documents and other models when processing EDI

- On account_edi_document, lock the documents successively instead of all at once.
- Lock account_move that should be cancelled. Before, cancelling the invoice after cancelling it on the web-service could fail.
- Lock ir_attachment that might be unlinked. Before, attachments that weren't attached to any model could become unreachable but still present in the database when an invoice was cancelled or a new attachment was produced.

closes odoo/odoo#64946

X-original-commit: 8d0c25f359f92533eb25f2990d6e2aceef33b77a
Signed-off-by: Quentin De Paoli (qdp) <qdp@openerp.com>
Signed-off-by: bfr-o <bfr-o@users.noreply.github.com>
This commit is contained in:
Benjamin Frantzen (bfr)
2021-01-22 15:02:57 +00:00
parent 8252f8123d
commit 684587fbe1
@@ -141,10 +141,25 @@ class AccountEdiDocument(models.Model):
continue # payments are processed after invoices
for documents in batches:
move_to_cancel = documents.filtered(lambda doc: doc.edi_format_id._needs_web_services() \
and doc.attachment_id \
and doc.state == 'to_cancel' \
and doc.move_id.is_invoice(include_receipts=True) \
and doc.edi_format_id._is_required_for_invoice(doc.move_id)).move_id
attachments_potential_unlink = documents.attachment_id.filtered(lambda a: not a.res_model and not a.res_id)
try:
with self.env.cr.savepoint(flush=False):
# Locks the documents in DB. Avoid sending an invoice twice (the documents can be processed by the CRON but also manually).
self._cr.execute('SELECT * FROM account_edi_document WHERE id IN %s FOR UPDATE NOWAIT', [tuple(self.ids)])
self._cr.execute('SELECT * FROM account_edi_document WHERE id IN %s FOR UPDATE NOWAIT', [tuple(documents.ids)])
# Locks the move that will be cancelled.
if move_to_cancel:
self._cr.execute('SELECT * FROM account_move WHERE id IN %s FOR UPDATE NOWAIT', [tuple(move_to_cancel.ids)])
# Locks the attachments that might be unlinked
if attachments_potential_unlink:
self._cr.execute('SELECT * FROM ir_attachment WHERE id IN %s FOR UPDATE NOWAIT', [tuple(attachments_potential_unlink.ids)])
if state == 'to_send':
edi_result = edi_format._post_invoice_edi(documents.move_id, test_mode=test_mode)