From dee53d8aecd3d1eedd37bfa93c07ca28a3441fbe Mon Sep 17 00:00:00 2001
From: Goffin Simon <sig@odoo.com>
Date: Thu, 2 Sep 2021 10:55:10 +0000
Subject: [PATCH] [FIX] sale: Partial payment link with invoice policy based on
 deliverd qty
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- Configure payment stripe to be available on the web shop
- Let's consider a product with P (sales price = 100€) invoice policy based on delivered qty
- Set in the config parameter sale.automatic_invoice to True
- Create a SO with P and generate a payment link PL for 50€
- Go to PL and pay it

Bug:

An error was raised because there was no invoicable line when computing the
invoice of SO

opw:2635175

closes odoo/odoo#75892

Signed-off-by: Simon Goffin (sig) <sig@openerp.com>
---
 addons/sale/models/payment.py              | 12 +++++++-----
 addons/sale/tests/test_sale_transaction.py | 14 ++++++++++++++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/addons/sale/models/payment.py b/addons/sale/models/payment.py
index 1d6b8a0a6800..b5f5e0b8964f 100644
--- a/addons/sale/models/payment.py
+++ b/addons/sale/models/payment.py
@@ -113,10 +113,10 @@ class PaymentTransaction(models.Model):
         # invoice the sale orders if needed
         self._invoice_sale_orders()
         res = super(PaymentTransaction, self)._reconcile_after_transaction_done()
-        if self.env['ir.config_parameter'].sudo().get_param('sale.automatic_invoice'):
+        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_email_template')
             if default_template:
-                for trans in self.filtered(lambda t: t.sale_order_ids):
+                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,
@@ -130,9 +130,11 @@ class PaymentTransaction(models.Model):
             for trans in self.filtered(lambda t: t.sale_order_ids):
                 trans = trans.with_company(trans.acquirer_id.company_id)\
                     .with_context(company_id=trans.acquirer_id.company_id.id)
-                trans.sale_order_ids._force_lines_to_invoice_policy_order()
-                invoices = trans.sale_order_ids._create_invoices()
-                trans.invoice_ids = [(6, 0, invoices.ids)]
+                confirmed_orders = trans.sale_order_ids.filtered(lambda so: so.state in ('sale', 'done'))
+                if confirmed_orders:
+                    confirmed_orders._force_lines_to_invoice_policy_order()
+                    invoices = confirmed_orders._create_invoices()
+                    trans.invoice_ids = [(6, 0, invoices.ids)]
 
     @api.model
     def _compute_reference_prefix(self, values):
diff --git a/addons/sale/tests/test_sale_transaction.py b/addons/sale/tests/test_sale_transaction.py
index cd7c5dad4f73..8bc551302341 100644
--- a/addons/sale/tests/test_sale_transaction.py
+++ b/addons/sale/tests/test_sale_transaction.py
@@ -58,3 +58,17 @@ class TestSaleTransaction(AccountTestInvoicingCommon):
         with mute_logger('odoo.addons.sale.models.payment'):
             self.transaction._post_process_after_done()
         self.assertEqual(self.order.state, 'draft', 'a transaction for an incorrect amount should not validate a quote')
+
+    def test_sale_transaction_partial_delivery(self):
+        """Test that with automatic invoice and invoicing policy based on delivered quantity, a transaction for the partial
+        amount does not validate the SO."""
+        # set automatic invoice
+        self.env['ir.config_parameter'].sudo().set_param('sale.automatic_invoice', 'True')
+        # modify order total
+        self.order.order_line[0].price_unit = 200.0
+        # invoicing policy is based on delivered quantity
+        self.product_a.invoice_policy = 'delivery'
+        self.transaction._set_transaction_done()
+        with mute_logger('odoo.addons.sale.models.payment'):
+            self.transaction.sudo()._post_process_after_done()
+        self.assertEqual(self.order.state, 'draft', 'a partial transaction with automatic invoice and invoice_policy = delivery should not validate a quote')
-- 
GitLab