[FIX] sale: send invoice only when ready to be send
Issues ------ In the module sale, with the automatic invoicing configured. Payment transaction generate, post and send the invoice when they are post process. In some country the invoice is not directly ready to be sent due to some edi document Solution -------- use the mechanism introduce with https://github.com/odoo/odoo/commit/3a29371eb70309f46e3b8938434287fefc23b351 to delay the sending. Introduce a cron that check invoice to send closes odoo/odoo#81526 X-original-commit: 97b74d8304337d901d9422418cbd0dcdcc46fcf5 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
@@ -6,3 +6,13 @@ from . import controllers
|
||||
from . import report
|
||||
from . import wizard
|
||||
from . import populate
|
||||
|
||||
from odoo.api import Environment, SUPERUSER_ID
|
||||
|
||||
|
||||
def _synchronize_cron(cr, registry):
|
||||
env = Environment(cr, SUPERUSER_ID, {'active_test': False})
|
||||
send_invoice_cron = env.ref('sale.send_invoice_cron', raise_if_not_found=False)
|
||||
if send_invoice_cron:
|
||||
config = env['ir.config_parameter'].get_param('sale.automatic_invoice', False)
|
||||
send_invoice_cron.active = bool(config)
|
||||
|
||||
@@ -72,5 +72,6 @@ This module contains all the common features of Sales Management and eCommerce.
|
||||
'sale/static/tests/sales_team_dashboard_tests.js',
|
||||
],
|
||||
},
|
||||
'post_init_hook': '_synchronize_cron',
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
||||
@@ -16,5 +16,17 @@
|
||||
<field name="key">sale.default_confirmation_template</field>
|
||||
<field name="value" ref="sale.mail_template_sale_confirmation"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.cron" id="send_invoice_cron">
|
||||
<field name="name">automatic invoicing: send ready invoice</field>
|
||||
<field name="model_id" ref="payment.model_payment_transaction" />
|
||||
<field name="state">code</field>
|
||||
<field name="code">model._cron_send_invoice()</field>
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -109,3 +109,19 @@ class AccountMove(models.Model):
|
||||
for (order, name) in todo:
|
||||
order.message_post(body=_("Invoice %s paid", name))
|
||||
return res
|
||||
|
||||
def _get_invoice_delivery_partner_id(self):
|
||||
# OVERRIDE
|
||||
self.ensure_one()
|
||||
return self.partner_shipping_id.id or super(AccountMove, self)._get_invoice_delivery_partner_id()
|
||||
|
||||
def _action_invoice_ready_to_be_sent(self):
|
||||
# OVERRIDE
|
||||
# Make sure the send invoice CRON is called when an invoice becomes ready to be sent by mail.
|
||||
res = super()._action_invoice_ready_to_be_sent()
|
||||
|
||||
send_invoice_cron = self.env.ref('sale.send_invoice_cron', raise_if_not_found=False)
|
||||
if send_invoice_cron:
|
||||
send_invoice_cron._trigger()
|
||||
|
||||
return res
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil import relativedelta
|
||||
|
||||
from odoo import api, fields, models, _, SUPERUSER_ID
|
||||
from odoo.tools import float_compare
|
||||
|
||||
@@ -98,17 +101,46 @@ class PaymentTransaction(models.Model):
|
||||
self._invoice_sale_orders()
|
||||
res = super()._reconcile_after_done()
|
||||
if self.env['ir.config_parameter'].sudo().get_param('sale.automatic_invoice') and any(so.state in ('sale', 'done') for so in self.sale_order_ids):
|
||||
default_template = self.env['ir.config_parameter'].sudo().get_param('sale.default_invoice_email_template')
|
||||
if default_template:
|
||||
for trans in self.filtered(lambda t: t.sale_order_ids.filtered(lambda so: so.state in ('sale', 'done'))):
|
||||
trans = trans.with_company(trans.acquirer_id.company_id).with_context(
|
||||
mark_invoice_as_sent=True,
|
||||
company_id=trans.acquirer_id.company_id.id,
|
||||
)
|
||||
for invoice in trans.invoice_ids.with_user(SUPERUSER_ID):
|
||||
invoice.message_post_with_template(int(default_template), email_layout_xmlid="mail.mail_notification_paynow")
|
||||
self.filtered(lambda t: t.sale_order_ids.filtered(lambda so: so.state in ('sale', 'done')))._send_invoice()
|
||||
return res
|
||||
|
||||
def _send_invoice(self):
|
||||
default_template = self.env['ir.config_parameter'].sudo().get_param('sale.default_invoice_email_template')
|
||||
if not default_template:
|
||||
return
|
||||
|
||||
for trans in self:
|
||||
trans = trans.with_company(trans.acquirer_id.company_id).with_context(
|
||||
company_id=trans.acquirer_id.company_id.id,
|
||||
)
|
||||
invoice_to_send = trans.invoice_ids.filtered(
|
||||
lambda i: not i.is_move_sent and i.state == 'posted' and i._is_ready_to_be_sent()
|
||||
)
|
||||
invoice_to_send.is_move_sent = True # Mark invoice as sent
|
||||
for invoice in invoice_to_send.with_user(SUPERUSER_ID):
|
||||
invoice.message_post_with_template(int(default_template), email_layout_xmlid="mail.mail_notification_paynow")
|
||||
|
||||
def _cron_send_invoice(self):
|
||||
"""
|
||||
Cron to send invoice that where not ready to be send directly after posting
|
||||
"""
|
||||
if not self.env['ir.config_parameter'].sudo().get_param('sale.automatic_invoice'):
|
||||
return
|
||||
|
||||
# No need to retrieve old transactions
|
||||
retry_limit_date = datetime.now() - relativedelta.relativedelta(days=2)
|
||||
# Retrieve all transactions matching the criteria for post-processing
|
||||
self.search([
|
||||
('state', '=', 'done'),
|
||||
('is_post_processed', '=', True),
|
||||
('invoice_ids', 'in', self.env['account.move']._search([
|
||||
('is_move_sent', '=', False),
|
||||
('state', '=', 'posted'),
|
||||
])),
|
||||
('sale_order_ids.state', 'in', ('sale', 'done')),
|
||||
('last_state_change', '>=', retry_limit_date),
|
||||
])._send_invoice()
|
||||
|
||||
def _invoice_sale_orders(self):
|
||||
if self.env['ir.config_parameter'].sudo().get_param('sale.automatic_invoice'):
|
||||
for trans in self.filtered(lambda t: t.sale_order_ids):
|
||||
|
||||
@@ -75,6 +75,10 @@ class ResConfigSettings(models.TransientModel):
|
||||
if self.default_invoice_policy != 'order':
|
||||
self.env['ir.config_parameter'].set_param('sale.automatic_invoice', False)
|
||||
|
||||
send_invoice_cron = self.env.ref('sale.send_invoice_cron', raise_if_not_found=False)
|
||||
if send_invoice_cron:
|
||||
send_invoice_cron.active = self.automatic_invoice
|
||||
|
||||
@api.onchange('use_quotation_validity_days')
|
||||
def _onchange_use_quotation_validity_days(self):
|
||||
if self.quotation_validity_days <= 0:
|
||||
|
||||
Reference in New Issue
Block a user