diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/mrp_account/tests | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/mrp_account/tests')
| -rw-r--r-- | addons/mrp_account/tests/__init__.py | 5 | ||||
| -rw-r--r-- | addons/mrp_account/tests/test_bom_price.py | 202 | ||||
| -rw-r--r-- | addons/mrp_account/tests/test_mrp_account.py | 325 | ||||
| -rw-r--r-- | addons/mrp_account/tests/test_valuation_layers.py | 278 |
4 files changed, 810 insertions, 0 deletions
diff --git a/addons/mrp_account/tests/__init__.py b/addons/mrp_account/tests/__init__.py new file mode 100644 index 00000000..832146f1 --- /dev/null +++ b/addons/mrp_account/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# 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_bom_price.py b/addons/mrp_account/tests/test_bom_price.py new file mode 100644 index 00000000..fd5b76c9 --- /dev/null +++ b/addons/mrp_account/tests/test_bom_price.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.exceptions import UserError +from odoo.tests import common, Form +from odoo.tools.float_utils import float_round, float_compare + + +class TestBom(common.TransactionCase): + + def _create_product(self, name, price): + return self.Product.create({ + 'name': name, + 'type': 'product', + 'standard_price': price, + }) + + def setUp(self): + super(TestBom, self).setUp() + self.Product = self.env['product.product'] + self.Bom = self.env['mrp.bom'] + #self.Routing = self.env['mrp.routing'] + self.operation = self.env['mrp.routing.workcenter'] + + # Products. + self.dining_table = self._create_product('Dining Table', 1000) + self.table_head = self._create_product('Table Head', 300) + self.screw = self._create_product('Screw', 10) + self.leg = self._create_product('Leg', 25) + self.glass = self._create_product('Glass', 100) + + # Unit of Measure. + self.unit = self.env.ref("uom.product_uom_unit") + self.dozen = self.env.ref("uom.product_uom_dozen") + + # Bills Of Materials. + # ------------------------------------------------------------------------------- + # Cost of BoM (Dining Table 1 Unit) + # Component Cost = Table Head 1 Unit * 300 = 300 (468.75 from it's components) + # Screw 5 Unit * 10 = 50 + # Leg 4 Unit * 25 = 100 + # Glass 1 Unit * 100 = 100 + # Total = 550 [718.75 if components of Table Head considered] (for 1 Unit) + # ------------------------------------------------------------------------------- + + bom_form = Form(self.Bom) + bom_form.product_id = self.dining_table + bom_form.product_tmpl_id = self.dining_table.product_tmpl_id + bom_form.product_qty = 1.0 + bom_form.product_uom_id = self.unit + bom_form.type = 'normal' + with bom_form.bom_line_ids.new() as line: + line.product_id = self.table_head + line.product_qty = 1 + with bom_form.bom_line_ids.new() as line: + line.product_id = self.screw + line.product_qty = 5 + with bom_form.bom_line_ids.new() as line: + line.product_id = self.leg + line.product_qty = 4 + with bom_form.bom_line_ids.new() as line: + line.product_id = self.glass + line.product_qty = 1 + self.bom_1 = bom_form.save() + + # Table Head's components. + self.plywood_sheet = self._create_product('Plywood Sheet', 200) + self.bolt = self._create_product('Bolt', 10) + self.colour = self._create_product('Colour', 100) + self.corner_slide = self._create_product('Corner Slide', 25) + + # ----------------------------------------------------------------- + # Cost of BoM (Table Head 1 Dozen) + # Component Cost = Plywood Sheet 12 Unit * 200 = 2400 + # Bolt 60 Unit * 10 = 600 + # Colour 12 Unit * 100 = 1200 + # Corner Slide 57 Unit * 25 = 1425 + # Total = 5625 + # 1 Unit price (5625/12) = 468.75 + # ----------------------------------------------------------------- + + bom_form2 = Form(self.Bom) + bom_form2.product_id = self.table_head + bom_form2.product_tmpl_id = self.table_head.product_tmpl_id + bom_form2.product_qty = 1.0 + bom_form2.product_uom_id = self.dozen + bom_form2.type = 'phantom' + with bom_form2.bom_line_ids.new() as line: + line.product_id = self.plywood_sheet + line.product_qty = 12 + with bom_form2.bom_line_ids.new() as line: + line.product_id = self.bolt + line.product_qty = 60 + with bom_form2.bom_line_ids.new() as line: + line.product_id = self.colour + line.product_qty = 12 + with bom_form2.bom_line_ids.new() as line: + line.product_id = self.corner_slide + line.product_qty = 57 + self.bom_2 = bom_form2.save() + + def test_00_compute_price(self): + """Test multi-level BoM cost""" + self.assertEqual(self.dining_table.standard_price, 1000, "Initial price of the Product should be 1000") + self.dining_table.button_bom_cost() + self.assertEqual(self.dining_table.standard_price, 550, "After computing price from BoM price should be 550") + + def test_01_compute_price_operation_cost(self): + """Test calcuation of bom cost with operations.""" + workcenter_from1 = Form(self.env['mrp.workcenter']) + workcenter_from1.name = 'Workcenter' + workcenter_from1.time_efficiency = 100 + workcenter_from1.capacity = 2 + workcenter_from1.oee_target = 100 + workcenter_from1.time_start = 0 + workcenter_from1.time_stop = 0 + workcenter_from1.costs_hour = 100 + workcenter_1 = workcenter_from1.save() + + self.bom_1.write({ + 'operation_ids': [ + (0, 0, { + 'name': 'Cutting', + 'workcenter_id': workcenter_1.id, + 'time_mode': 'manual', + 'time_cycle_manual': 20, + 'sequence': 1, + }), + (0, 0, { + 'name': 'Drilling', + 'workcenter_id': workcenter_1.id, + 'time_mode': 'manual', + 'time_cycle_manual': 25, + 'sequence': 2, + }), + (0, 0, { + 'name': 'Fitting', + 'workcenter_id': workcenter_1.id, + 'time_mode': 'manual', + 'time_cycle_manual': 30, + 'sequence': 3, + }), + ], + }), + self.bom_2.write({ + 'operation_ids': [ + (0, 0, { + 'name': 'Cutting', + 'workcenter_id': workcenter_1.id, + 'time_mode': 'manual', + 'time_cycle_manual': 20, + 'sequence': 1, + }), + (0, 0, { + 'name': 'Drilling', + 'workcenter_id': workcenter_1.id, + 'time_mode': 'manual', + 'time_cycle_manual': 25, + 'sequence': 2, + }), + (0, 0, { + 'name': 'Fitting', + 'workcenter_id': workcenter_1.id, + 'time_mode': 'manual', + 'time_cycle_manual': 30, + 'sequence': 3, + }), + ], + }), + + + # ----------------------------------------------------------------- + # Dinning Table Operation Cost(1 Unit) + # ----------------------------------------------------------------- + # Operation cost calculate for 1 units + # Cutting (20 / 60) * 100 = 33.33 + # Drilling (25 / 60) * 100 = 41.67 + # Fitting (30 / 60) * 100 = 50.00 + # ---------------------------------------- + # Operation Cost 1 unit = 125 + # ----------------------------------------------------------------- + + + # -------------------------------------------------------------------------- + # Table Head Operation Cost (1 Dozen) + # -------------------------------------------------------------------------- + # Operation cost calculate for 1 dozens + # Cutting (20 * 1 / 60) * 100 = 33,33 + # Drilling (25 * 1 / 60) * 100 = 41,67 + # Fitting (30 * 1 / 60) * 100 = 50 + # ---------------------------------------- + # Operation Cost 1 dozen (125 per dozen) and 10.42 for 1 Unit + # -------------------------------------------------------------------------- + + + self.assertEqual(self.dining_table.standard_price, 1000, "Initial price of the Product should be 1000") + self.dining_table.button_bom_cost() + # Total cost of Dining Table = (550) + Total cost of operations (125) = 675.0 + self.assertEqual(float_round(self.dining_table.standard_price, precision_digits=2), 675.0, "After computing price from BoM price should be 612.5") + self.Product.browse([self.dining_table.id, self.table_head.id]).action_bom_cost() + # Total cost of Dining Table = (718.75) + Total cost of all operations (125 + 10.42) = 854.17 + self.assertEqual(float_compare(self.dining_table.standard_price, 854.17, precision_digits=2), 0, "After computing price from BoM price should be 786.46") diff --git a/addons/mrp_account/tests/test_mrp_account.py b/addons/mrp_account/tests/test_mrp_account.py new file mode 100644 index 00000000..3464e147 --- /dev/null +++ b/addons/mrp_account/tests/test_mrp_account.py @@ -0,0 +1,325 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.mrp.tests.common import TestMrpCommon +from odoo.addons.stock_account.tests.test_account_move import TestAccountMove +from odoo.tests import Form, tagged + + +class TestMrpAccount(TestMrpCommon): + + @classmethod + def setUpClass(cls): + super(TestMrpAccount, cls).setUpClass() + cls.source_location_id = cls.stock_location_14.id + cls.warehouse = cls.env.ref('stock.warehouse0') + # setting up alternative workcenters + cls.wc_alt_1 = cls.env['mrp.workcenter'].create({ + 'name': 'Nuclear Workcenter bis', + 'capacity': 3, + 'time_start': 9, + 'time_stop': 5, + 'time_efficiency': 80, + }) + cls.wc_alt_2 = cls.env['mrp.workcenter'].create({ + 'name': 'Nuclear Workcenter ter', + 'capacity': 1, + 'time_start': 10, + 'time_stop': 5, + 'time_efficiency': 85, + }) + cls.product_4.uom_id = cls.uom_unit + cls.planning_bom = cls.env['mrp.bom'].create({ + 'product_id': cls.product_4.id, + 'product_tmpl_id': cls.product_4.product_tmpl_id.id, + 'product_uom_id': cls.uom_unit.id, + 'product_qty': 4.0, + 'consumption': 'flexible', + 'operation_ids': [ + (0, 0, {'name': 'Gift Wrap Maching', 'workcenter_id': cls.workcenter_1.id, 'time_cycle': 15, 'sequence': 1}), + ], + 'type': 'normal', + 'bom_line_ids': [ + (0, 0, {'product_id': cls.product_2.id, 'product_qty': 2}), + (0, 0, {'product_id': cls.product_1.id, 'product_qty': 4}) + ]}) + cls.dining_table = cls.env['product.product'].create({ + 'name': 'Table (MTO)', + 'type': 'product', + 'tracking': 'serial', + }) + cls.product_table_sheet = cls.env['product.product'].create({ + 'name': 'Table Top', + 'type': 'product', + 'tracking': 'serial', + }) + cls.product_table_leg = cls.env['product.product'].create({ + 'name': 'Table Leg', + 'type': 'product', + 'tracking': 'lot', + }) + cls.product_bolt = cls.env['product.product'].create({ + 'name': 'Bolt', + 'type': 'product', + }) + cls.product_screw = cls.env['product.product'].create({ + 'name': 'Screw', + 'type': 'product', + }) + + cls.mrp_workcenter = cls.env['mrp.workcenter'].create({ + 'name': 'Assembly Line 1', + 'resource_calendar_id': cls.env.ref('resource.resource_calendar_std').id, + }) + cls.mrp_bom_desk = cls.env['mrp.bom'].create({ + 'product_tmpl_id': cls.dining_table.product_tmpl_id.id, + 'product_uom_id': cls.env.ref('uom.product_uom_unit').id, + 'sequence': 3, + 'consumption': 'flexible', + 'operation_ids': [ + (0, 0, {'workcenter_id': cls.mrp_workcenter.id, 'name': 'Manual Assembly'}), + ], + }) + cls.mrp_bom_desk.write({ + 'bom_line_ids': [ + (0, 0, { + 'product_id': cls.product_table_sheet.id, + 'product_qty': 1, + 'product_uom_id': cls.env.ref('uom.product_uom_unit').id, + 'sequence': 1, + 'operation_id': cls.mrp_bom_desk.operation_ids.id}), + (0, 0, { + 'product_id': cls.product_table_leg.id, + 'product_qty': 4, + 'product_uom_id': cls.env.ref('uom.product_uom_unit').id, + 'sequence': 2, + 'operation_id': cls.mrp_bom_desk.operation_ids.id}), + (0, 0, { + 'product_id': cls.product_bolt.id, + 'product_qty': 4, + 'product_uom_id': cls.env.ref('uom.product_uom_unit').id, + 'sequence': 3, + 'operation_id': cls.mrp_bom_desk.operation_ids.id}), + (0, 0, { + 'product_id': cls.product_screw.id, + 'product_qty': 10, + 'product_uom_id': cls.env.ref('uom.product_uom_unit').id, + 'sequence': 4, + 'operation_id': cls.mrp_bom_desk.operation_ids.id}), + ] + }) + cls.mrp_workcenter_1 = cls.env['mrp.workcenter'].create({ + 'name': 'Drill Station 1', + 'resource_calendar_id': cls.env.ref('resource.resource_calendar_std').id, + }) + cls.mrp_workcenter_3 = cls.env['mrp.workcenter'].create({ + 'name': 'Assembly Line 1', + 'resource_calendar_id': cls.env.ref('resource.resource_calendar_std').id, + }) + cls.categ_standard = cls.env['product.category'].create({ + 'name': 'STANDARD', + 'property_cost_method': 'standard' + }) + cls.categ_real = cls.env['product.category'].create({ + 'name': 'REAL', + 'property_cost_method': 'fifo' + }) + cls.categ_average = cls.env['product.category'].create({ + 'name': 'AVERAGE', + 'property_cost_method': 'average' + }) + cls.dining_table.categ_id = cls.categ_real.id + cls.product_table_sheet.categ_id = cls.categ_real.id + cls.product_table_leg.categ_id = cls.categ_average.id + cls.product_bolt.categ_id = cls.categ_standard.id + cls.product_screw.categ_id = cls.categ_standard.id + cls.env['stock.move'].search([('product_id', 'in', [cls.product_bolt.id, cls.product_screw.id])])._do_unreserve() + (cls.product_bolt + cls.product_screw).write({'type': 'product'}) + cls.dining_table.tracking = 'none' + + def test_00_production_order_with_accounting(self): + self.product_table_sheet.standard_price = 20.0 + self.product_table_leg.standard_price = 15.0 + self.product_bolt.standard_price = 10.0 + self.product_screw.standard_price = 0.1 + self.product_table_leg.tracking = 'none' + self.product_table_sheet.tracking = 'none' + inventory = self.env['stock.inventory'].create({ + 'name': 'Inventory Product Table', + 'line_ids': [(0, 0, { + 'product_id': self.product_table_sheet.id, # tracking serial + 'product_uom_id': self.product_table_sheet.uom_id.id, + 'product_qty': 20, + 'location_id': self.source_location_id + }), (0, 0, { + 'product_id': self.product_table_leg.id, # tracking lot + 'product_uom_id': self.product_table_leg.uom_id.id, + 'product_qty': 20, + 'location_id': self.source_location_id + }), (0, 0, { + 'product_id': self.product_bolt.id, + 'product_uom_id': self.product_bolt.uom_id.id, + 'product_qty': 20, + 'location_id': self.source_location_id + }), (0, 0, { + 'product_id': self.product_screw.id, + 'product_uom_id': self.product_screw.uom_id.id, + 'product_qty': 200000, + 'location_id': self.source_location_id + }), + ] + }) + inventory.action_validate + bom = self.mrp_bom_desk.copy() + bom.operation_ids = False + production_table_form = Form(self.env['mrp.production']) + production_table_form.product_id = self.dining_table + production_table_form.bom_id = bom + production_table_form.product_qty = 1 + production_table = production_table_form.save() + + production_table.extra_cost = 20 + production_table.action_confirm() + + mo_form = Form(production_table) + mo_form.qty_producing = 1 + production_table = mo_form.save() + production_table._post_inventory() + move_value = production_table.move_finished_ids.filtered(lambda x: x.state == "done").stock_valuation_layer_ids.value + + # 1 table head at 20 + 4 table leg at 15 + 4 bolt at 10 + 10 screw at 10 + 1*20 (extra cost) + self.assertEqual(move_value, 141, 'Thing should have the correct price') + + +@tagged("post_install", "-at_install") +class TestMrpAccountMove(TestAccountMove): + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.product_B = cls.env["product.product"].create( + { + "name": "Product B", + "type": "product", + "default_code": "prda", + "categ_id": cls.env.ref("product.product_category_all").id, + "taxes_id": [(5, 0, 0)], + "supplier_taxes_id": [(5, 0, 0)], + "lst_price": 100.0, + "standard_price": 10.0, + "property_account_income_id": cls.company_data["default_account_revenue"].id, + "property_account_expense_id": cls.company_data["default_account_expense"].id, + } + ) + cls.bom = cls.env['mrp.bom'].create({ + 'product_id': cls.product_A.id, + 'product_tmpl_id': cls.product_A.product_tmpl_id.id, + 'product_qty': 1.0, + 'bom_line_ids': [ + (0, 0, {'product_id': cls.product_B.id, 'product_qty': 1}), + ]}) + + def test_unbuild_account_00(self): + """Test when after unbuild, the journal entries are the reversal of the + journal entries created when produce the product. + """ + # build + production_form = Form(self.env['mrp.production']) + production_form.product_id = self.product_A + production_form.bom_id = self.bom + production_form.product_qty = 1 + production = production_form.save() + production.action_confirm() + mo_form = Form(production) + mo_form.qty_producing = 1 + production = mo_form.save() + production._post_inventory() + production.button_mark_done() + + # finished product move + productA_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product A'), ('credit', '=', 0)]) + productA_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product A'), ('debit', '=', 0)]) + self.assertEqual(productA_debit_line.account_id, self.stock_valuation_account) + self.assertEqual(productA_credit_line.account_id, self.stock_input_account) + # component move + productB_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product B'), ('credit', '=', 0)]) + productB_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product B'), ('debit', '=', 0)]) + self.assertEqual(productB_debit_line.account_id, self.stock_output_account) + self.assertEqual(productB_credit_line.account_id, self.stock_valuation_account) + + # unbuild + res_dict = production.button_unbuild() + wizard = Form(self.env[res_dict['res_model']].with_context(res_dict['context'])).save() + wizard.action_validate() + + # finished product move + productA_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product A'), ('credit', '=', 0)]) + productA_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product A'), ('debit', '=', 0)]) + self.assertEqual(productA_debit_line.account_id, self.stock_input_account) + self.assertEqual(productA_credit_line.account_id, self.stock_valuation_account) + # component move + productB_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product B'), ('credit', '=', 0)]) + productB_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product B'), ('debit', '=', 0)]) + self.assertEqual(productB_debit_line.account_id, self.stock_valuation_account) + self.assertEqual(productB_credit_line.account_id, self.stock_output_account) + + def test_unbuild_account_01(self): + """Test when production location has its valuation accounts. After unbuild, + the journal entries are the reversal of the journal entries created when + produce the product. + """ + # set accounts for production location + production_location = self.product_A.property_stock_production + wip_incoming_account = self.env['account.account'].create({ + 'name': 'wip incoming', + 'code': '000001', + 'user_type_id': self.env.ref('account.data_account_type_current_assets').id, + }) + wip_outgoing_account = self.env['account.account'].create({ + 'name': 'wip outgoing', + 'code': '000002', + 'user_type_id': self.env.ref('account.data_account_type_current_assets').id, + }) + production_location.write({ + 'valuation_in_account_id': wip_incoming_account.id, + 'valuation_out_account_id': wip_outgoing_account.id, + }) + + # build + production_form = Form(self.env['mrp.production']) + production_form.product_id = self.product_A + production_form.bom_id = self.bom + production_form.product_qty = 1 + production = production_form.save() + production.action_confirm() + mo_form = Form(production) + mo_form.qty_producing = 1 + production = mo_form.save() + production._post_inventory() + production.button_mark_done() + + # finished product move + productA_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product A'), ('credit', '=', 0)]) + productA_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product A'), ('debit', '=', 0)]) + self.assertEqual(productA_debit_line.account_id, self.stock_valuation_account) + self.assertEqual(productA_credit_line.account_id, wip_outgoing_account) + # component move + productB_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product B'), ('credit', '=', 0)]) + productB_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product B'), ('debit', '=', 0)]) + self.assertEqual(productB_debit_line.account_id, wip_incoming_account) + self.assertEqual(productB_credit_line.account_id, self.stock_valuation_account) + + # unbuild + res_dict = production.button_unbuild() + wizard = Form(self.env[res_dict['res_model']].with_context(res_dict['context'])).save() + wizard.action_validate() + + productA_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product A'), ('credit', '=', 0)]) + productA_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product A'), ('debit', '=', 0)]) + self.assertEqual(productA_debit_line.account_id, wip_outgoing_account) + self.assertEqual(productA_credit_line.account_id, self.stock_valuation_account) + # component move + productB_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product B'), ('credit', '=', 0)]) + productB_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product B'), ('debit', '=', 0)]) + self.assertEqual(productB_debit_line.account_id, self.stock_valuation_account) + self.assertEqual(productB_credit_line.account_id, wip_incoming_account) 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 00000000..df03cc16 --- /dev/null +++ b/addons/mrp_account/tests/test_valuation_layers.py @@ -0,0 +1,278 @@ +# -*- 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): + mo_form = Form(mo) + if not quantity: + quantity = mo.product_qty - mo.qty_produced + mo_form.qty_producing += quantity + mo = mo_form.save() + + +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) + action = mo.button_mark_done() + backorder = Form(self.env['mrp.production.backorder'].with_context(**action['context'])) + backorder.save().action_backorder() + mo = mo.procurement_group_id.mrp_production_ids[-1] + 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) + action = mo.button_mark_done() + backorder = Form(self.env['mrp.production.backorder'].with_context(**action['context'])) + backorder.save().action_backorder() + mo = mo.procurement_group_id.mrp_production_ids[-1] + 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) |
