mirror of
https://github.com/bringout/oca-purchase.git
synced 2026-04-21 03:22:05 +02:00
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
216 lines
9.3 KiB
Python
216 lines
9.3 KiB
Python
# @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.tests import tagged
|
|
from odoo.tests.common import Form, TransactionCase
|
|
|
|
|
|
@tagged("post_install", "-at_install")
|
|
class TestQuickPurchase(TransactionCase):
|
|
@classmethod
|
|
def _add_seller(cls, product, prices):
|
|
# drop existing seller
|
|
product.seller_ids.filtered(lambda s: s.partner_id == cls.partner).unlink()
|
|
for min_qty, price in prices:
|
|
cls.env["product.supplierinfo"].create(
|
|
{
|
|
"product_tmpl_id": product.product_tmpl_id.id,
|
|
"partner_id": cls.partner.id,
|
|
"price": price,
|
|
"min_qty": min_qty,
|
|
}
|
|
)
|
|
|
|
@classmethod
|
|
def _setUpBasicSaleOrder(cls):
|
|
vals = {"partner_id": cls.partner.id}
|
|
if hasattr(cls.env["purchase.order"], "order_type"):
|
|
vals["order_type"] = cls.env.ref("purchase_order_type.po_type_blanket").id
|
|
cls.po = cls.env["purchase.order"].create(vals)
|
|
with Form(cls.po, "purchase.purchase_order_form") as po_form:
|
|
po_form.partner_id = cls.partner
|
|
ctx = {"parent_id": cls.po.id, "parent_model": "purchase.order"}
|
|
cls.product_1 = cls.product_1.with_context(**ctx)
|
|
cls.product_2 = cls.product_2.with_context(**ctx)
|
|
cls.product_1.qty_to_process = 5.0
|
|
cls.product_2.qty_to_process = 6.0
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.partner = cls.env.ref("base.res_partner_1")
|
|
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
|
|
cls.uom_dozen = cls.env.ref("uom.product_uom_dozen")
|
|
cls.product_1 = cls.env.ref("product.product_product_8")
|
|
cls.product_2 = cls.env.ref("product.product_product_11")
|
|
cls._add_seller(cls.product_1, [(0, 10), (10, 8)])
|
|
cls._add_seller(cls.product_2, [(0, 5), (10, 4)])
|
|
cls._setUpBasicSaleOrder()
|
|
|
|
def test_product_seller_price(self):
|
|
self.assertEqual(self.product_1.seller_price, 10)
|
|
self.product_1.qty_to_process = 10.0
|
|
self.assertEqual(self.product_1.seller_price, 8)
|
|
self.product_1.quick_uom_id = self.uom_dozen
|
|
self.assertEqual(self.product_1.seller_price, 96)
|
|
|
|
def test_product_seller_price_with_currency(self):
|
|
self.po.currency_id = self.env.ref("base.EUR")
|
|
usd = self.env.ref("base.USD")
|
|
usd.rate_ids[1:].unlink()
|
|
usd.rate_ids.name = self.po.date_order.date()
|
|
usd.rate_ids.rate = 2
|
|
self.assertEqual(self.product_1.seller_price, 5)
|
|
self.product_1.qty_to_process = 10.0
|
|
self.assertEqual(self.product_1.seller_price, 4)
|
|
self.product_1.quick_uom_id = self.uom_dozen
|
|
self.assertEqual(self.product_1.seller_price, 48)
|
|
|
|
def test_quick_line_add_1(self):
|
|
"""
|
|
set non-null quantity to any product with no PO line:
|
|
-> a new PO line is created with that quantity
|
|
"""
|
|
line_1, line_2 = self.po.order_line
|
|
self.assertAlmostEqual(line_1.product_uom_qty, 5.0)
|
|
self.assertAlmostEqual(line_1.price_unit, 10)
|
|
self.assertAlmostEqual(line_2.product_uom_qty, 6.0)
|
|
self.assertAlmostEqual(line_2.price_unit, 5)
|
|
|
|
def test_quick_line_add_2(self):
|
|
"""
|
|
same as previous, but include a different UoM as well
|
|
We duplicate _setUpBasicSaleOrder except we ~simultaneously~
|
|
write on qty_to_process as well as quick_uom_id
|
|
(we want to make sure to test _inverse function when it is triggered twice)
|
|
"""
|
|
vals = {"partner_id": self.partner.id}
|
|
if hasattr(self.env["purchase.order"], "order_type"):
|
|
vals["order_type"] = self.env.ref("purchase_order_type.po_type_blanket").id
|
|
po = self.env["purchase.order"].create(vals)
|
|
with Form(po, "purchase.purchase_order_form") as po_form:
|
|
po_form.partner_id = self.partner
|
|
ctx = {"parent_id": self.po.id, "parent_model": "purchase.order"}
|
|
self.product_1 = self.product_1.with_context(**ctx)
|
|
self.product_2 = self.product_2.with_context(**ctx)
|
|
self.product_1.write({"qty_to_process": 5.0, "quick_uom_id": self.uom_unit.id})
|
|
self.product_2.write({"qty_to_process": 6.0, "quick_uom_id": self.uom_dozen.id})
|
|
|
|
line_1, line_2 = self.po.order_line
|
|
self.assertAlmostEqual(line_1.product_uom_qty, 5.0)
|
|
self.assertAlmostEqual(line_1.product_qty, 5.0)
|
|
self.assertEqual(line_1.product_uom, self.uom_unit)
|
|
self.assertAlmostEqual(line_1.price_unit, 10)
|
|
|
|
self.assertAlmostEqual(line_2.product_uom_qty, 72.0) # 12 * 6
|
|
self.assertAlmostEqual(line_2.product_qty, 6.0)
|
|
self.assertEqual(line_2.product_uom, self.uom_dozen)
|
|
self.assertAlmostEqual(line_2.price_unit, 48) # 12 * 4
|
|
|
|
def test_quick_line_update_1(self):
|
|
"""
|
|
set non-null quantity to any product with an already existing PO line:
|
|
-> same PO line is updated with that quantity
|
|
"""
|
|
self.product_1.qty_to_process = 7.0
|
|
self.product_2.qty_to_process = 13.0
|
|
line_1, line_2 = self.po.order_line
|
|
self.assertAlmostEqual(line_1.product_qty, 7.0)
|
|
self.assertAlmostEqual(line_1.price_unit, 10.0)
|
|
self.assertAlmostEqual(line_2.product_qty, 13.0)
|
|
self.assertAlmostEqual(line_2.price_unit, 4.0)
|
|
|
|
def test_quick_line_update_2(self):
|
|
"""
|
|
same as previous update only UoM in isolation, not qty
|
|
"""
|
|
self.product_1.quick_uom_id = self.uom_dozen
|
|
self.product_2.quick_uom_id = self.uom_unit
|
|
line_1, line_2 = self.po.order_line
|
|
|
|
self.assertEqual(line_1.product_uom, self.uom_dozen)
|
|
self.assertAlmostEqual(line_1.product_qty, 5.0)
|
|
self.assertAlmostEqual(line_1.product_uom_qty, 60.0)
|
|
self.assertAlmostEqual(line_1.price_unit, 96)
|
|
|
|
self.assertEqual(line_2.product_uom, self.uom_unit)
|
|
self.assertAlmostEqual(line_2.product_qty, 6.0)
|
|
self.assertAlmostEqual(line_2.product_uom_qty, 6.0)
|
|
self.assertAlmostEqual(line_2.price_unit, 5.0)
|
|
|
|
def test_quick_line_update_3(self):
|
|
"""
|
|
same as previous 2 tests combined: we do simultaneous qty + uom updates
|
|
"""
|
|
self.product_1.qty_to_process = 7.0
|
|
self.product_2.qty_to_process = 13.0
|
|
self.product_1.quick_uom_id = self.uom_dozen
|
|
self.product_2.quick_uom_id = self.uom_unit
|
|
|
|
line_1, line_2 = self.po.order_line
|
|
self.assertEqual(line_1.product_uom, self.uom_dozen)
|
|
self.assertEqual(line_2.product_uom, self.uom_unit)
|
|
|
|
self.assertEqual(line_1.product_uom, self.uom_dozen)
|
|
self.assertAlmostEqual(line_1.product_qty, 7.0)
|
|
self.assertAlmostEqual(line_1.product_uom_qty, 84.0)
|
|
self.assertAlmostEqual(line_1.price_unit, 96)
|
|
|
|
self.assertEqual(line_2.product_uom, self.uom_unit)
|
|
self.assertAlmostEqual(line_2.product_qty, 13.0)
|
|
self.assertAlmostEqual(line_2.product_uom_qty, 13.0)
|
|
self.assertAlmostEqual(line_2.price_unit, 4.0)
|
|
|
|
def test_quick_line_delete(self):
|
|
"""
|
|
set null quantity to any product with existing PO line:
|
|
-> PO line is deleted
|
|
"""
|
|
self.product_1.qty_to_process = 0.0
|
|
self.product_2.qty_to_process = 0.0
|
|
self.assertEqual(len(self.po.order_line), 0)
|
|
|
|
def test_open_quick_view(self):
|
|
"""
|
|
Test that the "Add" button opens the right action
|
|
"""
|
|
product_act_from_po = self.po.add_product()
|
|
self.assertEqual(product_act_from_po["type"], "ir.actions.act_window")
|
|
self.assertEqual(product_act_from_po["res_model"], "product.product")
|
|
self.assertEqual(product_act_from_po["view_mode"], "tree")
|
|
self.assertEqual(product_act_from_po["target"], "current")
|
|
self.assertEqual(
|
|
product_act_from_po["view_id"][0],
|
|
self.env.ref("purchase_quick.product_tree_view4purchase").id,
|
|
)
|
|
self.assertEqual(product_act_from_po["context"]["parent_id"], self.po.id)
|
|
|
|
def test_several_po_for_one_product(self):
|
|
"""
|
|
Test that when we try to mass add a product that already has
|
|
several lines with the same product we get a raise
|
|
"""
|
|
self.po.order_line[0].copy()
|
|
with self.assertRaises(ValidationError):
|
|
self.product_1.qty_to_process = 3.0
|
|
|
|
def test_no_pricelist_for_the_min_qty(self):
|
|
"""
|
|
Checks that if you enter a qty_to_process lower than the seller's min_qty,
|
|
the price_unit in de pusrchase.order.line is the standard_price.
|
|
"""
|
|
po = self.env["purchase.order"].create({"partner_id": self.partner.id})
|
|
ctx = {
|
|
"parent_id": po.id,
|
|
"parent_model": "purchase.order",
|
|
"quick_access_rights_purchase": 1,
|
|
}
|
|
product_3 = self.env.ref("product.product_product_5")
|
|
self._add_seller(product_3, [(5, 5), (10, 1)])
|
|
product_3 = product_3.with_context(**ctx)
|
|
product_3.write({"qty_to_process": 1.0, "quick_uom_id": self.uom_unit.id})
|
|
line_1 = po.order_line
|
|
self.assertEqual(line_1.product_qty, 1.0)
|
|
self.assertEqual(line_1.product_uom, self.uom_unit)
|
|
self.assertEqual(line_1.price_unit, product_3.standard_price)
|