Files
enterprise-addons/mrp_account_enterprise/tests/test_report.py
T

142 lines
5.7 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mrp_account.tests.common import TestBomPriceOperationCommon
from freezegun import freeze_time
class TestReportsCommon(TestBomPriceOperationCommon):
@freeze_time('2022-05-28')
def test_mrp_avg_cost_calculation(self):
"""
Check that the average cost is calculated based on the quantity produced in each MO
1:/ MO1:
- qty to produce: 10 units
- work_order duration: 300
unit_component_cost = (12 * 200 + 60 * 10 + 12 * 100 + 57 * 25) + (50 * 3)) = 5625
unit_duration = 300 / 10 = 30
unit_operation_cost = 100 * 30'unit_duration' = 50
unit_cost = 5623 + 50 = 5675
2:/ MO2:
- update plywood_sheet cost to: $300
- qty to produce: 20 units
- work order duration: 600
unit_component_cost = (12 * 300 + 60 * 10 + 12 * 100 + 57 * 25) + (50 * 3)) = 6825
unit_duration = 600 / 20 = 30
unit_operation_cost = 100 * 30'unit_duration' = 50
unit_cost = 6825 + 50 = 6875
total_qty_produced = 30
avg_unit_component_cost = ((5625 * 10) + (6825 * 20)) / 30 = $6425
avg_unit_operation_cost = ((50*20) + (50*10)) / 30 = $50
avg_unit_duration = (600 + 300) / 30 = 30
avg_unit_cost = avg_unit_component_cost + avg_unit_operation_cost = $6525
"""
self.table_head.categ_id = self.category_avco
self.bom_2.type = 'normal'
self.bom_2.product_uom_id = self.uom
# MO_1
mo_1 = self._create_mo(self.bom_2, 10)
mo_1.button_plan()
wo = mo_1.workorder_ids
wo.button_start()
wo.duration = 100 # 3 wo * 100 = 300
wo.qty_producing = 10
mo_1.button_mark_done()
self.plywood_sheet.standard_price = 300
# MO_2
self.glass.standard_price = 30
mo_2 = self._create_mo(self.bom_2, 20)
mo_2.button_plan()
wo = mo_2.workorder_ids
wo.button_start()
wo.duration = 200
wo.qty_producing = 20
mo_2.button_mark_done()
# must flush else SQL request in report is not accurate
self.env.flush_all()
report = self.env['mrp.report']._read_group(
[('product_id', '=', self.table_head.id)],
aggregates=['unit_cost:avg', 'unit_component_cost:avg', 'unit_operation_cost:avg', 'unit_duration:avg'],
)[0]
unit_cost, unit_component_cost, unit_operation_cost, unit_duration = report
self.assertEqual(self.company.currency_id.round(unit_cost), 6475)
self.assertEqual(self.company.currency_id.round(unit_component_cost), 6425)
self.assertEqual(self.company.currency_id.round(unit_operation_cost), 50)
self.assertEqual(self.company.currency_id.round(unit_duration), 30)
def test_report_uom_conversion_quantities_and_costs(self):
"""Ensure mrp.report correctly handles UoM conversions when aggregating MOs.
Scenario:
- Product with UoM = Unit
- BoM: 1 unit of component C1 with cost = $10
Create two MOs with different UoMs:
- MO1 in Dozen (produce 1 dozen = 12 units)
- MO2 in Unit (produce 1 unit)
The report should:
- Convert all quantities into the product's UoM (Unit)
- Keep consistent unit costs across MOs
- Aggregate quantities correctly
Expected:
- Total produced quantity = 13 units
- Unit cost = $10
"""
# Set component cost
self.bom_2.type = 'normal'
self.bom_2.product_uom_id = self.env.ref('uom.product_uom_unit').id
self.bom_2.bom_line_ids = self.bom_2.bom_line_ids[0]
self.bom_2.bom_line_ids.product_id.standard_price = 10
self.bom_2.bom_line_ids.product_qty = 1
self.bom_2.operation_ids = False # Remove operation to simplify the test and focus on UoM conversion
# Mo1: Dozen
mo = self.env['mrp.production'].create({
'bom_id': self.bom_2.id,
'product_uom_id': self.env.ref('uom.product_uom_dozen').id,
'product_qty': 1,
})
mo.action_confirm()
mo.move_raw_ids.quantity = 12
mo.move_raw_ids.picked = True
mo.button_mark_done()
self.assertEqual(mo.state, 'done')
# must flush else SQL request in report is not accurate
self.env.flush_all()
report = self.env['mrp.report']._read_group(
[('product_id', '=', self.bom_2.product_id.id)],
aggregates=['unit_cost:avg', 'unit_component_cost:avg', 'qty_produced:sum'],
)[0]
unit_cost, unit_component_cost, qty_produced = report
self.assertEqual(unit_cost, 10)
self.assertEqual(unit_component_cost, 10)
self.assertEqual(qty_produced, 12)
# Mo2: Unit
mo_2 = self.env['mrp.production'].create({
'bom_id': self.bom_2.id,
})
mo_2.action_confirm()
mo_2.move_raw_ids.quantity = 1
mo_2.move_raw_ids.picked = True
mo_2.button_mark_done()
self.assertEqual(mo_2.state, 'done')
self.env.flush_all()
report = self.env['mrp.report']._read_group(
[('product_id', '=', self.bom_2.product_id.id)],
aggregates=['unit_cost:avg', 'unit_component_cost:avg', 'qty_produced:sum'],
)[0]
unit_cost, unit_component_cost, qty_produced = report
self.assertEqual(unit_cost, 10)
self.assertEqual(unit_component_cost, 10)
self.assertEqual(qty_produced, 13)