def test_rounding(self): """ In previous versions we had rounding and efficiency fields. We check if we can still do the same, but with only the rounding on the UoM""" self.product_6.uom_id.rounding = 1.0 bom_eff = self.env['mrp.bom'].create({'product_id': self.product_6.id, 'product_tmpl_id': self.product_6.product_tmpl_id.id, 'product_qty': 1, 'product_uom_id': self.product_6.uom_id.id, 'type': 'normal', 'bom_line_ids': [ (0, 0, {'product_id': self.product_2.id, 'product_qty': 2.03}), (0, 0, {'product_id': self.product_8.id, 'product_qty': 4.16}) ]}) production = self.env['mrp.production'].create({'name': 'MO efficiency test', 'product_id': self.product_6.id, 'product_qty': 20, 'bom_id': bom_eff.id, 'product_uom_id': self.product_6.uom_id.id,}) #Check the production order has the right quantities self.assertEqual(production.move_raw_ids[0].product_qty, 41, 'The quantity should be rounded up') self.assertEqual(production.move_raw_ids[1].product_qty, 84, 'The quantity should be rounded up') # produce product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': production.id, 'active_ids': [production.id], })) produce_form.product_qty = 8 produce_wizard = produce_form.save() produce_wizard.do_produce() self.assertEqual(production.move_raw_ids[0].quantity_done, 16, 'Should use half-up rounding when producing') self.assertEqual(production.move_raw_ids[1].quantity_done, 34, 'Should use half-up rounding when producing')
def test_split_move_line(self): """ Consume more component quantity than the initial demand. It should create extra move and share the quantity between the two stock moves """ mo, _, p_final, p1, p2 = self.generate_mo(qty_base_1=10, qty_final=1, qty_base_2=1) mo.action_assign() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) for i in range(len(produce_form.produce_line_ids)): with produce_form.produce_line_ids.edit(i) as line: line.qty_done += 1 product_produce = produce_form.save() product_produce.do_produce() self.assertEqual(len(mo.move_raw_ids), 2) self.assertEqual(len(mo.move_raw_ids.mapped('move_line_ids')), 2) self.assertEqual(mo.move_raw_ids[0].move_line_ids.mapped('qty_done'), [2]) self.assertEqual(mo.move_raw_ids[1].move_line_ids.mapped('qty_done'), [11]) self.assertEqual(mo.move_raw_ids[0].quantity_done, 2) self.assertEqual(mo.move_raw_ids[1].quantity_done, 11) mo.button_mark_done() self.assertEqual(len(mo.move_raw_ids), 4) self.assertEqual(len(mo.move_raw_ids.mapped('move_line_ids')), 4) self.assertEqual(mo.move_raw_ids.mapped('quantity_done'), [1, 10, 1, 1]) self.assertEqual(mo.move_raw_ids.mapped('move_line_ids.qty_done'), [1, 10, 1, 1])
def test_employee_resource(self): _tz = 'Pacific/Apia' self.res_users_hr_officer.company_id.resource_calendar_id.tz = _tz Employee = self.env['hr.employee'].sudo(self.res_users_hr_officer) employee_form = Form(Employee) employee_form.name = 'Raoul Grosbedon' employee_form.work_email = '*****@*****.**' employee = employee_form.save() self.assertEqual(employee.tz, _tz)
def test_00_product_company_level_delays(self): """ In order to check schedule date, set product's Manufacturing Lead Time and Customer Lead Time and also set company's Manufacturing Lead Time and Sales Safety Days.""" company = self.env.ref('base.main_company') # Update company with Manufacturing Lead Time and Sales Safety Days company.write({'manufacturing_lead': 3.0, 'security_lead': 3.0}) # Create sale order of product_1 order_form = Form(self.env['sale.order']) order_form.partner_id = self.partner_1 with order_form.order_line.new() as line: line.product_id = self.product_1 line.product_uom_qty = 10 order = order_form.save() # Confirm sale order order.action_confirm() # Check manufacturing order created or not manufacturing_order = self.env['mrp.production'].search([ ('product_id', '=', self.product_1.id), ('move_dest_ids', 'in', order.picking_ids[0].move_lines.ids) ]) self.assertTrue(manufacturing_order, 'Manufacturing order should be created.') # Check schedule date of picking out_date = fields.Datetime.from_string(order.date_order) + timedelta( days=self.product_1.sale_delay) - timedelta( days=company.security_lead) min_date = fields.Datetime.from_string( order.picking_ids[0].scheduled_date) self.assertAlmostEqual( min_date, out_date, delta=timedelta(seconds=1), msg= 'Schedule date of picking should be equal to: Order date + Customer Lead Time - Sales Safety Days.' ) # Check schedule date of manufacturing order mo_date = out_date - timedelta( days=self.product_1.produce_delay) - timedelta( days=company.manufacturing_lead) date_planned_start = fields.Datetime.from_string( manufacturing_order.date_planned_start) self.assertAlmostEqual( date_planned_start, mo_date, delta=timedelta(seconds=1), msg= "Schedule date of manufacturing order should be equal to: Schedule date of picking - product's Manufacturing Lead Time - company's Manufacturing Lead Time." )
def test_01_warehouse_twostep_manufacturing(self): """ Warehouse testing for picking before manufacturing """ with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'pbm' self._check_location_and_routes() self.assertEqual(len(self.warehouse.pbm_route_id.rule_ids), 2) self.assertEqual(self.warehouse.manufacture_pull_id.location_id.id, self.warehouse.lot_stock_id.id)
def test_02_warehouse_twostep_manufacturing(self): """ Warehouse testing for picking ans store after manufacturing """ with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'pbm_sam' self._check_location_and_routes() self.assertEqual(len(self.warehouse.pbm_route_id.rule_ids), 3) self.assertEqual(self.warehouse.manufacture_pull_id.location_id.id, self.warehouse.sam_loc_id.id)
def test_pricelist_application(self): """ Test different prices are correctly applied based on dates """ support_product = self.env.ref('product.product_product_2') support_product.list_price = 100 partner = self.res_partner_model.create(dict(name="George")) christmas_pricelist = self.env['product.pricelist'].create({ 'name': 'Christmas pricelist', 'item_ids': [(0, 0, { 'date_start': "2017-12-01", 'date_end': "2017-12-24", 'compute_price': 'percentage', 'base': 'list_price', 'percent_price': 20, 'applied_on': '3_global', 'name': 'Pre-Christmas discount' }), (0, 0, { 'date_start': "2017-12-25", 'date_end': "2017-12-31", 'compute_price': 'percentage', 'base': 'list_price', 'percent_price': 50, 'applied_on': '3_global', 'name': 'Post-Christmas super-discount' })] }) # Create the SO with pricelist based on date order_form = Form( self.env['sale.order'].with_context(tracking_disable=True)) order_form.partner_id = partner order_form.date_order = '2017-12-20' order_form.pricelist_id = christmas_pricelist with order_form.order_line.new() as line: line.product_id = support_product so = order_form.save() # Check the unit price and subtotal of SO line self.assertEqual(so.order_line[0].price_unit, 80, "First date pricelist rule not applied") self.assertEquals( so.order_line[0].price_subtotal, so.order_line[0].price_unit * so.order_line[0].product_uom_qty, 'Total of SO line should be a multiplication of unit price and ordered quantity' ) # Change order date of the SO and check the unit price and subtotal of SO line with Form(so) as order: order.date_order = '2017-12-30' with order.order_line.edit(0) as line: line.product_id = support_product self.assertEqual(so.order_line[0].price_unit, 50, "Second date pricelist rule not applied") self.assertEquals( so.order_line[0].price_subtotal, so.order_line[0].price_unit * so.order_line[0].product_uom_qty, 'Total of SO line should be a multiplication of unit price and ordered quantity' )
def test_product_produce_1(self): """ Check that no produce line are created when the consumed products are not tracked """ self.stock_location = self.env.ref('stock.stock_location_stock') mo, bom, p_final, p1, p2 = self.generate_mo() self.assertEqual(len(mo), 1, 'MO should have been created') self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 100) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5) mo.action_assign() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) product_produce = produce_form.save() product_produce.do_produce() self.assertEqual(len(product_produce.produce_line_ids), 2, 'You should have produce lines even the consumed products are not tracked.')
def test_product_produce_uom(self): plastic_laminate = self.env.ref('mrp.product_product_plastic_laminate') bom = self.env.ref('mrp.mrp_bom_plastic_laminate') dozen = self.env.ref('uom.product_uom_dozen') unit = self.env.ref('uom.product_uom_unit') plastic_laminate.tracking = 'serial' mo = self.env['mrp.production'].create({ 'name': 'Dozen Plastic Laminate', 'product_id': plastic_laminate.id, 'product_uom_id': dozen.id, 'product_qty': 1, 'bom_id': bom.id, }) final_product_lot = self.env['stock.production.lot'].create({ 'name': 'lot1', 'product_id': plastic_laminate.id, }) mo.action_assign() self.assertEqual(mo.move_raw_ids.product_qty, 12, '12 units should be reserved.') # produce product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.lot_id = final_product_lot product_produce = produce_form.save() self.assertEqual(product_produce.product_qty, 1) self.assertEqual(product_produce.product_uom_id, unit, 'Should be 1 unit since the tracking is serial.') product_produce.lot_id = final_product_lot.id product_produce.do_produce() move_line_raw = mo.move_raw_ids.mapped('move_line_ids').filtered(lambda m: m.qty_done) self.assertEqual(move_line_raw.qty_done, 1) self.assertEqual(move_line_raw.product_uom_id, unit, 'Should be 1 unit since the tracking is serial.') move_line_finished = mo.move_finished_ids.mapped('move_line_ids').filtered(lambda m: m.qty_done) self.assertEqual(move_line_finished.qty_done, 1) self.assertEqual(move_line_finished.product_uom_id, unit, 'Should be 1 unit since the tracking is serial.')
def create_account_invoice(self, invoice_type, partner, product, quantity=0.0, price_unit=0.0): """ Create an invoice as in a view by triggering its onchange methods""" invoice_form = Form( self.env['account.invoice'].with_context(type=invoice_type)) invoice_form.partner_id = partner with invoice_form.invoice_line_ids.new() as line: line.product_id = product line.quantity = quantity line.price_unit = price_unit invoice = invoice_form.save() invoice.action_invoice_open() return invoice
def test_00_create_warehouse(self): """ Warehouse testing for direct manufacturing """ with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'mrp_one_step' self._check_location_and_routes() # Check locations of existing pull rule self.assertFalse( self.warehouse.pbm_route_id.rule_ids, 'only the update of global manufacture route should happen.') self.assertEqual(self.warehouse.manufacture_pull_id.location_id.id, self.warehouse.lot_stock_id.id)
def setUp(self): super(TestSaleMrpLeadTime, self).setUp() # Update the product_1 with type, route, Manufacturing Lead Time and Customer Lead Time with Form(self.product_1) as p1: p1.type = 'product' p1.produce_delay = 5.0 p1.sale_delay = 5.0 p1.route_ids.clear() p1.route_ids.add(self.warehouse_1.manufacture_pull_id.route_id) p1.route_ids.add(self.warehouse_1.mto_pull_id.route_id) # Update the product_2 with type with Form(self.product_2) as p2: p2.type = 'consu' # Create Bill of materials for product_1 with Form(self.env['mrp.bom']) as bom: bom.product_tmpl_id = self.product_1.product_tmpl_id bom.product_qty = 2 with bom.bom_line_ids.new() as line: line.product_id = self.product_2 line.product_qty = 4
def test_employee_from_user_tz_no_reset(self): _tz = 'Pacific/Apia' self.res_users_hr_officer.tz = False Employee = self.env['hr.employee'].sudo(self.res_users_hr_officer) employee_form = Form(Employee) employee_form.name = 'Raoul Grosbedon' employee_form.work_email = '*****@*****.**' employee_form.tz = _tz employee_form.user_id = self.res_users_hr_officer employee = employee_form.save() self.assertEqual(employee.name, self.res_users_hr_officer.name) self.assertEqual(employee.work_email, self.res_users_hr_officer.email) self.assertEqual(employee.tz, _tz)
def test_01_manufacturing_step_two(self): """ Testing for Step-2 """ with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'pbm' self.sale_order.action_confirm() # Get manufactured procurement mo_procurement = self.MrpProduction.search([('origin', '=', self.sale_order.name)]) self.assertEqual(mo_procurement.location_src_id.id, self.warehouse.pbm_loc_id.id, "Source loction does not match.") self.assertEqual(mo_procurement.location_dest_id.id, self.warehouse.lot_stock_id.id, "Destination location does not match.") self.assertEqual(len(mo_procurement), 1, "No Procurement !")
def test_00_manufacturing_step_one(self): """ Testing for Step-1 """ # Change steps of manufacturing. with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'mrp_one_step' # Confirm sale order. self.sale_order.action_confirm() # Check all procurements for created sale order mo_procurement = self.MrpProduction.search([('origin', '=', self.sale_order.name)]) # Get manufactured procurement self.assertEqual(mo_procurement.location_src_id.id, self.warehouse.lot_stock_id.id, "Source loction does not match.") self.assertEqual(mo_procurement.location_dest_id.id, self.warehouse.lot_stock_id.id, "Destination location does not match.") self.assertEqual(len(mo_procurement), 1, "No Procurement !")
def test_employee_from_user(self): _tz = 'Pacific/Apia' _tz2 = 'America/Tijuana' self.res_users_hr_officer.company_id.resource_calendar_id.tz = _tz self.res_users_hr_officer.tz = _tz2 Employee = self.env['hr.employee'].sudo(self.res_users_hr_officer) employee_form = Form(Employee) employee_form.name = 'Raoul Grosbedon' employee_form.work_email = '*****@*****.**' employee_form.user_id = self.res_users_hr_officer employee = employee_form.save() self.assertEqual(employee.name, self.res_users_hr_officer.name) self.assertEqual(employee.work_email, self.res_users_hr_officer.email) self.assertEqual(employee.tz, self.res_users_hr_officer.tz)
def test_onchange_product_id(self): uom_id = self.product_uom_model.search([('name', '=', 'Unit(s)')])[0] pricelist = self.pricelist_model.search([('name', '=', 'Public Pricelist')])[0] partner_id = self.res_partner_model.create(dict(name="George")) tax_include_id = self.tax_model.create( dict(name="Include tax", amount='21.00', price_include=True, type_tax_use='sale')) tax_exclude_id = self.tax_model.create( dict(name="Exclude tax", amount='0.00', type_tax_use='sale')) product_tmpl_id = self.product_tmpl_model.create( dict(name="Voiture", list_price=121, taxes_id=[(6, 0, [tax_include_id.id])])) product_id = self.product_model.create( dict(product_tmpl_id=product_tmpl_id.id)) fp_id = self.fiscal_position_model.create( dict(name="fiscal position", sequence=1)) fp_tax_id = self.fiscal_position_tax_model.create( dict(position_id=fp_id.id, tax_src_id=tax_include_id.id, tax_dest_id=tax_exclude_id.id)) # Create the SO with one SO line and apply a pricelist and fiscal position on it order_form = Form( self.env['sale.order'].with_context(tracking_disable=True)) order_form.partner_id = partner_id order_form.pricelist_id = pricelist order_form.fiscal_position_id = fp_id with order_form.order_line.new() as line: line.name = product_id.name line.product_id = product_id line.product_uom_qty = 1.0 line.product_uom = uom_id sale_order = order_form.save() # Check the unit price of SO line self.assertEquals(100, sale_order.order_line[0].price_unit, "The included tax must be subtracted to the price")
def test_product_produce_7(self): """ Plan 100 products to produce. Produce 50. Do a 'Post Inventory'. Update the quantity to produce to 200. Produce 50 again. Check that the components has been consumed correctly. """ self.stock_location = self.env.ref('stock.stock_location_stock') mo, bom, p_final, p1, p2 = self.generate_mo(qty_base_1=2, qty_base_2=2, qty_final=100) self.assertEqual(len(mo), 1, 'MO should have been created') self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 200) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 200) produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 50.0 produce_wizard = produce_form.save() produce_wizard.do_produce() mo.post_inventory() update_quantity_wizard = self.env['change.production.qty'].create({ 'mo_id': mo.id, 'product_qty': 200, }) update_quantity_wizard.change_prod_qty() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 50.0 produce_wizard = produce_form.save() produce_wizard.do_produce() self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).mapped('quantity_done')), 200) self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id == p2).mapped('quantity_done')), 200) self.assertEqual(sum(mo.move_finished_ids.mapped('quantity_done')), 100)
def test_product_produce_2(self): """ Check that line are created when the consumed products are tracked by serial and the lot proposed are correct. """ self.stock_location = self.env.ref('stock.stock_location_stock') mo, bom, p_final, p1, p2 = self.generate_mo(tracking_base_1='serial', qty_base_1=1, qty_final=2) self.assertEqual(len(mo), 1, 'MO should have been created') lot_p1_1 = self.env['stock.production.lot'].create({ 'name': 'lot1', 'product_id': p1.id, }) lot_p1_2 = self.env['stock.production.lot'].create({ 'name': 'lot2', 'product_id': p1.id, }) self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 1, lot_id=lot_p1_1) self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 1, lot_id=lot_p1_2) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5) mo.action_assign() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) product_produce = produce_form.save() self.assertEqual(len(product_produce.produce_line_ids), 3, 'You should have 3 produce lines. One for each serial to consume') product_produce.product_qty = 1 produce_line_1 = product_produce.produce_line_ids[0] produce_line_1.qty_done = 1 remaining_lot = (lot_p1_1 | lot_p1_2) - produce_line_1.lot_id product_produce.do_produce() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) product_produce = produce_form.save() self.assertEqual(len(product_produce.produce_line_ids), 2, 'You should have 2 produce lines since one has already be consumed.') for line in product_produce.produce_line_ids.filtered(lambda x: x.lot_id): self.assertEqual(line.lot_id, remaining_lot, 'Wrong lot proposed.')
def test_update_quantity_3(self): """ Build 1 final products then update the Manufacturing order quantity. Check the remaining quantity to produce take care of the first quantity produced.""" self.stock_location = self.env.ref('stock.stock_location_stock') mo, bom, p_final, p1, p2 = self.generate_mo(qty_final=2) self.assertEqual(len(mo), 1, 'MO should have been created') self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 20) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5) mo.action_assign() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 1 produce_wizard = produce_form.save() produce_wizard.do_produce() update_quantity_wizard = self.env['change.production.qty'].create({ 'mo_id': mo.id, 'product_qty': 3, }) update_quantity_wizard.change_prod_qty() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_wizard = produce_form.save() produce_wizard.do_produce() mo.button_mark_done() self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).mapped('quantity_done')), 12) self.assertEqual(sum(mo.move_finished_ids.mapped('quantity_done')), 3)
def test_manufacturing_3_steps(self): """ Test MO/picking before manufacturing/picking after manufacturing components and move_orig/move_dest. Ensure that everything is created correctly. """ with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'pbm_sam' production_form = Form(self.env['mrp.production']) production_form.product_id = self.finished_product production_form.picking_type_id = self.warehouse.manu_type_id production = production_form.save() move_raw_ids = production.move_raw_ids self.assertEqual(len(move_raw_ids), 1) self.assertEqual(move_raw_ids.product_id, self.raw_product) self.assertEqual(move_raw_ids.picking_type_id, self.warehouse.manu_type_id) pbm_move = move_raw_ids.move_orig_ids self.assertEqual(len(pbm_move), 1) self.assertEqual(pbm_move.location_id, self.warehouse.lot_stock_id) self.assertEqual(pbm_move.location_dest_id, self.warehouse.pbm_loc_id) self.assertEqual(pbm_move.picking_type_id, self.warehouse.pbm_type_id) self.assertFalse(pbm_move.move_orig_ids) move_finished_ids = production.move_finished_ids self.assertEqual(len(move_finished_ids), 1) self.assertEqual(move_finished_ids.product_id, self.finished_product) self.assertEqual(move_finished_ids.picking_type_id, self.warehouse.manu_type_id) sam_move = move_finished_ids.move_dest_ids self.assertEqual(len(sam_move), 1) self.assertEqual(sam_move.location_id, self.warehouse.sam_loc_id) self.assertEqual(sam_move.location_dest_id, self.warehouse.lot_stock_id) self.assertEqual(sam_move.picking_type_id, self.warehouse.sam_type_id) self.assertFalse(sam_move.move_dest_ids)
def test_02_different_uom_on_bomlines(self): """ Testing bill of material with different unit of measure.""" route_manufacture = self.warehouse.manufacture_pull_id.route_id.id route_mto = self.warehouse.mto_pull_id.route_id.id unit = self.ref("uom.product_uom_unit") dozen = self.ref("uom.product_uom_dozen") kg = self.ref("uom.product_uom_kgm") gm = self.ref("uom.product_uom_gram") # Create Product A, B, C product_A = self.env['product.product'].create({ 'name': 'Product A', 'type': 'product', 'tracking': 'lot', 'uom_id': dozen, 'uom_po_id': dozen, 'route_ids': [(6, 0, [route_manufacture, route_mto])] }) product_B = self.env['product.product'].create({ 'name': 'Product B', 'type': 'product', 'tracking': 'lot', 'uom_id': dozen, 'uom_po_id': dozen }) product_C = self.env['product.product'].create({ 'name': 'Product C', 'type': 'product', 'tracking': 'lot', 'uom_id': kg, 'uom_po_id': kg }) # Bill of materials # ----------------- #=================================== # Product A 1 Unit # Product B 4 Unit # Product C 600 gram # ----------------------------------- bom_a = self.env['mrp.bom'].create({ 'product_tmpl_id': product_A.product_tmpl_id.id, 'product_qty': 2, 'product_uom_id': unit, 'bom_line_ids': [(0, 0, { 'product_id': product_B.id, 'product_qty': 4, 'product_uom_id': unit }), (0, 0, { 'product_id': product_C.id, 'product_qty': 600, 'product_uom_id': gm })] }) # Create production order with product A 10 Unit. # ----------------------------------------------- mo_custom_product = self.env['mrp.production'].create({ 'product_id': product_A.id, 'product_qty': 10, 'product_uom_id': unit, 'bom_id': bom_a.id }) move_product_b = mo_custom_product.move_raw_ids.filtered( lambda x: x.product_id == product_B) move_product_c = mo_custom_product.move_raw_ids.filtered( lambda x: x.product_id == product_C) # Check move correctly created or not. self.assertEqual(move_product_b.product_uom_qty, 20) self.assertEqual(move_product_b.product_uom.id, unit) self.assertEqual(move_product_c.product_uom_qty, 3000) self.assertEqual(move_product_c.product_uom.id, gm) # Lot create for product B and product C # --------------------------------------- lot_a = self.env['stock.production.lot'].create( {'product_id': product_A.id}) lot_b = self.env['stock.production.lot'].create( {'product_id': product_B.id}) lot_c = self.env['stock.production.lot'].create( {'product_id': product_C.id}) # Inventory Update # ---------------- inventory = self.env['stock.inventory'].create({ 'name': 'Inventory Product B and C', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': product_B.id, 'product_uom_id': product_B.uom_id.id, 'product_qty': 3, 'prod_lot_id': lot_b.id, 'location_id': self.source_location_id }), (0, 0, { 'product_id': product_C.id, 'product_uom_id': product_C.uom_id.id, 'product_qty': 3, 'prod_lot_id': lot_c.id, 'location_id': self.source_location_id })] }) # inventory.action_start() inventory.action_validate() # Start Production ... # -------------------- mo_custom_product.action_assign() context = { "active_ids": [mo_custom_product.id], "active_id": mo_custom_product.id } produce_form = Form( self.env['mrp.product.produce'].with_context(context)) produce_form.product_qty = 10.00 produce_form.lot_id = lot_a product_consume = produce_form.save() # laptop_lot_002 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id}) self.assertEquals(len(product_consume.produce_line_ids), 2) product_consume.produce_line_ids.filtered( lambda x: x.product_id == product_C).write({'qty_done': 3000}) product_consume.produce_line_ids.filtered( lambda x: x.product_id == product_B).write({'qty_done': 20}) product_consume.do_produce() mo_custom_product.post_inventory()
def test_01_without_workorder(self): """ Testing consume quants and produced quants without workorder """ unit = self.ref("uom.product_uom_unit") custom_laptop = self.env.ref("product.product_product_27") custom_laptop.tracking = 'lot' # Create new product charger and keybord # -------------------------------------- product_charger = self.env['product.product'].create({ 'name': 'Charger', 'type': 'product', 'tracking': 'lot', 'uom_id': unit, 'uom_po_id': unit }) product_keybord = self.env['product.product'].create({ 'name': 'Usb Keybord', 'type': 'product', 'tracking': 'lot', 'uom_id': unit, 'uom_po_id': unit }) # Create bill of material for customized laptop. bom_custom_laptop = self.env['mrp.bom'].create({ 'product_tmpl_id': custom_laptop.product_tmpl_id.id, 'product_qty': 10, 'product_uom_id': unit, 'bom_line_ids': [(0, 0, { 'product_id': product_charger.id, 'product_qty': 20, 'product_uom_id': unit }), (0, 0, { 'product_id': product_keybord.id, 'product_qty': 20, 'product_uom_id': unit })] }) # Create production order for customize laptop. mo_custom_laptop = self.env['mrp.production'].create({ 'product_id': custom_laptop.id, 'product_qty': 10, 'product_uom_id': unit, 'bom_id': bom_custom_laptop.id }) # Assign component to production order. mo_custom_laptop.action_assign() # Check production order status of availablity self.assertEqual(mo_custom_laptop.availability, 'waiting') # -------------------------------------------------- # Set inventory for rawmaterial charger and keybord # -------------------------------------------------- lot_charger = self.env['stock.production.lot'].create( {'product_id': product_charger.id}) lot_keybord = self.env['stock.production.lot'].create( {'product_id': product_keybord.id}) # Initialize Inventory # -------------------- inventory = self.env['stock.inventory'].create({ 'name': 'Inventory Product Table', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': product_charger.id, 'product_uom_id': product_charger.uom_id.id, 'product_qty': 20, 'prod_lot_id': lot_charger.id, 'location_id': self.source_location_id }), (0, 0, { 'product_id': product_keybord.id, 'product_uom_id': product_keybord.uom_id.id, 'product_qty': 20, 'prod_lot_id': lot_keybord.id, 'location_id': self.source_location_id })] }) # inventory.action_start() inventory.action_validate() # Check consumed move status mo_custom_laptop.action_assign() self.assertEqual(mo_custom_laptop.availability, 'assigned') # Check current status of raw materials. for move in mo_custom_laptop.move_raw_ids: self.assertEqual( move.product_uom_qty, 20, "Wrong consume quantity of raw material %s: %s instead of %s" % (move.product_id.name, move.product_uom_qty, 20)) self.assertEqual( move.quantity_done, 0, "Wrong produced quantity on raw material %s: %s instead of %s" % (move.product_id.name, move.quantity_done, 0)) # ----------------- # Start production # ----------------- # Produce 6 Unit of custom laptop will consume ( 12 Unit of keybord and 12 Unit of charger) context = { "active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id } product_form = Form( self.env['mrp.product.produce'].with_context(context)) product_form.product_qty = 6.00 laptop_lot_001 = self.env['stock.production.lot'].create( {'product_id': custom_laptop.id}) product_form.lot_id = laptop_lot_001 product_consume = product_form.save() product_consume.produce_line_ids[0].qty_done = 12 product_consume.do_produce() # Check consumed move after produce 6 quantity of customized laptop. for move in mo_custom_laptop.move_raw_ids: self.assertEqual( move.quantity_done, 12, "Wrong produced quantity on raw material %s" % (move.product_id.name)) self.assertEqual(len(mo_custom_laptop.move_raw_ids), 2) mo_custom_laptop.post_inventory() self.assertEqual(len(mo_custom_laptop.move_raw_ids), 4) # Check done move and confirmed move quantity. charger_done_move = mo_custom_laptop.move_raw_ids.filtered( lambda x: x.product_id.id == product_charger.id and x.state == 'done') keybord_done_move = mo_custom_laptop.move_raw_ids.filtered( lambda x: x.product_id.id == product_keybord.id and x.state == 'done') self.assertEquals(charger_done_move.product_uom_qty, 12) self.assertEquals(keybord_done_move.product_uom_qty, 12) # Produce remaining 4 quantity # ---------------------------- # Produce 4 Unit of custom laptop will consume ( 8 Unit of keybord and 8 Unit of charger). context = { "active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id } produce_form = Form( self.env['mrp.product.produce'].with_context(context)) produce_form.product_qty = 4.00 laptop_lot_002 = self.env['stock.production.lot'].create( {'product_id': custom_laptop.id}) produce_form.lot_id = laptop_lot_002 product_consume = produce_form.save() self.assertEquals(len(product_consume.produce_line_ids), 2) product_consume.produce_line_ids[0].qty_done = 8 product_consume.do_produce() charger_move = mo_custom_laptop.move_raw_ids.filtered( lambda x: x.product_id.id == product_charger.id and x.state != 'done') keybord_move = mo_custom_laptop.move_raw_ids.filtered( lambda x: x.product_id.id == product_keybord.id and x.state != 'done') self.assertEquals( charger_move.quantity_done, 8, "Wrong consumed quantity of %s" % charger_move.product_id.name) self.assertEquals( keybord_move.quantity_done, 8, "Wrong consumed quantity of %s" % keybord_move.product_id.name) # Post Inventory of production order. mo_custom_laptop.post_inventory()
def test_00_account_voucher_flow(self): """ Create Account Voucher for Customer and Vendor """ self._load('account', 'test', 'account_minimal_test.xml') # User-groups and References partner_id = self.env.ref('base.res_partner_12') cash_journal_id = self.env.ref('account_voucher.cash_journal') sales_journal_id = self.env.ref('account_voucher.sales_journal') account_receivable_id = self.env.ref('account_voucher.a_recv') # Create a Account Voucher User voucher_user = self.env['res.users'].create({ 'name': 'Voucher Accountant', 'login': '******', 'email': '*****@*****.**', 'company_id': self.env.ref('base.main_company').id, 'groups_id': [(6, 0, [ self.ref('base.group_partner_manager'), self.ref('account.group_account_user'), self.ref('account.group_account_invoice'), ])] }) Voucher = self.env['account.voucher'].sudo(voucher_user) # Create Customer Voucher c = Form(Voucher.with_context(default_voucher_type="sale", voucher_type="sale"), view='account_voucher.view_sale_receipt_form') c.partner_id = partner_id c.journal_id = sales_journal_id with c.line_ids.new() as line: line.name = "Voucher for Axelor" line.account_id = account_receivable_id line.price_unit = 1000.0 account_voucher_customer = c.save() # Check Customer Voucher status. self.assertEquals(account_voucher_customer.state, 'draft', 'Initially customer voucher should be in the "Draft" state') # Validate Customer voucher account_voucher_customer.proforma_voucher() # Check for Journal Entry of customer voucher self.assertTrue(account_voucher_customer.move_id, 'No journal entry created !.') # Find related account move line for Customer Voucher. customer_voucher_move = account_voucher_customer.move_id # Check state of Account move line. self.assertEquals(customer_voucher_move.state, 'posted', 'Account move state is incorrect.') # Check partner of Account move line. self.assertEquals(customer_voucher_move.partner_id, partner_id, 'Partner is incorrect on account move.') # Check journal in Account move line. self.assertEquals(customer_voucher_move.journal_id, sales_journal_id, 'Journal is incorrect on account move.') # Check amount in Account move line. self.assertEquals(customer_voucher_move.amount, 1000.0, 'Amount is incorrect in account move.') # Create Vendor Voucher v = Form(Voucher.with_context(default_voucher_type="purchase", voucher_type="purchase")) v.partner_id = partner_id v.journal_id = cash_journal_id with v.line_ids.new() as line: line.name = "Voucher Axelor" line.account_id = account_receivable_id line.price_unit = 1000.0 account_voucher_vendor = v.save() # Check Vendor Voucher status. self.assertEquals(account_voucher_vendor.state, 'draft', 'Initially vendor voucher should be in the "Draft" state') # Validate Vendor voucher account_voucher_vendor.proforma_voucher() # Check for Journal Entry of vendor voucher self.assertTrue(account_voucher_vendor.move_id, 'No journal entry created !.') # Find related account move line for Vendor Voucher. vendor_voucher_move = account_voucher_vendor.move_id # Check state of Account move line. self.assertEquals(vendor_voucher_move.state, 'posted', 'Account move state is incorrect.') # Check partner of Account move line. self.assertEquals(vendor_voucher_move.partner_id, partner_id, 'Partner is incorrect on account move.') # Check journal in Account move line. self.assertEquals(vendor_voucher_move.journal_id, cash_journal_id, 'Journal is incorrect on account move.') # Check amount in Account move line. self.assertEquals(vendor_voucher_move.amount, 1000.0, 'Amount is incorrect in acccount move.')
def test_00_crossdock(self): # Create a supplier supplier_crossdock = self.env['res.partner'].create( {'name': "Crossdocking supplier"}) # I first create a warehouse with pick-pack-ship and reception in 2 steps wh_f = Form(self.env['stock.warehouse']) wh_f.name = 'WareHouse PickPackShip' wh_f.code = 'whpps' wh_f.reception_steps = 'two_steps' wh_f.delivery_steps = 'pick_pack_ship' wh_pps = wh_f.save() # Check that cross-dock route is active self.assertTrue( wh_pps.crossdock_route_id.active, "Crossdock route should be active when reception_steps is not in 'single_step'" ) p_f = Form(self.env['product.template']) p_f.name = 'PCE' p_f.type = 'product' p_f.categ_id = self.env.ref('product.product_category_1') p_f.list_price = 100.0 p_f.standard_price = 70.0 with p_f.seller_ids.new() as seller: seller.name = supplier_crossdock p_f.route_ids.add(wh_pps.crossdock_route_id) cross_shop_product = p_f.save() # Create a sales order with a line of 100 PCE incoming shipment with route_id crossdock shipping so_form = Form(self.env['sale.order']) so_form.partner_id = self.env.ref('base.res_partner_4') so_form.warehouse_id = wh_pps with mute_logger('swerp.tests.common.onchange'): # otherwise complains that there's not enough inventory and # apparently that's normal according to @jco and @sle with so_form.order_line.new() as line: line.product_id = cross_shop_product.product_variant_ids line.product_uom_qty = 100.0 sale_order_crossdock = so_form.save() # Confirm sales order sale_order_crossdock.action_confirm() # Run the scheduler self.env['procurement.group'].run_scheduler() # Check a quotation was created for the created supplier and confirm it po = self.env['purchase.order'].search([('partner_id', '=', supplier_crossdock.id), ('state', '=', 'draft')]) self.assertTrue(po, "an RFQ should have been created by the scheduler") po.button_confirm()
def test_unbuild_with_routes(self): """ This test creates a MO of a stockable product (Table). A new route for rule QC/Unbuild -> Stock is created with Warehouse -> True. The unbuild order should revert the consumed components into QC/Unbuild location for quality check and then a picking should be generated for transferring components from QC/Unbuild location to stock. """ StockQuant = self.env['stock.quant'] ProductObj = self.env['product.product'] # Create new QC/Unbuild location warehouse = self.env.ref('stock.warehouse0') unbuild_location = self.env['stock.location'].create({ 'name': 'QC/Unbuild', 'usage': 'internal', 'location_id': warehouse.view_location_id.id }) # Create a product route containing a stock rule that will move product from QC/Unbuild location to stock product_route = self.env['stock.location.route'].create({ 'name': 'QC/Unbuild -> Stock', 'warehouse_selectable': True, 'warehouse_ids': [(4, warehouse.id)], 'rule_ids': [(0, 0, { 'name': 'Send Matrial QC/Unbuild -> Stock', 'action': 'push', 'picking_type_id': self.ref('stock.picking_type_internal'), 'location_src_id': unbuild_location.id, 'location_id': self.stock_location.id, })], }) # Create a stockable product and its components finshed_product = ProductObj.create({ 'name': 'Table', 'type': 'product', }) component1 = ProductObj.create({ 'name': 'Table head', 'type': 'product', }) component2 = ProductObj.create({ 'name': 'Table stand', 'type': 'product', }) # Create bom and add components bom = self.env['mrp.bom'].create({ 'product_id': finshed_product.id, 'product_tmpl_id': finshed_product.product_tmpl_id.id, 'product_uom_id': self.uom_unit.id, 'product_qty': 1.0, 'type': 'normal', 'bom_line_ids': [(0, 0, { 'product_id': component1.id, 'product_qty': 1 }), (0, 0, { 'product_id': component2.id, 'product_qty': 1 })] }) # Set on hand quantity StockQuant._update_available_quantity(component1, self.stock_location, 1) StockQuant._update_available_quantity(component2, self.stock_location, 1) # Create mo mo = self.env['mrp.production'].create({ 'name': 'MO 1', 'product_id': finshed_product.id, 'product_uom_id': finshed_product.uom_id.id, 'product_qty': 1.0, 'bom_id': bom.id, }) self.assertEqual(len(mo), 1, 'MO should have been created') mo.action_assign() # Produce the final product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 1.0 produce_wizard = produce_form.save() produce_wizard.do_produce() mo.button_mark_done() self.assertEqual(mo.state, 'done', "Production order should be in done state.") # Check quantity in stock before unbuild self.assertEqual( StockQuant._get_available_quantity(finshed_product, self.stock_location), 1, 'Table should be available in stock') self.assertEqual( StockQuant._get_available_quantity(component1, self.stock_location), 0, 'Table head should not be available in stock') self.assertEqual( StockQuant._get_available_quantity(component2, self.stock_location), 0, 'Table stand should not be available in stock') # --------------------------------------------------- # Unbuild # --------------------------------------------------- # Create an unbuild order of the finished product and set the destination loacation = QC/Unbuild self.env['mrp.unbuild'].create({ 'product_id': finshed_product.id, 'bom_id': bom.id, 'product_qty': 1.0, 'product_uom_id': self.uom_unit.id, 'mo_id': mo.id, 'location_id': self.stock_location.id, 'location_dest_id': unbuild_location.id }).action_unbuild() # Check the available quantity of components and final product in stock self.assertEqual( StockQuant._get_available_quantity(finshed_product, self.stock_location), 0, 'Table should not be available in stock as it is unbuild') self.assertEqual( StockQuant._get_available_quantity(component1, self.stock_location), 0, 'Table head should not be available in stock as it is in QC/Unbuild location' ) self.assertEqual( StockQuant._get_available_quantity(component2, self.stock_location), 0, 'Table stand should not be available in stock as it is in QC/Unbuild location' ) # Find new generated picking picking = self.env['stock.picking'].search([ ('product_id', 'in', [component1.id, component2.id]) ]) self.assertEqual(picking.location_id.id, unbuild_location.id, 'Wrong source location in picking') self.assertEqual(picking.location_dest_id.id, self.stock_location.id, 'Wrong destination location in picking') # Transfer it for ml in picking.move_ids_without_package: ml.quantity_done = 1 picking.action_done() # Check the available quantity of components and final product in stock self.assertEqual( StockQuant._get_available_quantity(finshed_product, self.stock_location), 0, 'Table should not be available in stock') self.assertEqual( StockQuant._get_available_quantity(component1, self.stock_location), 1, 'Table head should be available in stock as the picking is transferred' ) self.assertEqual( StockQuant._get_available_quantity(component2, self.stock_location), 1, 'Table stand should be available in stock as the picking is transferred' )
def test_production_links_with_non_tracked_lots(self): """ This test produces an MO in two times and checks that the move lines are linked in a correct way """ mo, bom, p_final, p1, p2 = self.generate_mo(tracking_final='lot', tracking_base_1='none', tracking_base_2='lot') lot_1 = self.env['stock.production.lot'].create({ 'name': 'lot_1', 'product_id': p2.id, }) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 3, lot_id=lot_1) lot_finished_1 = self.env['stock.production.lot'].create({ 'name': 'lot_finished_1', 'product_id': p_final.id, }) produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 3.0 produce_form.lot_id = lot_finished_1 produce_wizard = produce_form.save() produce_wizard.produce_line_ids[0].lot_id = lot_1 produce_wizard.do_produce() lot_2 = self.env['stock.production.lot'].create({ 'name': 'lot_2', 'product_id': p2.id, }) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 4, lot_id=lot_2) lot_finished_2 = self.env['stock.production.lot'].create({ 'name': 'lot_finished_2', 'product_id': p_final.id, }) produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 2.0 produce_form.lot_id = lot_finished_2 produce_wizard = produce_form.save() produce_wizard.produce_line_ids[0].lot_id = lot_2 produce_wizard.do_produce() mo.button_mark_done() ml = mo.finished_move_line_ids[0].consume_line_ids.filtered( lambda m: m.product_id == p1 and m.lot_produced_id == lot_finished_1) self.assertEqual(ml[0].qty_done, 12.0, 'Should have consumed 12 for the first lot') ml = mo.finished_move_line_ids[1].consume_line_ids.filtered( lambda m: m.product_id == p1 and m.lot_produced_id == lot_finished_2) self.assertEqual(ml[0].qty_done, 8.0, 'Should have consumed 8 for the second lot')
def test_unbuild_with_duplicate_move(self): """ This test creates a MO from 3 different lot on a consumed product (p2). The unbuild order should revert the correct quantity for each specific lot. """ mo, bom, p_final, p1, p2 = self.generate_mo(tracking_final='none', tracking_base_2='lot', tracking_base_1='none') self.assertEqual(len(mo), 1, 'MO should have been created') lot_1 = self.env['stock.production.lot'].create({ 'name': 'lot_1', 'product_id': p2.id, }) lot_2 = self.env['stock.production.lot'].create({ 'name': 'lot_2', 'product_id': p2.id, }) lot_3 = self.env['stock.production.lot'].create({ 'name': 'lot_3', 'product_id': p2.id, }) self.env['stock.quant']._update_available_quantity( p1, self.stock_location, 100) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 1, lot_id=lot_1) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 3, lot_id=lot_2) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 2, lot_id=lot_3) mo.action_assign() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 5.0 produce_wizard = produce_form.save() produce_wizard.do_produce() mo.button_mark_done() self.assertEqual(mo.state, 'done', "Production order should be in done state.") # Check quantity in stock before unbuild. self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location), 5, 'You should have the 5 final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location), 80, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_1), 0, 'You should have consumed all the 1 product for lot 1 in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_2), 0, 'You should have consumed all the 3 product for lot 2 in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_3), 1, 'You should have consumed only 1 product for lot3 in stock') self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 5.0, 'mo_id': mo.id, 'product_uom_id': self.uom_unit.id, }).action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location), 0, 'You should have no more final product in stock after unbuild') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location), 100, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_1), 1, 'You should have get your product with lot 1 in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_2), 3, 'You should have the 3 basic product for lot 2 in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_3), 2, 'You should have get one product back for lot 3')
def test_unbuild_with_everything_tracked(self): """ This test creates a MO and then creates 3 unbuild orders for the final product. All the products for this test are tracked. It checks the stock state after each order and ensure it is correct. """ mo, bom, p_final, p1, p2 = self.generate_mo(tracking_final='lot', tracking_base_2='lot', tracking_base_1='lot') self.assertEqual(len(mo), 1, 'MO should have been created') lot_final = self.env['stock.production.lot'].create({ 'name': 'lot_final', 'product_id': p_final.id, }) lot_1 = self.env['stock.production.lot'].create({ 'name': 'lot_consumed_1', 'product_id': p1.id, }) lot_2 = self.env['stock.production.lot'].create({ 'name': 'lot_consumed_2', 'product_id': p2.id, }) self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 100, lot_id=lot_1) self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5, lot_id=lot_2) mo.action_assign() produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 5.0 produce_form.lot_id = lot_final produce_wizard = produce_form.save() produce_wizard.do_produce() mo.button_mark_done() self.assertEqual(mo.state, 'done', "Production order should be in done state.") # Check quantity in stock before unbuild. self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, lot_id=lot_final), 5, 'You should have the 5 final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot_1), 80, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_2), 0, 'You should have consumed all the 5 product in stock') # --------------------------------------------------- # unbuild # --------------------------------------------------- unbuild_order = self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 3.0, 'product_uom_id': self.uom_unit.id, }) with self.assertRaises(UserError): unbuild_order.action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, lot_id=lot_final), 5, 'You should have consumed 3 final product in stock') unbuild_order.mo_id = mo.id with self.assertRaises(UserError): unbuild_order.action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, lot_id=lot_final), 5, 'You should have consumed 3 final product in stock') unbuild_order.lot_id = lot_final.id unbuild_order.action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, lot_id=lot_final), 2, 'You should have consumed 3 final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot_1), 92, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_2), 3, 'You should have consumed all the 5 product in stock') self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 2.0, 'mo_id': mo.id, 'lot_id': lot_final.id, 'product_uom_id': self.uom_unit.id, }).action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, lot_id=lot_final), 0, 'You should have 0 finalproduct in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot_1), 100, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_2), 5, 'You should have consumed all the 5 product in stock') self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 5.0, 'mo_id': mo.id, 'lot_id': lot_final.id, 'product_uom_id': self.uom_unit.id, }).action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, lot_id=lot_final, allow_negative=True), -5, 'You should have negative quantity for final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot_1), 120, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location, lot_id=lot_2), 10, 'You should have consumed all the 5 product in stock')
def test_unbuild_with_comnsumed_lot(self): """ This test creates a MO and then creates 3 unbuild orders for the final product. Only once of the two consumed product is tracked by lot. It checks the stock state after each order and ensure it is correct. """ mo, bom, p_final, p1, p2 = self.generate_mo(tracking_base_1='lot') self.assertEqual(len(mo), 1, 'MO should have been created') lot = self.env['stock.production.lot'].create({ 'name': 'lot1', 'product_id': p1.id, }) self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 100, lot_id=lot) self.env['stock.quant']._update_available_quantity( p2, self.stock_location, 5) mo.action_assign() for ml in mo.move_raw_ids.mapped('move_line_ids'): if ml.product_id.tracking != 'none': self.assertEqual(ml.lot_id, lot, 'Wrong reserved lot.') produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) produce_form.product_qty = 5.0 produce_wizard = produce_form.save() produce_wizard.do_produce() mo.button_mark_done() self.assertEqual(mo.state, 'done', "Production order should be in done state.") # Check quantity in stock before unbuild. self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location), 5, 'You should have the 5 final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot), 80, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location), 0, 'You should have consumed all the 5 product in stock') # --------------------------------------------------- # unbuild # --------------------------------------------------- unbuild_order = self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 3.0, 'product_uom_id': self.uom_unit.id, }) # This should fail since we do not provide the MO that we wanted to unbuild. (without MO we do not know which consumed lot we have to restore) with self.assertRaises(UserError): unbuild_order.action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location), 5, 'You should have consumed 3 final product in stock') unbuild_order.mo_id = mo.id unbuild_order.action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location), 2, 'You should have consumed 3 final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot), 92, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location), 3, 'You should have consumed all the 5 product in stock') self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 2.0, 'mo_id': mo.id, 'product_uom_id': self.uom_unit.id, }).action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location), 0, 'You should have 0 finalproduct in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot), 100, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location), 5, 'You should have consumed all the 5 product in stock') self.env['mrp.unbuild'].create({ 'product_id': p_final.id, 'bom_id': bom.id, 'product_qty': 5.0, 'mo_id': mo.id, 'product_uom_id': self.uom_unit.id, }).action_unbuild() self.assertEqual( self.env['stock.quant']._get_available_quantity( p_final, self.stock_location, allow_negative=True), -5, 'You should have negative quantity for final product in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p1, self.stock_location, lot_id=lot), 120, 'You should have 80 products in stock') self.assertEqual( self.env['stock.quant']._get_available_quantity( p2, self.stock_location), 10, 'You should have consumed all the 5 product in stock')