summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorWilliam Henrotin <whe@odoo.com>2019-12-10 12:41:06 +0000
committerWilliam Henrotin <whe@odoo.com>2019-12-10 12:41:06 +0000
commit9503f463e38c51b516d6e339b08b934c4e5cf36a (patch)
tree9188ced07d39f6b1877100071194df24ef0aced2 /addons
parent9debcaf377f4ce371150950dd4e501dde1d40551 (diff)
[FIX] mrp: always show post inventory button
The inventory button was shown or hide depending of the product valuation. As the valuation was previously stored on the stock moves and posting split the stock moves. Fifo and Avco valuation was not well computed. The migration to stock valuation layer fixed this behavior. This commit shows the post inventory button as soon as there are some finished move to be posted. task : 54665 closes odoo/odoo#41781 X-original-commit: 5dfa3f817d3a9f47a863a587569a862a40c7d159 Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/mrp/models/mrp_production.py7
-rw-r--r--addons/mrp_account/tests/__init__.py1
-rw-r--r--addons/mrp_account/tests/test_valuation_layers.py275
-rw-r--r--addons/stock/models/product.py3
-rw-r--r--addons/stock_account/models/product.py3
5 files changed, 278 insertions, 11 deletions
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index 248ac58e562..a262e1eaeed 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -368,13 +368,10 @@ class MrpProduction(models.Model):
any_quantity_done = any([m.quantity_done > 0 for m in order.move_raw_ids])
order.unreserve_visible = not any_quantity_done and already_reserved
- @api.depends('move_raw_ids.quantity_done', 'move_finished_ids.quantity_done', 'is_locked')
+ @api.depends('move_finished_ids.quantity_done', 'move_finished_ids.state', 'is_locked')
def _compute_post_visible(self):
for order in self:
- if order.product_tmpl_id._is_cost_method_standard():
- order.post_visible = order.is_locked and any((x.quantity_done > 0 and x.state not in ['done', 'cancel']) for x in order.move_raw_ids | order.move_finished_ids)
- else:
- order.post_visible = order.is_locked and any((x.quantity_done > 0 and x.state not in ['done', 'cancel']) for x in order.move_finished_ids)
+ order.post_visible = order.is_locked and any((x.quantity_done > 0 and x.state not in ['done', 'cancel']) for x in order.move_finished_ids)
@api.depends('workorder_ids.state', 'move_finished_ids', 'move_finished_ids.quantity_done', 'is_locked')
def _get_produced_qty(self):
diff --git a/addons/mrp_account/tests/__init__.py b/addons/mrp_account/tests/__init__.py
index 349bd9d4fed..832146f1555 100644
--- a/addons/mrp_account/tests/__init__.py
+++ b/addons/mrp_account/tests/__init__.py
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_mrp_account
from . import test_bom_price
+from . import test_valuation_layers
diff --git a/addons/mrp_account/tests/test_valuation_layers.py b/addons/mrp_account/tests/test_valuation_layers.py
new file mode 100644
index 00000000000..bf50edf042b
--- /dev/null
+++ b/addons/mrp_account/tests/test_valuation_layers.py
@@ -0,0 +1,275 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+""" Implementation of "INVENTORY VALUATION TESTS (With valuation layers)" spreadsheet. """
+
+from odoo.addons.stock_account.tests.test_stockvaluationlayer import TestStockValuationCommon
+from odoo.tests import Form
+
+
+class TestMrpValuationCommon(TestStockValuationCommon):
+ @classmethod
+ def setUpClass(cls):
+ super(TestMrpValuationCommon, cls).setUpClass()
+ cls.component_category = cls.env['product.category'].create(
+ {'name': 'category2'}
+ )
+ cls.component = cls.env['product.product'].create({
+ 'name': 'component1',
+ 'type': 'product',
+ 'categ_id': cls.component_category.id,
+ })
+ cls.bom = cls.env['mrp.bom'].create({
+ 'product_id': cls.product1.id,
+ 'product_tmpl_id': cls.product1.product_tmpl_id.id,
+ 'product_uom_id': cls.uom_unit.id,
+ 'product_qty': 1.0,
+ 'type': 'normal',
+ 'bom_line_ids': [
+ (0, 0, {'product_id': cls.component.id, 'product_qty': 1})
+ ]})
+
+ def _make_mo(self, bom, quantity=1):
+ mo_form = Form(self.env['mrp.production'])
+ mo_form.product_id = bom.product_id
+ mo_form.bom_id = bom
+ mo_form.product_qty = quantity
+ mo = mo_form.save()
+ mo.action_confirm()
+ return mo
+
+ def _produce(self, mo, quantity=0):
+ produce_form = Form(self.env['mrp.product.produce'].with_context({
+ 'active_id': mo.id,
+ 'active_ids': [mo.id],
+ }))
+ if quantity:
+ produce_form.qty_producing = quantity
+ product_produce = produce_form.save()
+ product_produce.do_produce()
+
+
+class TestMrpValuationStandard(TestMrpValuationCommon):
+ def test_fifo_fifo_1(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo, 1)
+ mo.post_inventory()
+ self.assertEqual(self.component.value_svl, 20)
+ self.assertEqual(self.product1.value_svl, 10)
+ self.assertEqual(self.component.quantity_svl, 1)
+ self.assertEqual(self.product1.quantity_svl, 1)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 30)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+
+ def test_fifo_fifo_2(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 30)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+ self._make_out_move(self.product1, 1)
+ self.assertEqual(self.product1.value_svl, 15)
+
+ def test_fifo_avco_1(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo, 1)
+ mo.post_inventory()
+ self.assertEqual(self.component.value_svl, 20)
+ self.assertEqual(self.product1.value_svl, 10)
+ self.assertEqual(self.component.quantity_svl, 1)
+ self.assertEqual(self.product1.quantity_svl, 1)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 30)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+
+ def test_fifo_avco_2(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 30)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+ self._make_out_move(self.product1, 1)
+ self.assertEqual(self.product1.value_svl, 15)
+
+ def test_fifo_std_1(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.product1.standard_price = 8.8
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo, 1)
+ mo.post_inventory()
+ self.assertEqual(self.component.value_svl, 20)
+ self.assertEqual(self.product1.value_svl, 8.8)
+ self.assertEqual(self.component.quantity_svl, 1)
+ self.assertEqual(self.product1.quantity_svl, 1)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 8.8 * 2)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+
+ def test_fifo_std_2(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'fifo'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.product1.standard_price = 8.8
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 8.8 * 2)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+ self._make_out_move(self.product1, 1)
+ self.assertEqual(self.product1.value_svl, 8.8)
+
+ def test_std_avco_1(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
+ self.component.standard_price = 8.8
+
+ self._make_in_move(self.component, 1)
+ self._make_in_move(self.component, 1)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo, 1)
+ mo.post_inventory()
+ self.assertEqual(self.component.value_svl, 8.8)
+ self.assertEqual(self.product1.value_svl, 8.8)
+ self.assertEqual(self.component.quantity_svl, 1)
+ self.assertEqual(self.product1.quantity_svl, 1)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 8.8 * 2)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+
+ def test_std_avco_2(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
+ self.component.standard_price = 8.8
+
+ self._make_in_move(self.component, 1)
+ self._make_in_move(self.component, 1)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 8.8 * 2)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+ self._make_out_move(self.product1, 1)
+ self.assertEqual(self.product1.value_svl, 8.8)
+
+ def test_std_std_1(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.component.standard_price = 8.8
+ self.product1.standard_price = 7.2
+
+ self._make_in_move(self.component, 1)
+ self._make_in_move(self.component, 1)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo, 1)
+ mo.post_inventory()
+ self.assertEqual(self.component.value_svl, 8.8)
+ self.assertEqual(self.product1.value_svl, 7.2)
+ self.assertEqual(self.component.quantity_svl, 1)
+ self.assertEqual(self.product1.quantity_svl, 1)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 7.2 * 2)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+
+ def test_std_std_2(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
+ self.component.standard_price = 8.8
+ self.product1.standard_price = 7.2
+
+ self._make_in_move(self.component, 1)
+ self._make_in_move(self.component, 1)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 7.2 * 2)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+ self._make_out_move(self.product1, 1)
+ self.assertEqual(self.product1.value_svl, 7.2)
+
+ def test_avco_avco_1(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'average'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo, 1)
+ mo.post_inventory()
+ self.assertEqual(self.component.value_svl, 15)
+ self.assertEqual(self.product1.value_svl, 15)
+ self.assertEqual(self.component.quantity_svl, 1)
+ self.assertEqual(self.product1.quantity_svl, 1)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 30)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+
+ def test_avco_avco_2(self):
+ self.component.product_tmpl_id.categ_id.property_cost_method = 'average'
+ self.product1.product_tmpl_id.categ_id.property_cost_method = 'average'
+
+ self._make_in_move(self.component, 1, 10)
+ self._make_in_move(self.component, 1, 20)
+ mo = self._make_mo(self.bom, 2)
+ self._produce(mo)
+ mo.button_mark_done()
+ self.assertEqual(self.component.value_svl, 0)
+ self.assertEqual(self.product1.value_svl, 30)
+ self.assertEqual(self.component.quantity_svl, 0)
+ self.assertEqual(self.product1.quantity_svl, 2)
+ self._make_out_move(self.product1, 1)
+ self.assertEqual(self.product1.value_svl, 15)
diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py
index aa9202d996c..f5056f25894 100644
--- a/addons/stock/models/product.py
+++ b/addons/stock/models/product.py
@@ -580,9 +580,6 @@ class ProductTemplate(models.Model):
relation="stock.location.route", string="Category Routes",
related='categ_id.total_route_ids', readonly=False)
- def _is_cost_method_standard(self):
- return True
-
@api.depends(
'product_variant_ids',
'product_variant_ids.stock_move_ids.product_qty',
diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py
index e5bb309e0b5..49d5018ddb8 100644
--- a/addons/stock_account/models/product.py
+++ b/addons/stock_account/models/product.py
@@ -64,9 +64,6 @@ class ProductTemplate(models.Model):
# -------------------------------------------------------------------------
# Misc.
# -------------------------------------------------------------------------
- def _is_cost_method_standard(self):
- return self.categ_id.property_cost_method == 'standard'
-
def _get_product_accounts(self):
""" Add the stock accounts related to product to the result of super()
@return: dictionary which contains information regarding stock accounts and super (income+expense accounts)