def setUp(self): super(TestSubcontractingTracking, self).setUp() # 1: Create a subcontracting partner main_company_1 = self.env['res.partner'].create( {'name': 'main_partner'}) self.subcontractor_partner1 = self.env['res.partner'].create({ 'name': 'Subcontractor 1', 'parent_id': main_company_1.id, 'company_id': self.env.ref('base.main_company').id }) # 2. Create a BOM of subcontracting type # 2.1. Comp1 has tracking by lot self.comp1_sn = self.env['product.product'].create({ 'name': 'Component1', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, 'tracking': 'serial' }) self.comp2 = self.env['product.product'].create({ 'name': 'Component2', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, }) # 2.2. Finished prodcut has tracking by serial number self.finished_lot = self.env['product.product'].create({ 'name': 'finished', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, 'tracking': 'lot' }) bom_form = Form(self.env['mrp.bom']) bom_form.type = 'subcontract' bom_form.subcontractor_ids.add(self.subcontractor_partner1) bom_form.product_tmpl_id = self.finished_lot.product_tmpl_id with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.comp1_sn bom_line.product_qty = 1 with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.comp2 bom_line.product_qty = 1 self.bom_tracked = bom_form.save()
def setUp(self): super(TestMultistepManufacturing, self).setUp() self.MrpProduction = self.env['mrp.production'] # Create warehouse warehouse_form = Form(self.env['stock.warehouse']) warehouse_form.name = 'Test' warehouse_form.code = 'Test' self.warehouse = warehouse_form.save() self.uom_unit = self.env.ref('uom.product_uom_unit') # Create manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Stick' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit product_form.route_ids.clear() product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id) product_form.route_ids.add(self.warehouse.mto_pull_id.route_id) self.product_manu = product_form.save() # Create raw product for manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Raw Stick' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit self.product_raw = product_form.save() # Create bom for manufactured product bom_product_form = Form(self.env['mrp.bom']) bom_product_form.product_id = self.product_manu bom_product_form.product_tmpl_id = self.product_manu.product_tmpl_id bom_product_form.product_qty = 1.0 bom_product_form.type = 'normal' with bom_product_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.product_raw bom_line.product_qty = 2.0 self.bom_prod_manu = bom_product_form.save() # Create sale order sale_form = Form(self.env['sale.order']) sale_form.partner_id = self.env.ref('base.res_partner_1') sale_form.picking_policy = 'direct' sale_form.warehouse_id = self.warehouse with sale_form.order_line.new() as line: line.name = self.product_manu.name line.product_id = self.product_manu line.product_uom_qty = 1.0 line.product_uom = self.uom_unit line.price_unit = 10.0 self.sale_order = sale_form.save()
def setUp(self): super(TestMultistepManufacturingWarehouse, self).setUp() # Create warehouse self.customer_location = self.env['ir.model.data'].xmlid_to_res_id( 'stock.stock_location_customers') warehouse_form = Form(self.env['stock.warehouse']) warehouse_form.name = 'Test Warehouse' warehouse_form.code = 'TWH' self.warehouse = warehouse_form.save() self.uom_unit = self.env.ref('uom.product_uom_unit') # Create manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Stick' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit product_form.type = 'product' product_form.route_ids.clear() product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id) product_form.route_ids.add(self.warehouse.mto_pull_id.route_id) self.finished_product = product_form.save() # Create raw product for manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Raw Stick' product_form.type = 'product' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit self.raw_product = product_form.save() # Create bom for manufactured product bom_product_form = Form(self.env['mrp.bom']) bom_product_form.product_id = self.finished_product bom_product_form.product_tmpl_id = self.finished_product.product_tmpl_id bom_product_form.product_qty = 1.0 bom_product_form.type = 'normal' with bom_product_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.raw_product bom_line.product_qty = 2.0 self.bom = bom_product_form.save()
def test_flow_6(self): """ Extra quantity on the move. """ # We create a second partner of type subcontractor main_partner_2 = self.env['res.partner'].create( {'name': 'main_partner'}) subcontractor_partner2 = self.env['res.partner'].create({ 'name': 'subcontractor_partner', 'parent_id': main_partner_2.id, 'company_id': self.env.ref('base.main_company').id, }) self.env.cache.invalidate() # We create a different BoM for the same product comp3 = self.env['product.product'].create({ 'name': 'Component3', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, }) bom_form = Form(self.env['mrp.bom']) bom_form.type = 'subcontract' bom_form.product_tmpl_id = self.finished.product_tmpl_id with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.comp1 bom_line.product_qty = 1 with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = comp3 bom_line.product_qty = 2 bom2 = bom_form.save() # We assign the second BoM to the new partner self.bom.write( {'subcontractor_ids': [(4, self.subcontractor_partner1.id, None)]}) bom2.write( {'subcontractor_ids': [(4, subcontractor_partner2.id, None)]}) # Create a receipt picking from the subcontractor1 picking_form = Form(self.env['stock.picking']) picking_form.picking_type_id = self.env.ref('stock.picking_type_in') picking_form.partner_id = subcontractor_partner2 with picking_form.move_ids_without_package.new() as move: move.product_id = self.finished move.product_uom_qty = 1 picking_receipt = picking_form.save() picking_receipt.action_confirm() picking_receipt.move_lines.quantity_done = 3.0 picking_receipt.action_done() mo = picking_receipt._get_subcontracted_productions() move_comp1 = mo.move_raw_ids.filtered( lambda m: m.product_id == self.comp1) move_comp3 = mo.move_raw_ids.filtered(lambda m: m.product_id == comp3) self.assertEqual(sum(move_comp1.mapped('product_uom_qty')), 3.0) self.assertEqual(sum(move_comp3.mapped('product_uom_qty')), 6.0) self.assertEqual(sum(move_comp1.mapped('quantity_done')), 3.0) self.assertEqual(sum(move_comp3.mapped('quantity_done')), 6.0) move_finished = mo.move_finished_ids self.assertEqual(sum(move_finished.mapped('product_uom_qty')), 3.0) self.assertEqual(sum(move_finished.mapped('quantity_done')), 3.0)
def test_flow_5(self): """ Check that the correct BoM is chosen accordingly to the partner """ # We create a second partner of type subcontractor main_partner_2 = self.env['res.partner'].create( {'name': 'main_partner'}) subcontractor_partner2 = self.env['res.partner'].create({ 'name': 'subcontractor_partner', 'parent_id': main_partner_2.id, 'company_id': self.env.ref('base.main_company').id }) # We create a different BoM for the same product comp3 = self.env['product.product'].create({ 'name': 'Component1', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, }) bom_form = Form(self.env['mrp.bom']) bom_form.type = 'subcontract' bom_form.product_tmpl_id = self.finished.product_tmpl_id with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.comp1 bom_line.product_qty = 1 with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = comp3 bom_line.product_qty = 1 bom2 = bom_form.save() # We assign the second BoM to the new partner self.bom.write( {'subcontractor_ids': [(4, self.subcontractor_partner1.id, None)]}) bom2.write( {'subcontractor_ids': [(4, subcontractor_partner2.id, None)]}) # Create a receipt picking from the subcontractor1 picking_form = Form(self.env['stock.picking']) picking_form.picking_type_id = self.env.ref('stock.picking_type_in') picking_form.partner_id = self.subcontractor_partner1 with picking_form.move_ids_without_package.new() as move: move.product_id = self.finished move.product_uom_qty = 1 picking_receipt1 = picking_form.save() picking_receipt1.action_confirm() # Create a receipt picking from the subcontractor2 picking_form = Form(self.env['stock.picking']) picking_form.picking_type_id = self.env.ref('stock.picking_type_in') picking_form.partner_id = subcontractor_partner2 with picking_form.move_ids_without_package.new() as move: move.product_id = self.finished move.product_uom_qty = 1 picking_receipt2 = picking_form.save() picking_receipt2.action_confirm() mo_pick1 = picking_receipt1.move_lines.mapped( 'move_orig_ids.production_id') mo_pick2 = picking_receipt2.move_lines.mapped( 'move_orig_ids.production_id') self.assertEquals(len(mo_pick1), 1) self.assertEquals(len(mo_pick2), 1) self.assertEquals(mo_pick1.bom_id, self.bom) self.assertEquals(mo_pick2.bom_id, bom2)
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_22_bom_report_recursive_bom(self): """ Test report with recursive BoM and different quantities. BoM 1: product = Finished (units) quantity = 100 units - Semi-Finished 5 kg BoM 2: product = Semi-Finished (kg) quantity = 11 kg - Assembly 2 dozens BoM 3: product = Assembly (dozens) quantity = 5 dozens - Raw Material 4 litres (product.product 5$/litre) Check the Price for 80 units of Finished -> 2.92$: """ # Create a products templates uom_unit = self.env.ref('uom.product_uom_unit') uom_kg = self.env.ref('uom.product_uom_kgm') uom_dozen = self.env.ref('uom.product_uom_dozen') uom_litre = self.env.ref('uom.product_uom_litre') finished = self.env['product.product'].create({ 'name': 'Finished', 'type': 'product', 'uom_id': uom_unit.id, 'uom_po_id': uom_unit.id, }) semi_finished = self.env['product.product'].create({ 'name': 'Semi-Finished', 'type': 'product', 'uom_id': uom_kg.id, 'uom_po_id': uom_kg.id, }) assembly = self.env['product.product'].create({ 'name': 'Assembly', 'type': 'product', 'uom_id': uom_dozen.id, 'uom_po_id': uom_dozen.id, }) raw_material = self.env['product.product'].create({ 'name': 'Raw Material', 'type': 'product', 'uom_id': uom_litre.id, 'uom_po_id': uom_litre.id, 'standard_price': 5, }) #Create bom bom_finished = Form(self.env['mrp.bom']) bom_finished.product_tmpl_id = finished.product_tmpl_id bom_finished.product_qty = 100 with bom_finished.bom_line_ids.new() as line: line.product_id = semi_finished line.product_uom_id = uom_kg line.product_qty = 5 bom_finished = bom_finished.save() bom_semi_finished = Form(self.env['mrp.bom']) bom_semi_finished.product_tmpl_id = semi_finished.product_tmpl_id bom_semi_finished.product_qty = 11 with bom_semi_finished.bom_line_ids.new() as line: line.product_id = assembly line.product_uom_id = uom_dozen line.product_qty = 2 bom_semi_finished = bom_semi_finished.save() bom_assembly = Form(self.env['mrp.bom']) bom_assembly.product_tmpl_id = assembly.product_tmpl_id bom_assembly.product_qty = 5 with bom_assembly.bom_line_ids.new() as line: line.product_id = raw_material line.product_uom_id = uom_litre line.product_qty = 4 bom_assembly = bom_assembly.save() report_values = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_finished.id, searchQty=80) self.assertAlmostEqual(report_values['lines']['total'], 2.92)
def test_21_bom_report_variant(self): """ Test a sub BoM process with multiple variants. BOM 1: product template = car quantity = 5 units - red paint 50l -> red car (product.product) - blue paint 50l -> blue car - red dashboard with gps -> red car with GPS - red dashboard w/h gps -> red w/h GPS - blue dashboard with gps -> blue car with GPS - blue dashboard w/h gps -> blue w/h GPS BOM 2: product_tmpl = dashboard quantity = 2 - red paint 1l -> red dashboard (product.product) - blue paint 1l -> blue dashboard - gps -> dashboard with gps Check the Price for a Blue Car with GPS -> 910$: 10l of blue paint -> 200$ 1 blue dashboard GPS -> 710$: - 0.5l of blue paint -> 10$ - GPS -> 700$ Check the price for a red car -> 10.5l of red paint -> 210$ """ # Create a product template car with attributes gps(yes, no), color(red, blue) self.car = self.env['product.template'].create({ 'name': 'Car', }) self.gps_attribute = self.env['product.attribute'].create({ 'name': 'GPS', 'sequence': 1 }) self.gps_yes = self.env['product.attribute.value'].create({ 'name': 'Yes', 'attribute_id': self.gps_attribute.id, 'sequence': 1, }) self.gps_no = self.env['product.attribute.value'].create({ 'name': 'No', 'attribute_id': self.gps_attribute.id, 'sequence': 2, }) self.car_gps_attribute_line = self.env[ 'product.template.attribute.line'].create({ 'product_tmpl_id': self.car.id, 'attribute_id': self.gps_attribute.id, 'value_ids': [(6, 0, [self.gps_yes.id, self.gps_no.id])], }) self.car_gps_yes = self.car_gps_attribute_line.product_template_value_ids[ 0] self.car_gps_no = self.car_gps_attribute_line.product_template_value_ids[ 1] self.color_attribute = self.env['product.attribute'].create({ 'name': 'Color', 'sequence': 1 }) self.color_red = self.env['product.attribute.value'].create({ 'name': 'Red', 'attribute_id': self.color_attribute.id, 'sequence': 1, }) self.color_blue = self.env['product.attribute.value'].create({ 'name': 'Blue', 'attribute_id': self.color_attribute.id, 'sequence': 2, }) self.car_color_attribute_line = self.env[ 'product.template.attribute.line'].create({ 'product_tmpl_id': self.car.id, 'attribute_id': self.color_attribute.id, 'value_ids': [(6, 0, [self.color_red.id, self.color_blue.id])], }) self.car_color_red = self.car_color_attribute_line.product_template_value_ids[ 0] self.car_color_blue = self.car_color_attribute_line.product_template_value_ids[ 1] # Blue and red paint uom_litre = self.env.ref('uom.product_uom_litre') self.paint = self.env['product.template'].create({ 'name': 'Paint', 'uom_id': uom_litre.id, 'uom_po_id': uom_litre.id }) self.paint_color_attribute_line = self.env[ 'product.template.attribute.line'].create({ 'product_tmpl_id': self.paint.id, 'attribute_id': self.color_attribute.id, 'value_ids': [(6, 0, [self.color_red.id, self.color_blue.id])], }) self.paint_color_red = self.paint_color_attribute_line.product_template_value_ids[ 0] self.paint_color_blue = self.paint_color_attribute_line.product_template_value_ids[ 1] self.paint.product_variant_ids.write({'standard_price': 20}) self.dashboard = self.env['product.template'].create({ 'name': 'Dashboard', 'standard_price': 1000, }) self.dashboard_gps_attribute_line = self.env[ 'product.template.attribute.line'].create({ 'product_tmpl_id': self.dashboard.id, 'attribute_id': self.gps_attribute.id, 'value_ids': [(6, 0, [self.gps_yes.id, self.gps_no.id])], }) self.dashboard_gps_yes = self.dashboard_gps_attribute_line.product_template_value_ids[ 0] self.dashboard_gps_no = self.dashboard_gps_attribute_line.product_template_value_ids[ 1] self.dashboard_color_attribute_line = self.env[ 'product.template.attribute.line'].create({ 'product_tmpl_id': self.dashboard.id, 'attribute_id': self.color_attribute.id, 'value_ids': [(6, 0, [self.color_red.id, self.color_blue.id])], }) self.dashboard_color_red = self.dashboard_color_attribute_line.product_template_value_ids[ 0] self.dashboard_color_blue = self.dashboard_color_attribute_line.product_template_value_ids[ 1] self.gps = self.env['product.product'].create({ 'name': 'GPS', 'standard_price': 700, }) bom_form_car = Form(self.env['mrp.bom']) bom_form_car.product_tmpl_id = self.car bom_form_car.product_qty = 5 with bom_form_car.bom_line_ids.new() as line: line.product_id = self.paint._get_variant_for_combination( self.paint_color_red) line.product_uom_id = uom_litre line.product_qty = 50 line.bom_product_template_attribute_value_ids.add( self.car_color_red) with bom_form_car.bom_line_ids.new() as line: line.product_id = self.paint._get_variant_for_combination( self.paint_color_blue) line.product_uom_id = uom_litre line.product_qty = 50 line.bom_product_template_attribute_value_ids.add( self.car_color_blue) with bom_form_car.bom_line_ids.new() as line: line.product_id = self.dashboard._get_variant_for_combination( self.dashboard_gps_yes + self.dashboard_color_red) line.product_qty = 5 line.bom_product_template_attribute_value_ids.add(self.car_gps_yes) line.bom_product_template_attribute_value_ids.add( self.car_color_red) with bom_form_car.bom_line_ids.new() as line: line.product_id = self.dashboard._get_variant_for_combination( self.dashboard_gps_yes + self.dashboard_color_blue) line.product_qty = 5 line.bom_product_template_attribute_value_ids.add(self.car_gps_yes) line.bom_product_template_attribute_value_ids.add( self.car_color_blue) with bom_form_car.bom_line_ids.new() as line: line.product_id = self.dashboard._get_variant_for_combination( self.dashboard_gps_no + self.dashboard_color_red) line.product_qty = 5 line.bom_product_template_attribute_value_ids.add(self.car_gps_no) line.bom_product_template_attribute_value_ids.add( self.car_color_red) with bom_form_car.bom_line_ids.new() as line: line.product_id = self.dashboard._get_variant_for_combination( self.dashboard_gps_no + self.dashboard_color_blue) line.product_qty = 5 line.bom_product_template_attribute_value_ids.add(self.car_gps_no) line.bom_product_template_attribute_value_ids.add( self.car_color_blue) bom_car = bom_form_car.save() bom_dashboard = Form(self.env['mrp.bom']) bom_dashboard.product_tmpl_id = self.dashboard bom_dashboard.product_qty = 2 with bom_dashboard.bom_line_ids.new() as line: line.product_id = self.paint._get_variant_for_combination( self.paint_color_red) line.product_uom_id = uom_litre line.product_qty = 1 line.bom_product_template_attribute_value_ids.add( self.dashboard_color_red) with bom_dashboard.bom_line_ids.new() as line: line.product_id = self.paint._get_variant_for_combination( self.paint_color_blue) line.product_uom_id = uom_litre line.product_qty = 1 line.bom_product_template_attribute_value_ids.add( self.dashboard_color_blue) with bom_dashboard.bom_line_ids.new() as line: line.product_id = self.gps line.product_qty = 2 line.bom_product_template_attribute_value_ids.add( self.dashboard_gps_yes) bom_dashboard = bom_dashboard.save() blue_car_with_gps = self.car._get_variant_for_combination( self.car_color_blue + self.car_gps_yes) report_values = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_car.id, searchQty=1, searchVariant=blue_car_with_gps.id) # Two lines. blue dashboard with gps and blue paint. self.assertEqual(len(report_values['lines']['components']), 2) # 10l of blue paint blue_paint = self.paint._get_variant_for_combination( self.paint_color_blue) self.assertEqual(blue_paint.id, report_values['lines']['components'][0]['prod_id']) self.assertEqual(report_values['lines']['components'][0]['prod_qty'], 10) # 1 blue dashboard with GPS blue_dashboard_gps = self.dashboard._get_variant_for_combination( self.dashboard_color_blue + self.dashboard_gps_yes) self.assertEqual(blue_dashboard_gps.id, report_values['lines']['components'][1]['prod_id']) self.assertEqual(report_values['lines']['components'][1]['prod_qty'], 1) component = report_values['lines']['components'][1] report_values_dashboad = self.env[ 'report.mrp.report_bom_structure']._get_bom( component['child_bom'], component['prod_id'], component['prod_qty'], component['line_id'], component['level'] + 1) self.assertEqual(len(report_values_dashboad['components']), 2) self.assertEqual(blue_paint.id, report_values_dashboad['components'][0]['prod_id']) self.assertEqual(self.gps.id, report_values_dashboad['components'][1]['prod_id']) # 0.5l of paint at price of 20$/litre -> 10$ self.assertEqual(report_values_dashboad['components'][0]['total'], 10) # GPS 700$ self.assertEqual(report_values_dashboad['components'][1]['total'], 700) # Dashboard blue with GPS should have a BoM cost of 710$ self.assertEqual(report_values['lines']['components'][1]['total'], 710) # 10l of paint at price of 20$/litre -> 200$ self.assertEqual(report_values['lines']['components'][0]['total'], 200) # Total cost of blue car with GPS: 10 + 700 + 200 = 910 self.assertEqual(report_values['lines']['total'], 910) red_car_without_gps = self.car._get_variant_for_combination( self.car_color_red + self.car_gps_no) report_values = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_car.id, searchQty=1, searchVariant=red_car_without_gps.id) # Same math than before but without GPS self.assertEqual(report_values['lines']['total'], 210)
def test_20_bom_report(self): """ Simulate a crumble receipt with mrp and open the bom structure report and check that data insde are correct. """ uom_kg = self.env.ref('uom.product_uom_kgm') uom_litre = self.env.ref('uom.product_uom_litre') crumble = self.env['product.product'].create({ 'name': 'Crumble', 'type': 'product', 'uom_id': uom_kg.id, 'uom_po_id': uom_kg.id, }) butter = self.env['product.product'].create({ 'name': 'Butter', 'type': 'product', 'uom_id': uom_kg.id, 'uom_po_id': uom_kg.id, 'standard_price': 7.01 }) biscuit = self.env['product.product'].create({ 'name': 'Biscuit', 'type': 'product', 'uom_id': uom_kg.id, 'uom_po_id': uom_kg.id, 'standard_price': 1.5 }) bom_form_crumble = Form(self.env['mrp.bom']) bom_form_crumble.product_tmpl_id = crumble.product_tmpl_id bom_form_crumble.product_qty = 11 bom_form_crumble.product_uom_id = uom_kg bom_crumble = bom_form_crumble.save() with Form(bom_crumble) as bom: with bom.bom_line_ids.new() as line: line.product_id = butter line.product_uom_id = uom_kg line.product_qty = 5 with bom.bom_line_ids.new() as line: line.product_id = biscuit line.product_uom_id = uom_kg line.product_qty = 6 workcenter = self.env['mrp.workcenter'].create({ 'costs_hour': 10, 'name': 'Deserts Table' }) routing_form = Form(self.env['mrp.routing']) routing_form.name = "Crumble process" routing_crumble = routing_form.save() with Form(routing_crumble) as routing: with routing.operation_ids.new() as operation: operation.workcenter_id = workcenter operation.name = 'Prepare biscuits' operation.time_cycle_manual = 5 with routing.operation_ids.new() as operation: operation.workcenter_id = workcenter operation.name = 'Prepare butter' operation.time_cycle_manual = 3 with routing.operation_ids.new() as operation: operation.workcenter_id = workcenter operation.name = 'Mix manually' operation.time_cycle_manual = 5 bom_crumble.routing_id = routing_crumble.id # TEST BOM STRUCTURE VALUE WITH BOM QUANTITY report_values = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_crumble.id, searchQty=11, searchVariant=False) # 5 min 'Prepare biscuits' + 3 min 'Prepare butter' + 5 min 'Mix manually' = 13 minutes self.assertEqual( report_values['lines']['operations_time'], 13.0, 'Operation time should be the same for 1 unit or for the batch') # Operation cost is the sum of operation line. operation_cost = float_round(5 / 60 * 10, precision_digits=2) * 2 + float_round( 3 / 60 * 10, precision_digits=2) self.assertEqual( float_compare(report_values['lines']['operations_cost'], operation_cost, precision_digits=2), 0, '13 minute for 10$/hours -> 2.16') for component_line in report_values['lines']['components']: # standard price * bom line quantity * current quantity / bom finished product quantity if component_line['prod_id'] == butter.id: # 5 kg of butter at 7.01$ for 11kg of crumble -> 35.05$ self.assertEqual( float_compare(component_line['total'], (7.01 * 5), precision_digits=2), 0) if component_line['prod_id'] == biscuit.id: # 6 kg of biscuits at 1.50$ for 11kg of crumble -> 9$ self.assertEqual( float_compare(component_line['total'], (1.5 * 6), precision_digits=2), 0) # total price = 35.05 + 9 + operation_cost(0.83 + 0.83 + 0.5 = 2.16) = 46,21 self.assertEqual( float_compare(report_values['lines']['total'], 46.21, precision_digits=2), 0, 'Product Bom Price is not correct') self.assertEqual( float_compare(report_values['lines']['total'] / 11.0, 4.20, precision_digits=2), 0, 'Product Unit Bom Price is not correct') # TEST BOM STRUCTURE VALUE BY UNIT report_values = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_crumble.id, searchQty=1, searchVariant=False) # 5 min 'Prepare biscuits' + 3 min 'Prepare butter' + 5 min 'Mix manually' = 13 minutes self.assertEqual( report_values['lines']['operations_time'], 13.0, 'Operation time should be the same for 1 unit or for the batch') # Operation cost is the sum of operation line. operation_cost = float_round(5 / 60 * 10, precision_digits=2) * 2 + float_round( 3 / 60 * 10, precision_digits=2) self.assertEqual( float_compare(report_values['lines']['operations_cost'], operation_cost, precision_digits=2), 0, '13 minute for 10$/hours -> 2.16') for component_line in report_values['lines']['components']: # standard price * bom line quantity * current quantity / bom finished product quantity if component_line['prod_id'] == butter.id: # 5 kg of butter at 7.01$ for 11kg of crumble -> / 11 for price per unit (3.19) self.assertEqual( float_compare(component_line['total'], (7.01 * 5) * (1 / 11), precision_digits=2), 0) if component_line['prod_id'] == biscuit.id: # 6 kg of biscuits at 1.50$ for 11kg of crumble -> / 11 for price per unit (0.82) self.assertEqual( float_compare(component_line['total'], (1.5 * 6) * (1 / 11), precision_digits=2), 0) # total price = 3.19 + 0.82 + operation_cost(0.83 + 0.83 + 0.5 = 2.16) = 6,17 self.assertEqual( float_compare(report_values['lines']['total'], 6.17, precision_digits=2), 0, 'Product Unit Bom Price is not correct') # TEST OPERATION COST WHEN PRODUCED QTY > BOM QUANTITY report_values_12 = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_crumble.id, searchQty=12, searchVariant=False) report_values_22 = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_crumble.id, searchQty=22, searchVariant=False) operation_cost = float_round(10 / 60 * 10, precision_digits=2) * 2 + float_round( 6 / 60 * 10, precision_digits=2) # Both needs 2 operation cycle self.assertEqual(report_values_12['lines']['operations_cost'], report_values_22['lines']['operations_cost']) self.assertEqual(report_values_22['lines']['operations_cost'], operation_cost) report_values_23 = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_crumble.id, searchQty=23, searchVariant=False) operation_cost = float_round(15 / 60 * 10, precision_digits=2) * 2 + float_round( 9 / 60 * 10, precision_digits=2) self.assertEqual(report_values_23['lines']['operations_cost'], operation_cost) # Create a more complex BoM with a sub product cheese_cake = self.env['product.product'].create({ 'name': 'Cheese Cake 300g', 'type': 'product', }) cream = self.env['product.product'].create({ 'name': 'cream', 'type': 'product', 'uom_id': uom_litre.id, 'uom_po_id': uom_litre.id, 'standard_price': 5.17, }) bom_form_cheese_cake = Form(self.env['mrp.bom']) bom_form_cheese_cake.product_tmpl_id = cheese_cake.product_tmpl_id bom_form_cheese_cake.product_qty = 60 bom_form_cheese_cake.product_uom_id = self.uom_unit bom_cheese_cake = bom_form_cheese_cake.save() with Form(bom_cheese_cake) as bom: with bom.bom_line_ids.new() as line: line.product_id = cream line.product_uom_id = uom_litre line.product_qty = 3 with bom.bom_line_ids.new() as line: line.product_id = crumble line.product_uom_id = uom_kg line.product_qty = 5.4 workcenter_2 = self.env['mrp.workcenter'].create({ 'name': 'cake mounting', 'costs_hour': 20, 'time_start': 10, 'time_stop': 15 }) routing_form = Form(self.env['mrp.routing']) routing_form.name = "Cheese cake process" routing_cheese = routing_form.save() with Form(routing_cheese) as routing: with routing.operation_ids.new() as operation: operation.workcenter_id = workcenter operation.name = 'Mix cheese and crumble' operation.time_cycle_manual = 10 with routing.operation_ids.new() as operation: operation.workcenter_id = workcenter_2 operation.name = 'Cake mounting' operation.time_cycle_manual = 5 bom_cheese_cake.routing_id = routing_cheese.id # TEST CHEESE BOM STRUCTURE VALUE WITH BOM QUANTITY report_values = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_cheese_cake.id, searchQty=60, searchVariant=False) self.assertEqual( report_values['lines']['operations_time'], 40.0, 'Operation time should be the same for 1 unit or for the batch') # Operation cost is the sum of operation line. operation_cost = float_round( 10 / 60 * 10, precision_digits=2) + float_round(30 / 60 * 20, precision_digits=2) self.assertEqual( float_compare(report_values['lines']['operations_cost'], operation_cost, precision_digits=2), 0) for component_line in report_values['lines']['components']: # standard price * bom line quantity * current quantity / bom finished product quantity if component_line['prod_id'] == cream.id: # 3 liter of cream at 5.17$ for 60 unit of cheese cake -> 15.51$ self.assertEqual( float_compare(component_line['total'], (3 * 5.17), precision_digits=2), 0) if component_line['prod_id'] == crumble.id: # 5.4 kg of crumble at the cost of a batch. crumble_cost = self.env[ 'report.mrp.report_bom_structure']._get_report_data( bom_id=bom_crumble.id, searchQty=5.4, searchVariant=False)['lines']['total'] self.assertEqual( float_compare(component_line['total'], crumble_cost, precision_digits=2), 0) # total price = 15.51 + crumble_cost + operation_cost(10 + 1.67 = 11.67) = 27.18 + crumble_cost self.assertEqual( float_compare(report_values['lines']['total'], 27.18 + crumble_cost, precision_digits=2), 0, 'Product Bom Price is not correct')