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 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_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_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_product_produce_7(self): """ Check that for products tracked by lots, with component product UOM different from UOM used in the BOM, we do not create a new move line due to extra reserved quantity caused by decimal rounding conversions. """ # the overall decimal accuracy is set to 3 digits precision = self.env.ref('product.decimal_product_uom') precision.write({ 'digits': 3 }) # define L and ml, L has rounding .001 but ml has rounding .01 # when producing e.g. 187.5ml, it will be rounded to .188L categ_test = self.env['uom.category'].create({'name': 'Volume Test'}) uom_L = self.env['uom.uom'].create({ 'name': 'Test Liters', 'category_id': categ_test.id, 'uom_type': 'reference', 'rounding': 0.001 }) uom_ml = self.env['uom.uom'].create({ 'name': 'Test ml', 'category_id': categ_test.id, 'uom_type': 'smaller', 'rounding': 0.01, 'factor_inv': 0.001, }) # create a product component and the final product using the component product_comp = self.env['product.product'].create({ 'name': 'Product Component', 'type': 'product', 'tracking': 'lot', 'categ_id': self.env.ref('product.product_category_all').id, 'uom_id': uom_L.id, 'uom_po_id': uom_L.id, }) product_final = self.env['product.product'].create({ 'name': 'Product Final', 'type': 'product', 'tracking': 'lot', 'categ_id': self.env.ref('product.product_category_all').id, 'uom_id': uom_L.id, 'uom_po_id': uom_L.id, }) # the products are tracked by lot, so we go through _generate_consumed_move_line lot_final = self.env['stock.production.lot'].create({ 'name': 'Lot Final', 'product_id': product_final.id, }) lot_comp = self.env['stock.production.lot'].create({ 'name': 'Lot Component', 'product_id': product_comp.id, }) # update the quantity on hand for Component, in a lot self.stock_location = self.env.ref('stock.stock_location_stock') self.env['stock.quant']._update_available_quantity(product_comp, self.stock_location, 1, lot_id=lot_comp) # create a BOM for Final, using Component test_bom = self.env['mrp.bom'].create({ 'product_id': product_final.id, 'product_tmpl_id': product_final.product_tmpl_id.id, 'product_uom_id': uom_L.id, 'product_qty': 1.0, 'type': 'normal', 'bom_line_ids': [(0, 0, { 'product_id': product_comp.id, 'product_qty': 375.00, 'product_uom_id': uom_ml.id })], }) # create a MO for this BOM mo_product_final = self.env['mrp.production'].create({ 'product_id': product_final.id, 'product_qty': 0.5, 'product_uom_id': uom_L.id, 'bom_id': test_bom.id, }) mo_product_final.action_assign() self.assertEqual(mo_product_final.availability, 'assigned') # produce context = {"active_ids": [mo_product_final.id], "active_id": mo_product_final.id} produce_form = Form(self.env['mrp.product.produce'].with_context(context)) produce_form.product_qty = 0.5 produce_form.lot_id = lot_final produce_wizard = produce_form.save() produce_wizard.do_produce() # check that in _generate_consumed_move_line, # we do not create an extra move line because # of a conversion 187.5ml = 0.188L # thus creating an extra line with 'product_uom_qty': 0.5 self.assertEqual(len(mo_product_final.move_raw_ids.move_line_ids), 1, 'One move line should exist for the MO.')
def test_tracking_types_on_mo(self): finished_no_track = self._create_product('none') finished_lot = self._create_product('lot') finished_serial = self._create_product('serial') consumed_no_track = self._create_product('none') consumed_lot = self._create_product('lot') consumed_serial = self._create_product('serial') stock_id = self.env.ref('stock.stock_location_stock').id inventory_adjustment = self.env['stock.inventory'].create({ 'name': 'Initial Inventory', 'location_id': stock_id, 'filter': 'partial', }) inventory_adjustment.action_start() inventory_adjustment.write({ 'line_ids': [ (0,0, {'product_id': consumed_no_track.id, 'product_qty': 3, 'location_id': stock_id}), (0,0, {'product_id': consumed_lot.id, 'product_qty': 3, 'prod_lot_id': self.env['stock.production.lot'].create({'name': 'L1', 'product_id': consumed_lot.id}).id, 'location_id': stock_id}), (0,0, {'product_id': consumed_serial.id, 'product_qty': 1, 'prod_lot_id': self.env['stock.production.lot'].create({'name': 'S1', 'product_id': consumed_serial.id}).id, 'location_id': stock_id}), (0,0, {'product_id': consumed_serial.id, 'product_qty': 1, 'prod_lot_id': self.env['stock.production.lot'].create({'name': 'S2', 'product_id': consumed_serial.id}).id, 'location_id': stock_id}), (0,0, {'product_id': consumed_serial.id, 'product_qty': 1, 'prod_lot_id': self.env['stock.production.lot'].create({'name': 'S3', 'product_id': consumed_serial.id}).id, 'location_id': stock_id}), ] }) inventory_adjustment.action_validate() for finished_product in [finished_no_track, finished_lot, finished_serial]: bom = self.env['mrp.bom'].create({ 'product_id': finished_product.id, 'product_tmpl_id': finished_product.product_tmpl_id.id, 'product_uom_id': self.env.ref('uom.product_uom_unit').id, 'product_qty': 1.0, 'type': 'normal', 'bom_line_ids': [ (0, 0, {'product_id': consumed_no_track.id, 'product_qty': 1}), (0, 0, {'product_id': consumed_lot.id, 'product_qty': 1}), (0, 0, {'product_id': consumed_serial.id, 'product_qty': 1}), ], }) mo = self.env['mrp.production'].create({ 'name': 'MO %s' % finished_product.tracking, 'product_id': finished_product.id, 'product_uom_id': self.env.ref('uom.product_uom_unit').id, 'product_qty': 1, 'bom_id': bom.id, }) mo.action_assign() # Start MO production produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': mo.id, 'active_ids': [mo.id], })) if finished_product.tracking != 'serial': produce_form.product_qty = 1 if finished_product.tracking != 'none': produce_form.lot_id = self.env['stock.production.lot'].create({'name': 'Serial or Lot finished', 'product_id': finished_product.id}) 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 results of traceability context = ({ 'active_id': mo.id, 'model': 'mrp.production', }) lines = self.env['stock.traceability.report'].with_context(context).get_lines() self.assertEqual(len(lines), 1, "Should always return 1 line : the final product") final_product = lines[0] self.assertEqual(final_product['unfoldable'], True, "Final product should always be unfoldable") # Find parts of the final products lines = self.env['stock.traceability.report'].get_lines(final_product['id'], **{ 'level': final_product['level'], 'model_id': final_product['model_id'], 'model_name': final_product['model'], }) self.assertEqual(len(lines), 3, "There should be 3 lines. 1 for untracked, 1 for lot, and 1 for serial") for line in lines: tracking = line['columns'][1].split(' ')[1] self.assertEqual( line['columns'][-1], "1.000 Unit(s)", 'Part with tracking type "%s", should have quantity = 1' % (tracking) ) unfoldable = False if tracking == 'none' else True self.assertEqual( line['unfoldable'], unfoldable, 'Parts with tracking type "%s", should have be unfoldable : %s' % (tracking, unfoldable) )