Ejemplo n.º 1
0
    def test_change_product(self):
        """ Create a production order for a specific product with a BoM. Then change the BoM and the finished product for
        other ones and check the finished product of the first mo did not became a byproduct of the second one."""
        # Create BOM for product A with product B as component
        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_b.id,
                'product_uom_id': self.uom_unit_id,
                'product_qty': 2
            })],
        })

        bom_product_a_2 = 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 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 = 1.0
        mnf_product_a = mnf_product_a_form.save()
        mnf_product_a_form = Form(mnf_product_a)
        mnf_product_a_form.bom_id = bom_product_a_2
        mnf_product_a = mnf_product_a_form.save()
        self.assertEqual(mnf_product_a.move_raw_ids.product_id.id,
                         self.product_c_id)
        self.assertFalse(mnf_product_a.move_byproduct_ids)
Ejemplo n.º 2
0
    def test_unbuild_account_01(self):
        """Test when production location has its valuation accounts. After unbuild,
        the journal entries are the reversal of the journal entries created when
        produce the product.
        """
        # set accounts for production location
        production_location = self.product_A.property_stock_production
        wip_incoming_account = self.env['account.account'].create({
            'name': 'wip incoming',
            'code': '000001',
            'user_type_id': self.env.ref('account.data_account_type_current_assets').id,
        })
        wip_outgoing_account = self.env['account.account'].create({
            'name': 'wip outgoing',
            'code': '000002',
            'user_type_id': self.env.ref('account.data_account_type_current_assets').id,
        })
        production_location.write({
            'valuation_in_account_id': wip_incoming_account.id,
            'valuation_out_account_id': wip_outgoing_account.id,
        })

        # 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, wip_outgoing_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, wip_incoming_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()

        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, wip_outgoing_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, wip_incoming_account)
Ejemplo n.º 3
0
    def test_unbuild_decimal_qty(self):
        """
        Use case:
        - decimal accuracy of Product UoM > decimal accuracy of Units
        - unbuild a product with a decimal quantity of component
        """
        self.env['decimal.precision'].search([
            ('name', '=', 'Product Unit of Measure')
        ]).digits = 4
        self.uom_unit.rounding = 0.001

        self.bom_1.product_qty = 3
        self.bom_1.bom_line_ids.product_qty = 5
        self.env['stock.quant']._update_available_quantity(
            self.product_2, self.stock_location, 3)

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

        mo_form = Form(mo)
        mo_form.qty_producing = 3
        mo_form.save()
        mo.button_mark_done()

        uo_form = Form(self.env['mrp.unbuild'])
        uo_form.mo_id = mo
        # Unbuilding one product means a decimal quantity equal to 1 / 3 * 5 for each component
        uo_form.product_qty = 1
        uo = uo_form.save()
        uo.action_unbuild()
        self.assertEqual(uo.state, 'done')
Ejemplo n.º 4
0
 def _make_mo(self, bom, quantity=1):
     mo_form = Form(self.env['mrp.production'])
     mo_form.product_id = bom.product_id
     mo_form.bom_id = bom
     mo_form.product_qty = quantity
     mo = mo_form.save()
     mo.action_confirm()
     return mo
Ejemplo n.º 5
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.º 6
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.operation_ids = False
        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 = 1
        production_table = production_table_form.save()

        production_table.extra_cost = 20
        production_table.action_confirm()

        mo_form = Form(production_table)
        mo_form.qty_producing = 1
        production_table = mo_form.save()
        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.º 7
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.º 8
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.º 9
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.º 10
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.º 11
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.º 12
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.º 13
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.º 14
0
    def test_procurement_3(self):
        warehouse = self.env['stock.warehouse'].search([], limit=1)
        warehouse.write({'reception_steps': 'three_steps'})
        warehouse.mto_pull_id.route_id.active = True
        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})
        picking_qc_to_stock.with_context(
            skip_backorder=True,
            picking_ids_not_to_backorder=picking_qc_to_stock.ids
        ).button_validate()
        self.assertEqual(picking_qc_to_stock.state, 'done')
        mo.action_assign()
        self.assertEqual(mo.move_raw_ids.reserved_availability, 3.0)
        produce_form = Form(mo)
        produce_form.qty_producing = 3.0
        mo = produce_form.save()
        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.º 15
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 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.
        mo_form = Form(mnf_product_a)
        mo_form.qty_producing = 2.00
        mnf_product_a = mo_form.save()
        # I finish the production order.
        self.assertEqual(len(mnf_product_a.move_raw_ids), 1,
                         "Wrong consume move on production order.")
        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!')
    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
        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'

        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.º 17
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,
                        'company_id':
                        self.env.company.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,
                        'company_id':
                        self.env.company.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,
                        'company_id':
                        self.env.company.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,
                        'company_id':
                        self.env.company.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
            mo_form = Form(mo)
            mo_form.qty_producing = 1
            if finished_product.tracking != 'none':
                mo_form.lot_producing_id = self.env[
                    'stock.production.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.º 18
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.production.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.production.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.production.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.production.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.production.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.production.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.production.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.production.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.production.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.production.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.º 19
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
        mo_form = Form(mo)
        mo_form.qty_producing = 1.0
        produce_wizard = 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(
            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
        x = Form(self.env['mrp.unbuild'])
        x.product_id = finshed_product
        x.bom_id = bom
        x.mo_id = mo
        x.product_qty = 1
        x.location_id = self.stock_location
        x.location_dest_id = unbuild_location
        x.save().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.º 20
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,
            'company_id':
            self.env.company.id,
        })
        lot_product_2 = self.env['stock.production.lot'].create({
            'name':
            '0000000000002',
            'product_id':
            self.product_2.id,
            'company_id':
            self.env.company.id,
        })

        stock_inv_product_4 = self.env['stock.inventory'].create({
            'name':
            'Stock Inventory for Stick',
            'product_ids': [(4, 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.stock_location_14.id
                }),
            ]
        })

        stock_inv_product_2 = self.env['stock.inventory'].create({
            'name':
            'Stock Inventory for Stone Tools',
            'product_ids': [(4, 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.stock_location_14.id
            })]
        })
        (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(UserError):
            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.º 21
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')
        self.warehouse.mto_pull_id.route_id.active = True
        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')

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

        mo_form = Form(produce_product_4)
        mo_form.qty_producing = produce_product_4.product_qty
        produce_product_4 = mo_form.save()
        # 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")
        mo_form = Form(production_product_6)
        mo_form.qty_producing = production_product_6.product_qty
        production_product_6 = mo_form.save()
        # 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.')