diff options
| author | Anh Thao Pham (pta) <pta@odoo.com> | 2021-04-19 13:45:49 +0000 |
|---|---|---|
| committer | Anh Thao Pham (pta) <pta@odoo.com> | 2021-04-21 12:27:51 +0000 |
| commit | b41cf0077c9a6d1d74cc0c7987c0edcc58e368d1 (patch) | |
| tree | 563efae2961faf4cb75f4fd78f5ecb98e4bb4482 | |
| parent | 33a690a6a554e5f2addc7c00a3a37bdf3b691984 (diff) | |
[FIX] sale: avoid re-invoicing invoiced SO lines
- Create a product:
* Invoicing Policy: Delivered quantities
* Re-invoice Expenses: At cost
- Create a SO with the created product in Order Lines
- Make sure the subtotal of the SO line is equal to 0, by setting an Unit Price to 0
or by applying a 100% discount
- Confirm SO and create an invoice (Regular invoice)
- Post the invoice
A new line with the same product and the same delivered quantity is added to the SO.
It is not possible to invoice a SO line with a product having an expense policy and
a subtotal equal to 0, without having it reinvoiced to the SO.
This fix will prevent account move lines linked to a SO line from being reinvoiced.
opw-2479560
closes odoo/odoo#69603
X-original-commit: 1aeb8c955fdddf044bf5f54122c4e73a26e21939
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Signed-off-by: Anh Thao PHAM <kitan191@users.noreply.github.com>
| -rw-r--r-- | addons/sale/models/account_move.py | 2 | ||||
| -rw-r--r-- | addons/sale/tests/test_reinvoice.py | 41 |
2 files changed, 43 insertions, 0 deletions
diff --git a/addons/sale/models/account_move.py b/addons/sale/models/account_move.py index 8c14faee2b5..caae347ee13 100644 --- a/addons/sale/models/account_move.py +++ b/addons/sale/models/account_move.py @@ -72,6 +72,8 @@ class AccountMoveLine(models.Model): For Vendor Bill flow, if the product has a 'erinvoice policy' and is a cost, then we will find the SO on which reinvoice the AAL """ self.ensure_one() + if self.sale_line_ids: + return False uom_precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure') return float_compare(self.credit or 0.0, self.debit or 0.0, precision_digits=uom_precision_digits) != 1 and self.product_id.expense_policy not in [False, 'no'] diff --git a/addons/sale/tests/test_reinvoice.py b/addons/sale/tests/test_reinvoice.py index 56e887fa9ce..0ecb15ed54d 100644 --- a/addons/sale/tests/test_reinvoice.py +++ b/addons/sale/tests/test_reinvoice.py @@ -223,3 +223,44 @@ class TestReInvoice(TestSaleCommon): self.assertEqual(len(self.sale_order.order_line), 1, "No SO line should have been created (or removed) when validating vendor bill") self.assertTrue(invoice_a.mapped('line_ids.analytic_line_ids'), "Analytic lines should be generated") + + def test_not_reinvoicing_invoiced_so_lines(self): + """ Test that invoiced SO lines are not re-invoiced. """ + so_line1 = self.env['sale.order.line'].create({ + 'name': self.company_data['product_delivery_cost'].name, + 'product_id': self.company_data['product_delivery_cost'].id, + 'product_uom_qty': 1, + 'product_uom': self.company_data['product_delivery_cost'].uom_id.id, + 'price_unit': self.company_data['product_delivery_cost'].list_price, + 'discount': 100.00, + 'order_id': self.sale_order.id, + }) + so_line1.product_id_change() + so_line2 = self.env['sale.order.line'].create({ + 'name': self.company_data['product_delivery_sales_price'].name, + 'product_id': self.company_data['product_delivery_sales_price'].id, + 'product_uom_qty': 1, + 'product_uom': self.company_data['product_delivery_sales_price'].uom_id.id, + 'price_unit': self.company_data['product_delivery_sales_price'].list_price, + 'discount': 100.00, + 'order_id': self.sale_order.id, + }) + so_line2.product_id_change() + + self.sale_order.onchange_partner_id() + self.sale_order._compute_tax_id() + self.sale_order.action_confirm() + + for line in self.sale_order.order_line: + line.qty_delivered = 1 + # create invoice and validate it + invoice = self.sale_order._create_invoices() + invoice.action_post() + + so_line3 = self.sale_order.order_line.filtered(lambda sol: sol != so_line1 and sol.product_id == self.company_data['product_delivery_cost']) + so_line4 = self.sale_order.order_line.filtered(lambda sol: sol != so_line2 and sol.product_id == self.company_data['product_delivery_sales_price']) + + self.assertFalse(so_line3, "No re-invoicing should have created a new sale line with product #1") + self.assertFalse(so_line4, "No re-invoicing should have created a new sale line with product #2") + self.assertEqual(so_line1.qty_delivered, 1, "No re-invoicing should have impacted exising SO line 1") + self.assertEqual(so_line2.qty_delivered, 1, "No re-invoicing should have impacted exising SO line 2") |
