189 lines
7.2 KiB
Python
Executable File
189 lines
7.2 KiB
Python
Executable File
# Copyright 2017 Acsone SA/NV (http://www.acsone.eu)
|
|
# Copyright 2025 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
import odoo.tests.common as common
|
|
|
|
|
|
class TestSaleOrderInvoicePolicy(common.TransactionCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.product_obj = cls.env["product.product"]
|
|
cls.sale_obj = cls.env["sale.order"]
|
|
cls.partner = cls.env.ref("base.res_partner_2")
|
|
cls.product = cls.product_obj.create(
|
|
{"name": "Test", "type": "consu", "list_price": 20.0}
|
|
)
|
|
cls.product2 = cls.product_obj.create(
|
|
{"name": "Test 2", "type": "consu", "list_price": 45.0}
|
|
)
|
|
cls.product3 = cls.product_obj.create(
|
|
{
|
|
"name": "Test 3 (service)",
|
|
"type": "service",
|
|
"list_price": 850.5,
|
|
}
|
|
)
|
|
|
|
def test_sale_order_invoice_order(self):
|
|
"""Test invoicing based on ordered quantities"""
|
|
so = self.env["sale.order"].create(
|
|
{
|
|
"partner_id": self.env.ref("base.res_partner_2").id,
|
|
"order_line": [
|
|
(0, 0, {"product_id": self.product.id, "product_uom_qty": 2.0}),
|
|
(0, 0, {"product_id": self.product2.id, "product_uom_qty": 3.0}),
|
|
],
|
|
"invoice_policy": "order",
|
|
}
|
|
)
|
|
self.assertEqual(so.invoice_policy, "order")
|
|
|
|
# SO is not confirmed yet
|
|
self.assertEqual([0.0, 0.0], so.order_line.mapped("untaxed_amount_to_invoice"))
|
|
|
|
so.action_confirm()
|
|
|
|
self.assertEqual(len(so.picking_ids), 1)
|
|
|
|
picking = so.picking_ids
|
|
picking.action_assign()
|
|
self.assertEqual(picking.state, "assigned")
|
|
so_line = so.order_line[0]
|
|
self.assertEqual(so_line.qty_to_invoice, 2)
|
|
self.assertEqual(so_line.invoice_status, "to invoice")
|
|
self.assertEqual(so_line.product_id.invoice_policy, "order")
|
|
|
|
so_line = so.order_line[1]
|
|
self.assertEqual(so_line.qty_to_invoice, 3)
|
|
self.assertEqual(so_line.invoice_status, "to invoice")
|
|
self.assertEqual(so_line.product_id.invoice_policy, "order")
|
|
|
|
def test_sale_order_invoice_deliver(self):
|
|
"""Test invoicing based on delivered quantities"""
|
|
self.assertEqual("order", self.product.invoice_policy)
|
|
so = self.env["sale.order"].create(
|
|
{
|
|
"partner_id": self.env.ref("base.res_partner_2").id,
|
|
"invoice_policy": "delivery",
|
|
"order_line": [
|
|
(0, 0, {"product_id": self.product.id, "product_uom_qty": 2.0}),
|
|
(0, 0, {"product_id": self.product2.id, "product_uom_qty": 3.0}),
|
|
],
|
|
}
|
|
)
|
|
self.assertEqual(so.invoice_policy, "delivery")
|
|
|
|
# SO is not confirmed yet
|
|
self.assertEqual([0.0, 0.0], so.order_line.mapped("untaxed_amount_to_invoice"))
|
|
|
|
so.action_confirm()
|
|
|
|
# SO is not delivered
|
|
self.assertEqual([0.0, 0.0], so.order_line.mapped("untaxed_amount_to_invoice"))
|
|
|
|
self.assertEqual(len(so.picking_ids), 1)
|
|
|
|
picking = so.picking_ids
|
|
picking.action_assign()
|
|
self.assertEqual(picking.state, "assigned")
|
|
|
|
so_line = so.order_line[0]
|
|
self.assertEqual(so_line.qty_to_invoice, 0)
|
|
self.assertEqual(so_line.invoice_status, "no")
|
|
|
|
so_line = so.order_line[1]
|
|
self.assertEqual(so_line.qty_to_invoice, 0)
|
|
self.assertEqual(so_line.invoice_status, "no")
|
|
|
|
for mv in picking.move_line_ids:
|
|
mv.quantity = mv.quantity_product_uom
|
|
picking.button_validate()
|
|
self.assertEqual(picking.state, "done")
|
|
|
|
so_line = so.order_line[0]
|
|
self.assertEqual(so_line.qty_to_invoice, 2)
|
|
self.assertEqual(so_line.invoice_status, "to invoice")
|
|
|
|
self.assertEqual(40.0, so_line.untaxed_amount_to_invoice)
|
|
# Check that product has still its original invoice policy
|
|
self.assertEqual("order", self.product.invoice_policy)
|
|
|
|
so_line = so.order_line[1]
|
|
self.assertEqual(so_line.qty_to_invoice, 3)
|
|
self.assertEqual(so_line.invoice_status, "to invoice")
|
|
|
|
self.assertEqual(135.0, so_line.untaxed_amount_to_invoice)
|
|
|
|
def test_settings(self):
|
|
# delivery policy is the default
|
|
settings = self.env["res.config.settings"].create({})
|
|
settings.sale_default_invoice_policy = "delivery"
|
|
settings.execute()
|
|
so = self.env["sale.order"].create(
|
|
{"partner_id": self.env.ref("base.res_partner_2").id}
|
|
)
|
|
self.assertEqual(so.invoice_policy, "delivery")
|
|
# order policy is the default
|
|
settings.sale_default_invoice_policy = "order"
|
|
settings.execute()
|
|
so = self.env["sale.order"].create(
|
|
{"partner_id": self.env.ref("base.res_partner_2").id}
|
|
)
|
|
self.assertEqual(so.invoice_policy, "order")
|
|
|
|
def test_context_manager_exception(self):
|
|
"""Check the exception is well managed when called with several
|
|
invoice policies"""
|
|
self.assertEqual("order", self.product.invoice_policy)
|
|
so = self.env["sale.order"].create(
|
|
{
|
|
"partner_id": self.env.ref("base.res_partner_2").id,
|
|
"invoice_policy": "delivery",
|
|
"order_line": [
|
|
(0, 0, {"product_id": self.product.id, "product_uom_qty": 2.0}),
|
|
(0, 0, {"product_id": self.product2.id, "product_uom_qty": 3.0}),
|
|
],
|
|
}
|
|
)
|
|
|
|
so2 = self.env["sale.order"].create(
|
|
{
|
|
"partner_id": self.env.ref("base.res_partner_2").id,
|
|
"invoice_policy": "order",
|
|
"order_line": [
|
|
(0, 0, {"product_id": self.product.id, "product_uom_qty": 2.0}),
|
|
(0, 0, {"product_id": self.product2.id, "product_uom_qty": 3.0}),
|
|
],
|
|
}
|
|
)
|
|
lines = (so | so2).order_line
|
|
with self.assertRaises(Exception) as exc:
|
|
with self.env["sale.order.line"]._sale_invoice_policy(
|
|
lines
|
|
): # pragma: no cover
|
|
pass
|
|
self.assertEqual(
|
|
"The method _sale_invoice_policy() must be called with lines sharing "
|
|
"the same invoice policy",
|
|
exc.exception.args[0],
|
|
)
|
|
|
|
def test_force_lines_to_invoice_policy_order(self):
|
|
"""Check when a SO is fully paid by a payment transaction and the automatic
|
|
invoicing is enabled, that the policy is changed on order."""
|
|
so = self.env["sale.order"].create(
|
|
{
|
|
"partner_id": self.env.ref("base.res_partner_2").id,
|
|
"order_line": [
|
|
(0, 0, {"product_id": self.product.id, "product_uom_qty": 2.0}),
|
|
(0, 0, {"product_id": self.product2.id, "product_uom_qty": 3.0}),
|
|
],
|
|
"invoice_policy": "delivery",
|
|
}
|
|
)
|
|
so.action_confirm()
|
|
self.assertEqual(so.invoice_policy, "delivery")
|
|
so._force_lines_to_invoice_policy_order()
|
|
self.assertEqual(so.invoice_policy, "order")
|