Ejemplo n.º 1
0
    def test_product_produce_uom_2(self):
        """ Create a bom with a serial tracked component and a pair UoM (2 x unit).
        The produce wizard should create 2 line with quantity = 1 and UoM = unit for
        this component. """

        unit = self.env.ref("uom.product_uom_unit")
        categ_unit_id = self.env.ref('uom.product_uom_categ_unit')
        paire = self.env['uom.uom'].create({
            'name': 'Paire',
            'factor_inv': 2,
            'uom_type': 'bigger',
            'rounding': 0.001,
            'category_id': categ_unit_id.id
        })
        binocular = self.env['product.product'].create({
            'name': 'Binocular',
            'type': 'product',
            'uom_id': unit.id,
            'uom_po_id': unit.id
        })
        nocular = self.env['product.product'].create({
            'name': 'Nocular',
            'type': 'product',
            'tracking': 'serial',
            'uom_id': unit.id,
            'uom_po_id': unit.id
        })
        bom_binocular = self.env['mrp.bom'].create({
            'product_tmpl_id': binocular.product_tmpl_id.id,
            'product_qty': 1,
            'product_uom_id': unit.id,
            'bom_line_ids': [(0, 0, {
                'product_id': nocular.id,
                'product_qty': 1,
                'product_uom_id': paire.id
            })]
        })
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = binocular
        mo_form.bom_id = bom_binocular
        mo_form.product_uom_id = unit
        mo_form.product_qty = 1
        mo = mo_form.save()

        mo.action_confirm()
        self.assertEqual(mo.move_raw_ids.product_uom_qty, 1, 'Quantity should be 1.')
        self.assertEqual(mo.move_raw_ids.product_uom, paire, 'Move UoM should be "Paire".')

        # produce product
        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(product_produce.qty_producing, 1)
        self.assertEqual(len(product_produce.workorder_line_ids), 2, 'Should be 2 lines since the component tracking is serial and quantity 2.')
        self.assertEqual(product_produce.workorder_line_ids[0].qty_to_consume, 1, 'Should be 1 unit since the tracking is serial and quantity 2.')
        self.assertEqual(product_produce.workorder_line_ids[0].product_uom_id, unit, 'Should be the product uom so "unit"')
        self.assertEqual(product_produce.workorder_line_ids[1].qty_to_consume, 1, 'Should be 1 unit since the tracking is serial and quantity 2.')
        self.assertEqual(product_produce.workorder_line_ids[1].product_uom_id, unit, 'should be the product uom so "unit"')
Ejemplo n.º 2
0
    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_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = bom_eff
        production_form.product_qty = 20
        production_form.product_uom_id = self.product_6.uom_id
        production = production_form.save()
        production.action_confirm()
        #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.qty_producing = 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')
Ejemplo n.º 3
0
    def test_04b_test_planning_date(self):
        """ Test that workorder are planned at the correct time when setting a start date """
        # Remove attendances linked to the calendar, this means that the workcenter is working 24/7
        self.env['resource.calendar'].search([]).write({'attendance_ids': [(5, False, False)]})

        dining_table = self.env.ref("mrp.product_product_computer_desk")

        date_start = datetime.now() + timedelta(days=1)

        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = dining_table
        production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
        production_table_form.product_qty = 1.0
        production_table_form.product_uom_id = dining_table.uom_id
        production_table_form.date_start_wo = date_start
        production_table = production_table_form.save()
        production_table.action_confirm()

        # Create work order
        production_table.button_plan()
        workorder = production_table.workorder_ids[0]

        # Check that the workorder is planned now and that it lasts one hour
        self.assertEqual(workorder.date_planned_start, date_start, msg="Workorder should be planned tomorrow.")
        self.assertEqual(workorder.date_planned_finished, date_start + timedelta(hours=1), msg="Workorder should be done one hour later.")
Ejemplo n.º 4
0
    def test_04b_test_planning_date(self):
        """ Test that workorder are planned at the correct time when setting a start date """
        # The workcenter is working 24/7
        self.full_availability()

        dining_table = self.env.ref("mrp.product_product_computer_desk")

        date_start = datetime.now() + timedelta(days=1)

        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = dining_table
        production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
        production_table_form.product_qty = 1.0
        production_table_form.product_uom_id = dining_table.uom_id
        production_table_form.date_start_wo = date_start
        production_table = production_table_form.save()
        production_table.action_confirm()

        # Create work order
        production_table.button_plan()
        workorder = production_table.workorder_ids[0]

        # Check that the workorder is planned now and that it lasts one hour
        self.assertAlmostEqual(workorder.date_planned_start, date_start, delta=timedelta(seconds=1), msg="Workorder should be planned tomorrow.")
        self.assertAlmostEqual(workorder.date_planned_finished, date_start + timedelta(hours=1), delta=timedelta(seconds=1), msg="Workorder should be done one hour later.")
Ejemplo n.º 5
0
    def test_03b_test_serial_number_defaults(self):
        """ Check the constraint on the workorder final_lot. The first workorder
        produces 2/2 units without serial number (serial is only required when
        you register a component) then the second workorder try to register a
        serial number. It should be allowed since the first workorder did not
        specify a seiral number.
        """
        bom = self.env.ref('mrp.mrp_bom_laptop_cust_rout')
        product = bom.product_tmpl_id.product_variant_id
        product.tracking = 'serial'

        lot_1 = self.env['stock.production.lot'].create({
            'product_id': product.id,
            'name': 'LOT000001'
        })

        lot_2 = self.env['stock.production.lot'].create({
            'product_id': product.id,
            'name': 'LOT000002'
        })
        self.env['stock.production.lot'].create({
            'product_id': product.id,
            'name': 'LOT000003'
        })

        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = product
        mo_form.bom_id = bom
        mo_form.product_qty = 2.0
        mo = mo_form.save()

        mo.action_confirm()
        mo.button_plan()

        workorder_0 = mo.workorder_ids[0]
        workorder_0.record_production()
        workorder_0.record_production()
        with self.assertRaises(UserError):
            workorder_0.record_production()

        workorder_1 = mo.workorder_ids[1]
        with Form(workorder_1) as wo:
            wo.finished_lot_id = lot_1
        workorder_1.record_production()

        self.assertTrue(len(workorder_1.allowed_lots_domain) > 1)
        with Form(workorder_1) as wo:
            wo.finished_lot_id = lot_2
        workorder_1.record_production()

        workorder_2 = mo.workorder_ids[2]
        self.assertEqual(workorder_2.allowed_lots_domain, lot_1 | lot_2)

        self.assertEqual(workorder_0.finished_workorder_line_ids.qty_done, 2)
        self.assertFalse(workorder_0.finished_workorder_line_ids.lot_id)
        self.assertEqual(sum(workorder_1.finished_workorder_line_ids.mapped('qty_done')), 2)
        self.assertEqual(workorder_1.finished_workorder_line_ids.mapped('lot_id'), lot_1 | lot_2)
Ejemplo n.º 6
0
 def new_mo_laptop(self):
     form = Form(self.env['mrp.production'])
     form.product_id = self.laptop
     form.product_qty = 1
     form.bom_id = self.bom_laptop
     p = form.save()
     p.action_confirm()
     p.action_assign()
     return p
Ejemplo n.º 7
0
    def test_00_production_order_with_accounting(self):
        self.product_table_sheet.standard_price = 20.0
        self.product_table_leg.standard_price = 15.0
        self.product_bolt.standard_price = 10.0
        self.product_table_leg.tracking = 'none'
        self.product_table_sheet.tracking = 'none'
        inventory = self.env['stock.inventory'].create({
            'name': 'Inventory Product Table',
            'filter': 'partial',
            'line_ids': [(0, 0, {
                'product_id': self.product_table_sheet.id,  # tracking serial
                'product_uom_id': self.product_table_sheet.uom_id.id,
                'product_qty': 20,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': self.product_table_leg.id,  # tracking lot
                'product_uom_id': self.product_table_leg.uom_id.id,
                'product_qty': 20,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': self.product_bolt.id,
                'product_uom_id': self.product_bolt.uom_id.id,
                'product_qty': 20,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': self.product_screw.id,
                'product_uom_id': self.product_screw.uom_id.id,
                'product_qty': 200000,
                'location_id': self.source_location_id
            }),
            ]
        })
        inventory.action_validate
        bom = self.env.ref('mrp.mrp_bom_desk').copy()
        bom.routing_id = False # TODO: extend the test later with the necessary operations
        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = self.dining_table
        production_table_form.bom_id = bom
        production_table_form.product_qty = 5.0
        production_table = production_table_form.save()

        production_table.extra_cost = 20
        production_table.action_confirm()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': production_table.id,
            'active_ids': [production_table.id],
        }))
        produce_form.qty_producing = 1.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()
        production_table.post_inventory()
        move_value = production_table.move_finished_ids.filtered(lambda x: x.state == "done").value

        # 1 table head at 20 + 4 table leg at 15 + 4 bolt at 10 + 10 screw at 10 + 1*20 (extra cost)
        self.assertEqual(move_value, 141, 'Thing should have the correct price')
Ejemplo n.º 8
0
 def test_access_rights_user(self):
     man_order_form = Form(self.env['mrp.production'].sudo(self.user_mrp_user))
     man_order_form.product_id = self.product_4
     man_order_form.product_qty = 5.0
     man_order_form.bom_id = self.bom_1
     man_order_form.location_src_id = self.location_1
     man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id
     man_order = man_order_form.save()
     man_order.action_cancel()
     self.assertEqual(man_order.state, 'cancel', "Production order should be in cancel state.")
     man_order.unlink()
Ejemplo n.º 9
0
    def test_03_test_serial_number_defaults(self):
        """ Test that the correct serial number is suggested on consecutive work orders. """
        laptop = self.env.ref("product.product_product_25")
        graphics_card = self.env.ref("product.product_product_24")
        unit = self.env.ref("uom.product_uom_unit")
        three_step_routing = self.env.ref("mrp.mrp_routing_1")

        laptop.tracking = 'serial'

        bom_laptop = self.env['mrp.bom'].create({
            'product_tmpl_id': laptop.product_tmpl_id.id,
            'product_qty': 1,
            'product_uom_id': unit.id,
            'bom_line_ids': [(0, 0, {
                'product_id': graphics_card.id,
                'product_qty': 1,
                'product_uom_id': unit.id
            })],
            'routing_id': three_step_routing.id
        })

        mo_laptop_form = Form(self.env['mrp.production'])
        mo_laptop_form.product_id = laptop
        mo_laptop_form.bom_id = bom_laptop
        mo_laptop_form.product_qty = 3
        mo_laptop = mo_laptop_form.save()

        mo_laptop.action_confirm()
        mo_laptop.button_plan()
        workorders = mo_laptop.workorder_ids
        self.assertEqual(len(workorders), 3)

        workorders[0].button_start()
        serial_a = self.env['stock.production.lot'].create({'product_id': laptop.id})
        workorders[0].final_lot_id = serial_a
        workorders[0].record_production()
        serial_b = self.env['stock.production.lot'].create({'product_id': laptop.id})
        workorders[0].final_lot_id = serial_b
        workorders[0].record_production()
        serial_c = self.env['stock.production.lot'].create({'product_id': laptop.id})
        workorders[0].final_lot_id = serial_c
        workorders[0].record_production()
        self.assertEqual(workorders[0].state, 'done')

        for workorder in workorders - workorders[0]:
            self.assertEqual(workorder.final_lot_id, serial_a)
            workorder.record_production()
            self.assertEqual(workorder.final_lot_id, serial_b)
            workorder.record_production()
            self.assertEqual(workorder.final_lot_id, serial_c)
            workorder.record_production()
            self.assertEqual(workorder.state, 'done')
Ejemplo n.º 10
0
    def test_planning_3(self):
        """ Plan some manufacturing orders with 1 workorder on 1 workcenter
        the first workorder will be hard set in the future to see if the second
        one take the free slot before on the calendar
        calendar after first mo : [   ][mo1]
        calendar after second mo: [mo2][mo1] """

        self.workcenter_1.alternative_workcenter_ids = self.wc_alt_1 | self.wc_alt_2
        self.env['mrp.workcenter'].search([]).write({'tz': 'UTC'}) # compute all date in UTC

        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product_4
        mo_form.bom_id = self.planning_bom
        mo_form.product_qty = 1
        mo_form.date_start_wo = datetime(2019, 5, 13, 14, 0, 0, 0)
        mo = mo_form.save()
        start = mo.date_start_wo
        mo.action_confirm()
        mo.button_plan()
        self.assertEqual(mo.workorder_ids[0].workcenter_id, self.wc_alt_2, "wrong workcenter")
        wo1_start = mo.workorder_ids[0].date_planned_start
        wo1_stop = mo.workorder_ids[0].date_planned_finished
        self.assertAlmostEqual(wo1_start, start, delta=timedelta(seconds=10), msg="Wrong plannification")
        self.assertAlmostEqual(wo1_stop, start + timedelta(minutes=85.58), delta=timedelta(seconds=10), msg="Wrong plannification")

        # second MO should be plan before as there is a free slot before
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product_4
        mo_form.bom_id = self.planning_bom
        mo_form.product_qty = 1
        mo_form.date_start_wo = datetime(2019, 5, 13, 9, 0, 0, 0)
        mo = mo_form.save()
        mo.action_confirm()
        mo.button_plan()
        self.assertEqual(mo.workorder_ids[0].workcenter_id, self.wc_alt_2, "wrong workcenter")
        wo1_start = mo.workorder_ids[0].date_planned_start
        wo1_stop = mo.workorder_ids[0].date_planned_finished
        self.assertAlmostEqual(wo1_start, datetime(2019, 5, 13, 9, 0, 0, 0), delta=timedelta(seconds=10), msg="Wrong plannification")
        self.assertAlmostEqual(wo1_stop, datetime(2019, 5, 13, 9, 0, 0, 0) + timedelta(minutes=85.59), delta=timedelta(seconds=10), msg="Wrong plannification")
Ejemplo n.º 11
0
 def test_access_rights_manager(self):
     """ Checks an MRP manager can create, confirm and cancel a manufacturing order. """
     man_order_form = Form(self.env['mrp.production'].sudo(self.user_mrp_manager))
     man_order_form.product_id = self.product_4
     man_order_form.product_qty = 5.0
     man_order_form.bom_id = self.bom_1
     man_order_form.location_src_id = self.location_1
     man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id
     man_order = man_order_form.save()
     man_order.action_confirm()
     man_order.action_cancel()
     self.assertEqual(man_order.state, 'cancel', "Production order should be in cancel state.")
     man_order.unlink()
Ejemplo n.º 12
0
    def test_planning_1(self):
        """ Testing planning workorder with alternative workcenters
        Plan 6 times the same MO, the workorders should be split accross workcenters
        The 3 workcenters are free, this test plans 3 workorder in a row then three next.
        The workcenters have not exactly the same parameters (efficiency, start time) so the
        the last 3 workorder are not dispatched like the 3 first.
        At the end of the test, the calendars will look like:
            - calendar wc1 :[mo1][mo4]
            - calendar wc2 :[mo2 ][mo5 ]
            - calendar wc3 :[mo3  ][mo6  ]"""
        self.workcenter_1.alternative_workcenter_ids = self.wc_alt_1 | self.wc_alt_2
        workcenters = [self.wc_alt_2, self.wc_alt_1, self.workcenter_1]
        for i in range(3):
            # Create an MO for product4
            mo_form = Form(self.env['mrp.production'])
            mo_form.product_id = self.product_4
            mo_form.bom_id = self.planning_bom
            mo_form.product_qty = 1
            mo = mo_form.save()
            mo.action_confirm()
            mo.button_plan()
            # Check that workcenters change
            self.assertEqual(mo.workorder_ids.workcenter_id, workcenters[i], "wrong workcenter %d" % i)

        for i in range(3):
            # Planning 3 more should choose workcenters in opposite order as
            # - wc_alt_2 as the best efficiency
            # - wc_alt_1 take a little less start time
            # - workcenter_1 is the worst
            mo_form = Form(self.env['mrp.production'])
            mo_form.product_id = self.product_4
            mo_form.bom_id = self.planning_bom
            mo_form.product_qty = 1
            mo = mo_form.save()
            mo.action_confirm()
            mo.button_plan()
            # Check that workcenters change
            self.assertEqual(mo.workorder_ids.workcenter_id, workcenters[i], "wrong workcenter %d" % i)
Ejemplo n.º 13
0
    def test_planning_4(self):
        """ Plan a manufacturing orders with 1 workorder on 1 workcenter
        the workcenter calendar is empty. which means the workcenter is never
        available. Planning a workorder on it should raise an error"""

        self.workcenter_1.alternative_workcenter_ids = self.wc_alt_1 | self.wc_alt_2
        self.env['resource.calendar'].search([]).write({'attendance_ids': [(5, False, False)]})

        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product_4
        mo_form.bom_id = self.planning_bom
        mo_form.product_qty = 1
        mo = mo_form.save()
        mo.action_confirm()
        with self.assertRaises(UserError):
            mo.button_plan()
Ejemplo n.º 14
0
    def test_product_produce_uom(self):
        """ Produce a finished product tracked by serial number. Set another
        UoM on the bom. The produce wizard should keep the UoM of the product (unit)
        and quantity = 1."""

        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_form = Form(self.env['mrp.production'])
        mo_form.product_id = plastic_laminate
        mo_form.bom_id = bom
        mo_form.product_uom_id = dozen
        mo_form.product_qty = 1
        mo = mo_form.save()

        final_product_lot = self.env['stock.production.lot'].create({
            'name': 'lot1',
            'product_id': plastic_laminate.id,
        })

        mo.action_confirm()
        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.final_lot_id = final_product_lot
        product_produce = produce_form.save()
        self.assertEqual(product_produce.qty_producing, 1)
        self.assertEqual(product_produce.product_uom_id, unit, 'Should be 1 unit since the tracking is serial.')
        product_produce.final_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.')
Ejemplo n.º 15
0
    def test_reuse_unbuilt_usn(self):
        """
        Produce a SN product
        Unbuilt it
        Produce a new SN product with same lot
        """
        mo, bom, p_final, p1, p2 = self.generate_mo(qty_base_1=1, qty_base_2=1, qty_final=1, tracking_final='serial')
        stock_location = self.env.ref('stock.stock_location_stock')
        self.env['stock.quant']._update_available_quantity(p1, stock_location, 1)
        self.env['stock.quant']._update_available_quantity(p2, stock_location, 1)
        mo.action_assign()

        lot = self.env['stock.lot'].create({
            'name': 'lot1',
            'product_id': p_final.id,
            'company_id': self.env.company.id,
        })

        mo_form = Form(mo)
        mo_form.qty_producing = 1.0
        mo_form.lot_producing_id = lot
        mo = mo_form.save()
        mo.button_mark_done()

        unbuild_form = Form(self.env['mrp.unbuild'])
        unbuild_form.mo_id = mo
        unbuild_form.lot_id = lot
        unbuild_form.save().action_unbuild()

        mo_form = Form(self.env['mrp.production'])
        mo_form.bom_id = bom
        mo = mo_form.save()
        mo.action_confirm()

        with self.assertLogs(level="WARNING") as log_catcher:
            mo_form = Form(mo)
            mo_form.qty_producing = 1.0
            mo_form.lot_producing_id = lot
            mo = mo_form.save()
            _logger.warning('Dummy')
        self.assertEqual(len(log_catcher.output), 1, "Useless warnings: \n%s" % "\n".join(log_catcher.output[:-1]))

        mo.button_mark_done()
        self.assertEqual(mo.state, 'done')
Ejemplo n.º 16
0
    def test_unbuild_account_00(self):
        """Test when after unbuild, the journal entries are the reversal of the
        journal entries created when produce the product.
        """
        # build
        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_A
        production_form.bom_id = self.bom
        production_form.product_qty = 1
        production = production_form.save()
        production.action_confirm()
        mo_form = Form(production)
        mo_form.qty_producing = 1
        production = mo_form.save()
        production._post_inventory()
        production.button_mark_done()

        # finished product move
        productA_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product A'), ('credit', '=', 0)])
        productA_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product A'), ('debit', '=', 0)])
        self.assertEqual(productA_debit_line.account_id, self.stock_valuation_account)
        self.assertEqual(productA_credit_line.account_id, self.stock_input_account)
        # component move
        productB_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product B'), ('credit', '=', 0)])
        productB_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'MO%Product B'), ('debit', '=', 0)])
        self.assertEqual(productB_debit_line.account_id, self.stock_output_account)
        self.assertEqual(productB_credit_line.account_id, self.stock_valuation_account)

        # unbuild
        res_dict = production.button_unbuild()
        wizard = Form(self.env[res_dict['res_model']].with_context(res_dict['context'])).save()
        wizard.action_validate()

        # finished product move
        productA_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product A'), ('credit', '=', 0)])
        productA_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product A'), ('debit', '=', 0)])
        self.assertEqual(productA_debit_line.account_id, self.stock_input_account)
        self.assertEqual(productA_credit_line.account_id, self.stock_valuation_account)
        # component move
        productB_debit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product B'), ('credit', '=', 0)])
        productB_credit_line = self.env['account.move.line'].search([('ref', 'ilike', 'UB%Product B'), ('debit', '=', 0)])
        self.assertEqual(productB_debit_line.account_id, self.stock_valuation_account)
        self.assertEqual(productB_credit_line.account_id, self.stock_output_account)
Ejemplo n.º 17
0
    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_form = Form(self.env['mrp.production'])
        mo_form.product_id = plastic_laminate
        mo_form.bom_id = bom
        mo_form.product_uom_id = dozen
        mo_form.product_qty = 1
        mo = mo_form.save()

        final_product_lot = self.env['stock.production.lot'].create({
            'name': 'lot1',
            'product_id': plastic_laminate.id,
        })

        mo.action_confirm()
        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.final_lot_id = final_product_lot
        product_produce = produce_form.save()
        self.assertEqual(product_produce.qty_producing, 1)
        self.assertEqual(product_produce.product_uom_id, unit, 'Should be 1 unit since the tracking is serial.')
        product_produce.final_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.')
Ejemplo n.º 18
0
    def test_production_avialability(self):
        """
            Test availability of production order.
        """
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_4).unlink()
        self.bom_3.ready_to_produce = 'all_available'

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 5.0
        production_form.product_uom_id = self.product_6.uom_id
        production_2 = production_form.save()

        production_2.action_confirm()
        production_2.action_assign()

        # check sub product availability state is waiting
        self.assertEqual(production_2.reservation_state, 'confirmed', 'Production order should be availability for waiting state')

        # Update Inventory
        inventory_wizard = self.env['stock.change.product.qty'].create({
            'product_id': self.product_2.id,
            'new_quantity': 2.0,
        })
        inventory_wizard.change_product_qty()

        production_2.action_assign()
        # check sub product availability state is partially available
        self.assertEqual(production_2.reservation_state, 'confirmed', 'Production order should be availability for partially available state')

        # Update Inventory
        inventory_wizard = self.env['stock.change.product.qty'].create({
            'product_id': self.product_2.id,
            'new_quantity': 5.0,
        })
        inventory_wizard.change_product_qty()

        production_2.action_assign()
        # check sub product availability state is assigned
        self.assertEqual(production_2.reservation_state, 'assigned', 'Production order should be availability for assigned state')
Ejemplo n.º 19
0
    def test_production_avialability(self):
        """
            Test availability of production order.
        """
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_4).unlink()
        self.bom_3.ready_to_produce = 'all_available'

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 5.0
        production_form.product_uom_id = self.product_6.uom_id
        production_2 = production_form.save()

        production_2.action_confirm()
        production_2.action_assign()

        # check sub product availability state is waiting
        self.assertEqual(production_2.reservation_state, 'confirmed', 'Production order should be availability for waiting state')

        # Update Inventory
        inventory_wizard = self.env['stock.change.product.qty'].create({
            'product_id': self.product_2.id,
            'new_quantity': 2.0,
        })
        inventory_wizard.change_product_qty()

        production_2.action_assign()
        # check sub product availability state is partially available
        self.assertEqual(production_2.reservation_state, 'confirmed', 'Production order should be availability for partially available state')

        # Update Inventory
        inventory_wizard = self.env['stock.change.product.qty'].create({
            'product_id': self.product_2.id,
            'new_quantity': 5.0,
        })
        inventory_wizard.change_product_qty()

        production_2.action_assign()
        # check sub product availability state is assigned
        self.assertEqual(production_2.reservation_state, 'assigned', 'Production order should be availability for assigned state')
Ejemplo n.º 20
0
    def test_workcenter_same_analytic_account(self):
        """Test when workcenter and MO are using the same analytic account, no
        duplicated lines will be post.
        """
        # set wc analytic account to be the same of the one on the bom
        self.workcenter.costs_hour_account_id = self.analytic_account

        # create a mo
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product
        mo_form.bom_id = self.bom
        mo_form.product_qty = 10.0
        mo_form.analytic_account_id = self.analytic_account
        mo = mo_form.save()
        mo.action_confirm()
        self.assertEqual(len(mo.workorder_ids.wc_analytic_account_line_id), 0)

        # change duration to 60
        with mo_form.workorder_ids.edit(0) as line_edit:
            line_edit.duration = 60.0
        mo_form.save()
        self.assertEqual(mo.workorder_ids.mo_analytic_account_line_id.amount,
                         -10.0)
        self.assertEqual(len(mo.workorder_ids.wc_analytic_account_line_id), 0)

        # change duration to 120
        with mo_form.workorder_ids.edit(0) as line_edit:
            line_edit.duration = 120.0
        mo_form.save()
        self.assertEqual(mo.workorder_ids.mo_analytic_account_line_id.amount,
                         -20.0)
        self.assertEqual(len(mo.workorder_ids.wc_analytic_account_line_id), 0)

        # mark as done
        mo_form.qty_producing = 10.0
        mo_form.save()
        mo.button_mark_done()
        self.assertEqual(mo.state, 'done')
        self.assertEqual(mo.workorder_ids.mo_analytic_account_line_id.amount,
                         -20.0)
        self.assertEqual(len(mo.workorder_ids.wc_analytic_account_line_id), 0)
Ejemplo n.º 21
0
 def generate_mo(self, tracking_final='none', tracking_base_1='none', tracking_base_2='none', qty_final=5, qty_base_1=4, qty_base_2=1, picking_type_id=False, consumption=False):
     """ This function generate a manufacturing order with one final
     product and two consumed product. Arguments allows to choose
     the tracking/qty for each different products. It returns the
     MO, used bom and the tree products.
     """
     product_to_build = self.env['product.product'].create({
         'name': 'Young Tom',
         'type': 'product',
         'tracking': tracking_final,
     })
     product_to_use_1 = self.env['product.product'].create({
         'name': 'Botox',
         'type': 'product',
         'tracking': tracking_base_1,
     })
     product_to_use_2 = self.env['product.product'].create({
         'name': 'Old Tom',
         'type': 'product',
         'tracking': tracking_base_2,
     })
     bom_1 = self.env['mrp.bom'].create({
         'product_id': product_to_build.id,
         'product_tmpl_id': product_to_build.product_tmpl_id.id,
         'product_uom_id': self.uom_unit.id,
         'product_qty': 1.0,
         'type': 'normal',
         'consumption': consumption if consumption else 'flexible',
         'bom_line_ids': [
             (0, 0, {'product_id': product_to_use_2.id, 'product_qty': qty_base_2}),
             (0, 0, {'product_id': product_to_use_1.id, 'product_qty': qty_base_1})
         ]})
     mo_form = Form(self.env['mrp.production'])
     if picking_type_id:
         mo_form.picking_type_id = picking_type_id
     mo_form.product_id = product_to_build
     mo_form.bom_id = bom_1
     mo_form.product_qty = qty_final
     mo = mo_form.save()
     mo.action_confirm()
     return mo, bom_1, product_to_build, product_to_use_1, product_to_use_2
Ejemplo n.º 22
0
    def test_production_avialability(self):
        """ Checks the availability of a production order through mutliple calls to `action_assign`.
        """
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_4).unlink()
        self.bom_3.ready_to_produce = 'all_available'

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 5.0
        production_form.product_uom_id = self.product_6.uom_id
        production_2 = production_form.save()

        production_2.action_confirm()
        production_2.action_assign()

        # check sub product availability state is waiting
        self.assertEqual(production_2.reservation_state, 'confirmed', 'Production order should be availability for waiting state')

        # Update Inventory
        self.env['stock.quant'].with_context(inventory_mode=True).create({
            'product_id': self.product_2.id,
            'inventory_quantity': 2.0,
            'location_id': self.ref('stock.stock_location_14')
        })

        production_2.action_assign()
        # check sub product availability state is partially available
        self.assertEqual(production_2.reservation_state, 'confirmed', 'Production order should be availability for partially available state')

        # Update Inventory
        self.env['stock.quant'].with_context(inventory_mode=True).create({
            'product_id': self.product_2.id,
            'inventory_quantity': 5.0,
            'location_id': self.ref('stock.stock_location_14')
        })

        production_2.action_assign()
        # check sub product availability state is assigned
        self.assertEqual(production_2.reservation_state, 'assigned', 'Production order should be availability for assigned state')
Ejemplo n.º 23
0
    def test_changing_mo_analytic_account(self):
        """ Check if the MO account analytic lines are correctly updated
            after the change of the MO account analytic.
        """
        # create a mo
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product
        mo_form.bom_id = self.bom
        mo_form.product_qty = 1
        mo_form.analytic_account_id = self.analytic_account
        mo = mo_form.save()
        mo.action_confirm()
        self.assertEqual(mo.state, 'confirmed')
        self.assertEqual(len(mo.move_raw_ids.analytic_account_line_id), 0)

        # Mark as done
        wizard_dict = mo.button_mark_done()
        Form(self.env[(wizard_dict.get('res_model'))].with_context(
            wizard_dict['context'])).save().process()
        self.assertEqual(mo.state, 'done')
        self.assertEqual(len(mo.move_raw_ids.analytic_account_line_id), 1)

        # Create a new analytic account
        new_analytic_account = self.env['account.analytic.account'].create(
            {'name': 'test_analytic_account_2'})
        # Change the MO analytic account
        mo.analytic_account_id = new_analytic_account
        self.assertEqual(
            mo.move_raw_ids.analytic_account_line_id.account_id.id,
            new_analytic_account.id)

        #Get the MO analytic account lines
        mo_analytic_account_lines = mo.move_raw_ids.analytic_account_line_id
        mo.analytic_account_id = False
        # Check that the MO analytic account lines are deleted
        self.assertEqual(len(mo.move_raw_ids.analytic_account_line_id), 0)
        self.assertFalse(mo_analytic_account_lines.exists())
        # Check that the AA lines are recreated correctly if we delete the AA, save the MO, and assign a new one
        mo.analytic_account_id = self.analytic_account
        self.assertEqual(len(mo.move_raw_ids.analytic_account_line_id), 1)
Ejemplo n.º 24
0
    def test_04_test_planning_date(self):
        """ Test that workorder are planned at the correct time. """
        # Remove attendances linked to the calendar, this means that the workcenter is working 24/7
        self.env['resource.calendar'].search([]).write({'attendance_ids': [(5, False, False)]})

        dining_table = self.env.ref("mrp.product_product_computer_desk")

        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = dining_table
        production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
        production_table_form.product_qty = 1.0
        production_table_form.product_uom_id = dining_table.uom_id
        production_table = production_table_form.save()
        production_table.action_confirm()

        # Create work order
        production_table.button_plan()
        workorder = production_table.workorder_ids[0]

        # Check that the workorder is planned now and that it lasts one hour
        self.assertAlmostEqual(workorder.date_planned_start, datetime.now(), delta=timedelta(seconds=10), msg="Workorder should be planned now.")
        self.assertAlmostEqual(workorder.date_planned_finished, datetime.now() + timedelta(hours=1), delta=timedelta(seconds=10), msg="Workorder should be done in an hour.")
Ejemplo n.º 25
0
 def generate_mo(self, tracking_final='none', tracking_base_1='none', tracking_base_2='none', qty_final=5, qty_base_1=4, qty_base_2=1):
     """ This function generate a manufacturing order with one final
     product and two consumed product. Arguments allows to choose
     the tracking/qty for each different products. It returns the
     MO, used bom and the tree products.
     """
     product_to_build = self.env['product.product'].create({
         'name': 'Young Tom',
         'type': 'product',
         'tracking': tracking_final,
     })
     product_to_use_1 = self.env['product.product'].create({
         'name': 'Botox',
         'type': 'product',
         'tracking': tracking_base_1,
     })
     product_to_use_2 = self.env['product.product'].create({
         'name': 'Old Tom',
         'type': 'product',
         'tracking': tracking_base_2,
     })
     bom_1 = self.env['mrp.bom'].create({
         'product_id': product_to_build.id,
         'product_tmpl_id': product_to_build.product_tmpl_id.id,
         'product_uom_id': self.uom_unit.id,
         'product_qty': 1.0,
         'type': 'normal',
         'bom_line_ids': [
             (0, 0, {'product_id': product_to_use_2.id, 'product_qty': qty_base_2}),
             (0, 0, {'product_id': product_to_use_1.id, 'product_qty': qty_base_1})
         ]})
     mo_form = Form(self.env['mrp.production'])
     mo_form.product_id = product_to_build
     mo_form.bom_id = bom_1
     mo_form.product_qty = qty_final
     mo = mo_form.save()
     mo.action_confirm()
     return mo, bom_1, product_to_build, product_to_use_1, product_to_use_2
Ejemplo n.º 26
0
    def test_mo_analytic(self):
        """Test the amount on analytic line will change when consumed qty of the
        component changed.
        """
        # create a mo
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product
        mo_form.bom_id = self.bom
        mo_form.product_qty = 10.0
        mo_form.analytic_account_id = self.analytic_account
        mo = mo_form.save()
        mo.action_confirm()
        self.assertEqual(mo.state, 'confirmed')
        self.assertEqual(len(mo.move_raw_ids.analytic_account_line_id), 0)
        # increase qty_producing to 5.0
        mo_form = Form(mo)
        mo_form.qty_producing = 5.0
        mo_form.save()
        self.assertEqual(mo.state, 'progress')
        self.assertEqual(mo.move_raw_ids.analytic_account_line_id.amount,
                         -50.0)

        # increase qty_producing to 10.0
        mo_form = Form(mo)
        mo_form.qty_producing = 10.0
        mo_form.save()
        # Hack to bypass test doing strange things
        mo._set_qty_producing()
        mo.workorder_ids.button_finish()
        self.assertEqual(mo.state, 'to_close')
        self.assertEqual(mo.move_raw_ids.analytic_account_line_id.amount,
                         -100.0)

        # mark as done
        mo.button_mark_done()
        self.assertEqual(mo.state, 'done')
        self.assertEqual(mo.move_raw_ids.analytic_account_line_id.amount,
                         -100.0)
Ejemplo n.º 27
0
    def test_rounding(self):
        """ Checks we round up when bringing goods to produce and round half-up when producing.
        This implementation allows to implement an efficiency notion (see rev 347f140fe63612ee05e).
        """
        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_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = bom_eff
        production_form.product_qty = 20
        production_form.product_uom_id = self.product_6.uom_id
        production = production_form.save()
        production.action_confirm()
        #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.qty_producing = 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')
Ejemplo n.º 28
0
    def test_planning_2(self):
        """ Plan some manufacturing orders with 2 workorders each
        Batch size of the operation will influence start dates of workorders
        The first unit to be produced can go the second workorder before finishing
        to produce the second unit.
        calendar wc1 : [q1][q2]
        calendar wc2 :     [q1][q2]"""
        self.workcenter_1.alternative_workcenter_ids = self.wc_alt_1 | self.wc_alt_2
        self.planning_bom.routing_id = self.routing_2
        # Allow second workorder to start once the first one is not ended yet
        self.operation_2.batch = 'yes'
        self.operation_2.batch_size = 1
        self.env['mrp.workcenter'].search([]).write({'capacity': 1})
        # workcenters work 24/7
        self.full_availability()

        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = self.product_4
        mo_form.bom_id = self.planning_bom
        mo_form.product_qty = 2
        mo = mo_form.save()
        mo.action_confirm()
        plan = datetime.now()
        mo.button_plan()
        self.assertEqual(mo.workorder_ids[0].workcenter_id, self.wc_alt_2, "wrong workcenter")
        self.assertEqual(mo.workorder_ids[1].workcenter_id, self.wc_alt_1, "wrong workcenter")

        duration1 = self.operation_2.time_cycle * 100.0 / self.wc_alt_2.time_efficiency + self.wc_alt_2.time_start
        duration2 = 2.0 * self.operation_2.time_cycle * 100.0 / self.wc_alt_1.time_efficiency + self.wc_alt_1.time_start + self.wc_alt_1.time_stop
        wo2_start = mo.workorder_ids[1].date_planned_start
        wo2_stop = mo.workorder_ids[1].date_planned_finished

        wo2_start_theo = self.wc_alt_2.resource_calendar_id.plan_hours(duration1 / 60.0, plan, compute_leaves=False, resource=self.wc_alt_2.resource_id)
        wo2_stop_theo = self.wc_alt_1.resource_calendar_id.plan_hours(duration2 / 60.0, wo2_start, compute_leaves=False, resource=self.wc_alt_2.resource_id)

        self.assertAlmostEqual(wo2_start, wo2_start_theo, delta=timedelta(seconds=10), msg="Wrong plannification")
        self.assertAlmostEqual(wo2_stop, wo2_stop_theo, delta=timedelta(seconds=10), msg="Wrong plannification")
Ejemplo n.º 29
0
    def test_rounding(self):
        """ Checks we round up when bringing goods to produce and round half-up when producing.
        This implementation allows to implement an efficiency notion (see rev 347f140fe63612ee05e).
        """
        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_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = bom_eff
        production_form.product_qty = 20
        production_form.product_uom_id = self.product_6.uom_id
        production = production_form.save()
        production.action_confirm()
        #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.qty_producing = 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')
Ejemplo n.º 30
0
    def test_00_production_order_with_accounting(self):
        self.product_table_sheet.standard_price = 20.0
        self.product_table_leg.standard_price = 15.0
        self.product_bolt.standard_price = 10.0
        self.product_screw.standard_price = 0.1
        self.product_table_leg.tracking = 'none'
        self.product_table_sheet.tracking = 'none'
        inventory = self.env['stock.inventory'].create({
            'name':
            'Inventory Product Table',
            'line_ids': [
                (
                    0,
                    0,
                    {
                        'product_id':
                        self.product_table_sheet.id,  # tracking serial
                        'product_uom_id': self.product_table_sheet.uom_id.id,
                        'product_qty': 20,
                        'location_id': self.source_location_id
                    }),
                (
                    0,
                    0,
                    {
                        'product_id':
                        self.product_table_leg.id,  # tracking lot
                        'product_uom_id': self.product_table_leg.uom_id.id,
                        'product_qty': 20,
                        'location_id': self.source_location_id
                    }),
                (0, 0, {
                    'product_id': self.product_bolt.id,
                    'product_uom_id': self.product_bolt.uom_id.id,
                    'product_qty': 20,
                    'location_id': self.source_location_id
                }),
                (0, 0, {
                    'product_id': self.product_screw.id,
                    'product_uom_id': self.product_screw.uom_id.id,
                    'product_qty': 200000,
                    'location_id': self.source_location_id
                }),
            ]
        })
        inventory.action_validate
        bom = self.mrp_bom_desk.copy()
        bom.routing_id = False  # TODO: extend the test later with the necessary operations
        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = self.dining_table
        production_table_form.bom_id = bom
        production_table_form.product_qty = 5.0
        production_table = production_table_form.save()

        production_table.extra_cost = 20
        production_table.action_confirm()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            production_table.id,
            'active_ids': [production_table.id],
        }))
        produce_form.qty_producing = 1.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()
        production_table.post_inventory()
        move_value = production_table.move_finished_ids.filtered(
            lambda x: x.state == "done").stock_valuation_layer_ids.value

        # 1 table head at 20 + 4 table leg at 15 + 4 bolt at 10 + 10 screw at 10 + 1*20 (extra cost)
        self.assertEqual(move_value, 141,
                         'Thing should have the correct price')
Ejemplo n.º 31
0
    def test_procurement(self):
        """This test case when create production order check procurement is create"""
        # Update BOM
        self.bom_3.bom_line_ids.filtered(
            lambda x: x.product_id == self.product_5).unlink()
        self.bom_1.bom_line_ids.filtered(
            lambda x: x.product_id == self.product_1).unlink()

        # Update route
        self.warehouse = self.env.ref('stock.warehouse0')
        route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
        route_mto = self.warehouse.mto_pull_id.route_id.id
        self.product_4.write(
            {'route_ids': [(6, 0, [route_manufacture, route_mto])]})

        # Create production order
        # -------------------------
        # Product6 Unit 24
        #    Product4 8 Dozen
        #    Product2 12 Unit
        # -----------------------

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 24
        production_form.product_uom_id = self.product_6.uom_id
        production_product_6 = production_form.save()
        production_product_6.action_confirm()
        production_product_6.action_assign()

        # check production state is Confirmed
        self.assertEqual(production_product_6.state, 'confirmed',
                         'Production order should be for Confirmed state')

        # Check procurement for product 4 created or not.
        # Check it created a purchase order

        move_raw_product4 = production_product_6.move_raw_ids.filtered(
            lambda x: x.product_id == self.product_4)
        produce_product_4 = self.env['mrp.production'].search([
            ('product_id', '=', self.product_4.id),
            ('move_dest_ids', '=', move_raw_product4[0].id)
        ])
        # produce product
        self.assertEqual(produce_product_4.reservation_state, 'confirmed',
                         "Consume material not available")

        # Create production order
        # -------------------------
        # Product 4  96 Unit
        #    Product2 48 Unit
        # ---------------------
        # Update Inventory
        self.env['stock.quant'].with_context(inventory_mode=True).create({
            'product_id':
            self.product_2.id,
            'inventory_quantity':
            48,
            'location_id':
            self.warehouse.lot_stock_id.id,
        })
        produce_product_4.action_assign()
        self.assertEqual(produce_product_4.product_qty, 8,
                         "Wrong quantity of finish product.")
        self.assertEqual(produce_product_4.product_uom_id, self.uom_dozen,
                         "Wrong quantity of finish product.")
        self.assertEqual(produce_product_4.reservation_state, 'assigned',
                         "Consume material not available")

        # produce product4
        # ---------------

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            produce_product_4.id,
            'active_ids': [produce_product_4.id],
        }))
        produce_form.qty_producing = produce_product_4.product_qty
        product_produce = produce_form.save()
        product_produce.do_produce()
        produce_product_4.post_inventory()
        # Check procurement and Production state for product 4.
        produce_product_4.button_mark_done()
        self.assertEqual(produce_product_4.state, 'done',
                         'Production order should be in state done')

        # Produce product 6
        # ------------------

        # Update Inventory
        self.env['stock.quant'].with_context(inventory_mode=True).create({
            'product_id':
            self.product_2.id,
            'inventory_quantity':
            12,
            'location_id':
            self.warehouse.lot_stock_id.id,
        })
        production_product_6.action_assign()

        # ------------------------------------

        self.assertEqual(production_product_6.reservation_state, 'assigned',
                         "Consume material not available")
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            production_product_6.id,
            'active_ids': [production_product_6.id],
        }))
        produce_form.qty_producing = production_product_6.product_qty
        product_produce = produce_form.save()
        product_produce.do_produce()
        production_product_6.post_inventory()
        # Check procurement and Production state for product 6.
        production_product_6.button_mark_done()
        self.assertEqual(production_product_6.state, 'done',
                         'Production order should be in state done')
        self.assertEqual(self.product_6.qty_available, 24,
                         'Wrong quantity available of finished product.')
Ejemplo n.º 32
0
    def test_manufacturing_scrap(self):
        """
            Testing to do a scrap of consumed material.
        """

        # Update demo products
        (self.product_4 | self.product_2).write({
            'tracking': 'lot',
        })

        # Update Bill Of Material to remove product with phantom bom.
        self.bom_3.bom_line_ids.filtered(
            lambda x: x.product_id == self.product_5).unlink()

        # Create Inventory Adjustment For Stick and Stone Tools with lot.
        lot_product_4 = self.env['stock.production.lot'].create({
            'name':
            '0000000000001',
            'product_id':
            self.product_4.id,
        })
        lot_product_2 = self.env['stock.production.lot'].create({
            'name':
            '0000000000002',
            'product_id':
            self.product_2.id,
        })

        stock_inv_product_4 = self.env['stock.inventory'].create({
            'name':
            'Stock Inventory for Stick',
            'filter':
            'product',
            'product_id':
            self.product_4.id,
            'line_ids': [
                (0, 0, {
                    'product_id': self.product_4.id,
                    'product_uom_id': self.product_4.uom_id.id,
                    'product_qty': 8,
                    'prod_lot_id': lot_product_4.id,
                    'location_id': self.ref('stock.stock_location_14')
                }),
            ]
        })

        stock_inv_product_2 = self.env['stock.inventory'].create({
            'name':
            'Stock Inventory for Stone Tools',
            'filter':
            'product',
            'product_id':
            self.product_2.id,
            'line_ids': [(0, 0, {
                'product_id': self.product_2.id,
                'product_uom_id': self.product_2.uom_id.id,
                'product_qty': 12,
                'prod_lot_id': lot_product_2.id,
                'location_id': self.ref('stock.stock_location_14')
            })]
        })
        (stock_inv_product_4 | stock_inv_product_2).action_start()
        stock_inv_product_2.action_validate()
        stock_inv_product_4.action_validate()

        #Create Manufacturing order.
        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 12
        production_form.product_uom_id = self.product_6.uom_id
        production_3 = production_form.save()
        production_3.action_confirm()
        production_3.action_assign()

        # Check Manufacturing order's availability.
        self.assertEqual(
            production_3.reservation_state, 'assigned',
            "Production order's availability should be Available.")

        location_id = production_3.move_raw_ids.filtered(
            lambda x: x.state not in ('done', 'cancel')
        ) and production_3.location_src_id.id or production_3.location_dest_id.id,

        # Scrap Product Wood without lot to check assert raise ?.
        scrap_id = self.env['stock.scrap'].with_context(
            active_model='mrp.production', active_id=production_3.id).create({
                'product_id':
                self.product_2.id,
                'scrap_qty':
                1.0,
                'product_uom_id':
                self.product_2.uom_id.id,
                'location_id':
                location_id,
                'production_id':
                production_3.id
            })
        with self.assertRaises(except_orm):
            scrap_id.do_scrap()

        # Scrap Product Wood with lot.
        self.env['stock.scrap'].with_context(active_model='mrp.production',
                                             active_id=production_3.id).create(
                                                 {
                                                     'product_id':
                                                     self.product_2.id,
                                                     'scrap_qty':
                                                     1.0,
                                                     'product_uom_id':
                                                     self.product_2.uom_id.id,
                                                     'location_id':
                                                     location_id,
                                                     'lot_id':
                                                     lot_product_2.id,
                                                     'production_id':
                                                     production_3.id
                                                 })
Ejemplo n.º 33
0
    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_form = Form(self.env['mrp.production'])
        mo_form.product_id = finshed_product
        mo_form.bom_id = bom
        mo_form.product_uom_id = finshed_product.uom_id
        mo_form.product_qty = 1.0
        mo = mo_form.save()
        self.assertEqual(len(mo), 1, 'MO should have been created')
        mo.action_confirm()
        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.qty_producing = 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')
Ejemplo n.º 34
0
    def test_basic(self):
        """ Basic order test: no routing (thus no workorders), no lot """
        self.product_1.type = 'product'
        self.product_2.type = 'product'
        inventory = self.env['stock.inventory'].create({
            'name': 'Initial inventory',
            'filter': 'partial',
            'line_ids': [(0, 0, {
                'product_id': self.product_1.id,
                'product_uom_id': self.product_1.uom_id.id,
                'product_qty': 500,
                'location_id': self.warehouse_1.lot_stock_id.id
            }), (0, 0, {
                'product_id': self.product_2.id,
                'product_uom_id': self.product_2.uom_id.id,
                'product_qty': 500,
                'location_id': self.warehouse_1.lot_stock_id.id
            })]
        })
        inventory.action_validate()

        test_date_planned = Dt.now() - timedelta(days=1)
        test_quantity = 2.0
        self.bom_1.routing_id = False
        man_order_form = Form(self.env['mrp.production'].sudo(self.user_mrp_user))
        man_order_form.product_id = self.product_4
        man_order_form.bom_id = self.bom_1
        man_order_form.product_uom_id = self.product_4.uom_id
        man_order_form.product_qty = test_quantity
        man_order_form.date_planned_start = test_date_planned
        man_order_form.location_src_id = self.location_1
        man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id
        man_order = man_order_form.save()

        self.assertEqual(man_order.state, 'draft', "Production order should be in draft state.")
        man_order.action_confirm()
        self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.")

        # check production move
        production_move = man_order.move_finished_ids
        self.assertEqual(production_move.date, test_date_planned)
        self.assertEqual(production_move.product_id, self.product_4)
        self.assertEqual(production_move.product_uom, man_order.product_uom_id)
        self.assertEqual(production_move.product_qty, man_order.product_qty)
        self.assertEqual(production_move.location_id, self.product_4.property_stock_production)
        self.assertEqual(production_move.location_dest_id, man_order.location_dest_id)

        # check consumption moves
        for move in man_order.move_raw_ids:
            self.assertEqual(move.date, test_date_planned)
        first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2)
        self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2)
        first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1)
        self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4)

        # waste some material, create a scrap
        # scrap = self.env['stock.scrap'].with_context(
        #     active_model='mrp.production', active_id=man_order.id
        # ).create({})
        # scrap = self.env['stock.scrap'].create({
        #     'production_id': man_order.id,
        #     'product_id': first_move.product_id.id,
        #     'product_uom_id': first_move.product_uom.id,
        #     'scrap_qty': 5.0,
        # })
        # check created scrap


        # procurements = self.env['procurement.order'].search([('move_dest_id', 'in', man_order.move_raw_ids.ids)])
        # print procurements
        # procurements = self.env['procurement.order'].search([('production_id', '=', man_order.id)])
        # print procurements
        # for proc in self.env['procurement.order'].browse(procurements):
        #     date_planned = self.mrp_production_test1.date_planned
        #     if proc.product_id.type not in ('product', 'consu'):
        #         continue
        #     if proc.product_id.id == order_line.product_id.id:
        #         self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond")
        #       # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which
        #       # case it could already be in `running` or `exception` state (not enough stock)
        #         expected_states = ('confirmed', 'running', 'exception')
        #         self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states))

        # Change production quantity
        qty_wizard = self.env['change.production.qty'].create({
            'mo_id': man_order.id,
            'product_qty': 3.0,
        })
        # qty_wizard.change_prod_qty()

        # # I check qty after changed in production order.
        # #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.")
        # move = self.mrp_production_test1.move_finished_ids[0]
        # self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.")

        # # I run scheduler.
        # self.env['procurement.order'].run_scheduler()

        # # The production order is Waiting Goods, will force production which should set consume lines as available
        # self.mrp_production_test1.button_plan()
        # # I check that production order in ready state after forcing production.

        # #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available')

        # produce product
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': man_order.id,
            'active_ids': [man_order.id],
        }))
        produce_form.qty_producing = 1.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()

        # man_order.button_mark_done()
        man_order.button_mark_done()
        self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
Ejemplo n.º 35
0
    def test_landed_cost_on_mrp(self):
        # Initial inventory
        quants = self.env['stock.quant'].with_context(
            inventory_mode=True).create({
                'product_id':
                self.product_component1.id,
                'inventory_quantity':
                500,
                'location_id':
                self.warehouse_1.lot_stock_id.id,
            })
        quants |= self.env['stock.quant'].with_context(
            inventory_mode=True).create({
                'product_id':
                self.product_component2.id,
                'inventory_quantity':
                500,
                'location_id':
                self.warehouse_1.lot_stock_id.id,
            })
        quants.action_apply_inventory()

        man_order_form = Form(self.env['mrp.production'].with_user(
            self.allow_user))
        man_order_form.product_id = self.product_refrigerator
        man_order_form.bom_id = self.bom_refri
        man_order_form.product_qty = 2.0
        man_order = man_order_form.save()

        self.assertEqual(man_order.state, 'draft',
                         "Production order should be in draft state.")
        man_order.action_confirm()
        self.assertEqual(man_order.state, 'confirmed',
                         "Production order should be in confirmed state.")

        # check production move
        production_move = man_order.move_finished_ids
        self.assertEqual(production_move.product_id, self.product_refrigerator)

        first_move = man_order.move_raw_ids.filtered(
            lambda move: move.product_id == self.product_component1)
        self.assertEqual(first_move.product_qty, 6.0)
        first_move = man_order.move_raw_ids.filtered(
            lambda move: move.product_id == self.product_component2)
        self.assertEqual(first_move.product_qty, 2.0)

        # produce product
        mo_form = Form(man_order.with_user(self.allow_user))
        mo_form.qty_producing = 2
        man_order = mo_form.save()
        man_order.button_mark_done()

        landed_cost = Form(self.env['stock.landed.cost'].with_user(
            self.allow_user)).save()
        landed_cost.target_model = 'manufacturing'

        # Check domain of the views
        self.assertTrue(man_order in self.env['mrp.production'].search([(
            'move_finished_ids.stock_valuation_layer_ids', '!=',
            False), ('company_id', '=', landed_cost.company_id.id)]))

        landed_cost.mrp_production_ids = [(6, 0, [man_order.id])]
        landed_cost.cost_lines = [(0, 0, {
            'product_id': self.landed_cost.id,
            'price_unit': 5.0,
            'split_method': 'equal'
        })]
        landed_cost.button_validate()

        self.assertEqual(landed_cost.state, 'done')
        self.assertTrue(landed_cost.account_move_id)
        # Link to one layer of product_refrigerator
        self.assertEqual(len(landed_cost.stock_valuation_layer_ids), 1)
        self.assertEqual(landed_cost.stock_valuation_layer_ids.product_id,
                         self.product_refrigerator)
        self.assertEqual(landed_cost.stock_valuation_layer_ids.value, 5.0)
Ejemplo n.º 36
0
    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
        Lot = self.env['stock.lot']
        # create inventory
        quants = self.env['stock.quant'].create({
            'location_id':
            stock_id,
            'product_id':
            consumed_no_track.id,
            'inventory_quantity':
            3
        })
        quants |= self.env['stock.quant'].create({
            'location_id':
            stock_id,
            'product_id':
            consumed_lot.id,
            'inventory_quantity':
            3,
            'lot_id':
            Lot.create({
                'name': 'L1',
                'product_id': consumed_lot.id,
                'company_id': self.env.company.id
            }).id
        })
        quants |= self.env['stock.quant'].create({
            'location_id':
            stock_id,
            'product_id':
            consumed_serial.id,
            'inventory_quantity':
            1,
            'lot_id':
            Lot.create({
                'name': 'S1',
                'product_id': consumed_serial.id,
                'company_id': self.env.company.id
            }).id
        })
        quants |= self.env['stock.quant'].create({
            'location_id':
            stock_id,
            'product_id':
            consumed_serial.id,
            'inventory_quantity':
            1,
            'lot_id':
            Lot.create({
                'name': 'S2',
                'product_id': consumed_serial.id,
                'company_id': self.env.company.id
            }).id
        })
        quants |= self.env['stock.quant'].create({
            'location_id':
            stock_id,
            'product_id':
            consumed_serial.id,
            'inventory_quantity':
            1,
            'lot_id':
            Lot.create({
                'name': 'S3',
                'product_id': consumed_serial.id,
                'company_id': self.env.company.id
            }).id
        })
        quants.action_apply_inventory()

        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_form = Form(self.env['mrp.production'])
            mo_form.product_id = finished_product
            mo_form.bom_id = bom
            mo_form.product_uom_id = self.env.ref('uom.product_uom_unit')
            mo_form.product_qty = 1
            mo = mo_form.save()
            mo.action_confirm()
            mo.action_assign()

            # Start MO production
            mo_form = Form(mo)
            mo_form.qty_producing = 1
            if finished_product.tracking != 'none':
                mo_form.lot_producing_id = self.env['stock.lot'].create({
                    'name':
                    'Serial or Lot finished',
                    'product_id':
                    finished_product.id,
                    'company_id':
                    self.env.company.id
                })
            mo = mo_form.save()

            details_operation_form = Form(
                mo.move_raw_ids[1],
                view=self.env.ref('stock.view_stock_move_operations'))
            with details_operation_form.move_line_ids.edit(0) as ml:
                ml.qty_done = 1
            details_operation_form.save()
            details_operation_form = Form(
                mo.move_raw_ids[2],
                view=self.env.ref('stock.view_stock_move_operations'))
            with details_operation_form.move_line_ids.edit(0) as ml:
                ml.qty_done = 1
            details_operation_form.save()

            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.00 Units",
                    '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))
Ejemplo n.º 37
0
    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,
            'company_id':
            self.env.company.id,
        })
        lot_1 = self.env['stock.production.lot'].create({
            'name':
            'lot_consumed_1',
            'product_id':
            p1.id,
            'company_id':
            self.env.company.id,
        })
        lot_2 = self.env['stock.production.lot'].create({
            'name':
            'lot_consumed_2',
            'product_id':
            p2.id,
            'company_id':
            self.env.company.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()

        # FIXME sle: behavior change
        mo_form = Form(mo)
        mo_form.qty_producing = 5.0
        mo_form.lot_producing_id = lot_final
        mo = mo_form.save()
        details_operation_form = Form(
            mo.move_raw_ids[0],
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.edit(0) as ml:
            ml.qty_done = 5
        details_operation_form.save()
        details_operation_form = Form(
            mo.move_raw_ids[1],
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.edit(0) as ml:
            ml.qty_done = 20
        details_operation_form.save()

        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
        # ---------------------------------------------------

        x = Form(self.env['mrp.unbuild'])
        with self.assertRaises(AssertionError):
            x.product_id = p_final
            x.bom_id = bom
            x.product_qty = 3
            x.save()

        with self.assertRaises(AssertionError):
            x.product_id = p_final
            x.bom_id = bom
            x.product_qty = 3
            x.save()

        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')

        with self.assertRaises(AssertionError):
            x.product_id = p_final
            x.bom_id = bom
            x.mo_id = mo
            x.product_qty = 3
            x.save()

        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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 3
        x.lot_id = lot_final
        x.save().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 92 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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 2
        x.lot_id = lot_final
        x.save().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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 5
        x.lot_id = lot_final
        x.save().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')
Ejemplo n.º 38
0
    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_form = Form(self.env['mrp.production'])
        mo_custom_product_form.product_id = product_A
        mo_custom_product_form.bom_id = bom_a
        mo_custom_product_form.product_qty = 10.0
        mo_custom_product_form.product_uom_id = self.env.ref("uom.product_uom_unit")
        mo_custom_product = mo_custom_product_form.save()

        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_confirm()
        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.qty_producing = 10.00
        produce_form.final_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.workorder_line_ids), 2)
        product_consume.workorder_line_ids.filtered(lambda x: x.product_id == product_C).write({'qty_done': 3000})
        product_consume.workorder_line_ids.filtered(lambda x: x.product_id == product_B).write({'qty_done': 20})
        product_consume.do_produce()
        mo_custom_product.post_inventory()
Ejemplo n.º 39
0
    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,
            'company_id':
            self.env.company.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.')

        # FIXME sle: behavior change
        mo_form = Form(mo)
        mo_form.qty_producing = 5.0
        mo = mo_form.save()
        details_operation_form = Form(
            mo.move_raw_ids[1],
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.edit(0) as ml:
            ml.lot_id = lot
            ml.qty_done = 20
        details_operation_form.save()

        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
        # ---------------------------------------------------

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 3
        unbuild_order = x.save()

        # 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 92 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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 2
        x.save().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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 5
        x.save().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')
Ejemplo n.º 40
0
    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_form = Form(self.env['mrp.production'])
        mo_custom_laptop_form.product_id = custom_laptop
        mo_custom_laptop_form.bom_id = bom_custom_laptop
        mo_custom_laptop_form.product_qty = 10.0
        mo_custom_laptop_form.product_uom_id = self.env.ref("uom.product_uom_unit")
        mo_custom_laptop = mo_custom_laptop_form.save()

        mo_custom_laptop.action_confirm()
        # Assign component to production order.
        mo_custom_laptop.action_assign()

        # Check production order status of availablity

        self.assertEqual(mo_custom_laptop.reservation_state, 'confirmed')

        # --------------------------------------------------
        # 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.reservation_state, '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.qty_producing = 6.00
        laptop_lot_001 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
        product_form.final_lot_id = laptop_lot_001
        product_consume = product_form.save()
        product_consume.workorder_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.qty_producing = 4.00
        laptop_lot_002 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
        produce_form.final_lot_id = laptop_lot_002
        product_consume = produce_form.save()
        self.assertEquals(len(product_consume.workorder_line_ids), 2)
        product_consume.workorder_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()
Ejemplo n.º 41
0
    def test_00_workorder_process(self):
        """ Testing consume quants and produced quants with workorder """

        dining_table = self.env.ref("mrp.product_product_computer_desk")
        product_table_sheet = self.env.ref('mrp.product_product_computer_desk_head')
        product_table_leg = self.env.ref('mrp.product_product_computer_desk_leg')
        product_bolt = self.env.ref('mrp.product_product_computer_desk_bolt')
        product_screw = self.env.ref('mrp.product_product_computer_desk_screw')
        self.env['stock.move'].search([('product_id', 'in', [product_bolt.id, product_screw.id])])._do_unreserve()
        (product_bolt + product_screw).write({'type': 'product'})

        self.env.ref("mrp.mrp_bom_desk").consumption = 'flexible'
        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = dining_table
        production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
        production_table_form.product_qty = 1.0
        production_table_form.product_uom_id = dining_table.uom_id
        production_table = production_table_form.save()
        production_table.action_confirm()

        # Set tracking lot on finish and consume products.
        dining_table.tracking = 'lot'
        product_table_sheet.tracking = 'lot'
        product_table_leg.tracking = 'lot'
        product_bolt.tracking = "lot"

        # Initial inventory of product sheet, lags and bolt
        lot_sheet = self.env['stock.production.lot'].create({'product_id': product_table_sheet.id})
        lot_leg = self.env['stock.production.lot'].create({'product_id': product_table_leg.id})
        lot_bolt = self.env['stock.production.lot'].create({'product_id': product_bolt.id})

        # Initialize inventory
        # --------------------
        inventory = self.env['stock.inventory'].create({
            'name': 'Inventory Product Table',
            'filter': 'partial',
            'line_ids': [(0, 0, {
                'product_id': product_table_sheet.id,
                'product_uom_id': product_table_sheet.uom_id.id,
                'product_qty': 20,
                'prod_lot_id': lot_sheet.id,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': product_table_leg.id,
                'product_uom_id': product_table_leg.uom_id.id,
                'product_qty': 20,
                'prod_lot_id': lot_leg.id,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': product_bolt.id,
                'product_uom_id': product_bolt.uom_id.id,
                'product_qty': 20,
                'prod_lot_id': lot_bolt.id,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': product_screw.id,
                'product_uom_id': product_screw.uom_id.id,
                'product_qty': 20,
                'location_id': self.source_location_id
            })]
        })
        inventory.action_validate()

        # Create work order
        production_table.button_plan()
        # Check Work order created or not
        self.assertEqual(len(production_table.workorder_ids), 1)

        # ---------------------------------------------------------
        # Process all workorder and check it state.
        # ----------------------------------------------------------

        workorder = production_table.workorder_ids[0]
        self.assertEqual(workorder.state, 'ready', "workorder state should be ready.")

        # --------------------------------------------------------------
        # Process assembly line
        # ---------------------------------------------------------
        finished_lot =self.env['stock.production.lot'].create({'product_id': production_table.product_id.id})
        workorder.write({'final_lot_id': finished_lot.id})
        workorder.button_start()
        for workorder_line_id in workorder.workorder_line_ids:
            if workorder_line_id.product_id.id == product_bolt.id:
                workorder_line_id.write({'lot_id': lot_bolt.id, 'qty_done': 1})
            if workorder_line_id.product_id.id == product_table_sheet.id:
                workorder_line_id.write({'lot_id': lot_sheet.id, 'qty_done': 1})
            if workorder_line_id.product_id.id == product_table_leg.id:
                workorder_line_id.write({'lot_id': lot_leg.id, 'qty_done': 1})
        self.assertEqual(workorder.state, 'progress')
        workorder.record_production()
        self.assertEqual(workorder.state, 'done')
        move_table_sheet = production_table.move_raw_ids.filtered(lambda x : x.product_id == product_table_sheet)
        self.assertEqual(move_table_sheet.quantity_done, 1)

        # ---------------------------------------------------------------
        # Check consume quants and produce quants after posting inventory
        # ---------------------------------------------------------------
        production_table.button_mark_done()

        self.assertEqual(product_screw.qty_available, 10)
        self.assertEqual(product_bolt.qty_available, 19)
        self.assertEqual(product_table_leg.qty_available, 19)
        self.assertEqual(product_table_sheet.qty_available, 19)
Ejemplo n.º 42
0
    def test_00b_workorder_process(self):
        """ Testing consume quants and produced quants with workorder """
        dining_table = self.env.ref("mrp.product_product_computer_desk")
        product_table_sheet = self.env.ref('mrp.product_product_computer_desk_head')
        product_table_leg = self.env.ref('mrp.product_product_computer_desk_leg')
        product_bolt = self.env.ref('mrp.product_product_computer_desk_bolt')
        self.env['stock.move'].search([('product_id', '=', product_bolt.id)])._do_unreserve()
        product_bolt.type = 'product'

        bom = self.env['mrp.bom'].browse(self.ref("mrp.mrp_bom_desk"))
        bom.routing_id = self.ref('mrp.mrp_routing_1')
        bom.consumption = 'flexible'

        bom.bom_line_ids.filtered(lambda p: p.product_id == product_table_sheet).operation_id = bom.routing_id.operation_ids[0]
        bom.bom_line_ids.filtered(lambda p: p.product_id == product_table_leg).operation_id = bom.routing_id.operation_ids[1]
        bom.bom_line_ids.filtered(lambda p: p.product_id == product_bolt).operation_id = bom.routing_id.operation_ids[2]

        production_table_form = Form(self.env['mrp.production'])
        production_table_form.product_id = dining_table
        production_table_form.bom_id = bom
        production_table_form.product_qty = 2.0
        production_table_form.product_uom_id = dining_table.uom_id
        production_table = production_table_form.save()
        # Set tracking lot on finish and consume products.
        dining_table.tracking = 'lot'
        product_table_sheet.tracking = 'lot'
        product_table_leg.tracking = 'lot'
        product_bolt.tracking = "lot"
        production_table.action_confirm()
        # Initial inventory of product sheet, lags and bolt
        lot_sheet = self.env['stock.production.lot'].create({'product_id': product_table_sheet.id})
        lot_leg = self.env['stock.production.lot'].create({'product_id': product_table_leg.id})
        lot_bolt = self.env['stock.production.lot'].create({'product_id': product_bolt.id})

        # Initialize inventory
        # --------------------
        inventory = self.env['stock.inventory'].create({
            'name': 'Inventory Product Table',
            'filter': 'partial',
            'line_ids': [(0, 0, {
                'product_id': product_table_sheet.id,
                'product_uom_id': product_table_sheet.uom_id.id,
                'product_qty': 20,
                'prod_lot_id': lot_sheet.id,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': product_table_leg.id,
                'product_uom_id': product_table_leg.uom_id.id,
                'product_qty': 20,
                'prod_lot_id': lot_leg.id,
                'location_id': self.source_location_id
            }), (0, 0, {
                'product_id': product_bolt.id,
                'product_uom_id': product_bolt.uom_id.id,
                'product_qty': 20,
                'prod_lot_id': lot_bolt.id,
                'location_id': self.source_location_id
            })]
        })
        inventory.action_validate()

        # Create work order
        production_table.button_plan()
        # Check Work order created or not
        self.assertEqual(len(production_table.workorder_ids), 3)

        # ---------------------------------------------------------
        # Process all workorder and check it state.
        # ----------------------------------------------------------

        workorders = production_table.workorder_ids
        self.assertEqual(workorders[0].state, 'ready', "First workorder state should be ready.")
        self.assertEqual(workorders[1].state, 'pending')
        self.assertEqual(workorders[2].state, 'pending')

        # --------------------------------------------------------------
        # Process cutting operation...
        # ---------------------------------------------------------
        finished_lot = self.env['stock.production.lot'].create({'product_id': production_table.product_id.id})
        workorders[0].write({'final_lot_id': finished_lot.id, 'qty_producing': 1.0})
        workorders[0].button_start()
        workorders[0].workorder_line_ids[0].write({'lot_id': lot_sheet.id, 'qty_done': 1})
        self.assertEqual(workorders[0].state, 'progress')
        workorders[0].record_production()

        move_table_sheet = production_table.move_raw_ids.filtered(lambda p: p.product_id == product_table_sheet)
        self.assertEqual(move_table_sheet.quantity_done, 1)

        # --------------------------------------------------------------
        # Process drilling operation ...
        # ---------------------------------------------------------
        workorders[1].button_start()
        workorders[1].qty_producing = 1.0
        workorders[1].workorder_line_ids[0].write({'lot_id': lot_leg.id, 'qty_done': 4})
        workorders[1].record_production()
        move_leg = production_table.move_raw_ids.filtered(lambda p: p.product_id == product_table_leg)
        #self.assertEqual(workorders[1].state, 'done')
        self.assertEqual(move_leg.quantity_done, 4)

        # --------------------------------------------------------------
        # Process fitting operation ...
        # ---------------------------------------------------------
        workorders[2].button_start()
        workorders[2].qty_producing = 1.0
        move_lot = workorders[2].workorder_line_ids[0]
        move_lot.write({'lot_id': lot_bolt.id, 'qty_done': 4})
        move_table_bolt = production_table.move_raw_ids.filtered(lambda p: p.product_id.id == product_bolt.id)
        workorders[2].record_production()
        self.assertEqual(move_table_bolt.quantity_done, 4)

        # Change the quantity of the production order to 1
        wiz = self.env['change.production.qty'].create({'mo_id': production_table.id ,
                                                        'product_qty': 1.0})
        wiz.change_prod_qty()
        # ---------------------------------------------------------------
        # Check consume quants and produce quants after posting inventory
        # ---------------------------------------------------------------
        production_table.post_inventory()
        self.assertEqual(sum(move_table_sheet.mapped('quantity_done')), 1, "Wrong quantity of consumed product %s" % move_table_sheet.product_id.name)
        self.assertEqual(sum(move_leg.mapped('quantity_done')), 4, "Wrong quantity of consumed product %s" % move_leg.product_id.name)
        self.assertEqual(sum(move_table_bolt.mapped('quantity_done')), 4, "Wrong quantity of consumed product %s" % move_table_bolt.product_id.name)
Ejemplo n.º 43
0
    def test_procurement_3(self):
        warehouse = self.env['stock.warehouse'].search([], limit=1)
        warehouse.write({'reception_steps': 'three_steps'})
        self.env['stock.location']._parent_store_compute()
        warehouse.reception_route_id.rule_ids.filtered(
            lambda p: p.location_src_id == warehouse.wh_input_stock_loc_id and
            p.location_id == warehouse.wh_qc_stock_loc_id).write(
                {'procure_method': 'make_to_stock'})

        finished_product = self.env['product.product'].create({
            'name':
            'Finished Product',
            'type':
            'product',
        })
        component = self.env['product.product'].create({
            'name':
            'Component',
            'type':
            'product',
            'route_ids': [(4, warehouse.mto_pull_id.route_id.id)]
        })
        self.env['stock.quant']._update_available_quantity(
            component, warehouse.wh_input_stock_loc_id, 100)
        bom = self.env['mrp.bom'].create({
            'product_id':
            finished_product.id,
            'product_tmpl_id':
            finished_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': component.id,
                'product_qty': 1.0
            })]
        })
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = finished_product
        mo_form.bom_id = bom
        mo_form.product_qty = 5
        mo_form.product_uom_id = finished_product.uom_id
        mo_form.location_src_id = warehouse.lot_stock_id
        mo = mo_form.save()
        mo.action_confirm()
        pickings = self.env['stock.picking'].search([('product_id', '=',
                                                      component.id)])
        self.assertEqual(len(pickings), 2.0)
        picking_input_to_qc = pickings.filtered(
            lambda p: p.location_id == warehouse.wh_input_stock_loc_id)
        picking_qc_to_stock = pickings - picking_input_to_qc
        self.assertTrue(picking_input_to_qc)
        self.assertTrue(picking_qc_to_stock)
        picking_input_to_qc.action_assign()
        self.assertEqual(picking_input_to_qc.state, 'assigned')
        picking_input_to_qc.move_line_ids.write({'qty_done': 5.0})
        picking_input_to_qc.action_done()
        picking_qc_to_stock.action_assign()
        self.assertEqual(picking_qc_to_stock.state, 'assigned')
        picking_qc_to_stock.move_line_ids.write({'qty_done': 3.0})
        self.env['stock.backorder.confirmation'].create({
            'pick_ids': [(4, picking_qc_to_stock.id)]
        }).process_cancel_backorder()
        self.assertEqual(picking_qc_to_stock.state, 'done')
        mo.action_assign()
        self.assertEqual(mo.move_raw_ids.reserved_availability, 3.0)
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.qty_producing = 3.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()
        self.assertEqual(mo.move_raw_ids.quantity_done, 3.0)
        picking_qc_to_stock.move_line_ids.qty_done = 5.0
        self.assertEqual(mo.move_raw_ids.reserved_availability, 5.0)
        self.assertEqual(mo.move_raw_ids.quantity_done, 3.0)
Ejemplo n.º 44
0
    def test_manufacturing_scrap(self):
        """
            Testing to do a scrap of consumed material.
        """

        # Update demo products
        (self.product_4 | self.product_2).write({
            'tracking': 'lot',
        })

        # Update Bill Of Material to remove product with phantom bom.
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()

        # Create Inventory Adjustment For Stick and Stone Tools with lot.
        lot_product_4 = self.env['stock.production.lot'].create({
            'name': '0000000000001',
            'product_id': self.product_4.id,
        })
        lot_product_2 = self.env['stock.production.lot'].create({
            'name': '0000000000002',
            'product_id': self.product_2.id,
        })

        stock_inv_product_4 = self.env['stock.inventory'].create({
            'name': 'Stock Inventory for Stick',
            'filter': 'product',
            'product_id': self.product_4.id,
            'line_ids': [
                (0, 0, {'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': 8, 'prod_lot_id': lot_product_4.id, 'location_id': self.ref('stock.stock_location_14')}),
            ]})

        stock_inv_product_2 = self.env['stock.inventory'].create({
            'name': 'Stock Inventory for Stone Tools',
            'filter': 'product',
            'product_id': self.product_2.id,
            'line_ids': [
                (0, 0, {'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 12, 'prod_lot_id': lot_product_2.id, 'location_id': self.ref('stock.stock_location_14')})
            ]})
        (stock_inv_product_4 | stock_inv_product_2).action_start()
        stock_inv_product_2.action_validate()
        stock_inv_product_4.action_validate()

        #Create Manufacturing order.
        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 12
        production_form.product_uom_id = self.product_6.uom_id
        production_3 = production_form.save()
        production_3.action_confirm()
        production_3.action_assign()

        # Check Manufacturing order's availability.
        self.assertEqual(production_3.reservation_state, 'assigned', "Production order's availability should be Available.")

        location_id = production_3.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel')) and production_3.location_src_id.id or production_3.location_dest_id.id,

        # Scrap Product Wood without lot to check assert raise ?.
        scrap_id = self.env['stock.scrap'].with_context(active_model='mrp.production', active_id=production_3.id).create({'product_id': self.product_2.id, 'scrap_qty': 1.0, 'product_uom_id': self.product_2.uom_id.id, 'location_id': location_id, 'production_id': production_3.id})
        with self.assertRaises(except_orm):
            scrap_id.do_scrap()

        # Scrap Product Wood with lot.
        self.env['stock.scrap'].with_context(active_model='mrp.production', active_id=production_3.id).create({'product_id': self.product_2.id, 'scrap_qty': 1.0, 'product_uom_id': self.product_2.uom_id.id, 'location_id': location_id, 'lot_id': lot_product_2.id, 'production_id': production_3.id})
Ejemplo n.º 45
0
    def test_tracking_on_byproducts(self):
        product_final = self.env['product.product'].create({
            'name':
            'Finished Product',
            'type':
            'product',
            'tracking':
            'serial',
        })
        product_1 = self.env['product.product'].create({
            'name': 'Raw 1',
            'type': 'product',
            'tracking': 'serial',
        })
        product_2 = self.env['product.product'].create({
            'name': 'Raw 2',
            'type': 'product',
            'tracking': 'serial',
        })
        byproduct_1 = self.env['product.product'].create({
            'name': 'Byproduct 1',
            'type': 'product',
            'tracking': 'serial',
        })
        byproduct_2 = self.env['product.product'].create({
            'name': 'Byproduct 2',
            'type': 'product',
            'tracking': 'serial',
        })
        bom_1 = self.env['mrp.bom'].create({
            'product_id':
            product_final.id,
            'product_tmpl_id':
            product_final.product_tmpl_id.id,
            'product_uom_id':
            self.uom_unit.id,
            'product_qty':
            1.0,
            'consumption':
            'flexible',
            'type':
            'normal',
            'bom_line_ids': [(0, 0, {
                'product_id': product_1.id,
                'product_qty': 1
            }), (0, 0, {
                'product_id': product_2.id,
                'product_qty': 1
            })],
            'byproduct_ids': [(0, 0, {
                'product_id': byproduct_1.id,
                'product_qty': 1,
                'product_uom_id': byproduct_1.uom_id.id
            }),
                              (0, 0, {
                                  'product_id': byproduct_2.id,
                                  'product_qty': 1,
                                  'product_uom_id': byproduct_2.uom_id.id
                              })]
        })
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = product_final
        mo_form.bom_id = bom_1
        mo_form.product_qty = 2
        mo = mo_form.save()
        mo.action_confirm()

        mo_form = Form(mo)
        mo_form.lot_producing_id = self.env['stock.lot'].create({
            'product_id':
            product_final.id,
            'name':
            'Final_lot_1',
            'company_id':
            self.env.company.id,
        })
        mo = mo_form.save()

        details_operation_form = Form(
            mo.move_raw_ids[0],
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                product_1.id,
                'name':
                'Raw_1_lot_1',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()
        details_operation_form = Form(
            mo.move_raw_ids[1],
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                product_2.id,
                'name':
                'Raw_2_lot_1',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()
        details_operation_form = Form(
            mo.move_finished_ids.filtered(
                lambda m: m.product_id == byproduct_1),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                byproduct_1.id,
                'name':
                'Byproduct_1_lot_1',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()
        details_operation_form = Form(
            mo.move_finished_ids.filtered(
                lambda m: m.product_id == byproduct_2),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                byproduct_2.id,
                'name':
                'Byproduct_2_lot_1',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()

        action = mo.button_mark_done()
        backorder = Form(self.env['mrp.production.backorder'].with_context(
            **action['context']))
        backorder.save().action_backorder()
        mo_backorder = mo.procurement_group_id.mrp_production_ids[-1]
        mo_form = Form(mo_backorder)
        mo_form.lot_producing_id = self.env['stock.lot'].create({
            'product_id':
            product_final.id,
            'name':
            'Final_lot_2',
            'company_id':
            self.env.company.id,
        })
        mo_form.qty_producing = 1
        mo_backorder = mo_form.save()

        details_operation_form = Form(
            mo_backorder.move_raw_ids.filtered(
                lambda m: m.product_id == product_1),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                product_1.id,
                'name':
                'Raw_1_lot_2',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()
        details_operation_form = Form(
            mo_backorder.move_raw_ids.filtered(
                lambda m: m.product_id == product_2),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                product_2.id,
                'name':
                'Raw_2_lot_2',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()
        details_operation_form = Form(
            mo_backorder.move_finished_ids.filtered(
                lambda m: m.product_id == byproduct_1),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                byproduct_1.id,
                'name':
                'Byproduct_1_lot_2',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()
        details_operation_form = Form(
            mo_backorder.move_finished_ids.filtered(
                lambda m: m.product_id == byproduct_2),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.new() as ml:
            ml.lot_id = self.env['stock.lot'].create({
                'product_id':
                byproduct_2.id,
                'name':
                'Byproduct_2_lot_2',
                'company_id':
                self.env.company.id,
            })
            ml.qty_done = 1
        details_operation_form.save()

        mo_backorder.button_mark_done()

        # self.assertEqual(len(mo.move_raw_ids.mapped('move_line_ids')), 4)
        # self.assertEqual(len(mo.move_finished_ids.mapped('move_line_ids')), 6)

        mo = mo | mo_backorder
        raw_move_lines = mo.move_raw_ids.mapped('move_line_ids')
        raw_line_raw_1_lot_1 = raw_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Raw_1_lot_1')
        self.assertEqual(
            set(raw_line_raw_1_lot_1.produce_line_ids.lot_id.mapped('name')),
            set(['Final_lot_1', 'Byproduct_1_lot_1', 'Byproduct_2_lot_1']))
        raw_line_raw_2_lot_1 = raw_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Raw_2_lot_1')
        self.assertEqual(
            set(raw_line_raw_2_lot_1.produce_line_ids.lot_id.mapped('name')),
            set(['Final_lot_1', 'Byproduct_1_lot_1', 'Byproduct_2_lot_1']))

        finished_move_lines = mo.move_finished_ids.mapped('move_line_ids')
        finished_move_line_lot_1 = finished_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Final_lot_1')
        self.assertEqual(
            finished_move_line_lot_1.consume_line_ids.filtered(
                lambda l: l.qty_done),
            raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
        finished_move_line_lot_2 = finished_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Final_lot_2')
        raw_line_raw_1_lot_2 = raw_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Raw_1_lot_2')
        raw_line_raw_2_lot_2 = raw_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Raw_2_lot_2')
        self.assertEqual(finished_move_line_lot_2.consume_line_ids,
                         raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)

        byproduct_move_line_1_lot_1 = finished_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Byproduct_1_lot_1')
        self.assertEqual(
            byproduct_move_line_1_lot_1.consume_line_ids.filtered(
                lambda l: l.qty_done),
            raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
        byproduct_move_line_1_lot_2 = finished_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Byproduct_1_lot_2')
        self.assertEqual(byproduct_move_line_1_lot_2.consume_line_ids,
                         raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)

        byproduct_move_line_2_lot_1 = finished_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Byproduct_2_lot_1')
        self.assertEqual(
            byproduct_move_line_2_lot_1.consume_line_ids.filtered(
                lambda l: l.qty_done),
            raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
        byproduct_move_line_2_lot_2 = finished_move_lines.filtered(
            lambda ml: ml.lot_id.name == 'Byproduct_2_lot_2')
        self.assertEqual(byproduct_move_line_2_lot_2.consume_line_ids,
                         raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)
Ejemplo n.º 46
0
    def test_explode_from_order(self):
        #
        # bom3 produces 2 Dozen of Doors (p6), aka 24
        # To produce 24 Units of Doors (p6)
        # - 2 Units of Tools (p5) -> need 4
        # - 8 Dozen of Sticks (p4) -> need 16
        # - 12 Units of Wood (p2) -> need 24
        # bom2 produces 1 Unit of Sticks (p4)
        # To produce 1 Unit of Sticks (p4)
        # - 2 Dozen of Sticks (p4) -> need 8
        # - 3 Dozen of Stones (p3) -> need 12

        # Update capacity, start time, stop time, and time efficiency.
        # ------------------------------------------------------------
        self.workcenter_1.write({
            'capacity': 1,
            'time_start': 0,
            'time_stop': 0,
            'time_efficiency': 100
        })

        # Set manual time cycle 20 and 10.
        # --------------------------------
        self.operation_1.write({'time_cycle_manual': 20})
        (self.operation_2 | self.operation_3).write({'time_cycle_manual': 10})

        man_order_form = Form(self.env['mrp.production'])
        man_order_form.product_id = self.product_6
        man_order_form.bom_id = self.bom_3
        man_order_form.product_qty = 48
        man_order_form.product_uom_id = self.product_6.uom_id
        man_order = man_order_form.save()
        # reset quantities
        self.product_1.type = "product"
        self.env['stock.change.product.qty'].create({
            'product_id':
            self.product_1.id,
            'new_quantity':
            0.0,
            'location_id':
            self.warehouse_1.lot_stock_id.id,
        }).change_product_qty()

        (self.product_2 | self.product_4).write({
            'tracking': 'none',
        })
        # assign consume material
        man_order.action_confirm()
        man_order.action_assign()
        self.assertEqual(man_order.reservation_state, 'confirmed',
                         "Production order should be in waiting state.")

        # check consume materials of manufacturing order
        self.assertEqual(len(man_order.move_raw_ids), 4,
                         "Consume material lines are not generated proper.")
        product_2_consume_moves = man_order.move_raw_ids.filtered(
            lambda x: x.product_id == self.product_2)
        product_3_consume_moves = man_order.move_raw_ids.filtered(
            lambda x: x.product_id == self.product_3)
        product_4_consume_moves = man_order.move_raw_ids.filtered(
            lambda x: x.product_id == self.product_4)
        product_5_consume_moves = man_order.move_raw_ids.filtered(
            lambda x: x.product_id == self.product_5)
        consume_qty_2 = product_2_consume_moves.product_uom_qty
        self.assertEqual(
            consume_qty_2, 24.0,
            "Consume material quantity of Wood should be 24 instead of %s" %
            str(consume_qty_2))
        consume_qty_3 = product_3_consume_moves.product_uom_qty
        self.assertEqual(
            consume_qty_3, 12.0,
            "Consume material quantity of Stone should be 12 instead of %s" %
            str(consume_qty_3))
        self.assertEqual(len(product_4_consume_moves), 2,
                         "Consume move are not generated proper.")
        for consume_moves in product_4_consume_moves:
            consume_qty_4 = consume_moves.product_uom_qty
            self.assertIn(
                consume_qty_4, [8.0, 16.0],
                "Consume material quantity of Stick should be 8 or 16 instead of %s"
                % str(consume_qty_4))
        self.assertFalse(product_5_consume_moves,
                         "Move should not create for phantom bom")

        # create required lots
        lot_product_2 = self.env['stock.production.lot'].create(
            {'product_id': self.product_2.id})
        lot_product_4 = self.env['stock.production.lot'].create(
            {'product_id': self.product_4.id})

        # refuel stock
        inventory = self.env['stock.inventory'].create({
            'name':
            'Inventory For Product C',
            'filter':
            'partial',
            'line_ids': [(0, 0, {
                'product_id': self.product_2.id,
                'product_uom_id': self.product_2.uom_id.id,
                'product_qty': 30,
                'prod_lot_id': lot_product_2.id,
                'location_id': self.ref('stock.stock_location_14')
            }),
                         (0, 0, {
                             'product_id': self.product_3.id,
                             'product_uom_id': self.product_3.uom_id.id,
                             'product_qty': 60,
                             'location_id': self.ref('stock.stock_location_14')
                         }),
                         (0, 0, {
                             'product_id': self.product_4.id,
                             'product_uom_id': self.product_4.uom_id.id,
                             'product_qty': 60,
                             'prod_lot_id': lot_product_4.id,
                             'location_id': self.ref('stock.stock_location_14')
                         })]
        })
        inventory.action_start()
        inventory.action_validate()

        # re-assign consume material
        man_order.action_assign()

        # Check production order status after assign.
        self.assertEqual(man_order.reservation_state, 'assigned',
                         "Production order should be in assigned state.")
        # Plan production order.
        man_order.button_plan()

        # check workorders
        # - main bom: Door: 2 operations
        #   operation 1: Cutting
        #   operation 2: Welding, waiting for the previous one
        # - kit bom: Stone Tool: 1 operation
        #   operation 1: Gift Wrapping
        workorders = man_order.workorder_ids
        kit_wo = man_order.workorder_ids.filtered(
            lambda wo: wo.operation_id == self.operation_1)
        door_wo_1 = man_order.workorder_ids.filtered(
            lambda wo: wo.operation_id == self.operation_2)
        door_wo_2 = man_order.workorder_ids.filtered(
            lambda wo: wo.operation_id == self.operation_3)
        for workorder in workorders:
            self.assertEqual(workorder.workcenter_id, self.workcenter_1,
                             "Workcenter does not match.")
        self.assertEqual(kit_wo.state, 'ready',
                         "Workorder should be in ready state.")
        self.assertEqual(door_wo_1.state, 'ready',
                         "Workorder should be in ready state.")
        self.assertEqual(door_wo_2.state, 'pending',
                         "Workorder should be in pending state.")
        self.assertEqual(
            kit_wo.duration_expected, 80,
            "Workorder duration should be 80 instead of %s." %
            str(kit_wo.duration_expected))
        self.assertEqual(
            door_wo_1.duration_expected, 20,
            "Workorder duration should be 20 instead of %s." %
            str(door_wo_1.duration_expected))
        self.assertEqual(
            door_wo_2.duration_expected, 20,
            "Workorder duration should be 20 instead of %s." %
            str(door_wo_2.duration_expected))

        # subbom: kit for stone tools
        kit_wo.button_start()
        finished_lot = self.env['stock.production.lot'].create(
            {'product_id': man_order.product_id.id})
        kit_wo.write({'final_lot_id': finished_lot.id, 'qty_producing': 48})

        kit_wo.record_production()

        self.assertEqual(kit_wo.state, 'done',
                         "Workorder should be in done state.")

        # first operation of main bom
        finished_lot = self.env['stock.production.lot'].create(
            {'product_id': man_order.product_id.id})
        door_wo_1.write({'final_lot_id': finished_lot.id, 'qty_producing': 48})
        door_wo_1.record_production()
        self.assertEqual(door_wo_1.state, 'done',
                         "Workorder should be in done state.")

        # second operation of main bom
        self.assertEqual(door_wo_2.state, 'ready',
                         "Workorder should be in ready state.")
        door_wo_2.record_production()
        self.assertEqual(door_wo_2.state, 'done',
                         "Workorder should be in done state.")
Ejemplo n.º 47
0
    def test_explode_from_order(self):
        #
        # bom3 produces 2 Dozen of Doors (p6), aka 24
        # To produce 24 Units of Doors (p6)
        # - 2 Units of Tools (p5) -> need 4
        # - 8 Dozen of Sticks (p4) -> need 16
        # - 12 Units of Wood (p2) -> need 24
        # bom2 produces 1 Unit of Sticks (p4)
        # To produce 1 Unit of Sticks (p4)
        # - 2 Dozen of Sticks (p4) -> need 8
        # - 3 Dozen of Stones (p3) -> need 12

        # Update capacity, start time, stop time, and time efficiency.
        # ------------------------------------------------------------
        self.workcenter_1.write({'capacity': 1, 'time_start': 0, 'time_stop': 0, 'time_efficiency': 100})

        # Set manual time cycle 20 and 10.
        # --------------------------------
        self.operation_1.write({'time_cycle_manual': 20})
        (self.operation_2 | self.operation_3).write({'time_cycle_manual': 10})

        man_order_form = Form(self.env['mrp.production'])
        man_order_form.product_id = self.product_6
        man_order_form.bom_id = self.bom_3
        man_order_form.product_qty = 48
        man_order_form.product_uom_id = self.product_6.uom_id
        man_order = man_order_form.save()
        # reset quantities
        self.product_1.type = "product"
        self.env['stock.change.product.qty'].create({
            'product_id': self.product_1.id,
            'new_quantity': 0.0,
            'location_id': self.warehouse_1.lot_stock_id.id,
        }).change_product_qty()

        (self.product_2 | self.product_4).write({
            'tracking': 'none',
        })
        # assign consume material
        man_order.action_confirm()
        man_order.action_assign()
        self.assertEqual(man_order.reservation_state, 'confirmed', "Production order should be in waiting state.")

        # check consume materials of manufacturing order
        self.assertEqual(len(man_order.move_raw_ids), 4, "Consume material lines are not generated proper.")
        product_2_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_2)
        product_3_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_3)
        product_4_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_4)
        product_5_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_5)
        consume_qty_2 = product_2_consume_moves.product_uom_qty
        self.assertEqual(consume_qty_2, 24.0, "Consume material quantity of Wood should be 24 instead of %s" % str(consume_qty_2))
        consume_qty_3 = product_3_consume_moves.product_uom_qty
        self.assertEqual(consume_qty_3, 12.0, "Consume material quantity of Stone should be 12 instead of %s" % str(consume_qty_3))
        self.assertEqual(len(product_4_consume_moves), 2, "Consume move are not generated proper.")
        for consume_moves in product_4_consume_moves:
            consume_qty_4 = consume_moves.product_uom_qty
            self.assertIn(consume_qty_4, [8.0, 16.0], "Consume material quantity of Stick should be 8 or 16 instead of %s" % str(consume_qty_4))
        self.assertFalse(product_5_consume_moves, "Move should not create for phantom bom")

        # create required lots
        lot_product_2 = self.env['stock.production.lot'].create({'product_id': self.product_2.id})
        lot_product_4 = self.env['stock.production.lot'].create({'product_id': self.product_4.id})

        # refuel stock
        inventory = self.env['stock.inventory'].create({
            'name': 'Inventory For Product C',
            'filter': 'partial',
            'line_ids': [(0, 0, {
                'product_id': self.product_2.id,
                'product_uom_id': self.product_2.uom_id.id,
                'product_qty': 30,
                'prod_lot_id': lot_product_2.id,
                'location_id': self.ref('stock.stock_location_14')
            }), (0, 0, {
                'product_id': self.product_3.id,
                'product_uom_id': self.product_3.uom_id.id,
                'product_qty': 60,
                'location_id': self.ref('stock.stock_location_14')
            }), (0, 0, {
                'product_id': self.product_4.id,
                'product_uom_id': self.product_4.uom_id.id,
                'product_qty': 60,
                'prod_lot_id': lot_product_4.id,
                'location_id': self.ref('stock.stock_location_14')
            })]
        })
        inventory.action_start()
        inventory.action_validate()

        # re-assign consume material
        man_order.action_assign()

        # Check production order status after assign.
        self.assertEqual(man_order.reservation_state, 'assigned', "Production order should be in assigned state.")
        # Plan production order.
        man_order.button_plan()

        # check workorders
        # - main bom: Door: 2 operations
        #   operation 1: Cutting
        #   operation 2: Welding, waiting for the previous one
        # - kit bom: Stone Tool: 1 operation
        #   operation 1: Gift Wrapping
        workorders = man_order.workorder_ids
        kit_wo = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_1)
        door_wo_1 = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_2)
        door_wo_2 = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_3)
        for workorder in workorders:
            self.assertEqual(workorder.workcenter_id, self.workcenter_1, "Workcenter does not match.")
        self.assertEqual(kit_wo.state, 'ready', "Workorder should be in ready state.")
        self.assertEqual(door_wo_1.state, 'ready', "Workorder should be in ready state.")
        self.assertEqual(door_wo_2.state, 'pending', "Workorder should be in pending state.")
        self.assertEqual(kit_wo.duration_expected, 80, "Workorder duration should be 80 instead of %s." % str(kit_wo.duration_expected))
        self.assertEqual(door_wo_1.duration_expected, 20, "Workorder duration should be 20 instead of %s." % str(door_wo_1.duration_expected))
        self.assertEqual(door_wo_2.duration_expected, 20, "Workorder duration should be 20 instead of %s." % str(door_wo_2.duration_expected))

        # subbom: kit for stone tools
        kit_wo.button_start()
        finished_lot = self.env['stock.production.lot'].create({'product_id': man_order.product_id.id})
        kit_wo.write({
            'final_lot_id': finished_lot.id,
            'qty_producing': 48
        })

        kit_wo.record_production()

        self.assertEqual(kit_wo.state, 'done', "Workorder should be in done state.")

        # first operation of main bom
        finished_lot = self.env['stock.production.lot'].create({'product_id': man_order.product_id.id})
        door_wo_1.write({
            'final_lot_id': finished_lot.id,
            'qty_producing': 48
        })
        door_wo_1.record_production()
        self.assertEqual(door_wo_1.state, 'done', "Workorder should be in done state.")

        # second operation of main bom
        self.assertEqual(door_wo_2.state, 'ready', "Workorder should be in ready state.")
        door_wo_2.record_production()
        self.assertEqual(door_wo_2.state, 'done', "Workorder should be in done state.")
Ejemplo n.º 48
0
    def test_basic(self):
        """ Checks a basic manufacturing order: no routing (thus no workorders), no lot and
        consume strictly what's needed. """
        self.product_1.type = 'product'
        self.product_2.type = 'product'
        inventory = self.env['stock.inventory'].create({
            'name': 'Initial inventory',
            'filter': 'partial',
            'line_ids': [(0, 0, {
                'product_id': self.product_1.id,
                'product_uom_id': self.product_1.uom_id.id,
                'product_qty': 500,
                'location_id': self.warehouse_1.lot_stock_id.id
            }), (0, 0, {
                'product_id': self.product_2.id,
                'product_uom_id': self.product_2.uom_id.id,
                'product_qty': 500,
                'location_id': self.warehouse_1.lot_stock_id.id
            })]
        })
        inventory.action_validate()

        test_date_planned = Dt.now() - timedelta(days=1)
        test_quantity = 2.0
        self.bom_1.routing_id = False
        man_order_form = Form(self.env['mrp.production'].sudo(self.user_mrp_user))
        man_order_form.product_id = self.product_4
        man_order_form.bom_id = self.bom_1
        man_order_form.product_uom_id = self.product_4.uom_id
        man_order_form.product_qty = test_quantity
        man_order_form.date_planned_start = test_date_planned
        man_order_form.location_src_id = self.location_1
        man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id
        man_order = man_order_form.save()

        self.assertEqual(man_order.state, 'draft', "Production order should be in draft state.")
        man_order.action_confirm()
        self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.")

        # check production move
        production_move = man_order.move_finished_ids
        self.assertEqual(production_move.date, test_date_planned)
        self.assertEqual(production_move.product_id, self.product_4)
        self.assertEqual(production_move.product_uom, man_order.product_uom_id)
        self.assertEqual(production_move.product_qty, man_order.product_qty)
        self.assertEqual(production_move.location_id, self.product_4.property_stock_production)
        self.assertEqual(production_move.location_dest_id, man_order.location_dest_id)

        # check consumption moves
        for move in man_order.move_raw_ids:
            self.assertEqual(move.date, test_date_planned)
        first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2)
        self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2)
        first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1)
        self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4)

        # produce product
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': man_order.id,
            'active_ids': [man_order.id],
        }))
        produce_form.qty_producing = 1.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()

        man_order.button_mark_done()
        self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
Ejemplo n.º 49
0
    def test_procurement(self):
        """This test case when create production order check procurement is create"""
        # Update BOM
        self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
        self.bom_1.bom_line_ids.filtered(lambda x: x.product_id == self.product_1).unlink()

        # Update route
        self.warehouse = self.env.ref('stock.warehouse0')
        route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
        route_mto = self.warehouse.mto_pull_id.route_id.id
        self.product_4.write({'route_ids': [(6, 0, [route_manufacture, route_mto])]})

        # Create production order
        # -------------------------
        # Product6 Unit 24
        #    Product4 8 Dozen
        #    Product2 12 Unit
        # -----------------------

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.product_6
        production_form.bom_id = self.bom_3
        production_form.product_qty = 24
        production_form.product_uom_id = self.product_6.uom_id
        production_product_6 = production_form.save()
        production_product_6.action_confirm()
        production_product_6.action_assign()

        # check production state is Confirmed
        self.assertEqual(production_product_6.state, 'confirmed', 'Production order should be for Confirmed state')

        # Check procurement for product 4 created or not.
        # Check it created a purchase order

        move_raw_product4 = production_product_6.move_raw_ids.filtered(lambda x: x.product_id == self.product_4)
        produce_product_4 = self.env['mrp.production'].search([('product_id', '=', self.product_4.id),
                                                               ('move_dest_ids', '=', move_raw_product4[0].id)])
        # produce product
        self.assertEqual(produce_product_4.reservation_state, 'confirmed', "Consume material not available")

        # Create production order
        # -------------------------
        # Product 4  96 Unit
        #    Product2 48 Unit
        # ---------------------
        # Update Inventory
        self.env['stock.quant'].with_context(inventory_mode=True).create({
            'product_id': self.product_2.id,
            'inventory_quantity': 48,
            'location_id': self.warehouse.lot_stock_id.id,
        })
        produce_product_4.action_assign()
        self.assertEqual(produce_product_4.product_qty, 8, "Wrong quantity of finish product.")
        self.assertEqual(produce_product_4.product_uom_id, self.uom_dozen, "Wrong quantity of finish product.")
        self.assertEqual(produce_product_4.reservation_state, 'assigned', "Consume material not available")

        # produce product4
        # ---------------

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': produce_product_4.id,
            'active_ids': [produce_product_4.id],
        }))
        produce_form.qty_producing = produce_product_4.product_qty
        product_produce = produce_form.save()
        product_produce.do_produce()
        produce_product_4.post_inventory()
        # Check procurement and Production state for product 4.
        produce_product_4.button_mark_done()
        self.assertEqual(produce_product_4.state, 'done', 'Production order should be in state done')

        # Produce product 6
        # ------------------

        # Update Inventory
        self.env['stock.quant'].with_context(inventory_mode=True).create({
            'product_id': self.product_2.id,
            'inventory_quantity': 12,
            'location_id': self.warehouse.lot_stock_id.id,
        })
        production_product_6.action_assign()

        # ------------------------------------

        self.assertEqual(production_product_6.reservation_state, 'assigned', "Consume material not available")
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': production_product_6.id,
            'active_ids': [production_product_6.id],
        }))
        produce_form.qty_producing = production_product_6.product_qty
        product_produce = produce_form.save()
        product_produce.do_produce()
        production_product_6.post_inventory()
        # Check procurement and Production state for product 6.
        production_product_6.button_mark_done()
        self.assertEqual(production_product_6.state, 'done', 'Production order should be in state done')
        self.assertEqual(self.product_6.qty_available, 24, 'Wrong quantity available of finished product.')
Ejemplo n.º 50
0
    def test_unbuild_standart(self):
        """ This test creates a MO and then creates 3 unbuild
        orders for the final product. None of 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()
        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()

        mo_form = Form(mo)
        mo_form.qty_producing = 5.0
        mo = mo_form.save()
        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), 0,
            'You should have consumed all the 5 product in stock')

        # ---------------------------------------------------
        #       unbuild
        # ---------------------------------------------------

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 3
        x.save().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), 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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 2
        x.save().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), 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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 5
        x.save().action_unbuild()

        # Check quantity in stock after last 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), 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')
Ejemplo n.º 51
0
    def test_landed_cost_on_mrp(self):
        inventory = self.env['stock.inventory'].create({
            'name':
            'Initial inventory',
            'line_ids': [(0, 0, {
                'product_id': self.product_component1.id,
                'product_uom_id': self.product_component1.uom_id.id,
                'product_qty': 500,
                'location_id': self.warehouse_1.lot_stock_id.id
            }),
                         (0, 0, {
                             'product_id': self.product_component2.id,
                             'product_uom_id':
                             self.product_component2.uom_id.id,
                             'product_qty': 500,
                             'location_id': self.warehouse_1.lot_stock_id.id
                         })]
        })
        inventory.action_start()
        inventory.action_validate()

        man_order_form = Form(self.env['mrp.production'].with_user(
            self.allow_user))
        man_order_form.product_id = self.product_refrigerator
        man_order_form.bom_id = self.bom_refri
        man_order_form.product_qty = 2.0
        man_order = man_order_form.save()

        self.assertEqual(man_order.state, 'draft',
                         "Production order should be in draft state.")
        man_order.action_confirm()
        self.assertEqual(man_order.state, 'confirmed',
                         "Production order should be in confirmed state.")

        # check production move
        production_move = man_order.move_finished_ids
        self.assertEqual(production_move.product_id, self.product_refrigerator)

        first_move = man_order.move_raw_ids.filtered(
            lambda move: move.product_id == self.product_component1)
        self.assertEqual(first_move.product_qty, 6.0)
        first_move = man_order.move_raw_ids.filtered(
            lambda move: move.product_id == self.product_component2)
        self.assertEqual(first_move.product_qty, 2.0)

        # produce product
        produce_form = Form(self.env['mrp.product.produce'].with_user(
            self.allow_user).with_context({
                'active_id': man_order.id,
                'active_ids': [man_order.id],
            }))
        produce_form.qty_producing = 2.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()

        man_order.button_mark_done()

        landed_cost = Form(self.env['stock.landed.cost'].with_user(
            self.allow_user)).save()
        landed_cost.target_model = 'manufacturing'

        self.assertTrue(
            man_order.id in landed_cost.allowed_mrp_production_ids.ids)
        landed_cost.mrp_production_ids = [(6, 0, [man_order.id])]
        landed_cost.cost_lines = [(0, 0, {
            'product_id': self.landed_cost.id,
            'price_unit': 5.0,
            'split_method': 'equal'
        })]

        landed_cost.button_validate()

        self.assertEqual(landed_cost.state, 'done')
        self.assertTrue(landed_cost.account_move_id)
        # Link to one layer of product_refrigerator
        self.assertEqual(len(landed_cost.stock_valuation_layer_ids), 1)
        self.assertEqual(landed_cost.stock_valuation_layer_ids.product_id,
                         self.product_refrigerator)
        self.assertEqual(landed_cost.stock_valuation_layer_ids.value, 5.0)
Ejemplo n.º 52
0
    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,
            'company_id':
            self.env.company.id,
        })
        lot_2 = self.env['stock.production.lot'].create({
            'name':
            'lot_2',
            'product_id':
            p2.id,
            'company_id':
            self.env.company.id,
        })
        lot_3 = self.env['stock.production.lot'].create({
            'name':
            'lot_3',
            'product_id':
            p2.id,
            'company_id':
            self.env.company.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()

        mo_form = Form(mo)
        mo_form.qty_producing = 5.0
        mo = mo_form.save()
        details_operation_form = Form(
            mo.move_raw_ids.filtered(lambda ml: ml.product_id == p2),
            view=self.env.ref('stock.view_stock_move_operations'))
        with details_operation_form.move_line_ids.edit(0) as ml:
            ml.qty_done = ml.product_uom_qty
        with details_operation_form.move_line_ids.edit(1) as ml:
            ml.qty_done = ml.product_uom_qty
        with details_operation_form.move_line_ids.edit(2) as ml:
            ml.qty_done = ml.product_uom_qty
        details_operation_form.save()

        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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 5
        x.save().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')
Ejemplo n.º 53
0
    def test_tracking_on_byproducts(self):
        product_final = self.env['product.product'].create({
            'name': 'Finished Product',
            'type': 'product',
            'tracking': 'serial',
        })
        product_1 = self.env['product.product'].create({
            'name': 'Raw 1',
            'type': 'product',
            'tracking': 'serial',
        })
        product_2 = self.env['product.product'].create({
            'name': 'Raw 2',
            'type': 'product',
            'tracking': 'serial',
        })
        byproduct_1 = self.env['product.product'].create({
            'name': 'Byproduct 1',
            'type': 'product',
            'tracking': 'serial',
        })
        byproduct_2 = self.env['product.product'].create({
            'name': 'Byproduct 2',
            'type': 'product',
            'tracking': 'serial',
        })
        bom_1 = self.env['mrp.bom'].create({
            'product_id': product_final.id,
            'product_tmpl_id': product_final.product_tmpl_id.id,
            'product_uom_id': self.uom_unit.id,
            'product_qty': 1.0,
            'type': 'normal',
            'bom_line_ids': [
                (0, 0, {'product_id': product_1.id, 'product_qty': 1}),
                (0, 0, {'product_id': product_2.id, 'product_qty': 1})
            ],
            'byproduct_ids': [
                (0, 0, {'product_id': byproduct_1.id, 'product_qty': 1, 'product_uom_id': byproduct_1.uom_id.id}),
                (0, 0, {'product_id': byproduct_2.id, 'product_qty': 1, 'product_uom_id': byproduct_2.uom_id.id})
            ]})
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = product_final
        mo_form.bom_id = bom_1
        mo_form.product_qty = 2
        mo = mo_form.save()
        mo.action_confirm()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.finished_lot_id = self.env['stock.production.lot'].create({
            'product_id': product_final.id,
            'name': 'Final_lot_1'
        })
        with produce_form.raw_workorder_line_ids.edit(0) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': product_1.id,
                'name': 'Raw_1_lot_1'
            })
        with produce_form.raw_workorder_line_ids.edit(1) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': product_2.id,
                'name': 'Raw_2_lot_1'
            })
        with produce_form.finished_workorder_line_ids.edit(0) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': byproduct_1.id,
                'name': 'Byproduct_1_lot_1'
            })
        with produce_form.finished_workorder_line_ids.edit(1) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': byproduct_2.id,
                'name': 'Byproduct_2_lot_1'
            })
        produce_wizard = produce_form.save()
        produce_wizard.continue_production()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.finished_lot_id = self.env['stock.production.lot'].create({
            'product_id': product_final.id,
            'name': 'Final_lot_2'
        })
        with produce_form.raw_workorder_line_ids.edit(0) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': product_1.id,
                'name': 'Raw_1_lot_2'
            })
        with produce_form.raw_workorder_line_ids.edit(1) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': product_2.id,
                'name': 'Raw_2_lot_2'
            })
        with produce_form.finished_workorder_line_ids.edit(0) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': byproduct_1.id,
                'name': 'Byproduct_1_lot_2'
            })
        with produce_form.finished_workorder_line_ids.edit(1) as line:
            line.lot_id = self.env['stock.production.lot'].create({
                'product_id': byproduct_2.id,
                'name': 'Byproduct_2_lot_2'
            })
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()
        mo.button_mark_done()

        self.assertEqual(len(mo.move_raw_ids.mapped('move_line_ids')), 4)
        self.assertEqual(len(mo.move_finished_ids.mapped('move_line_ids')), 6)

        raw_move_lines = mo.move_raw_ids.mapped('move_line_ids')
        raw_line_raw_1_lot_1 = raw_move_lines.filtered(lambda ml: ml.lot_id.name == 'Raw_1_lot_1')
        self.assertEqual(set(raw_line_raw_1_lot_1.lot_produced_ids.mapped('name')), set(['Final_lot_1', 'Byproduct_1_lot_1', 'Byproduct_2_lot_1']))
        raw_line_raw_1_lot_2 = raw_move_lines.filtered(lambda ml: ml.lot_id.name == 'Raw_1_lot_2')
        self.assertEqual(set(raw_line_raw_1_lot_2.lot_produced_ids.mapped('name')), set(['Final_lot_2', 'Byproduct_1_lot_2', 'Byproduct_2_lot_2']))
        raw_line_raw_2_lot_1 = raw_move_lines.filtered(lambda ml: ml.lot_id.name == 'Raw_2_lot_1')
        self.assertEqual(set(raw_line_raw_2_lot_1.lot_produced_ids.mapped('name')), set(['Final_lot_1', 'Byproduct_1_lot_1', 'Byproduct_2_lot_1']))
        raw_line_raw_2_lot_2 = raw_move_lines.filtered(lambda ml: ml.lot_id.name == 'Raw_2_lot_2')
        self.assertEqual(set(raw_line_raw_2_lot_2.lot_produced_ids.mapped('name')), set(['Final_lot_2', 'Byproduct_1_lot_2', 'Byproduct_2_lot_2']))

        finished_move_lines = mo.move_finished_ids.mapped('move_line_ids')
        finished_move_line_lot_1 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Final_lot_1')
        self.assertEqual(finished_move_line_lot_1.consume_line_ids, raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
        finished_move_line_lot_2 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Final_lot_2')
        self.assertEqual(finished_move_line_lot_2.consume_line_ids, raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)

        byproduct_move_line_1_lot_1 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Byproduct_1_lot_1')
        self.assertEqual(byproduct_move_line_1_lot_1.consume_line_ids, raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
        byproduct_move_line_1_lot_2 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Byproduct_1_lot_2')
        self.assertEqual(byproduct_move_line_1_lot_2.consume_line_ids, raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)

        byproduct_move_line_2_lot_1 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Byproduct_2_lot_1')
        self.assertEqual(byproduct_move_line_2_lot_1.consume_line_ids, raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
        byproduct_move_line_2_lot_2 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Byproduct_2_lot_2')
        self.assertEqual(byproduct_move_line_2_lot_2.consume_line_ids, raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)
Ejemplo n.º 54
0
    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_ids': [(4, stock_id)],
        })
        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_form = Form(self.env['mrp.production'])
            mo_form.product_id = finished_product
            mo_form.bom_id = bom
            mo_form.product_uom_id = self.env.ref('uom.product_uom_unit')
            mo_form.product_qty = 1
            mo = mo_form.save()
            mo.action_confirm()
            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.qty_producing = 1

            if finished_product.tracking != 'none':
                produce_form.finished_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 Units", '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)
                )
Ejemplo n.º 55
0
    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_form = Form(self.env['mrp.production'])
        mo_form.product_id = finshed_product
        mo_form.bom_id = bom
        mo_form.product_uom_id = finshed_product.uom_id
        mo_form.product_qty = 1.0
        mo = mo_form.save()
        self.assertEqual(len(mo), 1, 'MO should have been created')
        mo.action_confirm()
        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.qty_producing = 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')
Ejemplo n.º 56
0
    def test_unbuild_with_final_lot(self):
        """ This test creates a MO and then creates 3 unbuild
        orders for the final product. Only the final 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_final='lot')
        self.assertEqual(len(mo), 1, 'MO should have been created')

        lot = self.env['stock.production.lot'].create({
            'name':
            'lot1',
            'product_id':
            p_final.id,
            'company_id':
            self.env.company.id,
        })

        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()

        mo_form = Form(mo)
        mo_form.qty_producing = 5.0
        mo_form.lot_producing_id = lot
        mo = mo_form.save()

        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), 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), 0,
            'You should have consumed all the 5 product in stock')

        # ---------------------------------------------------
        #       unbuild
        # ---------------------------------------------------

        # This should fail since we do not choose a lot to unbuild for final product.
        with self.assertRaises(AssertionError):
            x = Form(self.env['mrp.unbuild'])
            x.product_id = p_final
            x.bom_id = bom
            x.product_qty = 3
            unbuild_order = x.save()

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 3
        x.lot_id = lot
        x.save().action_unbuild()

        self.assertEqual(
            self.env['stock.quant']._get_available_quantity(
                p_final, self.stock_location, lot_id=lot), 2,
            'You should have consumed 3 final product in stock')
        self.assertEqual(
            self.env['stock.quant']._get_available_quantity(
                p1, self.stock_location), 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')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 2
        x.lot_id = lot
        x.save().action_unbuild()

        self.assertEqual(
            self.env['stock.quant']._get_available_quantity(
                p_final, self.stock_location, lot_id=lot), 0,
            'You should have 0 finalproduct in stock')
        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), 5,
            'You should have consumed all the 5 product in stock')

        x = Form(self.env['mrp.unbuild'])
        x.product_id = p_final
        x.bom_id = bom
        x.product_qty = 5
        x.lot_id = lot
        x.save().action_unbuild()

        self.assertEqual(
            self.env['stock.quant']._get_available_quantity(
                p_final, self.stock_location, lot_id=lot, 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), 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')
Ejemplo n.º 57
0
    def test_smp_performance(self):

        total_quantity = 1000
        quantity = 1

        raw_materials_count = 10
        trackings = [
            'none',
            # 'lot',
            # 'serial'
        ]

        _logger.info('setting up environment')

        raw_materials = []
        for i in range(raw_materials_count):
            raw_materials.append(self.env['product.product'].create({
                'name':
                '@raw_material#' + str(i + 1),
                'type':
                'product',
                'tracking':
                trackings[i % len(trackings)]
            }))
        finished = self.env['product.product'].create({
            'name': '@finished',
            'type': 'product',
            'tracking': 'serial',
        })
        bom = self.env['mrp.bom'].create({
            'product_id':
            finished.id,
            'product_tmpl_id':
            finished.product_tmpl_id.id,
            'product_uom_id':
            finished.uom_id.id,
            'product_qty':
            1.0,
            'type':
            'normal',
            'consumption':
            'flexible',
            'bom_line_ids': [(0, 0, {
                'product_id': p[0]['id'],
                'product_qty': 1
            }) for p in raw_materials]
        })

        form = Form(self.env['mrp.production'])
        form.product_id = finished
        form.bom_id = bom
        form.product_qty = total_quantity

        mo = form.save()

        mo.action_confirm()

        for i in range(raw_materials_count):
            if raw_materials[i].tracking == 'none':
                self.env['stock.quant'].with_context(
                    inventory_mode=True).create({
                        'product_id':
                        raw_materials[i].id,
                        'inventory_quantity':
                        total_quantity,
                        'location_id':
                        mo.location_src_id.id,
                    })._apply_inventory()
            elif raw_materials[i].tracking == 'lot':
                qty = total_quantity
                while qty > 0:
                    lot = self.env['stock.lot'].create({
                        'product_id':
                        raw_materials[i].id,
                        'company_id':
                        self.env.company.id,
                    })
                    self.env['stock.quant'].with_context(
                        inventory_mode=True).create({
                            'product_id':
                            raw_materials[i].id,
                            'inventory_quantity':
                            10,
                            'location_id':
                            mo.location_src_id.id,
                            'lot_id':
                            lot.id,
                        })._apply_inventory()
                    qty -= 10
            else:
                for _ in range(total_quantity):
                    lot = self.env['stock.lot'].create({
                        'product_id':
                        raw_materials[i].id,
                        'company_id':
                        self.env.company.id,
                    })
                    self.env['stock.quant'].with_context(
                        inventory_mode=True).create({
                            'product_id':
                            raw_materials[i].id,
                            'inventory_quantity':
                            1,
                            'location_id':
                            mo.location_src_id.id,
                            'lot_id':
                            lot.id,
                        })._apply_inventory()

        mo.action_assign()

        action = mo.action_serial_mass_produce_wizard()
        wizard = Form(
            self.env['stock.assign.serial'].with_context(**action['context']))
        wizard.next_serial_number = "sn#1"
        wizard.next_serial_count = quantity
        action = wizard.save().generate_serial_numbers_production()
        wizard = Form(self.env['stock.assign.serial'].browse(action['res_id']))
        wizard = wizard.save()

        _logger.info('generating serial numbers')
        start = time.perf_counter()
        if quantity == total_quantity:
            wizard.apply()
        else:
            wizard.create_backorder()
        end = time.perf_counter()
        _logger.info('time to produce %s/%s: %s', quantity, total_quantity,
                     end - start)
Ejemplo n.º 58
0
    def test_00_mrp_byproduct(self):
        """ Test by product with production order."""
        # Create BOM for product B
        # ------------------------
        bom_product_b = self.MrpBom.create({
            'product_tmpl_id': self.product_b.product_tmpl_id.id,
            'product_qty': 1.0,
            'type': 'normal',
            'product_uom_id': self.uom_unit_id,
            'bom_line_ids': [(0, 0, {'product_id': self.product_c_id, 'product_uom_id': self.uom_unit_id, 'product_qty': 2})]
            })

        # Create BOM for product A and set byproduct product B
        bom_product_a = self.MrpBom.create({
            'product_tmpl_id': self.product_a.product_tmpl_id.id,
            'product_qty': 1.0,
            'type': 'normal',
            'product_uom_id': self.uom_unit_id,
            'bom_line_ids': [(0, 0, {'product_id': self.product_c_id, 'product_uom_id': self.uom_unit_id, 'product_qty': 2})],
            'byproduct_ids': [(0, 0, {'product_id': self.product_b.id, 'product_uom_id': self.uom_unit_id, 'product_qty': 1})]
            })

        # Create production order for product A
        # -------------------------------------

        mnf_product_a_form = Form(self.env['mrp.production'])
        mnf_product_a_form.product_id = self.product_a
        mnf_product_a_form.bom_id = bom_product_a
        mnf_product_a_form.product_qty = 2.0
        mnf_product_a = mnf_product_a_form.save()
        mnf_product_a.action_confirm()

        # I compute the data of production order
        context = {"active_model": "mrp.production", "active_ids": [mnf_product_a.id], "active_id": mnf_product_a.id}

        # I confirm the production order.
        self.assertEqual(mnf_product_a.state, 'confirmed', 'Production order should be in state confirmed')

        # Now I check the stock moves for the byproduct I created in the bill of material.
        # This move is created automatically when I confirmed the production order.
        moves = mnf_product_a.move_raw_ids | mnf_product_a.move_finished_ids
        self.assertTrue(moves, 'No moves are created !')

        # I consume and produce the production of products.
        # I create record for selecting mode and quantity of products to produce.
        produce_form = Form(self.env['mrp.product.produce'].with_context(context))
        produce_form.qty_producing = 2.00
        product_consume = produce_form.save()
        # I finish the production order.
        self.assertEqual(len(mnf_product_a.move_raw_ids), 1, "Wrong consume move on production order.")
        product_consume.do_produce()
        consume_move_c = mnf_product_a.move_raw_ids
        by_product_move = mnf_product_a.move_finished_ids.filtered(lambda x: x.product_id.id == self.product_b.id)
        # Check sub production produced quantity...
        self.assertEqual(consume_move_c.product_uom_qty, 4, "Wrong consumed quantity of product c.")
        self.assertEqual(by_product_move.product_uom_qty, 2, "Wrong produced quantity of sub product.")

        mnf_product_a.post_inventory()

        # I see that stock moves of External Hard Disk including Headset USB are done now.
        self.assertFalse(any(move.state != 'done' for move in moves), 'Moves are not done!')
Ejemplo n.º 59
0
    def test_basic(self):
        """ Basic order test: no routing (thus no workorders), no lot """
        self.product_1.type = 'product'
        self.product_2.type = 'product'
        inventory = self.env['stock.inventory'].create({
            'name':
            'Initial inventory',
            'filter':
            'partial',
            'line_ids': [(0, 0, {
                'product_id': self.product_1.id,
                'product_uom_id': self.product_1.uom_id.id,
                'product_qty': 500,
                'location_id': self.warehouse_1.lot_stock_id.id
            }),
                         (0, 0, {
                             'product_id': self.product_2.id,
                             'product_uom_id': self.product_2.uom_id.id,
                             'product_qty': 500,
                             'location_id': self.warehouse_1.lot_stock_id.id
                         })]
        })
        inventory.action_validate()

        test_date_planned = Dt.now() - timedelta(days=1)
        test_quantity = 2.0
        self.bom_1.routing_id = False
        man_order_form = Form(self.env['mrp.production'].sudo(
            self.user_mrp_user))
        man_order_form.product_id = self.product_4
        man_order_form.bom_id = self.bom_1
        man_order_form.product_uom_id = self.product_4.uom_id
        man_order_form.product_qty = test_quantity
        man_order_form.date_planned_start = test_date_planned
        man_order_form.location_src_id = self.location_1
        man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id
        man_order = man_order_form.save()

        self.assertEqual(man_order.state, 'draft',
                         "Production order should be in draft state.")
        man_order.action_confirm()
        self.assertEqual(man_order.state, 'confirmed',
                         "Production order should be in confirmed state.")

        # check production move
        production_move = man_order.move_finished_ids
        self.assertEqual(production_move.date, test_date_planned)
        self.assertEqual(production_move.product_id, self.product_4)
        self.assertEqual(production_move.product_uom, man_order.product_uom_id)
        self.assertEqual(production_move.product_qty, man_order.product_qty)
        self.assertEqual(production_move.location_id,
                         self.product_4.property_stock_production)
        self.assertEqual(production_move.location_dest_id,
                         man_order.location_dest_id)

        # check consumption moves
        for move in man_order.move_raw_ids:
            self.assertEqual(move.date, test_date_planned)
        first_move = man_order.move_raw_ids.filtered(
            lambda move: move.product_id == self.product_2)
        self.assertEqual(
            first_move.product_qty, test_quantity / self.bom_1.product_qty *
            self.product_4.uom_id.factor_inv * 2)
        first_move = man_order.move_raw_ids.filtered(
            lambda move: move.product_id == self.product_1)
        self.assertEqual(
            first_move.product_qty, test_quantity / self.bom_1.product_qty *
            self.product_4.uom_id.factor_inv * 4)

        # waste some material, create a scrap
        # scrap = self.env['stock.scrap'].with_context(
        #     active_model='mrp.production', active_id=man_order.id
        # ).create({})
        # scrap = self.env['stock.scrap'].create({
        #     'production_id': man_order.id,
        #     'product_id': first_move.product_id.id,
        #     'product_uom_id': first_move.product_uom.id,
        #     'scrap_qty': 5.0,
        # })
        # check created scrap

        # procurements = self.env['procurement.order'].search([('move_dest_id', 'in', man_order.move_raw_ids.ids)])
        # print procurements
        # procurements = self.env['procurement.order'].search([('production_id', '=', man_order.id)])
        # print procurements
        # for proc in self.env['procurement.order'].browse(procurements):
        #     date_planned = self.mrp_production_test1.date_planned
        #     if proc.product_id.type not in ('product', 'consu'):
        #         continue
        #     if proc.product_id.id == order_line.product_id.id:
        #         self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond")
        #       # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which
        #       # case it could already be in `running` or `exception` state (not enough stock)
        #         expected_states = ('confirmed', 'running', 'exception')
        #         self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states))

        # Change production quantity
        qty_wizard = self.env['change.production.qty'].create({
            'mo_id':
            man_order.id,
            'product_qty':
            3.0,
        })
        # qty_wizard.change_prod_qty()

        # # I check qty after changed in production order.
        # #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.")
        # move = self.mrp_production_test1.move_finished_ids[0]
        # self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.")

        # # I run scheduler.
        # self.env['procurement.order'].run_scheduler()

        # # The production order is Waiting Goods, will force production which should set consume lines as available
        # self.mrp_production_test1.button_plan()
        # # I check that production order in ready state after forcing production.

        # #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available')

        # produce product
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            man_order.id,
            'active_ids': [man_order.id],
        }))
        produce_form.product_qty = 1.0
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()

        # man_order.button_mark_done()
        man_order.button_mark_done()
        self.assertEqual(man_order.state, 'done',
                         "Production order should be in done state.")
Ejemplo n.º 60
0
    def test_auto_assign(self):
        """ When auto reordering rule exists, check for when:
        1. There is not enough of a manufactured product to assign (reserve for) a picking => auto-create 1st MO
        2. There is not enough of a manufactured component to assign the created MO => auto-create 2nd MO
        3. Add an extra manufactured component (not in stock) to 1st MO => auto-create 3rd MO
        4. When 2nd MO is completed => auto-assign to 1st MO
        5. When 1st MO is completed => auto-assign to picking
        6. Additionally check that a MO that has component in stock auto-reserves when MO is confirmed (since default setting = 'at_confirm')"""

        self.warehouse = self.env.ref('stock.warehouse0')
        route_manufacture = self.warehouse.manufacture_pull_id.route_id

        product_1 = self.env['product.product'].create({
            'name':
            'Cake',
            'type':
            'product',
            'route_ids': [(6, 0, [route_manufacture.id])]
        })
        product_2 = self.env['product.product'].create({
            'name':
            'Cake Mix',
            'type':
            'product',
            'route_ids': [(6, 0, [route_manufacture.id])]
        })
        product_3 = self.env['product.product'].create({
            'name': 'Flour',
            'type': 'consu',
        })

        bom1 = self.env['mrp.bom'].create({
            'product_id':
            product_1.id,
            'product_tmpl_id':
            product_1.product_tmpl_id.id,
            'product_uom_id':
            self.uom_unit.id,
            'product_qty':
            1,
            'consumption':
            'flexible',
            'type':
            'normal',
            'bom_line_ids': [
                (0, 0, {
                    'product_id': product_2.id,
                    'product_qty': 1
                }),
            ]
        })

        self.env['mrp.bom'].create({
            'product_id':
            product_2.id,
            'product_tmpl_id':
            product_2.product_tmpl_id.id,
            'product_uom_id':
            self.uom_unit.id,
            'product_qty':
            1,
            'type':
            'normal',
            'bom_line_ids': [
                (0, 0, {
                    'product_id': product_3.id,
                    'product_qty': 1
                }),
            ]
        })

        # extra manufactured component added to 1st MO after it is already confirmed
        product_4 = self.env['product.product'].create({
            'name':
            'Flavor Enchancer',
            'type':
            'product',
            'route_ids': [(6, 0, [route_manufacture.id])]
        })
        product_5 = self.env['product.product'].create({
            'name': 'MSG',
            'type': 'consu',
        })

        self.env['mrp.bom'].create({
            'product_id':
            product_4.id,
            'product_tmpl_id':
            product_4.product_tmpl_id.id,
            'product_uom_id':
            self.uom_unit.id,
            'product_qty':
            1,
            'type':
            'normal',
            'bom_line_ids': [
                (0, 0, {
                    'product_id': product_5.id,
                    'product_qty': 1
                }),
            ]
        })

        # setup auto orderpoints (reordering rules)
        self.env['stock.warehouse.orderpoint'].create({
            'name':
            'Cake RR',
            'location_id':
            self.warehouse.lot_stock_id.id,
            'product_id':
            product_1.id,
            'product_min_qty':
            0,
            'product_max_qty':
            5,
        })

        self.env['stock.warehouse.orderpoint'].create({
            'name':
            'Cake Mix RR',
            'location_id':
            self.warehouse.lot_stock_id.id,
            'product_id':
            product_2.id,
            'product_min_qty':
            0,
            'product_max_qty':
            5,
        })

        self.env['stock.warehouse.orderpoint'].create({
            'name':
            'Flavor Enchancer RR',
            'location_id':
            self.warehouse.lot_stock_id.id,
            'product_id':
            product_4.id,
            'product_min_qty':
            0,
            'product_max_qty':
            5,
        })

        # create picking output to trigger creating MO for reordering product_1
        pick_output = self.env['stock.picking'].create({
            'name':
            'Cake Delivery Order',
            'picking_type_id':
            self.ref('stock.picking_type_out'),
            'location_id':
            self.warehouse.lot_stock_id.id,
            'location_dest_id':
            self.ref('stock.stock_location_customers'),
            'move_lines': [(0, 0, {
                'name':
                '/',
                'product_id':
                product_1.id,
                'product_uom':
                product_1.uom_id.id,
                'product_uom_qty':
                10.00,
                'procure_method':
                'make_to_stock',
                'location_id':
                self.warehouse.lot_stock_id.id,
                'location_dest_id':
                self.ref('stock.stock_location_customers'),
            })],
        })
        pick_output.action_confirm(
        )  # should trigger orderpoint to create and confirm 1st MO
        pick_output.action_assign()

        mo = self.env['mrp.production'].search([('product_id', '=',
                                                 product_1.id),
                                                ('state', '=', 'confirmed')])

        self.assertEqual(len(mo), 1,
                         "Manufacture order was not automatically created")
        mo.action_assign()
        mo.is_locked = False
        self.assertEqual(mo.move_raw_ids.reserved_availability, 0,
                         "No components should be reserved yet")
        self.assertEqual(
            mo.product_qty, 15,
            "Quantity to produce should be picking demand + reordering rule max qty"
        )

        # 2nd MO for product_2 should have been created and confirmed when 1st MO for product_1 was confirmed
        mo2 = self.env['mrp.production'].search([('product_id', '=',
                                                  product_2.id),
                                                 ('state', '=', 'confirmed')])

        self.assertEqual(len(mo2), 1,
                         'Second manufacture order was not created')
        self.assertEqual(
            mo2.product_qty, 20,
            "Quantity to produce should be MO's 'to consume' qty + reordering rule max qty"
        )
        mo2_form = Form(mo2)
        mo2_form.qty_producing = 20
        mo2 = mo2_form.save()
        mo2.button_mark_done()

        self.assertEqual(mo.move_raw_ids.reserved_availability, 15,
                         "Components should have been auto-reserved")

        # add new component to 1st MO
        mo_form = Form(mo)
        with mo_form.move_raw_ids.new() as line:
            line.product_id = product_4
            line.product_uom_qty = 1
        mo_form.save(
        )  # should trigger orderpoint to create and confirm 3rd MO

        mo3 = self.env['mrp.production'].search([('product_id', '=',
                                                  product_4.id),
                                                 ('state', '=', 'confirmed')])

        self.assertEqual(
            len(mo3), 1,
            'Third manufacture order for added component was not created')
        self.assertEqual(
            mo3.product_qty, 6,
            "Quantity to produce should be 1 + reordering rule max qty")

        mo_form = Form(mo)
        mo.move_raw_ids.quantity_done = 15
        mo_form.qty_producing = 15
        mo = mo_form.save()
        mo.button_mark_done()

        self.assertEqual(
            pick_output.move_ids_without_package.reserved_availability, 10,
            "Completed products should have been auto-reserved in picking")

        # make sure next MO auto-reserves components now that they are in stock since
        # default reservation_method = 'at_confirm'
        mo_form = Form(self.env['mrp.production'])
        mo_form.product_id = product_1
        mo_form.bom_id = bom1
        mo_form.product_qty = 5
        mo_form.product_uom_id = product_1.uom_id
        mo_assign_at_confirm = mo_form.save()
        mo_assign_at_confirm.action_confirm()

        self.assertEqual(
            mo_assign_at_confirm.move_raw_ids.reserved_availability, 5,
            "Components should have been auto-reserved")