[IMP] account(_edi): Detect when an invoice is ready to be sent
In some flow like subscription, invoices are sent by mail automatically to the customer. Sometimes, the invoice must be approved by the government before sending the mail like the Mexican EDI. This commit aims to add a custom method to detect when an invoice is ready to be sent to the customer. PR (community): https://github.com/odoo/odoo/pull/78714 PR (enterprise): https://github.com/odoo/enterprise/pull/21809 closes odoo/odoo#79504 X-original-commit: 3a29371eb70309f46e3b8938434287fefc23b351 Related: odoo/enterprise#22171 Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
committed by
william-andre
parent
346dcd7ac1
commit
85f2ae03d3
@@ -7,6 +7,7 @@ from odoo.tools.misc import formatLang, format_date, get_lang
|
||||
|
||||
from datetime import date, timedelta
|
||||
from collections import defaultdict
|
||||
from contextlib import contextmanager
|
||||
from itertools import zip_longest
|
||||
from hashlib import sha256
|
||||
from json import dumps
|
||||
@@ -2758,6 +2759,30 @@ class AccountMove(models.Model):
|
||||
|
||||
return reverse_moves
|
||||
|
||||
def _action_invoice_ready_to_be_sent(self):
|
||||
""" Hook allowing custom code when an invoice becomes ready to be sent by mail to the customer.
|
||||
For example, when an EDI document must be sent to the government and be signed by it.
|
||||
"""
|
||||
|
||||
def _is_ready_to_be_sent(self):
|
||||
""" Helper telling if a journal entry is ready to be sent by mail to the customer.
|
||||
|
||||
:return: True if the invoice is ready, False otherwise.
|
||||
"""
|
||||
self.ensure_one()
|
||||
return True
|
||||
|
||||
@contextmanager
|
||||
def _send_only_when_ready(self):
|
||||
moves_not_ready = self.filtered(lambda x: not x._is_ready_to_be_sent())
|
||||
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
moves_now_ready = moves_not_ready.filtered(lambda x: x._is_ready_to_be_sent())
|
||||
if moves_now_ready:
|
||||
moves_now_ready._action_invoice_ready_to_be_sent()
|
||||
|
||||
def open_reconcile_view(self):
|
||||
return self.line_ids.open_reconcile_view()
|
||||
|
||||
|
||||
@@ -161,8 +161,10 @@ class AccountEdiDocument(models.Model):
|
||||
state = documents[0].state
|
||||
if doc_type == 'invoice':
|
||||
if state == 'to_send':
|
||||
edi_result = edi_format._post_invoice_edi(documents.move_id)
|
||||
_postprocess_post_edi_results(documents, edi_result)
|
||||
invoices = documents.move_id
|
||||
with invoices._send_only_when_ready():
|
||||
edi_result = edi_format._post_invoice_edi(invoices)
|
||||
_postprocess_post_edi_results(documents, edi_result)
|
||||
elif state == 'to_cancel':
|
||||
edi_result = edi_format._cancel_invoice_edi(documents.move_id)
|
||||
_postprocess_cancel_edi_results(documents, edi_result)
|
||||
|
||||
@@ -429,6 +429,17 @@ class AccountMove(models.Model):
|
||||
self.env['account.edi.document'].create(edi_document_vals_list)
|
||||
self.edi_document_ids._process_documents_no_web_services()
|
||||
|
||||
def _is_ready_to_be_sent(self):
|
||||
# OVERRIDE
|
||||
# Prevent a mail to be sent to the customer if the EDI document is not sent.
|
||||
res = super()._is_ready_to_be_sent()
|
||||
|
||||
if not res:
|
||||
return False
|
||||
|
||||
edi_documents_to_send = self.edi_document_ids.filtered(lambda x: x.state == 'to_send')
|
||||
return not bool(edi_documents_to_send)
|
||||
|
||||
def _post(self, soft=True):
|
||||
# OVERRIDE
|
||||
# Set the electronic document to be posted and post immediately for synchronous formats.
|
||||
|
||||
@@ -227,3 +227,68 @@ class TestAccountEdi(AccountEdiTestCommon, CronMixinCase):
|
||||
self.env.ref('account_edi.ir_cron_edi_network').method_direct_trigger()
|
||||
self.assertEqual(len(capt.records), 2, "Not all records have been processed in this run, the cron should "
|
||||
"re-trigger itself to process some more later")
|
||||
|
||||
def test_prepare_edi_vals_to_export(self):
|
||||
"""
|
||||
Test _prepare_edi_vals_to_export return values
|
||||
in the proper format
|
||||
|
||||
tag_ids should be a set of id and tags a proper recordset
|
||||
"""
|
||||
account_tag = self.env['account.account.tag'].create({
|
||||
"applicability": "taxes",
|
||||
"country_id": self.env.ref('base.us').id,
|
||||
"name": "Test Tag",
|
||||
})
|
||||
tax = self.env['account.tax'].create({
|
||||
"amount": 15,
|
||||
"amount_type": "percent",
|
||||
"description": "15%",
|
||||
"country_id": self.env.ref('base.us').id,
|
||||
"invoice_repartition_line_ids": [
|
||||
Command.create({
|
||||
"factor_percent": 100,
|
||||
"repartition_type": "base",
|
||||
"sequence": 1,
|
||||
}),
|
||||
Command.create({
|
||||
"factor_percent": 100,
|
||||
"repartition_type": "tax",
|
||||
"sequence": 1,
|
||||
"tag_ids": [Command.link(account_tag.id)]
|
||||
})
|
||||
],
|
||||
"name": "Test",
|
||||
"tax_exigibility": "on_invoice",
|
||||
"type_tax_use": "sale"
|
||||
})
|
||||
|
||||
invoices = self.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'invoice_date': '2019-01-01',
|
||||
'date': '2019-01-01',
|
||||
'partner_id': self.partner_a.id,
|
||||
'invoice_line_ids': [Command.create({
|
||||
'product_id': self.product_a.id,
|
||||
'tax_ids': [Command.link(tax.id)]
|
||||
})],
|
||||
})
|
||||
vals = invoices._prepare_edi_vals_to_export()
|
||||
self.assertEqual(
|
||||
vals['invoice_line_vals_list'][0]['tax_detail_vals_list'][0]['tag_ids'], set(account_tag.ids))
|
||||
self.assertEqual(
|
||||
vals['invoice_line_vals_list'][0]['tax_detail_vals_list'][0]['tags'].name, "Test Tag")
|
||||
|
||||
def test_invoice_ready_to_be_sent(self):
|
||||
def _is_needed_for_invoice(edi_format, invoice):
|
||||
return True
|
||||
|
||||
with self.mock_edi(
|
||||
_needs_web_services_method=_generate_mocked_needs_web_services(True),
|
||||
_is_required_for_invoice_method=_is_needed_for_invoice,
|
||||
):
|
||||
self.invoice.action_post()
|
||||
doc = self.invoice._get_edi_document(self.edi_format)
|
||||
self.assertFalse(self.invoice._is_ready_to_be_sent())
|
||||
doc._process_documents_web_services(with_commit=False)
|
||||
self.assertTrue(self.invoice._is_ready_to_be_sent())
|
||||
|
||||
Reference in New Issue
Block a user