Skip to content

Commit

Permalink
[IMP] account_edi: decouple attachment from the state of the edi_docu…
Browse files Browse the repository at this point in the history
…ment.

Before this commit, for an EDI to be successfully posted, returning an attachment from 'post_invoice_edi' was required. In some cases this caused problem:
- When an EDI is posted in two steps, sometimes the attachment is generated in the first step and nothing is returned until the second step. This forced to do some hack where the reference to the attachment in a seperate field to be able to return it after the second step.
- When an EDI doesn't have a file to return (maybe we just send data over an API and get a response without any file involved).
Now, the attachment are removed from account_edi flows. When returning from 'post_invoice_edi', it is still possible to return an attachment whose reference will be kept in the edi_document, but will not change the state of the document to 'sent'.
To make the state change to 'sent', 'post_invoice_edi' must return {'success': True}.
Nothing has changed in the 'cancel' flow, meaning that the buttons related to canceling or reseting an invoice to draft are now based on the state and not on the existence of an attachment on the document. Also, when an invoice is successfully cancelled, the reference to the attachment is STILL removed from the document, since the document does not represent an electronic invoice anymore.

closes odoo#70040

Related: odoo/upgrade#1946
Related: odoo/enterprise#13220
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
  • Loading branch information
bfr-o committed Jul 16, 2021
1 parent e615d4a commit 5319b71
Show file tree
Hide file tree
Showing 9 changed files with 23 additions and 27 deletions.
15 changes: 5 additions & 10 deletions addons/account_edi/models/account_edi_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,11 @@ def _postprocess_post_edi_results(documents, edi_result):
move_result = edi_result.get(move, {})
if move_result.get('attachment'):
old_attachment = document.attachment_id
values = {
'attachment_id': move_result['attachment'].id,
'error': move_result.get('error', False),
'blocking_level': move_result.get('blocking_level', DEFAULT_BLOCKING_LEVEL) if 'error' in move_result else False,
}
if not values.get('error'):
values.update({'state': 'sent'})
document.write(values)
document.attachment_id = move_result['attachment']
if not old_attachment.res_model or not old_attachment.res_id:
attachments_to_unlink |= old_attachment
if move_result.get('success') is True:
document.state = 'sent'
else:
document.write({
'error': move_result.get('error', False),
Expand Down Expand Up @@ -142,7 +137,7 @@ def _postprocess_cancel_edi_results(documents, edi_result):
if not old_attachment.res_model or not old_attachment.res_id:
attachments_to_unlink |= old_attachment

elif not move_result.get('success'):
else:
document.write({
'error': move_result.get('error', False),
'blocking_level': move_result.get('blocking_level', DEFAULT_BLOCKING_LEVEL) if move_result.get('error') else False,
Expand Down Expand Up @@ -198,7 +193,7 @@ def _process_documents_web_services(self, job_count=None, with_commit=True):
jobs_to_process = all_jobs[0:job_count] if job_count else all_jobs

for documents, doc_type in jobs_to_process:
move_to_lock = documents.move_id
move_to_lock = documents.filtered(lambda doc: doc.state == 'to_cancel').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):
Expand Down
3 changes: 2 additions & 1 deletion addons/account_edi/models/account_edi_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ def _post_invoice_edi(self, invoices):
:param invoices: A list of invoices to post.
:returns: A dictionary with the invoice as key and as value, another dictionary:
* attachment: The attachment representing the invoice in this edi_format if the edi was successfully posted.
* success: True if the edi was successfully posted.
* attachment: The attachment representing the invoice in this edi_format.
* error: An error if the edi was not successfully posted.
* blocking_level: (optional) How bad is the error (how should the edi flow be blocked ?)
"""
Expand Down
18 changes: 8 additions & 10 deletions addons/account_edi/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,16 @@ def _compute_edi_web_services_to_process(self):
format_web_services = to_process.edi_format_id.filtered(lambda f: f._needs_web_services())
move.edi_web_services_to_process = ', '.join(f.name for f in format_web_services)

@api.depends('restrict_mode_hash_table', 'state')
@api.depends(
'state',
'edi_document_ids.state')
def _compute_show_reset_to_draft_button(self):
# OVERRIDE
super()._compute_show_reset_to_draft_button()

for move in self:
for doc in move.edi_document_ids:
if doc.edi_format_id._needs_web_services() \
and doc.attachment_id \
and doc.state in ('sent', 'to_cancel') \
and move.is_invoice(include_receipts=True) \
and doc.edi_format_id._is_required_for_invoice(move):
Expand All @@ -105,25 +106,22 @@ def _compute_show_reset_to_draft_button(self):

@api.depends(
'state',
'edi_document_ids.state',
'edi_document_ids.attachment_id')
'edi_document_ids.state')
def _compute_edi_show_cancel_button(self):
for move in self:
if move.state != 'posted':
move.edi_show_cancel_button = False
continue

move.edi_show_cancel_button = any([doc.edi_format_id._needs_web_services()
and doc.attachment_id
and doc.state == 'sent'
and move.is_invoice(include_receipts=True)
and doc.edi_format_id._is_required_for_invoice(move)
for doc in move.edi_document_ids])

@api.depends(
'state',
'edi_document_ids.state',
'edi_document_ids.attachment_id')
'edi_document_ids.state')
def _compute_edi_show_abandon_cancel_button(self):
for move in self:
move.edi_show_abandon_cancel_button = any(doc.edi_format_id._needs_web_services()
Expand Down Expand Up @@ -420,8 +418,8 @@ def button_cancel(self):
# Set the electronic document to be canceled and cancel immediately for synchronous formats.
res = super().button_cancel()

self.edi_document_ids.filtered(lambda doc: doc.attachment_id).write({'state': 'to_cancel', 'error': False, 'blocking_level': False})
self.edi_document_ids.filtered(lambda doc: not doc.attachment_id).write({'state': 'cancelled', 'error': False, 'blocking_level': False})
self.edi_document_ids.filtered(lambda doc: doc.state != 'sent').write({'state': 'cancelled', 'error': False, 'blocking_level': False})
self.edi_document_ids.filtered(lambda doc: doc.state == 'sent').write({'state': 'to_cancel', 'error': False, 'blocking_level': False})
self.edi_document_ids._process_documents_no_web_services()
self.env.ref('account_edi.ir_cron_edi_network')._trigger()

Expand All @@ -438,7 +436,7 @@ def button_draft(self):

res = super().button_draft()

self.edi_document_ids.write({'state': False, 'error': False, 'blocking_level': False})
self.edi_document_ids.write({'error': False, 'blocking_level': False})

return res

Expand Down
4 changes: 2 additions & 2 deletions addons/account_edi/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _mocked_post(edi_format, invoices):
'datas': base64.encodebytes(b"<?xml version='1.0' encoding='UTF-8'?><Invoice/>"),
'mimetype': 'application/xml'
})
res[invoice] = {'attachment': attachment}
res[invoice] = {'success': True, 'attachment': attachment}
return res


Expand All @@ -58,7 +58,7 @@ def _mocked_post_two_steps(edi_format, invoices):
'datas': base64.encodebytes(b"<?xml version='1.0' encoding='UTF-8'?><Invoice/>"),
'mimetype': 'application/xml'
})
res[invoice] = {'attachment': attachment}
res[invoice] = {'success': True, 'attachment': attachment}
return res
else:
raise ValueError('wrong use of "_mocked_post_two_steps"')
Expand Down
2 changes: 1 addition & 1 deletion addons/account_edi_facturx/models/account_edi_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def _post_invoice_edi(self, invoices):
res = {}
for invoice in invoices:
attachment = self._export_facturx(invoice)
res[invoice] = {'attachment': attachment}
res[invoice] = {'success': True, 'attachment': attachment}
return res

def _is_embedding_to_invoice_pdf_needed(self):
Expand Down
2 changes: 1 addition & 1 deletion addons/account_edi_ubl/models/account_edi_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def _post_invoice_edi(self, invoices):
res = {}
for invoice in invoices:
attachment = self._export_ubl(invoice)
res[invoice] = {'attachment': attachment}
res[invoice] = {'success': True, 'attachment': attachment}
return res

def _is_embedding_to_invoice_pdf_needed(self):
Expand Down
2 changes: 1 addition & 1 deletion addons/l10n_be_edi/models/account_edi_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ def _post_invoice_edi(self, invoices):
res = {}
for invoice in invoices:
attachment = self._export_efff(invoice)
res[invoice] = {'attachment': attachment}
res[invoice] = {'success': True, 'attachment': attachment}
return res
2 changes: 2 additions & 0 deletions addons/l10n_it_edi/models/account_edi_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ def _post_fattura_pa(self, invoices):
)
else:
invoice.l10n_it_send_state = 'to_send'
if 'attachment' in res:
res['success'] = True
return {invoice: res}

def _post_invoice_edi(self, invoices, test_mode=False):
Expand Down
2 changes: 1 addition & 1 deletion addons/l10n_nl_edi/models/account_edi_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def _post_invoice_edi(self, invoices):

invoice = invoices # no batch ensure that there is only one invoice
attachment = self._export_nlcius(invoice)
return {invoice: {'attachment': attachment}}
return {invoice: {'success': True, 'attachment': attachment}}

def _is_embedding_to_invoice_pdf_needed(self):
self.ensure_one()
Expand Down

0 comments on commit 5319b71

Please sign in to comment.