add stock_account_avco_negative_fix
This commit is contained in:
parent
10a288f8d5
commit
b07082f70d
9 changed files with 302 additions and 4 deletions
1
stock_account_avco_negative_fix/tests/__init__.py
Normal file
1
stock_account_avco_negative_fix/tests/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from . import test_avco_negative_fix
|
||||
108
stock_account_avco_negative_fix/tests/test_avco_negative_fix.py
Normal file
108
stock_account_avco_negative_fix/tests/test_avco_negative_fix.py
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
from odoo.tests import tagged
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install")
|
||||
class TestAvcoNegativeFix(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
|
||||
cls.customer_location = cls.env.ref("stock.stock_location_customers")
|
||||
cls.stock_location = cls.env.ref("stock.stock_location_stock")
|
||||
cls.picking_type_in = cls.env.ref("stock.picking_type_in")
|
||||
cls.picking_type_out = cls.env.ref("stock.picking_type_out")
|
||||
cls.categ_avco = cls.env["product.category"].create(
|
||||
{"name": "Test AVCO category", "property_cost_method": "average"}
|
||||
)
|
||||
cls.categ_fifo = cls.env["product.category"].create(
|
||||
{"name": "Test FIFO category", "property_cost_method": "fifo"}
|
||||
)
|
||||
|
||||
def _create_product(self, categ, standard_price):
|
||||
return self.env["product.product"].create(
|
||||
{
|
||||
"name": "Test product %s" % categ.name,
|
||||
"type": "product",
|
||||
"categ_id": categ.id,
|
||||
"standard_price": standard_price,
|
||||
}
|
||||
)
|
||||
|
||||
def _validate_move(self, product, qty, location_id, location_dest_id, price_unit=None):
|
||||
move_vals = {
|
||||
"name": "test move",
|
||||
"product_id": product.id,
|
||||
"product_uom_qty": qty,
|
||||
"product_uom": product.uom_id.id,
|
||||
"location_id": location_id.id,
|
||||
"location_dest_id": location_dest_id.id,
|
||||
}
|
||||
if price_unit is not None:
|
||||
move_vals["price_unit"] = price_unit
|
||||
move = self.env["stock.move"].create(move_vals)
|
||||
move._action_confirm()
|
||||
move.quantity_done = qty
|
||||
move._action_done()
|
||||
return move
|
||||
|
||||
def _sell_without_stock(self, product, qty):
|
||||
return self._validate_move(
|
||||
product, qty, self.stock_location, self.customer_location
|
||||
)
|
||||
|
||||
def _receive(self, product, qty, price_unit):
|
||||
return self._validate_move(
|
||||
product, qty, self.supplier_location, self.stock_location, price_unit
|
||||
)
|
||||
|
||||
def test_negative_result_is_corrected(self):
|
||||
"""TC-01 (RF-01): incoming move on a product with quantity_svl <= 0
|
||||
(risk precondition) unconditionally gets standard_price set to the
|
||||
incoming move's price unit, reproducing product_id=8611."""
|
||||
product = self._create_product(self.categ_avco, 6.71)
|
||||
self._sell_without_stock(product, 1.056)
|
||||
self.assertAlmostEqual(product.quantity_svl, -1.056, places=3)
|
||||
self.assertAlmostEqual(product.standard_price, 6.71, places=2)
|
||||
|
||||
self._receive(product, 1.0, 7.56)
|
||||
|
||||
self.assertGreater(product.standard_price, 0.0)
|
||||
self.assertAlmostEqual(product.standard_price, 7.56, places=2)
|
||||
|
||||
def test_zero_result_is_corrected(self):
|
||||
"""TC-02 (RF-02): quantity_svl exactly 0 before the incoming move is
|
||||
also a risk precondition; standard_price is set to the incoming
|
||||
move's price unit."""
|
||||
product = self._create_product(self.categ_avco, 6.0)
|
||||
self._sell_without_stock(product, 2.0)
|
||||
self.assertAlmostEqual(product.quantity_svl, -2.0, places=3)
|
||||
self.assertAlmostEqual(product.standard_price, 6.0, places=2)
|
||||
|
||||
self._receive(product, 3.0, 4.0)
|
||||
|
||||
self.assertNotAlmostEqual(product.standard_price, 0.0, places=2)
|
||||
self.assertAlmostEqual(product.standard_price, 4.0, places=2)
|
||||
|
||||
def test_positive_result_is_untouched(self):
|
||||
"""TC-03 (RF-03): with quantity_svl > 0 before the incoming move
|
||||
(no risk precondition), the post-processing fix does not
|
||||
intervene at all and the core's weighted average is left as-is."""
|
||||
product = self._create_product(self.categ_avco, 1.0)
|
||||
self._receive(product, 10.0, 10.0)
|
||||
self.assertAlmostEqual(product.quantity_svl, 10.0, places=3)
|
||||
self.assertAlmostEqual(product.standard_price, 10.0, places=2)
|
||||
|
||||
self._receive(product, 10.0, 20.0)
|
||||
|
||||
self.assertAlmostEqual(product.standard_price, 15.0, places=2)
|
||||
|
||||
def test_non_avco_product_not_affected(self):
|
||||
"""TC-04 (RF-04): the fix only applies to cost_method == 'average'
|
||||
products; FIFO products follow the core's unmodified behaviour."""
|
||||
product = self._create_product(self.categ_fifo, 5.0)
|
||||
self.assertEqual(product.cost_method, "fifo")
|
||||
|
||||
self._receive(product, 10.0, 8.0)
|
||||
|
||||
self.assertAlmostEqual(product.standard_price, 8.0, places=2)
|
||||
Loading…
Add table
Add a link
Reference in a new issue