Exemplo n.º 1
0
    def test_survey_invite(self):
        Answer = self.env['survey.user_input']
        deadline = fields.Datetime.now() + relativedelta(months=1)

        self.survey.write({'access_mode': 'public'})
        action = self.survey.action_send_survey()
        invite_form = Form(self.env[action['res_model']].with_context(action['context']))

        # some lowlevel checks that action is correctly configured
        self.assertEqual(Answer.search([('survey_id', '=', self.survey.id)]), self.env['survey.user_input'])
        self.assertEqual(invite_form.survey_id, self.survey)

        invite_form.partner_ids.add(self.customer)
        invite_form.deadline = fields.Datetime.to_string(deadline)

        invite = invite_form.save()
        invite.action_invite()

        answers = Answer.search([('survey_id', '=', self.survey.id)])
        self.assertEqual(len(answers), 1)
        self.assertEqual(
            set(answers.mapped('email')),
            set([self.customer.email]))
        self.assertEqual(answers.mapped('partner_id'), self.customer)
        self.assertEqual(set(answers.mapped('deadline')), set([deadline]))
Exemplo n.º 2
0
    def test_flow_3(self):
        """ Tick "Resupply Subcontractor on Order" and "MTO" on the components and trigger the
        creation of the subcontracting manufacturing order through a receipt picking. Checks if the
        resupplying actually works. One of the component has also "manufacture" set and a BOM
        linked. Checks that an MO is created for this one.
        """
        # Tick "resupply subconractor on order"
        resupply_sub_on_order_route = self.env['stock.location.route'].search([('name', '=', 'Resupply Subcontractor on Order')])
        (self.comp1 + self.comp2).write({'route_ids': [(4, resupply_sub_on_order_route.id, None)]})

        # Tick "manufacture" and MTO on self.comp2
        mto_route = self.env['stock.location.route'].search([('name', '=', 'Replenish on Order (MTO)')])
        manufacture_route = self.env['stock.location.route'].search([('name', '=', 'Manufacture')])
        self.comp2.write({'route_ids': [(4, manufacture_route.id, None)]})
        self.comp2.write({'route_ids': [(4, mto_route.id, None)]})

        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # Nothing should be tracked
        self.assertFalse(picking_receipt.display_action_record_components)
        self.assertFalse(picking_receipt.display_view_subcontracted_move_lines)

        # Pickings should directly be created
        mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)])
        self.assertEqual(len(mo.picking_ids), 1)
        self.assertEquals(mo.state, 'to_close')
        self.assertEqual(len(mo.picking_ids.move_lines), 2)

        # The picking should be a delivery order
        wh = picking_receipt.picking_type_id.warehouse_id
        self.assertEquals(mo.picking_ids.picking_type_id, wh.out_type_id)

        self.assertEquals(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        # As well as a manufacturing order for `self.comp2`
        comp2mo = self.env['mrp.production'].search([('bom_id', '=', self.comp2_bom.id)])
        self.assertEqual(len(comp2mo), 1)
        picking_receipt.move_lines.quantity_done = 1
        picking_receipt.button_validate()
        self.assertEquals(mo.state, 'done')

        # Now that the picking is done, the details stat button should be visible
        self.assertTrue(picking_receipt.display_view_subcontracted_move_lines)

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(self.comp1, self.subcontractor_partner1.property_stock_supplier, allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(self.comp2, self.subcontractor_partner1.property_stock_supplier, allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(self.finished, wh.lot_stock_id)
        self.assertEquals(avail_qty_comp1, -1)
        self.assertEquals(avail_qty_comp2, -1)
        self.assertEquals(avail_qty_finished, 1)
Exemplo n.º 3
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 = self.env['mrp.production'].create({'name': 'MO efficiency test',
                                           'product_id': self.product_6.id,
                                           'product_qty': 20,
                                           'bom_id': bom_eff.id,
                                           'product_uom_id': self.product_6.uom_id.id,})
        #Check the production order has the right quantities
        self.assertEqual(production.move_raw_ids[0].product_qty, 41, 'The quantity should be rounded up')
        self.assertEqual(production.move_raw_ids[1].product_qty, 84, 'The quantity should be rounded up')

        # produce product
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': production.id,
            'active_ids': [production.id],
        }))
        produce_form.product_qty = 8
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()
        self.assertEqual(production.move_raw_ids[0].quantity_done, 16, 'Should use half-up rounding when producing')
        self.assertEqual(production.move_raw_ids[1].quantity_done, 34, 'Should use half-up rounding when producing')
Exemplo n.º 4
0
    def test_dropship_standard_perpetual_anglosaxon_ordered_return(self):
        self.env.user.company_id.anglo_saxon_accounting = True
        self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'
        self.product1.product_tmpl_id.standard_price = 10
        self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
        self.product1.product_tmpl_id.invoice_policy = 'order'

        all_amls = self._dropship_product1()

        # return what we've done
        stock_return_picking_form = Form(self.env['stock.return.picking']
            .with_context(active_ids=self.sale_order1.picking_ids.ids, active_id=self.sale_order1.picking_ids.ids[0],
            active_model='stock.picking'))
        stock_return_picking = stock_return_picking_form.save()
        stock_return_picking_action = stock_return_picking.create_returns()
        return_pick = self.env['stock.picking'].browse(stock_return_picking_action['res_id'])
        return_pick.move_lines[0].move_line_ids[0].qty_done = 1.0
        return_pick.action_done()
        self.assertEqual(return_pick.move_lines._is_dropshipped_returned(), True)

        all_amls_return = self.vendor_bill1.move_id.line_ids + self.customer_invoice1.move_id.line_ids
        if self.sale_order1.picking_ids.mapped('move_lines.account_move_ids'):
            all_amls_return |= self.sale_order1.picking_ids.mapped('move_lines.account_move_ids.line_ids')

        # Two extra AML should have been created for the return
        expected_aml = {
            self.acc_stock_in:   (10.0, 0.0),
            self.acc_stock_out:  (0.0, 10.0),
        }

        self._check_results(expected_aml, 2, all_amls_return - all_amls)
    def test_manufacturing_3_steps(self):
        """ Test MO/picking before manufacturing/picking after manufacturing
        components and move_orig/move_dest. Ensure that everything is created
        correctly.
        """
        with Form(self.warehouse) as warehouse:
            warehouse.manufacture_steps = 'pbm_sam'

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.finished_product
        production_form.picking_type_id = self.warehouse.manu_type_id
        production = production_form.save()

        move_raw_ids = production.move_raw_ids
        self.assertEqual(len(move_raw_ids), 1)
        self.assertEqual(move_raw_ids.product_id, self.raw_product)
        self.assertEqual(move_raw_ids.picking_type_id, self.warehouse.manu_type_id)
        pbm_move = move_raw_ids.move_orig_ids
        self.assertEqual(len(pbm_move), 1)
        self.assertEqual(pbm_move.location_id, self.warehouse.lot_stock_id)
        self.assertEqual(pbm_move.location_dest_id, self.warehouse.pbm_loc_id)
        self.assertEqual(pbm_move.picking_type_id, self.warehouse.pbm_type_id)
        self.assertFalse(pbm_move.move_orig_ids)

        move_finished_ids = production.move_finished_ids
        self.assertEqual(len(move_finished_ids), 1)
        self.assertEqual(move_finished_ids.product_id, self.finished_product)
        self.assertEqual(move_finished_ids.picking_type_id, self.warehouse.manu_type_id)
        sam_move = move_finished_ids.move_dest_ids
        self.assertEqual(len(sam_move), 1)
        self.assertEqual(sam_move.location_id, self.warehouse.sam_loc_id)
        self.assertEqual(sam_move.location_dest_id, self.warehouse.lot_stock_id)
        self.assertEqual(sam_move.picking_type_id, self.warehouse.sam_type_id)
        self.assertFalse(sam_move.move_dest_ids)
Exemplo n.º 6
0
    def test_survey_invite_authentication_nosignup(self):
        Answer = self.env['survey.user_input']

        self.survey.write({'access_mode': 'authentication'})
        action = self.survey.action_send_survey()
        invite_form = Form(self.env[action['res_model']].with_context(action['context']))

        with self.assertRaises(UserError):  # do not allow to add customer (partner without user)
            invite_form.partner_ids.add(self.customer)
        invite_form.partner_ids.clear()
        invite_form.partner_ids.add(self.user_portal.partner_id)
        invite_form.partner_ids.add(self.user_emp.partner_id)
        with self.assertRaises(UserError):
            invite_form.emails = '[email protected], Raoulette Vignolette <*****@*****.**>'
        invite_form.emails = False

        invite = invite_form.save()
        invite.action_invite()

        answers = Answer.search([('survey_id', '=', self.survey.id)])
        self.assertEqual(len(answers), 2)
        self.assertEqual(
            set(answers.mapped('email')),
            set([self.user_emp.email, self.user_portal.email]))
        self.assertEqual(answers.mapped('partner_id'), self.user_emp.partner_id | self.user_portal.partner_id)
Exemplo n.º 7
0
    def test_procurement_2(self):
        """Check that a manufacturing order create the right procurements when the route are set on
        a parent category of a product"""
        # find a child category id
        all_categ_id = self.env['product.category'].search([('parent_id', '=', None)], limit=1)
        child_categ_id = self.env['product.category'].search([('parent_id', '=', all_categ_id.id)], limit=1)

        # set the product of `self.bom_1` to this child category
        for bom_line_id in self.bom_1.bom_line_ids:
            # check that no routes are defined on the product
            self.assertEquals(len(bom_line_id.product_id.route_ids), 0)
            # set the category of the product to a child category
            bom_line_id.product_id.categ_id = child_categ_id

        # set the MTO route to the parent category (all)
        self.warehouse = self.env.ref('stock.warehouse0')
        mto_route = self.warehouse.mto_pull_id.route_id
        mto_route.product_categ_selectable = True
        all_categ_id.write({'route_ids': [(6, 0, [mto_route.id])]})

        # create MO, but check it raises error as components are in make to order and not everyone has
        with self.assertRaises(UserError):
            production_form = Form(self.env['mrp.production'])
            production_form.product_id = self.product_4
            production_form.product_uom_id = self.product_4.uom_id
            production_form.product_qty = 1
            production_product_4 = production_form.save()
            production_product_4.action_confirm()
Exemplo n.º 8
0
    def test_product_produce_6(self):
        """ Build some final products and change the quantity to produce
        directly in the wizard. The component line should be updated .
        """
        self.stock_location = self.env.ref('stock.stock_location_stock')
        mo, bom, p_final, p1, p2 = self.generate_mo(qty_final=1)
        self.assertEqual(len(mo), 1, 'MO should have been created')

        mo.action_assign()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.qty_producing = 3
        self.assertEqual(len(produce_form.workorder_line_ids._records), 4, 'Update the produce quantity should change the components quantity.')
        self.assertEqual(sum([x['qty_done'] for x in produce_form.workorder_line_ids._records]), 15, 'Update the produce quantity should change the components quantity.')
        produce_form.qty_producing = 4
        self.assertEqual(len(produce_form.workorder_line_ids._records), 6, 'Update the produce quantity should change the components quantity.')
        self.assertEqual(sum([x['qty_done'] for x in produce_form.workorder_line_ids._records]), 20, 'Update the produce quantity should change the components quantity.')
        produce_form.qty_producing = 1
        self.assertEqual(len(produce_form.workorder_line_ids._records), 2, 'Update the produce quantity should change the components quantity.')
        self.assertEqual(sum([x['qty_done'] for x in produce_form.workorder_line_ids._records]), 5, 'Update the produce quantity should change the components quantity.')
        produce_wizard = produce_form.save()
        produce_wizard.do_produce()
Exemplo n.º 9
0
    def test_product_produce_1(self):
        """ Checks the production wizard contains lines even for untracked products. """
        self.stock_location = self.env.ref('stock.stock_location_stock')
        mo, bom, p_final, p1, p2 = self.generate_mo()
        self.assertEqual(len(mo), 1, 'MO should have been created')

        self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 100)
        self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5)

        mo.action_assign()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))
        # change the quantity done in one line
        produce_form.workorder_line_ids._records[0]['qty_done'] = 1

        # change the quantity producing
        produce_form.qty_producing = 3

        # check than all quantities are update correctly
        line1 = produce_form.workorder_line_ids._records[0]
        line2 = produce_form.workorder_line_ids._records[1]
        self.assertEqual(line1['qty_to_consume'], 3, "Wrong quantity to consume")
        self.assertEqual(line1['qty_done'], 3, "Wrong quantity done")
        self.assertEqual(line2['qty_to_consume'], 12, "Wrong quantity to consume")
        self.assertEqual(line2['qty_done'], 12, "Wrong quantity done")
        
        product_produce = produce_form.save()
        self.assertEqual(len(product_produce.workorder_line_ids), 2, 'You should have produce lines even the consumed products are not tracked.')
        product_produce.do_produce()
Exemplo n.º 10
0
    def test_product_produce_9(self):
        """ Checks the constraints of a strict BOM without tracking when playing around in the
        produce wizard.
        """
        self.stock_location = self.env.ref('stock.stock_location_stock')
        mo, bom, p_final, p1, p2 = self.generate_mo()
        self.assertEqual(len(mo), 1, 'MO should have been created')

        self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 100)
        self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5)

        mo.action_assign()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))

        with self.assertRaises(UserError):
            # try adding another line for a bom product to increase the quantity
            produce_form.qty_producing = 1
            with produce_form.raw_workorder_line_ids.new() as line:
                line.product_id = p1
                line.qty_done = 1
            product_produce = produce_form.save()
            product_produce.do_produce()

        with self.assertRaises(UserError):
            # Try updating qty_done
            product_produce = produce_form.save()
            product_produce.raw_workorder_line_ids[0].qty_done += 1
            product_produce.do_produce()

        with self.assertRaises(UserError):
            # try adding another product
            produce_form = Form(self.env['mrp.product.produce'].with_context({
                'active_id': mo.id,
                'active_ids': [mo.id],
            }))
            produce_form.qty_producing = 1
            with produce_form.raw_workorder_line_ids.new() as line:
                line.product_id = self.product_4
                line.qty_done = 1
            product_produce = produce_form.save()
            product_produce.do_produce()

        # try adding another line for a bom product but the total quantity is good
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.qty_producing = 1

        with produce_form.raw_workorder_line_ids.new() as line:
            line.product_id = p1
            line.qty_done = 1
        product_produce = produce_form.save()
        product_produce.raw_workorder_line_ids[1].qty_done -= 1
        product_produce.do_produce()
Exemplo n.º 11
0
 def test_empty_routing(self):
     """ Check what happens when you work with an empty routing"""
     routing = self.env['mrp.routing'].create({'name': 'Routing without operations'})
     self.bom_3.routing_id = routing.id
     production_form = Form(self.env['mrp.production'])
     production_form.product_id = self.product_6
     production = production_form.save()
     self.assertEqual(production.routing_id.id, False, 'The routing field should be empty on the mo')
Exemplo n.º 12
0
    def test_flow_1(self):
        """ Don't tick any route on the components and trigger the creation of the subcontracting
        manufacturing order through a receipt picking. Create a reordering rule in the
        subcontracting locations for a component and run the scheduler to resupply. Checks if the
        resupplying actually works
        """
        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # Nothing should be tracked
        self.assertFalse(picking_receipt.display_action_record_components)
        self.assertFalse(picking_receipt.display_view_subcontracted_move_lines)

        # Check the created manufacturing order
        mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)])
        self.assertEqual(len(mo), 1)
        self.assertEqual(len(mo.picking_ids), 0)
        wh = picking_receipt.picking_type_id.warehouse_id
        self.assertEquals(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        # Create a RR
        pg1 = self.env['procurement.group'].create({})
        self.env['stock.warehouse.orderpoint'].create({
            'name': 'xxx',
            'product_id': self.comp1.id,
            'product_min_qty': 0,
            'product_max_qty': 0,
            'location_id': self.env.user.company_id.subcontracting_location_id.id,
            'group_id': pg1.id,
        })

        # Run the scheduler and check the created picking
        self.env['procurement.group'].run_scheduler()
        picking = self.env['stock.picking'].search([('group_id', '=', pg1.id)])
        self.assertEqual(len(picking), 1)
        self.assertEquals(picking.picking_type_id, wh.out_type_id)
        picking_receipt.move_lines.quantity_done = 1
        picking_receipt.button_validate()
        self.assertEquals(mo.state, 'done')

        # Now that the picking is done, the details stat button should be visible
        self.assertTrue(picking_receipt.display_view_subcontracted_move_lines)

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(self.comp1, self.subcontractor_partner1.property_stock_supplier, allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(self.comp2, self.subcontractor_partner1.property_stock_supplier, allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(self.finished, wh.lot_stock_id)
        self.assertEquals(avail_qty_comp1, -1)
        self.assertEquals(avail_qty_comp2, -1)
        self.assertEquals(avail_qty_finished, 1)
Exemplo n.º 13
0
    def test_00_dropship(self):

        # Create a vendor
        supplier_dropship = self.env['res.partner'].create({'name': 'Vendor of Dropshipping test'})

        # Create new product without any routes
        drop_shop_product = self.env['product.product'].create({
            'name': "Pen drive",
            'type': "product",
            'categ_id': self.env.ref('product.product_category_1').id,
            'lst_price': 100.0,
            'standard_price': 0.0,
            'uom_id': self.env.ref('uom.product_uom_unit').id,
            'uom_po_id': self.env.ref('uom.product_uom_unit').id,
            'seller_ids': [(0, 0, {
                'delay': 1,
                'name': supplier_dropship.id,
                'min_qty': 2.0
            })]
        })

        # Create a sales order with a line of 200 PCE incoming shipment, with route_id drop shipping
        so_form = Form(self.env['sale.order'])
        so_form.partner_id = self.env.ref('base.res_partner_2')
        so_form.payment_term_id = self.env.ref('account.account_payment_term')
        with mute_logger('odoo.tests.common.onchange'):
            # otherwise complains that there's not enough inventory and
            # apparently that's normal according to @jco and @sle
            with so_form.order_line.new() as line:
                line.product_id = drop_shop_product
                line.product_uom_qty = 200
                line.price_unit = 1.00
                line.route_id = self.env.ref('stock_dropshipping.route_drop_shipping')
        sale_order_drp_shpng = so_form.save()

        # Confirm sales order
        sale_order_drp_shpng.action_confirm()

        # Check the sales order created a procurement group which has a procurement of 200 pieces
        self.assertTrue(sale_order_drp_shpng.procurement_group_id, 'SO should have procurement group')

        # Check a quotation was created to a certain vendor and confirm so it becomes a confirmed purchase order
        purchase = self.env['purchase.order'].search([('partner_id', '=', supplier_dropship.id)])
        self.assertTrue(purchase, "an RFQ should have been created by the scheduler")
        purchase.button_confirm()
        self.assertEquals(purchase.state, 'purchase', 'Purchase order should be in the approved state')
        self.assertEquals(len(purchase.ids), 1, 'There should be one picking')

        # Send the 200 pieces
        purchase.picking_ids.move_lines.quantity_done = purchase.picking_ids.move_lines.product_qty
        purchase.picking_ids.button_validate()

        # Check one move line was created in Customers location with 200 pieces
        move_line = self.env['stock.move.line'].search([
            ('location_dest_id', '=', self.env.ref('stock.stock_location_customers').id),
            ('product_id', '=', drop_shop_product.id)])
        self.assertEquals(len(move_line.ids), 1, 'There should be exactly one move line')
Exemplo n.º 14
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
Exemplo n.º 15
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)
Exemplo n.º 16
0
    def test_00_purchase_order_report(self):
        uom_dozen = self.env.ref('uom.product_uom_dozen')

        eur_currency = self.env.ref('base.EUR')
        self.company_id.currency_id = self.env.ref('base.USD').id

        self.env['res.currency.rate'].search([]).unlink()
        self.env['res.currency.rate'].create({
            'name': datetime.today(),
            'rate': 2.0,
            'currency_id': eur_currency.id,
        })
        po = self.env['purchase.order'].create({
            'partner_id': self.partner_id.id,
            'currency_id': eur_currency.id,
            'order_line': [
                (0, 0, {
                    'name': self.product1.name,
                    'product_id': self.product1.id,
                    'product_qty': 1.0,
                    'product_uom': uom_dozen.id,
                    'price_unit': 100.0,
                    'date_planned': datetime.today(),
                }),
                (0, 0, {
                    'name': self.product2.name,
                    'product_id': self.product2.id,
                    'product_qty': 1.0,
                    'product_uom': uom_dozen.id,
                    'price_unit': 200.0,
                    'date_planned': datetime.today(),
                }),
            ],
        })
        po.button_confirm()

        f = Form(self.env['account.invoice'])
        f.partner_id = po.partner_id
        f.purchase_id = po
        invoice = f.save()
        invoice.action_invoice_open()

        res_product1 = self.PurchaseReport.search([
            ('order_id', '=', po.id), ('product_id', '=', self.product1.id)])

        # check that report will convert dozen to unit or not
        self.assertEquals(res_product1.qty_ordered, 12.0, 'UoM conversion is not working')
        # report should show in company currency (amount/rate) = (100/2)
        self.assertEquals(res_product1.price_total, 50.0, 'Currency conversion is not working')

        res_product2 = self.PurchaseReport.search([
            ('order_id', '=', po.id), ('product_id', '=', self.product2.id)])

        # Check that repost should show 6 unit of product
        self.assertEquals(res_product2.qty_ordered, 12.0, 'UoM conversion is not working')
        # report should show in company currency (amount/rate) = (200/2)
        self.assertEquals(res_product2.price_total, 100.0, 'Currency conversion is not working')
Exemplo n.º 17
0
 def test_employee_resource(self):
     _tz = 'Pacific/Apia'
     self.res_users_hr_officer.company_id.resource_calendar_id.tz = _tz
     Employee = self.env['hr.employee'].sudo(self.res_users_hr_officer)
     employee_form = Form(Employee)
     employee_form.name = 'Raoul Grosbedon'
     employee_form.work_email = '*****@*****.**'
     employee = employee_form.save()
     self.assertEqual(employee.tz, _tz)
    def test_invoice_shipment(self):
        """ Tests the case into which we make the invoice first, and then send
        the goods to our customer.
        """
        test_product = self.test_product_delivery
        #since the invoice come first, the COGS will use the standard price on product
        self.test_product_delivery.standard_price = 13
        self._set_initial_stock_for_product(test_product)

        sale_order = self._create_sale(test_product, '2018-01-01')

        invoice = self._create_invoice_for_so(sale_order, test_product, '2018-02-03')
        self.env['res.currency.rate'].create({
            'currency_id': self.currency_one.id,
            'company_id': self.company.id,
            'rate': 0.974784,
            'name': '2018-02-01',
        })
        invoice.action_invoice_open()

        self._process_pickings(sale_order.picking_ids)

        picking = self.env['stock.picking'].search([('sale_id', '=', sale_order.id)])
        self.check_reconciliation(invoice, picking, operation='sale')

        #return the goods and refund the invoice
        self.env['res.currency.rate'].create({
            'currency_id': self.currency_one.id,
            'company_id': self.company.id,
            'rate': 10.54739702,
            'name': '2018-03-01',
        })
        stock_return_picking_form = Form(self.env['stock.return.picking']
            .with_context(active_ids=picking.ids, active_id=picking.ids[0],
            active_model='stock.picking'))
        stock_return_picking = stock_return_picking_form.save()
        stock_return_picking.product_return_moves.quantity = 1.0
        stock_return_picking_action = stock_return_picking.create_returns()
        return_pick = self.env['stock.picking'].browse(stock_return_picking_action['res_id'])
        return_pick.action_assign()
        return_pick.move_lines.quantity_done = 1
        return_pick.action_done()
        self.env['res.currency.rate'].create({
            'currency_id': self.currency_one.id,
            'company_id': self.company.id,
            'rate': 9.56564564,
            'name': '2018-04-01',
        })
        refund_invoice_wiz = self.env['account.invoice.refund'].with_context(active_ids=[invoice.id]).create({
            'description': 'test_invoice_shipment_refund',
            'filter_refund': 'cancel',
        })
        refund_invoice_wiz.invoice_refund()
        refund_invoice = self.env['account.invoice'].search([('name', '=', 'test_invoice_shipment_refund')])[0]
        self.assertTrue(invoice.state == refund_invoice.state == 'paid'), "Invoice and refund should both be in 'Paid' state"
        self.check_reconciliation(refund_invoice, return_pick, operation='sale')
Exemplo n.º 19
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,
        })
        lot_2 = self.env['stock.production.lot'].create({
            'name': 'lot_2',
            'product_id': p2.id,
        })
        lot_3 = self.env['stock.production.lot'].create({
            'name': 'lot_3',
            'product_id': p2.id,
        })
        self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 100)
        self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 1, lot_id=lot_1)
        self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 3, lot_id=lot_2)
        self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 2, lot_id=lot_3)
        mo.action_assign()

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

        produce_wizard.do_produce()
        mo.button_mark_done()
        self.assertEqual(mo.state, 'done', "Production order should be in done state.")
        # Check quantity in stock before unbuild.
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p_final, self.stock_location), 5, 'You should have the 5 final product in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p1, self.stock_location), 80, 'You should have 80 products in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p2, self.stock_location, lot_id=lot_1), 0, 'You should have consumed all the 1 product for lot 1 in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p2, self.stock_location, lot_id=lot_2), 0, 'You should have consumed all the 3 product for lot 2 in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p2, self.stock_location, lot_id=lot_3), 1, 'You should have consumed only 1 product for lot3 in stock')

        self.env['mrp.unbuild'].create({
            'product_id': p_final.id,
            'bom_id': bom.id,
            'product_qty': 5.0,
            'mo_id': mo.id,
            'product_uom_id': self.uom_unit.id,
        }).action_unbuild()

        self.assertEqual(self.env['stock.quant']._get_available_quantity(p_final, self.stock_location), 0, 'You should have no more final product in stock after unbuild')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p1, self.stock_location), 100, 'You should have 80 products in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p2, self.stock_location, lot_id=lot_1), 1, 'You should have get your product with lot 1 in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p2, self.stock_location, lot_id=lot_2), 3, 'You should have the 3 basic product for lot 2 in stock')
        self.assertEqual(self.env['stock.quant']._get_available_quantity(p2, self.stock_location, lot_id=lot_3), 2, 'You should have get one product back for lot 3')
Exemplo n.º 20
0
    def test_01_sale_mrp_delivery_kit(self):
        """ Test delivered quantity on SO based on delivered quantity in pickings."""
        # intial so
        product = self.env.ref('mrp.product_product_table_kit')
        product.type = 'consu'
        product.invoice_policy = 'delivery'
        # Remove the MTO route as purchase is not installed and since the procurement removal the exception is directly raised
        product.write({'route_ids': [(6, 0, [self.warehouse.manufacture_pull_id.route_id.id])]})

        partner = self.env.ref('base.res_partner_1')
        # if `delivery` module is installed, a default property is set for the carrier to use
        # However this will lead to an extra line on the SO (the delivery line), which will force
        # the SO to have a different flow (and `invoice_state` value)
        partner.property_delivery_carrier_id = False

        f = Form(self.env['sale.order'])
        f.partner_id = partner
        with f.order_line.new() as line:
            line.product_id = product
            line.product_uom_qty = 5
        so = f.save()

        # confirm our standard so, check the picking
        so.action_confirm()
        self.assertTrue(so.picking_ids, 'Sale MRP: no picking created for "invoice on delivery" storable products')

        # invoice in on delivery, nothing should be invoiced
        with self.assertRaises(UserError):
            so.action_invoice_create()
        self.assertEqual(so.invoice_status, 'no', 'Sale MRP: so invoice_status should be "nothing to invoice" after invoicing')

        # deliver partially (1 of each instead of 5), check the so's invoice_status and delivered quantities
        pick = so.picking_ids
        pick.move_lines.write({'quantity_done': 1})
        wiz_act = pick.button_validate()
        wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
        wiz.process()
        self.assertEqual(so.invoice_status, 'no', 'Sale MRP: so invoice_status should be "no" after partial delivery of a kit')
        del_qty = sum(sol.qty_delivered for sol in so.order_line)
        self.assertEqual(del_qty, 0.0, 'Sale MRP: delivered quantity should be zero after partial delivery of a kit')
        # deliver remaining products, check the so's invoice_status and delivered quantities
        self.assertEqual(len(so.picking_ids), 2, 'Sale MRP: number of pickings should be 2')
        pick_2 = so.picking_ids[0]
        for move in pick_2.move_lines:
            if move.product_id.id == self.env.ref('mrp.product_product_computer_desk_bolt').id:
                move.write({'quantity_done': 19})
            else:
                move.write({'quantity_done': 4})
        pick_2.button_validate()

        del_qty = sum(sol.qty_delivered for sol in so.order_line)
        self.assertEqual(del_qty, 5.0, 'Sale MRP: delivered quantity should be 5.0 after complete delivery of a kit')
        self.assertEqual(so.invoice_status, 'to invoice', 'Sale MRP: so invoice_status should be "to invoice" after complete delivery of a kit')
Exemplo n.º 21
0
 def test_empty_routing(self):
     """ Check what happens when you work with an empty routing"""
     routing = self.env['mrp.routing'].create({'name': 'Routing without operations',
                                     'location_id': self.warehouse_1.wh_input_stock_loc_id.id,})
     self.bom_3.routing_id = routing.id
     production_form = Form(self.env['mrp.production'])
     production_form.product_id = self.product_6
     production_form.product_qty = 3
     production_form.product_uom_id = self.product_6.uom_id
     production = production_form.save()
     self.assertEqual(production.routing_id.id, False, 'The routing field should be empty on the mo')
     self.assertEqual(production.move_raw_ids[0].location_id.id, self.warehouse_1.wh_input_stock_loc_id.id, 'Raw moves start location should have altered.')
Exemplo n.º 22
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')
Exemplo n.º 23
0
    def test_shipping_cost(self):
        # Free delivery should not be taken into account when checking for minimum required threshold
        p_minimum_threshold_free_delivery = self.env['sale.coupon.program'].create({
            'name': 'free shipping if > 872 tax exl',
            'promo_code_usage': 'no_code_needed',
            'reward_type': 'free_shipping',
            'program_type': 'promotion_program',
            'rule_minimum_amount': 872,
        })
        p_minimum_threshold_discount = self.env['sale.coupon.program'].create({
            'name': '10% reduction if > 872 tax exl',
            'promo_code_usage': 'no_code_needed',
            'reward_type': 'discount',
            'program_type': 'promotion_program',
            'discount_type': 'percentage',
            'discount_percentage': 10.0,
            'rule_minimum_amount': 872,
        })
        order = self.empty_order
        self.iPadMini.taxes_id = self.tax_10pc_incl
        sol1 = self.env['sale.order.line'].create({
            'product_id': self.iPadMini.id,
            'name': 'Large Cabinet',
            'product_uom_qty': 3.0,
            'order_id': order.id,
        })
        order.recompute_coupon_lines()
        self.assertEqual(len(order.order_line.ids), 2, "We should get the 10% discount line since we bought 872.73$")
        order.carrier_id = self.env['delivery.carrier'].search([])[1]

        # I add delivery cost in Sales order
        delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({
            'default_order_id': order.id,
            'default_carrier_id': self.env['delivery.carrier'].search([])[1]
        }))
        choose_delivery_carrier = delivery_wizard.save()
        choose_delivery_carrier.button_confirm()

        order.recompute_coupon_lines()
        self.assertEqual(len(order.order_line.ids), 3, "We should get the delivery line but not the free delivery since we are below 872.73$ with the 10% discount")

        p_minimum_threshold_free_delivery.sequence = 10
        (order.order_line - sol1).unlink()
        # I add delivery cost in Sales order
        delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({
            'default_order_id': order.id,
            'default_carrier_id': self.env['delivery.carrier'].search([])[1]
        }))
        choose_delivery_carrier = delivery_wizard.save()
        choose_delivery_carrier.button_confirm()
        order.recompute_coupon_lines()
        self.assertEqual(len(order.order_line.ids), 4, "We should get both promotion line since the free delivery will be applied first and won't change the SO total")
Exemplo n.º 24
0
    def create_account_invoice(self, invoice_type, partner, product, quantity=0.0, price_unit=0.0):
        """ Create an invoice as in a view by triggering its onchange methods"""

        invoice_form = Form(self.env['account.invoice'].with_context(type=invoice_type))
        invoice_form.partner_id = partner
        with invoice_form.invoice_line_ids.new() as line:
            line.product_id = product
            line.quantity = quantity
            line.price_unit = price_unit

        invoice = invoice_form.save()
        invoice.action_invoice_open()
        return invoice
Exemplo n.º 25
0
    def test_product_produce_2(self):
        """ Checks that, for a BOM where one of the components is tracked by serial number and the
        other is not tracked, when creating a manufacturing order for two finished products and
        reserving, the produce wizards proposes the corrects lines when producing one at a time.
        """
        self.stock_location = self.env.ref('stock.stock_location_stock')
        mo, bom, p_final, p1, p2 = self.generate_mo(tracking_base_1='serial', qty_base_1=1, qty_final=2)
        self.assertEqual(len(mo), 1, 'MO should have been created')

        lot_p1_1 = self.env['stock.production.lot'].create({
            'name': 'lot1',
            'product_id': p1.id,
        })
        lot_p1_2 = self.env['stock.production.lot'].create({
            'name': 'lot2',
            'product_id': p1.id,
        })

        self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 1, lot_id=lot_p1_1)
        self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 1, lot_id=lot_p1_2)
        self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5)

        mo.action_assign()
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))

        self.assertEqual(len(produce_form.workorder_line_ids), 3, 'You should have 3 produce lines. One for each serial to consume and for the untracked product.')
        produce_form.qty_producing = 1

        # get the proposed lot
        consumed_lots = self.env['stock.production.lot']
        for workorder_line in produce_form.workorder_line_ids._records:
            if workorder_line['product_id'] == p1.id:
                consumed_lots |= self.env['stock.production.lot'].browse(workorder_line['lot_id'])
        consumed_lots.ensure_one()
        product_produce = produce_form.save()
        product_produce.do_produce()

        remaining_lot = (lot_p1_1 | lot_p1_2) - consumed_lots
        remaining_lot.ensure_one()

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id': mo.id,
            'active_ids': [mo.id],
        }))
        product_produce = produce_form.save()
        self.assertEqual(len(product_produce.workorder_line_ids), 2, 'You should have 2 produce lines left.')
        for line in product_produce.workorder_line_ids.filtered(lambda x: x.lot_id):
            self.assertEqual(line.lot_id, remaining_lot, 'Wrong lot proposed.')
Exemplo n.º 26
0
 def test_employee_from_user(self):
     _tz = 'Pacific/Apia'
     _tz2 = 'America/Tijuana'
     self.res_users_hr_officer.company_id.resource_calendar_id.tz = _tz
     self.res_users_hr_officer.tz = _tz2
     Employee = self.env['hr.employee'].sudo(self.res_users_hr_officer)
     employee_form = Form(Employee)
     employee_form.name = 'Raoul Grosbedon'
     employee_form.work_email = '*****@*****.**'
     employee_form.user_id = self.res_users_hr_officer
     employee = employee_form.save()
     self.assertEqual(employee.name, 'Raoul Grosbedon')
     self.assertEqual(employee.work_email, self.res_users_hr_officer.email)
     self.assertEqual(employee.tz, self.res_users_hr_officer.tz)
Exemplo n.º 27
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"')
Exemplo n.º 28
0
    def test_anglosaxon_valuation(self):
        self.env.user.company_id.anglo_saxon_accounting = True
        self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
        self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
        self.product1.product_tmpl_id.invoice_policy = 'delivery'
        price_diff_account = self.env['account.account'].create({
            'name': 'price diff account',
            'code': 'price diff account',
            'user_type_id': self.env.ref('account.data_account_type_current_assets').id,
        })
        self.product1.property_account_creditor_price_difference = price_diff_account

        # Create PO
        po_form = Form(self.env['purchase.order'])
        po_form.partner_id = self.partner_id
        with po_form.order_line.new() as po_line:
            po_line.product_id = self.product1
            po_line.product_qty = 1
            po_line.price_unit = 10.0
        order = po_form.save()
        order.button_confirm()

        # Receive the goods
        receipt = order.picking_ids[0]
        receipt.move_lines.quantity_done = 1
        receipt.button_validate()

        # Create an invoice with a different price
        invoice = self.env['account.invoice'].create({
            'partner_id': order.partner_id.id,
            'purchase_id': order.id,
            'account_id': order.partner_id.property_account_payable_id.id,
            'type': 'in_invoice',
        })
        invoice.purchase_order_change()
        invoice.invoice_line_ids[0].price_unit = 15.0
        invoice.action_invoice_open()

        # Check what was posted in the price difference account
        price_diff_aml = self.env['account.move.line'].search([('account_id','=',price_diff_account.id)])
        self.assertEquals(len(price_diff_aml), 1, "Only one line should have been generated in the price difference account.")
        self.assertAlmostEquals(price_diff_aml.debit, 5, "Price difference should be equal to 5 (15-10)")

        # Check what was posted in stock input account
        input_aml = self.env['account.move.line'].search([('account_id','=',self.stock_input_account.id)])
        self.assertEquals(len(input_aml), 2, "Only two lines should have been generated in stock input account: one when receiving the product, one when making the invoice.")
        self.assertAlmostEquals(sum(input_aml.mapped('debit')), 10, "Total debit value on stock input account should be equal to the original PO price of the product.")
        self.assertAlmostEquals(sum(input_aml.mapped('credit')), 10, "Total credit value on stock input account should be equal to the original PO price of the product.")
Exemplo n.º 29
0
 def test_partner_4(self):
     """ Create a new partner, select a parent company, and choose type subcontractor (debug
     not active). Checks the customer and supplier locations are set to the subcontracting one
     onces saved.
     """
     that_company = self.env['res.partner'].create({
         'is_company': True,
         'name': "That Company",
     })
     partner_form = Form(self.env['res.partner'])
     partner_form.name = 'That Guy'
     partner_form.parent_id = that_company
     partner_form.type = 'subcontractor'
     subcontractor = partner_form.save()
     self.assertEquals(subcontractor.property_stock_supplier, self.env.user.company_id.subcontracting_location_id)
     self.assertEquals(subcontractor.property_stock_customer, self.env.user.company_id.subcontracting_location_id)
Exemplo n.º 30
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()
Exemplo n.º 31
0
    def test_tracking_backorder_immediate_production_serial_1(self):
        """ Create a MO to build 2 of a SN tracked product.
        Build both the starting MO and its backorder as immediate productions
        (i.e. Mark As Done without setting SN/filling any quantities)
        """
        mo, _, p_final, p1, p2 = self.generate_mo(qty_final=2,
                                                  tracking_final='serial',
                                                  qty_base_1=2,
                                                  qty_base_2=2)
        self.env['stock.quant']._update_available_quantity(
            p1, self.stock_location_components, 2.0)
        self.env['stock.quant']._update_available_quantity(
            p2, self.stock_location_components, 2.0)
        mo.action_assign()
        res_dict = mo.button_mark_done()
        self.assertEqual(res_dict.get('res_model'), 'mrp.immediate.production')
        immediate_wizard = Form(self.env[res_dict['res_model']].with_context(
            res_dict['context'])).save()
        res_dict = immediate_wizard.process()
        self.assertEqual(res_dict.get('res_model'), 'mrp.production.backorder')
        backorder_wizard = Form(self.env[res_dict['res_model']].with_context(
            res_dict['context']))

        # backorder should automatically open
        action = backorder_wizard.save().action_backorder()
        self.assertEqual(action.get('res_model'), 'mrp.production')
        backorder_mo_form = Form(self.env[action['res_model']].with_context(
            action['context']).browse(action['res_id']))
        backorder_mo = backorder_mo_form.save()
        res_dict = backorder_mo.button_mark_done()
        self.assertEqual(res_dict.get('res_model'), 'mrp.immediate.production')
        immediate_wizard = Form(self.env[res_dict['res_model']].with_context(
            res_dict['context'])).save()
        immediate_wizard.process()

        self.assertEqual(
            self.env['stock.quant']._get_available_quantity(
                p_final, self.stock_location), 2,
            "Incorrect number of final product produced.")
        self.assertEqual(
            len(self.env['stock.production.lot'].search([
                ('product_id', '=', p_final.id)
            ])), 2, "Serial Numbers were not correctly produced.")
Exemplo n.º 32
0
    def test_03_po_return_and_modify(self):
        """Change the picking code of the delivery to internal. Make a PO for 10 units, go to the
        picking and return 5, edit the PO line to 15 units.
        The purpose of the test is to check the consistencies across the received quantities and the
        procurement quantities.
        """
        # Change the code of the picking type delivery
        self.env['stock.picking.type'].search([('code', '=', 'outgoing')
                                               ]).write({'code': 'internal'})

        # Sell and deliver 10 units
        item1 = self.product_id_1
        uom_unit = self.env.ref('uom.product_uom_unit')
        po1 = self.env['purchase.order'].create({
            'partner_id':
            self.partner_a.id,
            'order_line': [
                (0, 0, {
                    'name':
                    item1.name,
                    'product_id':
                    item1.id,
                    'product_qty':
                    10,
                    'product_uom':
                    uom_unit.id,
                    'price_unit':
                    123.0,
                    'date_planned':
                    datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                }),
            ],
        })
        po1.button_confirm()

        picking = po1.picking_ids
        wiz_act = picking.button_validate()
        wiz = Form(self.env[wiz_act['res_model']].with_context(
            wiz_act['context'])).save()
        wiz.process()

        # Return 5 units
        stock_return_picking_form = Form(
            self.env['stock.return.picking'].with_context(
                active_ids=picking.ids,
                active_id=picking.ids[0],
                active_model='stock.picking'))
        return_wiz = stock_return_picking_form.save()
        for return_move in return_wiz.product_return_moves:
            return_move.write({'quantity': 5, 'to_refund': True})
        res = return_wiz.create_returns()
        return_pick = self.env['stock.picking'].browse(res['res_id'])
        wiz_act = return_pick.button_validate()
        wiz = Form(self.env[wiz_act['res_model']].with_context(
            wiz_act['context'])).save()
        wiz.process()

        self.assertEqual(po1.order_line.qty_received, 5)

        # Deliver 15 instead of 10.
        po1.write(
            {'order_line': [
                (1, po1.order_line[0].id, {
                    'product_qty': 15
                }),
            ]})

        # A new move of 10 unit (15 - 5 units)
        self.assertEqual(po1.order_line.qty_received, 5)
        self.assertEqual(po1.picking_ids[-1].move_lines.product_qty, 10)
Exemplo n.º 33
0
    def test_pack_in_receipt_two_step_multi_putaway(self):
        """ Checks all works right in the following specific corner case:

          * For a two-step receipt, receives two products using two putaways
          targeting different locations.
          * Puts these products in a package then valid the receipt.
          * Cancels the automatically generated internal transfer then create a new one.
          * In this internal transfer, adds the package then valid it.
        """
        grp_multi_loc = self.env.ref('stock.group_stock_multi_locations')
        grp_multi_step_rule = self.env.ref('stock.group_adv_location')
        grp_pack = self.env.ref('stock.group_tracking_lot')
        self.env.user.write({'groups_id': [(3, grp_multi_loc.id)]})
        self.env.user.write({'groups_id': [(3, grp_multi_step_rule.id)]})
        self.env.user.write({'groups_id': [(3, grp_pack.id)]})
        self.warehouse.reception_steps = 'two_steps'
        # Settings of receipt.
        self.warehouse.in_type_id.show_operations = True
        self.warehouse.in_type_id.show_entire_packs = True
        self.warehouse.in_type_id.show_reserved = True
        # Settings of internal transfer.
        self.warehouse.int_type_id.show_operations = True
        self.warehouse.int_type_id.show_entire_packs = True
        self.warehouse.int_type_id.show_reserved = True

        # Creates two new locations for putaway.
        location_form = Form(self.env['stock.location'])
        location_form.name = 'Shelf A'
        location_form.location_id = self.stock_location
        loc_shelf_A = location_form.save()
        location_form = Form(self.env['stock.location'])
        location_form.name = 'Shelf B'
        location_form.location_id = self.stock_location
        loc_shelf_B = location_form.save()

        # Creates a new putaway rule for productA and productB.
        putaway_A = self.env['stock.putaway.rule'].create({
            'product_id':
            self.productA.id,
            'location_in_id':
            self.stock_location.id,
            'location_out_id':
            loc_shelf_A.id,
        })
        putaway_B = self.env['stock.putaway.rule'].create({
            'product_id':
            self.productB.id,
            'location_in_id':
            self.stock_location.id,
            'location_out_id':
            loc_shelf_B.id,
        })
        self.stock_location.putaway_rule_ids = [(4, putaway_A.id, 0),
                                                (4, putaway_B.id, 0)]
        # location_form = Form(self.stock_location)
        # location_form.putaway_rule_ids = [(4, putaway_A.id, 0), (4, putaway_B.id, 0), ],
        # self.stock_location = location_form.save()

        # Create a new receipt with the two products.
        receipt_form = Form(self.env['stock.picking'])
        receipt_form.picking_type_id = self.warehouse.in_type_id
        # Add 2 lines
        with receipt_form.move_ids_without_package.new() as move_line:
            move_line.product_id = self.productA
            move_line.product_uom_qty = 1
        with receipt_form.move_ids_without_package.new() as move_line:
            move_line.product_id = self.productB
            move_line.product_uom_qty = 1
        receipt = receipt_form.save()
        receipt.action_confirm()

        # Adds quantities then packs them and valids the receipt.
        receipt_form = Form(receipt)
        with receipt_form.move_line_ids_without_package.edit(0) as move_line:
            move_line.qty_done = 1
        with receipt_form.move_line_ids_without_package.edit(1) as move_line:
            move_line.qty_done = 1
        receipt = receipt_form.save()
        receipt.put_in_pack()
        receipt.button_validate()

        receipt_package = receipt.package_level_ids_details[0]
        self.assertEqual(receipt_package.location_dest_id.id,
                         receipt.location_dest_id.id)
        self.assertEqual(receipt_package.move_line_ids[0].location_dest_id.id,
                         receipt.location_dest_id.id)
        self.assertEqual(receipt_package.move_line_ids[1].location_dest_id.id,
                         receipt.location_dest_id.id)

        # Checks an internal transfer was created following the validation of the receipt.
        internal_transfer = self.env['stock.picking'].search(
            [('picking_type_id', '=', self.warehouse.int_type_id.id)],
            order='id desc',
            limit=1)
        self.assertEqual(internal_transfer.origin, receipt.name)
        self.assertEqual(len(internal_transfer.package_level_ids_details), 1)
        internal_package = internal_transfer.package_level_ids_details[0]
        self.assertEqual(internal_package.location_dest_id.id,
                         internal_transfer.location_dest_id.id)
        self.assertNotEqual(
            internal_package.location_dest_id.id, putaway_A.location_out_id.id,
            "The package destination location must be the one from the picking."
        )
        self.assertNotEqual(
            internal_package.move_line_ids[0].location_dest_id.id,
            putaway_A.location_out_id.id,
            "The move line destination location must be the one from the picking."
        )
        self.assertNotEqual(
            internal_package.move_line_ids[1].location_dest_id.id,
            putaway_A.location_out_id.id,
            "The move line destination location must be the one from the picking."
        )

        # Cancels the internal transfer and creates a new one.
        internal_transfer.action_cancel()
        internal_form = Form(self.env['stock.picking'])
        internal_form.picking_type_id = self.warehouse.int_type_id
        internal_form.location_id = self.warehouse.wh_input_stock_loc_id
        with internal_form.package_level_ids_details.new() as pack_line:
            pack_line.package_id = receipt_package.package_id
        internal_transfer = internal_form.save()

        # Checks the package fields have been correctly set.
        internal_package = internal_transfer.package_level_ids_details[0]
        self.assertEqual(internal_package.location_dest_id.id,
                         internal_transfer.location_dest_id.id)
        internal_transfer.action_assign()
        self.assertEqual(internal_package.location_dest_id.id,
                         internal_transfer.location_dest_id.id)
        self.assertNotEqual(
            internal_package.location_dest_id.id, putaway_A.location_out_id.id,
            "The package destination location must be the one from the picking."
        )
        self.assertNotEqual(
            internal_package.move_line_ids[0].location_dest_id.id,
            putaway_A.location_out_id.id,
            "The move line destination location must be the one from the picking."
        )
        self.assertNotEqual(
            internal_package.move_line_ids[1].location_dest_id.id,
            putaway_A.location_out_id.id,
            "The move line destination location must be the one from the picking."
        )
        internal_transfer.button_validate()
Exemplo n.º 34
0
    def test_manufacturing_complex_product_3_steps(self):
        """ Test MO/picking after manufacturing a complex product which uses
        manufactured components. Ensure that everything is created and picked
        correctly.
        """
        # Create manifactured product which uses another manifactured

        product_form = Form(self.env['product.product'])
        product_form.name = 'Arrow'
        product_form.type = 'product'
        product_form.route_ids.clear()
        product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id)
        product_form.route_ids.add(self.warehouse.mto_pull_id.route_id)
        self.complex_product = product_form.save()

        ## Create raw product for manufactured product
        product_form = Form(self.env['product.product'])
        product_form.name = 'Raw Iron'
        product_form.type = 'product'
        product_form.uom_id = self.uom_unit
        product_form.uom_po_id = self.uom_unit
        self.raw_product_2 = product_form.save()

        ## Create bom for manufactured product
        bom_product_form = Form(self.env['mrp.bom'])
        bom_product_form.product_id = self.complex_product
        bom_product_form.product_tmpl_id = self.complex_product.product_tmpl_id
        with bom_product_form.bom_line_ids.new() as line:
            line.product_id = self.finished_product
            line.product_qty = 1.0
        with bom_product_form.bom_line_ids.new() as line:
            line.product_id = self.raw_product_2
            line.product_qty = 1.0

        self.complex_bom = bom_product_form.save()

        with Form(self.warehouse) as warehouse:
            warehouse.manufacture_steps = 'pbm_sam'

        production_form = Form(self.env['mrp.production'])
        production_form.product_id = self.complex_product
        production_form.picking_type_id = self.warehouse.manu_type_id
        production = production_form.save()

        move_raw_ids = production.move_raw_ids
        self.assertEqual(len(move_raw_ids), 2)
        sfp_move_raw_id, raw_move_raw_id = move_raw_ids
        self.assertEqual(sfp_move_raw_id.product_id, self.finished_product)
        self.assertEqual(raw_move_raw_id.product_id, self.raw_product_2)

        for move_raw_id in move_raw_ids:
            self.assertEqual(move_raw_id.picking_type_id, self.warehouse.manu_type_id)

            pbm_move = move_raw_id.move_orig_ids
            self.assertEqual(len(pbm_move), 1)
            self.assertEqual(pbm_move.location_id, self.warehouse.lot_stock_id)
            self.assertEqual(pbm_move.location_dest_id, self.warehouse.pbm_loc_id)
            self.assertEqual(pbm_move.picking_type_id, self.warehouse.pbm_type_id)

        move_finished_ids = production.move_finished_ids
        self.assertEqual(len(move_finished_ids), 1)
        self.assertEqual(move_finished_ids.product_id, self.complex_product)
        self.assertEqual(move_finished_ids.picking_type_id, self.warehouse.manu_type_id)
        sam_move = move_finished_ids.move_dest_ids
        self.assertEqual(len(sam_move), 1)
        self.assertEqual(sam_move.location_id, self.warehouse.sam_loc_id)
        self.assertEqual(sam_move.location_dest_id, self.warehouse.lot_stock_id)
        self.assertEqual(sam_move.picking_type_id, self.warehouse.sam_type_id)
        self.assertFalse(sam_move.move_dest_ids)

        pickings = production.picking_ids.sorted('id', reverse=True)
        self.assertEqual(len(pickings), 3)

        # Picking: SFP PostProcessing -> Stock
        ## Stick from Subprocess
        picking = pickings[1]
        self.assertEqual(len(picking.move_lines), 1)
        picking.product_id = self.finished_product

        # Picking: PC Stock -> Preprocessing
        ## Stick
        ## Raw Iron
        picking = pickings[0]
        self.assertEqual(len(picking.move_lines), 2)
        picking.move_lines[0].product_id = self.finished_product
        picking.move_lines[1].product_id = self.raw_product_2

        # Picking: SFP PostProcessing -> Stock
        ## Arrow from this process
        picking = pickings[2]
        self.assertEqual(len(picking.move_lines), 1)
        picking.product_id = self.complex_product
Exemplo n.º 35
0
    def test_sale(self):
        so = Form(self.env["sale.order"])
        so.partner_id = self.partner_a

        with so.order_line.new() as so_line:
            so_line.product_id = self.product_a
            so_line.product_uom_qty = 100

        with so.order_line.new() as so_line:
            so_line.product_id = self.product_b
            so_line.product_uom_qty = 10

        self.so = so.save()
        self.so.action_confirm()

        wizard = Form(self.env["sale.advance.payment.inv"].with_context(active_ids=self.so.ids))
        wizard.advance_payment_method = "percentage"
        wizard.amount = "50"
        wizard = wizard.save()
        wizard.create_invoices()
    def setUp(self):
        super(TestMultistepManufacturingWarehouse, self).setUp()
        # Create warehouse
        self.customer_location = self.env['ir.model.data'].xmlid_to_res_id(
            'stock.stock_location_customers')
        warehouse_form = Form(self.env['stock.warehouse'])
        warehouse_form.name = 'Test Warehouse'
        warehouse_form.code = 'TWH'
        self.warehouse = warehouse_form.save()

        self.uom_unit = self.env.ref('uom.product_uom_unit')

        # Create manufactured product
        product_form = Form(self.env['product.product'])
        product_form.name = 'Stick'
        product_form.uom_id = self.uom_unit
        product_form.uom_po_id = self.uom_unit
        product_form.type = 'product'
        product_form.route_ids.clear()
        product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id)
        product_form.route_ids.add(self.warehouse.mto_pull_id.route_id)
        self.finished_product = product_form.save()

        # Create raw product for manufactured product
        product_form = Form(self.env['product.product'])
        product_form.name = 'Raw Stick'
        product_form.type = 'product'
        product_form.uom_id = self.uom_unit
        product_form.uom_po_id = self.uom_unit
        self.raw_product = product_form.save()

        # Create bom for manufactured product
        bom_product_form = Form(self.env['mrp.bom'])
        bom_product_form.product_id = self.finished_product
        bom_product_form.product_tmpl_id = self.finished_product.product_tmpl_id
        bom_product_form.product_qty = 1.0
        bom_product_form.type = 'normal'
        with bom_product_form.bom_line_ids.new() as bom_line:
            bom_line.product_id = self.raw_product
            bom_line.product_qty = 2.0

        self.bom = bom_product_form.save()
    def test_manufacturing_flow(self):
        """ Simulate a pick pack ship delivery combined with a picking before
        manufacturing and store after manufacturing. Also ensure that the MO and
        the moves to stock are created with the generic pull rules.
        In order to trigger the rule we create a picking to the customer with
        the 'make to order' procure method
        """
        with Form(self.warehouse) as warehouse:
            warehouse.manufacture_steps = 'pbm_sam'
            warehouse.delivery_steps = 'pick_pack_ship'
        self.warehouse.flush()
        self.env['stock.quant']._update_available_quantity(
            self.raw_product, self.warehouse.lot_stock_id, 4.0)
        picking_customer = self.env['stock.picking'].create({
            'location_id':
            self.warehouse.wh_output_stock_loc_id.id,
            'location_dest_id':
            self.customer_location,
            'partner_id':
            self.env['ir.model.data'].xmlid_to_res_id('base.res_partner_4'),
            'picking_type_id':
            self.warehouse.out_type_id.id,
        })
        self.env['stock.move'].create({
            'name':
            self.finished_product.name,
            'product_id':
            self.finished_product.id,
            'product_uom_qty':
            2,
            'product_uom':
            self.uom_unit.id,
            'picking_id':
            picking_customer.id,
            'location_id':
            self.warehouse.wh_output_stock_loc_id.id,
            'location_dest_id':
            self.customer_location,
            'procure_method':
            'make_to_order',
            'state':
            'draft',
        })
        picking_customer.action_confirm()
        production_order = self.env['mrp.production'].search([
            ('product_id', '=', self.finished_product.id)
        ])
        self.assertTrue(production_order)

        picking_stock_preprod = self.env['stock.move'].search([
            ('product_id', '=', self.raw_product.id),
            ('location_id', '=', self.warehouse.lot_stock_id.id),
            ('location_dest_id', '=', self.warehouse.pbm_loc_id.id),
            ('picking_type_id', '=', self.warehouse.pbm_type_id.id)
        ]).picking_id
        picking_stock_postprod = self.env['stock.move'].search([
            ('product_id', '=', self.finished_product.id),
            ('location_id', '=', self.warehouse.sam_loc_id.id),
            ('location_dest_id', '=', self.warehouse.lot_stock_id.id),
            ('picking_type_id', '=', self.warehouse.sam_type_id.id)
        ]).picking_id

        self.assertTrue(picking_stock_preprod)
        self.assertTrue(picking_stock_postprod)
        self.assertEqual(picking_stock_preprod.state, 'confirmed')
        self.assertEqual(picking_stock_postprod.state, 'waiting')

        picking_stock_preprod.action_assign()
        picking_stock_preprod.move_line_ids.qty_done = 4
        picking_stock_preprod._action_done()

        self.assertFalse(
            sum(self.env['stock.quant']._gather(
                self.raw_product,
                self.warehouse.lot_stock_id).mapped('quantity')))
        self.assertTrue(self.env['stock.quant']._gather(
            self.raw_product, self.warehouse.pbm_loc_id))

        production_order.action_assign()
        self.assertEqual(production_order.reservation_state, 'assigned')
        self.assertEqual(picking_stock_postprod.state, 'waiting')

        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            production_order.id,
            'active_ids': [production_order.id],
        }))
        produce_form.qty_producing = production_order.product_qty
        product_produce = produce_form.save()
        product_produce.do_produce()
        production_order.button_mark_done()

        self.assertFalse(
            sum(self.env['stock.quant']._gather(
                self.raw_product,
                self.warehouse.pbm_loc_id).mapped('quantity')))

        self.assertEqual(picking_stock_postprod.state, 'assigned')

        picking_stock_pick = self.env['stock.move'].search([
            ('product_id', '=', self.finished_product.id),
            ('location_id', '=', self.warehouse.lot_stock_id.id),
            ('location_dest_id', '=', self.warehouse.wh_pack_stock_loc_id.id),
            ('picking_type_id', '=', self.warehouse.pick_type_id.id)
        ]).picking_id
        self.assertEqual(
            picking_stock_pick.move_lines.move_orig_ids.picking_id,
            picking_stock_postprod)
Exemplo n.º 38
0
    def test_product_produce_uom_2(self):
        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"')
Exemplo n.º 39
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.')
Exemplo n.º 40
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.")
Exemplo n.º 41
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')
Exemplo n.º 42
0
    def test_no_tracking_pbm_sam_1(self):
        """Create a MO for 4 product. Produce 1. The backorder button should
        appear and hitting mark as done should open the backorder wizard. In the backorder
        wizard, choose to do the backorder. A new MO for 3 self.untracked_bom should be
        created.
        The sequence of the first MO should be MO/001-01, the sequence of the second MO
        should be MO/001-02.
        Check that all MO are reachable through the procurement group.
        """
        with Form(self.warehouse) as warehouse:
            warehouse.manufacture_steps = 'pbm_sam'
        production, _, product_to_build, product_to_use_1, product_to_use_2 = self.generate_mo(
            qty_base_1=4,
            qty_final=4,
            picking_type_id=self.warehouse.manu_type_id)

        move_raw_ids = production.move_raw_ids
        self.assertEqual(len(move_raw_ids), 2)
        self.assertEqual(set(move_raw_ids.mapped("product_id")),
                         {product_to_use_1, product_to_use_2})

        pbm_move = move_raw_ids.move_orig_ids
        self.assertEqual(len(pbm_move), 2)
        self.assertEqual(set(pbm_move.mapped("product_id")),
                         {product_to_use_1, product_to_use_2})
        self.assertFalse(pbm_move.move_orig_ids)
        self.assertEqual(
            sum(
                pbm_move.filtered(lambda m: m.product_id.id == product_to_use_1
                                  .id).mapped("product_qty")), 16)
        self.assertEqual(
            sum(
                pbm_move.filtered(lambda m: m.product_id.id == product_to_use_2
                                  .id).mapped("product_qty")), 4)

        sam_move = production.move_finished_ids.move_dest_ids
        self.assertEqual(len(sam_move), 1)
        self.assertEqual(sam_move.product_id.id, product_to_build.id)
        self.assertEqual(sum(sam_move.mapped("product_qty")), 4)

        mo_form = Form(production)
        mo_form.qty_producing = 1
        production = mo_form.save()

        action = production.button_mark_done()
        backorder = Form(self.env['mrp.production.backorder'].with_context(
            **action['context']))
        backorder.save().action_backorder()

        mo_backorder = production.procurement_group_id.mrp_production_ids[-1]
        self.assertEqual(mo_backorder.delivery_count, 2)

        pbm_move |= mo_backorder.move_raw_ids.move_orig_ids
        self.assertEqual(
            sum(
                pbm_move.filtered(lambda m: m.product_id.id == product_to_use_1
                                  .id).mapped("product_qty")), 16)
        self.assertEqual(
            sum(
                pbm_move.filtered(lambda m: m.product_id.id == product_to_use_2
                                  .id).mapped("product_qty")), 4)

        sam_move |= mo_backorder.move_finished_ids.move_orig_ids
        self.assertEqual(sum(sam_move.mapped("product_qty")), 4)
Exemplo n.º 43
0
    def test_multiple_post_inventory(self):
        """ Check the consumed quants of the produced quants when intermediate calls to `post_inventory` during a MO."""

        # create a bom for `custom_laptop` with components that aren't tracked
        unit = self.ref("uom.product_uom_unit")
        custom_laptop = self.env.ref("product.product_product_27")
        custom_laptop.tracking = 'none'
        product_charger = self.env['product.product'].create({
            'name': 'Charger',
            'type': 'product',
            'uom_id': unit,
            'uom_po_id': unit
        })
        product_keybord = self.env['product.product'].create({
            'name': 'Usb Keybord',
            'type': 'product',
            'uom_id': unit,
            'uom_po_id': unit
        })
        bom_custom_laptop = self.env['mrp.bom'].create({
            'product_tmpl_id':
            custom_laptop.product_tmpl_id.id,
            'product_qty':
            1,
            'product_uom_id':
            unit,
            'bom_line_ids': [(0, 0, {
                'product_id': product_charger.id,
                'product_qty': 1,
                'product_uom_id': unit
            }),
                             (0, 0, {
                                 'product_id': product_keybord.id,
                                 'product_qty': 1,
                                 'product_uom_id': unit
                             })]
        })

        # put the needed products in stock
        source_location_id = self.ref('stock.stock_location_14')
        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': 2,
                'location_id': source_location_id
            }),
                         (0, 0, {
                             'product_id': product_keybord.id,
                             'product_uom_id': product_keybord.uom_id.id,
                             'product_qty': 2,
                             'location_id': source_location_id
                         })]
        })
        inventory.action_validate()

        # create a mo for this bom
        mo_custom_laptop_form = Form(self.env['mrp.production'])
        mo_custom_laptop_form.product_id = custom_laptop
        mo_custom_laptop_form.product_qty = 2
        mo_custom_laptop = mo_custom_laptop_form.save()
        mo_custom_laptop.action_confirm()
        mo_custom_laptop.action_assign()
        self.assertEqual(mo_custom_laptop.reservation_state, 'assigned')

        # produce one item, call `post_inventory`
        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 = 1.00
        custom_laptop_produce = produce_form.save()
        custom_laptop_produce.do_produce()
        mo_custom_laptop.post_inventory()

        # check the consumed quants of the produced quant
        first_move = mo_custom_laptop.move_finished_ids.filtered(
            lambda mo: mo.state == 'done')

        second_move = mo_custom_laptop.move_finished_ids.filtered(
            lambda mo: mo.state == 'confirmed')

        # produce the second item, call `post_inventory`
        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 = 1.00
        custom_laptop_produce = produce_form.save()
        custom_laptop_produce.do_produce()
        mo_custom_laptop.post_inventory()
Exemplo n.º 44
0
    def test_reminder_1(self):
        """Set to send reminder today, check if a reminder can be send to the
        partner.
        """
        po = Form(self.env['purchase.order'])
        po.partner_id = self.partner_a
        with po.order_line.new() as po_line:
            po_line.product_id = self.product_a
            po_line.product_qty = 1
            po_line.price_unit = 100
        with po.order_line.new() as po_line:
            po_line.product_id = self.product_b
            po_line.product_qty = 10
            po_line.price_unit = 200
        # set to send reminder today
        po.date_planned = fields.Datetime.now() + timedelta(days=1)
        po.receipt_reminder_email = True
        po.reminder_date_before_receipt = 1
        po = po.save()
        po.button_confirm()

        # check vendor is a message recipient
        self.assertTrue(po.partner_id in po.message_partner_ids)

        old_messages = po.message_ids
        po._send_reminder_mail()
        messages_send = po.message_ids - old_messages
        # check reminder send
        self.assertTrue(messages_send)
        self.assertTrue(po.partner_id in messages_send.mapped('partner_ids'))

        # check confirm button
        po.confirm_reminder_mail()
        self.assertTrue(po.mail_reminder_confirmed)
Exemplo n.º 45
0
    def test_flow_tracked_backorder(self):
        """ This test uses tracked (serial and lot) component and tracked (serial) finished product """
        todo_nb = 4
        self.comp2.tracking = 'lot'
        self.finished_product.tracking = 'serial'

        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished_product
            move.product_uom_qty = todo_nb
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # We should be able to call the 'record_components' button
        self.assertTrue(picking_receipt.display_action_record_components)

        # Check the created manufacturing order
        mo = self.env['mrp.production'].search([('bom_id', '=',
                                                 self.bom_tracked.id)])
        self.assertEqual(len(mo), 1)
        self.assertEqual(len(mo.picking_ids), 0)
        wh = picking_receipt.picking_type_id.warehouse_id
        self.assertEqual(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        lot_comp2 = self.env['stock.production.lot'].create({
            'name':
            'lot_comp2',
            'product_id':
            self.comp2.id,
            'company_id':
            self.env.company.id,
        })
        serials_finished = []
        serials_comp1 = []
        for i in range(todo_nb):
            serials_finished.append(self.env['stock.production.lot'].create({
                'name':
                'serial_fin_%s' % i,
                'product_id':
                self.finished_product.id,
                'company_id':
                self.env.company.id,
            }))
            serials_comp1.append(self.env['stock.production.lot'].create({
                'name':
                'serials_comp1_%s' % i,
                'product_id':
                self.comp1_sn.id,
                'company_id':
                self.env.company.id,
            }))

        for i in range(todo_nb):
            action = picking_receipt.action_record_components()
            mo = self.env['mrp.production'].browse(action['res_id'])
            mo_form = Form(mo.with_context(**action['context']),
                           view=action['view_id'])
            mo_form.lot_producing_id = serials_finished[i]
            with mo_form.move_line_raw_ids.edit(0) as ml:
                self.assertEqual(ml.product_id, self.comp1_sn)
                ml.lot_id = serials_comp1[i]
            with mo_form.move_line_raw_ids.edit(1) as ml:
                self.assertEqual(ml.product_id, self.comp2)
                ml.lot_id = lot_comp2
            mo = mo_form.save()
            mo.subcontracting_record_component()

        # We should not be able to call the 'record_components' button
        self.assertFalse(picking_receipt.display_action_record_components)

        picking_receipt.button_validate()
        self.assertEqual(mo.state, 'done')
        self.assertEqual(
            mo.procurement_group_id.mrp_production_ids.mapped("state"),
            ['done'] * todo_nb)
        self.assertEqual(len(mo.procurement_group_id.mrp_production_ids),
                         todo_nb)
        self.assertEqual(
            mo.procurement_group_id.mrp_production_ids.mapped("qty_produced"),
            [1] * todo_nb)

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(
            self.comp1_sn,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(
            self.comp2,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(
            self.finished_product, wh.lot_stock_id)
        self.assertEqual(avail_qty_comp1, -todo_nb)
        self.assertEqual(avail_qty_comp2, -todo_nb)
        self.assertEqual(avail_qty_finished, todo_nb)
Exemplo n.º 46
0
    def test_flow_tracked_1(self):
        """ This test mimics test_flow_1 but with a BoM that has tracking included in it.
        """
        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished_product
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # We should be able to call the 'record_components' button
        self.assertTrue(picking_receipt.display_action_record_components)

        # Check the created manufacturing order
        mo = self.env['mrp.production'].search([('bom_id', '=',
                                                 self.bom_tracked.id)])
        self.assertEqual(len(mo), 1)
        self.assertEqual(len(mo.picking_ids), 0)
        wh = picking_receipt.picking_type_id.warehouse_id
        self.assertEqual(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        # Create a RR
        pg1 = self.env['procurement.group'].create({})
        self.env['stock.warehouse.orderpoint'].create({
            'name':
            'xxx',
            'product_id':
            self.comp1_sn.id,
            'product_min_qty':
            0,
            'product_max_qty':
            0,
            'location_id':
            self.env.user.company_id.subcontracting_location_id.id,
            'group_id':
            pg1.id,
        })

        # Run the scheduler and check the created picking
        self.env['procurement.group'].run_scheduler()
        picking = self.env['stock.picking'].search([('group_id', '=', pg1.id)])
        self.assertEqual(len(picking), 1)
        self.assertEqual(picking.picking_type_id, wh.out_type_id)

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

        action = picking_receipt.action_record_components()
        mo = self.env['mrp.production'].browse(action['res_id'])
        mo_form = Form(mo.with_context(**action['context']),
                       view=action['view_id'])
        mo_form.qty_producing = 1
        mo_form.lot_producing_id = lot_id
        with mo_form.move_line_raw_ids.edit(0) as ml:
            ml.lot_id = serial_id
        mo = mo_form.save()
        mo.subcontracting_record_component()

        # We should not be able to call the 'record_components' button
        self.assertFalse(picking_receipt.display_action_record_components)

        picking_receipt.button_validate()
        self.assertEqual(mo.state, 'done')

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(
            self.comp1_sn,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(
            self.comp2,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(
            self.finished_product, wh.lot_stock_id)
        self.assertEqual(avail_qty_comp1, -1)
        self.assertEqual(avail_qty_comp2, -1)
        self.assertEqual(avail_qty_finished, 1)
Exemplo n.º 47
0
    def _dropship_product1(self):
        # enable the dropship and MTO route on the product
        dropshipping_route = self.env.ref(
            'stock_dropshipping.route_drop_shipping')
        mto_route = self.env.ref('stock.route_warehouse0_mto')
        self.product1.write(
            {'route_ids': [(6, 0, [dropshipping_route.id, mto_route.id])]})

        # add a vendor
        vendor1 = self.env['res.partner'].create({'name': 'vendor1'})
        seller1 = self.env['product.supplierinfo'].create({
            'name': vendor1.id,
            'price': 8,
        })
        self.product1.write({'seller_ids': [(6, 0, [seller1.id])]})

        # sell one unit of this product
        customer1 = self.env['res.partner'].create({'name': 'customer1'})
        self.sale_order1 = self.env['sale.order'].create({
            'partner_id':
            customer1.id,
            'partner_invoice_id':
            customer1.id,
            'partner_shipping_id':
            customer1.id,
            'order_line': [(0, 0, {
                'name': self.product1.name,
                'product_id': self.product1.id,
                'product_uom_qty': 1,
                'product_uom': self.product1.uom_id.id,
                'price_unit': 12,
            })],
            'pricelist_id':
            self.env.ref('product.list0').id,
            'picking_policy':
            'direct',
        })
        self.sale_order1.action_confirm()

        # confirm the purchase order
        self.purchase_order1 = self.env['purchase.order'].search([
            ('group_id', '=', self.sale_order1.procurement_group_id.id)
        ])
        self.purchase_order1.button_confirm()

        # validate the dropshipping picking
        self.assertEqual(len(self.sale_order1.picking_ids), 1)
        #self.assertEqual(self.sale_order1.picking_ids.move_lines._is_dropshipped(), True)
        wizard = self.sale_order1.picking_ids.button_validate()
        immediate_transfer = self.env[wizard['res_model']].browse(
            wizard['res_id']).with_context(wizard['context'])
        immediate_transfer.process()
        self.assertEqual(self.sale_order1.picking_ids.state, 'done')

        # create the vendor bill
        move_form = Form(
            self.env['account.move'].with_context(default_type='in_invoice'))
        move_form.partner_id = vendor1
        move_form.purchase_id = self.purchase_order1
        self.vendor_bill1 = move_form.save()
        self.vendor_bill1.post()

        # create the customer invoice
        self.customer_invoice1 = self.sale_order1._create_invoices()
        self.customer_invoice1.post()

        all_amls = self.vendor_bill1.line_ids + self.customer_invoice1.line_ids
        if self.sale_order1.picking_ids.move_lines.account_move_ids:
            all_amls |= self.sale_order1.picking_ids.move_lines.account_move_ids.line_ids
        return all_amls
Exemplo n.º 48
0
    def test_flow_6(self):
        """ Extra quantity on the move.
        """
        # We create a second partner of type subcontractor
        main_partner_2 = self.env['res.partner'].create(
            {'name': 'main_partner'})
        subcontractor_partner2 = self.env['res.partner'].create({
            'name':
            'subcontractor_partner',
            'parent_id':
            main_partner_2.id,
            'company_id':
            self.env.ref('base.main_company').id,
        })
        self.env.cache.invalidate()

        # We create a different BoM for the same product
        comp3 = self.env['product.product'].create({
            'name':
            'Component3',
            'type':
            'product',
            'categ_id':
            self.env.ref('product.product_category_all').id,
        })

        bom_form = Form(self.env['mrp.bom'])
        bom_form.type = 'subcontract'
        bom_form.product_tmpl_id = self.finished.product_tmpl_id
        with bom_form.bom_line_ids.new() as bom_line:
            bom_line.product_id = self.comp1
            bom_line.product_qty = 1
        with bom_form.bom_line_ids.new() as bom_line:
            bom_line.product_id = comp3
            bom_line.product_qty = 2
        bom2 = bom_form.save()

        # We assign the second BoM to the new partner
        self.bom.write(
            {'subcontractor_ids': [(4, self.subcontractor_partner1.id, None)]})
        bom2.write(
            {'subcontractor_ids': [(4, subcontractor_partner2.id, None)]})

        # Create a receipt picking from the subcontractor1
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = subcontractor_partner2
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        picking_receipt.move_lines.quantity_done = 3.0
        picking_receipt._action_done()
        mo = picking_receipt._get_subcontracted_productions()
        move_comp1 = mo.move_raw_ids.filtered(
            lambda m: m.product_id == self.comp1)
        move_comp3 = mo.move_raw_ids.filtered(lambda m: m.product_id == comp3)
        self.assertEqual(sum(move_comp1.mapped('product_uom_qty')), 3.0)
        self.assertEqual(sum(move_comp3.mapped('product_uom_qty')), 6.0)
        self.assertEqual(sum(move_comp1.mapped('quantity_done')), 3.0)
        self.assertEqual(sum(move_comp3.mapped('quantity_done')), 6.0)
        move_finished = mo.move_finished_ids
        self.assertEqual(sum(move_finished.mapped('product_uom_qty')), 3.0)
        self.assertEqual(sum(move_finished.mapped('quantity_done')), 3.0)
    def test_01_product_route_level_delays(self):
        """ In order to check schedule dates, set product's Manufacturing Lead Time
            and Customer Lead Time and also set warehouse route's delay."""

        # Update warehouse_1 with Outgoing Shippings pick + pack + ship
        self.warehouse_1.write({'delivery_steps': 'pick_pack_ship'})

        # Set delay on pull rule
        for pull_rule in self.warehouse_1.delivery_route_id.rule_ids:
            pull_rule.write({'delay': 2})

        # Create sale order of product_1
        order_form = Form(self.env['sale.order'])
        order_form.partner_id = self.partner_1
        order_form.warehouse_id = self.warehouse_1
        with order_form.order_line.new() as line:
            line.product_id = self.product_1
            line.product_uom_qty = 6
        order = order_form.save()
        # Confirm sale order
        order.action_confirm()

        # Run scheduler
        self.env['procurement.group'].run_scheduler()

        # Check manufacturing order created or not
        manufacturing_order = self.env['mrp.production'].search([
            ('product_id', '=', self.product_1.id)
        ])
        self.assertTrue(manufacturing_order,
                        'Manufacturing order should be created.')

        # Check the picking crated or not
        self.assertTrue(order.picking_ids, "Pickings should be created.")

        # Check schedule date of ship type picking
        out = order.picking_ids.filtered(
            lambda r: r.picking_type_id == self.warehouse_1.out_type_id)
        out_min_date = fields.Datetime.from_string(out.scheduled_date)
        out_date = fields.Datetime.from_string(order.date_order) + timedelta(
            days=self.product_1.sale_delay) - timedelta(
                days=out.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            out_min_date,
            out_date,
            delta=timedelta(seconds=1),
            msg=
            'Schedule date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay.'
        )

        # Check schedule date of pack type picking
        pack = order.picking_ids.filtered(
            lambda r: r.picking_type_id == self.warehouse_1.pack_type_id)
        pack_min_date = fields.Datetime.from_string(pack.scheduled_date)
        pack_date = out_date - timedelta(days=pack.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            pack_min_date,
            pack_date,
            delta=timedelta(seconds=1),
            msg=
            'Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.'
        )

        # Check schedule date of pick type picking
        pick = order.picking_ids.filtered(
            lambda r: r.picking_type_id == self.warehouse_1.pick_type_id)
        pick_min_date = fields.Datetime.from_string(pick.scheduled_date)
        self.assertAlmostEqual(
            pick_min_date,
            pack_date,
            delta=timedelta(seconds=1),
            msg=
            'Schedule date of pick type picking should be equal to: Schedule date of pack type picking.'
        )

        # Check schedule date of manufacturing order
        mo_date = pack_date - timedelta(days=self.product_1.produce_delay)
        date_planned_start = fields.Datetime.from_string(
            manufacturing_order.date_planned_start)
        self.assertAlmostEqual(
            date_planned_start,
            mo_date,
            delta=timedelta(seconds=1),
            msg=
            "Schedule date of manufacturing order should be equal to: Schedule date of pack type picking - product's Manufacturing Lead Time."
        )
Exemplo n.º 50
0
    def test_flow_5(self):
        """ Check that the correct BoM is chosen accordingly to the partner
        """
        # We create a second partner of type subcontractor
        main_partner_2 = self.env['res.partner'].create(
            {'name': 'main_partner'})
        subcontractor_partner2 = self.env['res.partner'].create({
            'name':
            'subcontractor_partner',
            'parent_id':
            main_partner_2.id,
            'company_id':
            self.env.ref('base.main_company').id
        })

        # We create a different BoM for the same product
        comp3 = self.env['product.product'].create({
            'name':
            'Component1',
            'type':
            'product',
            'categ_id':
            self.env.ref('product.product_category_all').id,
        })

        bom_form = Form(self.env['mrp.bom'])
        bom_form.type = 'subcontract'
        bom_form.product_tmpl_id = self.finished.product_tmpl_id
        with bom_form.bom_line_ids.new() as bom_line:
            bom_line.product_id = self.comp1
            bom_line.product_qty = 1
        with bom_form.bom_line_ids.new() as bom_line:
            bom_line.product_id = comp3
            bom_line.product_qty = 1
        bom2 = bom_form.save()

        # We assign the second BoM to the new partner
        self.bom.write(
            {'subcontractor_ids': [(4, self.subcontractor_partner1.id, None)]})
        bom2.write(
            {'subcontractor_ids': [(4, subcontractor_partner2.id, None)]})

        # Create a receipt picking from the subcontractor1
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt1 = picking_form.save()
        picking_receipt1.action_confirm()

        # Create a receipt picking from the subcontractor2
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = subcontractor_partner2
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt2 = picking_form.save()
        picking_receipt2.action_confirm()

        mo_pick1 = picking_receipt1.move_lines.mapped(
            'move_orig_ids.production_id')
        mo_pick2 = picking_receipt2.move_lines.mapped(
            'move_orig_ids.production_id')
        self.assertEqual(len(mo_pick1), 1)
        self.assertEqual(len(mo_pick2), 1)
        self.assertEqual(mo_pick1.bom_id, self.bom)
        self.assertEqual(mo_pick2.bom_id, bom2)
Exemplo n.º 51
0
    def test_00_purchase_order_flow(self):
        # Ensure product_id_2 doesn't have res_partner_1 as supplier
        if self.partner_a in self.product_id_2.seller_ids.mapped('name'):
            id_to_remove = self.product_id_2.seller_ids.filtered(
                lambda r: r.name == self.partner_a
            ).ids[0] if self.product_id_2.seller_ids.filtered(
                lambda r: r.name == self.partner_a) else False
            if id_to_remove:
                self.product_id_2.write({
                    'seller_ids': [(2, id_to_remove, False)],
                })
        self.assertFalse(
            self.product_id_2.seller_ids.filtered(
                lambda r: r.name == self.partner_a),
            'Purchase: the partner should not be in the list of the product suppliers'
        )

        self.po = self.env['purchase.order'].create(self.po_vals)
        self.assertTrue(self.po, 'Purchase: no purchase order created')
        self.assertEqual(
            self.po.invoice_status, 'no',
            'Purchase: PO invoice_status should be "Not purchased"')
        self.assertEqual(self.po.order_line.mapped('qty_received'), [0.0, 0.0],
                         'Purchase: no product should be received"')
        self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [0.0, 0.0],
                         'Purchase: no product should be invoiced"')

        self.po.button_confirm()
        self.assertEqual(self.po.state, 'purchase',
                         'Purchase: PO state should be "Purchase"')
        self.assertEqual(
            self.po.invoice_status, 'to invoice',
            'Purchase: PO invoice_status should be "Waiting Invoices"')

        self.assertTrue(
            self.product_id_2.seller_ids.filtered(
                lambda r: r.name == self.partner_a),
            'Purchase: the partner should be in the list of the product suppliers'
        )

        seller = self.product_id_2._select_seller(
            partner_id=self.partner_a,
            quantity=2.0,
            date=self.po.date_planned,
            uom_id=self.product_id_2.uom_po_id)
        price_unit = seller.price if seller else 0.0
        if price_unit and seller and self.po.currency_id and seller.currency_id != self.po.currency_id:
            price_unit = seller.currency_id._convert(price_unit,
                                                     self.po.currency_id,
                                                     self.po.company_id,
                                                     self.po.date_order)
        self.assertEqual(
            price_unit, 250.0,
            'Purchase: the price of the product for the supplier should be 250.0.'
        )

        self.assertEqual(self.po.picking_count, 1,
                         'Purchase: one picking should be created"')
        self.picking = self.po.picking_ids[0]
        self.picking.move_line_ids.write({'qty_done': 5.0})
        self.picking.button_validate()
        self.assertEqual(self.po.order_line.mapped('qty_received'), [5.0, 5.0],
                         'Purchase: all products should be received"')

        move_form = Form(self.env['account.move'].with_context(
            default_move_type='in_invoice'))
        move_form.partner_id = self.partner_a
        move_form.purchase_id = self.po
        self.invoice = move_form.save()

        self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [5.0, 5.0],
                         'Purchase: all products should be invoiced"')
Exemplo n.º 52
0
    def test_flow_4(self):
        """ Tick "Manufacture" and "MTO" on the components and trigger the
        creation of the subcontracting manufacturing order through a receipt
        picking. Checks that the delivery and MO for its components are
        automatically created.
        """
        # Tick "manufacture" and MTO on self.comp2
        mto_route = self.env.ref('stock.route_warehouse0_mto')
        mto_route.active = True
        manufacture_route = self.env['stock.location.route'].search([
            ('name', '=', 'Manufacture')
        ])
        self.comp2.write({'route_ids': [(4, manufacture_route.id, None)]})
        self.comp2.write({'route_ids': [(4, mto_route.id, None)]})

        orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
        orderpoint_form.product_id = self.comp2
        orderpoint_form.product_min_qty = 0.0
        orderpoint_form.product_max_qty = 10.0
        orderpoint_form.location_id = self.env.company.subcontracting_location_id
        orderpoint = orderpoint_form.save()

        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        warehouse = picking_receipt.picking_type_id.warehouse_id

        # Pickings should directly be created
        mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)])
        self.assertEqual(mo.state, 'confirmed')

        picking_delivery = mo.picking_ids
        self.assertFalse(picking_delivery)

        picking_delivery = self.env['stock.picking'].search([
            ('origin', 'ilike', '%' + picking_receipt.name + '%')
        ])
        self.assertFalse(picking_delivery)

        move = self.env['stock.move'].search([
            ('product_id', '=', self.comp2.id),
            ('location_id', '=', warehouse.lot_stock_id.id),
            ('location_dest_id', '=',
             self.env.company.subcontracting_location_id.id)
        ])
        self.assertTrue(move)
        picking_delivery = move.picking_id
        self.assertTrue(picking_delivery)
        self.assertEqual(move.product_uom_qty, 11.0)

        # As well as a manufacturing order for `self.comp2`
        comp2mo = self.env['mrp.production'].search([('bom_id', '=',
                                                      self.comp2_bom.id)])
        self.assertEqual(len(comp2mo), 1)
Exemplo n.º 53
0
    def test_02_po_return(self):
        """
        Test a PO with a product on Incoming shipment. Validate the PO, then do a return
        of the picking with Refund.
        """
        # Draft purchase order created
        self.po = self.env['purchase.order'].create(self.po_vals)
        self.assertTrue(self.po, 'Purchase: no purchase order created')
        self.assertEqual(self.po.order_line.mapped('qty_received'), [0.0, 0.0],
                         'Purchase: no product should be received"')
        self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [0.0, 0.0],
                         'Purchase: no product should be invoiced"')

        self.po.button_confirm()
        self.assertEqual(self.po.state, 'purchase',
                         'Purchase: PO state should be "Purchase"')
        self.assertEqual(
            self.po.invoice_status, 'to invoice',
            'Purchase: PO invoice_status should be "Waiting Invoices"')

        # Confirm the purchase order
        self.po.button_confirm()
        self.assertEqual(self.po.state, 'purchase',
                         'Purchase: PO state should be "Purchase')
        self.assertEqual(self.po.picking_count, 1,
                         'Purchase: one picking should be created"')
        self.picking = self.po.picking_ids[0]
        self.picking.move_line_ids.write({'qty_done': 5.0})
        self.picking.button_validate()
        self.assertEqual(self.po.order_line.mapped('qty_received'), [5.0, 5.0],
                         'Purchase: all products should be received"')

        #After Receiving all products create vendor bill.
        move_form = Form(self.env['account.move'].with_context(
            default_move_type='in_invoice'))
        move_form.partner_id = self.partner_a
        move_form.purchase_id = self.po
        self.invoice = move_form.save()
        self.invoice.action_post()

        self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [5.0, 5.0],
                         'Purchase: all products should be invoiced"')

        # Check quantity received
        received_qty = sum(pol.qty_received for pol in self.po.order_line)
        self.assertEqual(
            received_qty, 10.0,
            'Purchase: Received quantity should be 10.0 instead of %s after validating incoming shipment'
            % received_qty)

        # Create return picking
        pick = self.po.picking_ids
        stock_return_picking_form = Form(
            self.env['stock.return.picking'].with_context(
                active_ids=pick.ids,
                active_id=pick.ids[0],
                active_model='stock.picking'))
        return_wiz = stock_return_picking_form.save()
        return_wiz.product_return_moves.write({
            'quantity': 2.0,
            'to_refund': True
        })  # Return only 2
        res = return_wiz.create_returns()
        return_pick = self.env['stock.picking'].browse(res['res_id'])

        # Validate picking
        return_pick.move_line_ids.write({'qty_done': 2})

        return_pick.button_validate()

        # Check Received quantity
        self.assertEqual(
            self.po.order_line[0].qty_received, 3.0,
            'Purchase: delivered quantity should be 3.0 instead of "%s" after picking return'
            % self.po.order_line[0].qty_received)
        #Create vendor bill for refund qty
        move_form = Form(self.env['account.move'].with_context(
            default_move_type='in_refund'))
        move_form.partner_id = self.partner_a
        move_form.purchase_id = self.po
        self.invoice = move_form.save()
        move_form = Form(self.invoice)
        with move_form.invoice_line_ids.edit(0) as line_form:
            line_form.quantity = 2.0
        with move_form.invoice_line_ids.edit(1) as line_form:
            line_form.quantity = 2.0
        self.invoice = move_form.save()
        self.invoice.action_post()

        self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [3.0, 3.0],
                         'Purchase: Billed quantity should be 3.0')
Exemplo n.º 54
0
    def test_flow_1(self):
        """ Don't tick any route on the components and trigger the creation of the subcontracting
        manufacturing order through a receipt picking. Create a reordering rule in the
        subcontracting locations for a component and run the scheduler to resupply. Checks if the
        resupplying actually works
        """
        # Check subcontracting picking Type
        self.assertTrue(
            all(self.env['stock.warehouse'].search(
                []).with_context(active_test=False).mapped(
                    'subcontracting_type_id.use_create_components_lots')))
        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # Nothing should be tracked
        self.assertTrue(
            all(m.product_uom_qty == m.reserved_availability
                for m in picking_receipt.move_lines))
        self.assertEqual(picking_receipt.state, 'assigned')
        self.assertFalse(picking_receipt.display_action_record_components)

        # Check the created manufacturing order
        mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)])
        self.assertEqual(len(mo), 1)
        self.assertEqual(len(mo.picking_ids), 0)
        wh = picking_receipt.picking_type_id.warehouse_id
        self.assertEqual(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        # Create a RR
        pg1 = self.env['procurement.group'].create({})
        self.env['stock.warehouse.orderpoint'].create({
            'name':
            'xxx',
            'product_id':
            self.comp1.id,
            'product_min_qty':
            0,
            'product_max_qty':
            0,
            'location_id':
            self.env.user.company_id.subcontracting_location_id.id,
            'group_id':
            pg1.id,
        })

        # Run the scheduler and check the created picking
        self.env['procurement.group'].run_scheduler()
        picking = self.env['stock.picking'].search([('group_id', '=', pg1.id)])
        self.assertEqual(len(picking), 1)
        self.assertEqual(picking.picking_type_id, wh.out_type_id)
        picking_receipt.move_lines.quantity_done = 1
        picking_receipt.button_validate()
        self.assertEqual(mo.state, 'done')

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(
            self.comp1,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(
            self.comp2,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(
            self.finished, wh.lot_stock_id)
        self.assertEqual(avail_qty_comp1, -1)
        self.assertEqual(avail_qty_comp2, -1)
        self.assertEqual(avail_qty_finished, 1)

        # Ensure returns to subcontractor location
        return_form = Form(self.env['stock.return.picking'].with_context(
            active_id=picking_receipt.id, active_model='stock.picking'))
        return_wizard = return_form.save()
        return_picking_id, pick_type_id = return_wizard._create_returns()
        return_picking = self.env['stock.picking'].browse(return_picking_id)
        self.assertEqual(len(return_picking), 1)
        self.assertEqual(
            return_picking.move_lines.location_dest_id,
            self.subcontractor_partner1.property_stock_subcontractor)
    def test_invoice_after_lc(self):
        self.env.company.anglo_saxon_accounting = True
        self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
        self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
        self.price_diff_account = self.env['account.account'].create({
            'name':
            'price diff account',
            'code':
            'price diff account',
            'user_type_id':
            self.env.ref('account.data_account_type_current_assets').id,
        })
        self.product1.property_account_creditor_price_difference = self.price_diff_account

        # Create PO
        po_form = Form(self.env['purchase.order'])
        po_form.partner_id = self.env['res.partner'].create({'name': 'vendor'})
        with po_form.order_line.new() as po_line:
            po_line.product_id = self.product1
            po_line.product_qty = 1
            po_line.price_unit = 455.0
        order = po_form.save()
        order.button_confirm()

        # Receive the goods
        receipt = order.picking_ids[0]
        receipt.move_lines.quantity_done = 1
        receipt.button_validate()

        # Check SVL and AML
        svl = self.env['stock.valuation.layer'].search([
            ('stock_move_id', '=', receipt.move_lines.id)
        ])
        self.assertAlmostEqual(svl.value, 455)
        aml = self.env['account.move.line'].search([
            ('account_id', '=',
             self.company_data['default_account_stock_valuation'].id)
        ])
        self.assertAlmostEqual(aml.debit, 455)

        # Create and validate LC
        lc = self.env['stock.landed.cost'].create(
            dict(
                picking_ids=[(6, 0, [receipt.id])],
                account_journal_id=self.stock_journal.id,
                cost_lines=[
                    (0, 0, {
                        'name': 'equal split',
                        'split_method': 'equal',
                        'price_unit': 99,
                        'product_id': self.productlc1.id,
                    }),
                ],
            ))
        lc.compute_landed_cost()
        lc.button_validate()

        # Check LC, SVL and AML
        self.assertAlmostEqual(lc.valuation_adjustment_lines.final_cost, 554)
        svl = self.env['stock.valuation.layer'].search(
            [('stock_move_id', '=', receipt.move_lines.id)],
            order='id desc',
            limit=1)
        self.assertAlmostEqual(svl.value, 99)
        aml = self.env['account.move.line'].search(
            [('account_id', '=',
              self.company_data['default_account_stock_valuation'].id)],
            order='id desc',
            limit=1)
        self.assertAlmostEqual(aml.debit, 99)

        # Create an invoice with the same price
        move_form = Form(self.env['account.move'].with_context(
            default_move_type='in_invoice'))
        move_form.partner_id = order.partner_id
        move_form.purchase_id = order
        move = move_form.save()
        move.action_post()

        # Check nothing was posted in the price difference account
        price_diff_aml = self.env['account.move.line'].search([
            ('account_id', '=', self.price_diff_account.id),
            ('move_id', '=', move.id)
        ])
        self.assertEqual(
            len(price_diff_aml), 0,
            "No line should have been generated in the price difference account."
        )
Exemplo n.º 56
0
    def test_flow_3(self):
        """ Tick "Resupply Subcontractor on Order" and "MTO" on the components and trigger the
        creation of the subcontracting manufacturing order through a receipt picking. Checks if the
        resupplying actually works. One of the component has also "manufacture" set and a BOM
        linked. Checks that an MO is created for this one.
        """
        # Tick "resupply subconractor on order"
        resupply_sub_on_order_route = self.env['stock.location.route'].search([
            ('name', '=', 'Resupply Subcontractor on Order')
        ])
        (self.comp1 + self.comp2).write(
            {'route_ids': [(4, resupply_sub_on_order_route.id, None)]})

        # Tick "manufacture" and MTO on self.comp2
        mto_route = self.env.ref('stock.route_warehouse0_mto')
        mto_route.active = True
        manufacture_route = self.env['stock.location.route'].search([
            ('name', '=', 'Manufacture')
        ])
        self.comp2.write({'route_ids': [(4, manufacture_route.id, None)]})
        self.comp2.write({'route_ids': [(4, mto_route.id, None)]})

        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # Nothing should be tracked
        self.assertFalse(picking_receipt.display_action_record_components)

        # Pickings should directly be created
        mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)])
        self.assertEqual(mo.state, 'confirmed')

        picking_delivery = mo.picking_ids
        self.assertEqual(len(picking_delivery), 1)
        self.assertEqual(len(picking_delivery.move_lines), 2)
        self.assertEqual(picking_delivery.origin, picking_receipt.name)
        self.assertEqual(picking_delivery.partner_id,
                         picking_receipt.partner_id)

        # The picking should be a delivery order
        wh = picking_receipt.picking_type_id.warehouse_id
        self.assertEqual(mo.picking_ids.picking_type_id, wh.out_type_id)

        self.assertEqual(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        # As well as a manufacturing order for `self.comp2`
        comp2mo = self.env['mrp.production'].search([('bom_id', '=',
                                                      self.comp2_bom.id)])
        self.assertEqual(len(comp2mo), 1)
        picking_receipt.move_lines.quantity_done = 1
        picking_receipt.button_validate()
        self.assertEqual(mo.state, 'done')

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(
            self.comp1,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(
            self.comp2,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(
            self.finished, wh.lot_stock_id)
        self.assertEqual(avail_qty_comp1, -1)
        self.assertEqual(avail_qty_comp2, -1)
        self.assertEqual(avail_qty_finished, 1)
Exemplo n.º 57
0
    def test_tracking_backorder_series_serial_1(self):
        """ Create a MO of 4 tracked products (serial) with pbm_sam.
        all component is tracked by serial
        Produce one by one with one bakorder for each until end.
        """
        nb_product_todo = 4
        production, _, p_final, p1, p2 = self.generate_mo(
            qty_final=nb_product_todo,
            tracking_final='serial',
            tracking_base_1='serial',
            tracking_base_2='serial',
            qty_base_1=1)
        serials_final, serials_p1, serials_p2 = [], [], []
        for i in range(nb_product_todo):
            serials_final.append(self.env['stock.production.lot'].create({
                'name':
                f'lot_final_{i}',
                'product_id':
                p_final.id,
                'company_id':
                self.env.company.id,
            }))
            serials_p1.append(self.env['stock.production.lot'].create({
                'name':
                f'lot_consumed_1_{i}',
                'product_id':
                p1.id,
                'company_id':
                self.env.company.id,
            }))
            serials_p2.append(self.env['stock.production.lot'].create({
                'name':
                f'lot_consumed_2_{i}',
                'product_id':
                p2.id,
                'company_id':
                self.env.company.id,
            }))
            self.env['stock.quant']._update_available_quantity(
                p1, self.stock_location, 1, lot_id=serials_p1[-1])
            self.env['stock.quant']._update_available_quantity(
                p2, self.stock_location, 1, lot_id=serials_p2[-1])

        production.action_assign()
        active_production = production
        for i in range(nb_product_todo):

            details_operation_form = Form(
                active_production.move_raw_ids.filtered(
                    lambda m: m.product_id == p1),
                view=self.env.ref('stock.view_stock_move_operations'))
            with details_operation_form.move_line_ids.edit(0) as ml:
                ml.qty_done = 1
                ml.lot_id = serials_p1[i]
            details_operation_form.save()
            details_operation_form = Form(
                active_production.move_raw_ids.filtered(
                    lambda m: m.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 = 1
                ml.lot_id = serials_p2[i]
            details_operation_form.save()

            production_form = Form(active_production)
            production_form.qty_producing = 1
            production_form.lot_producing_id = serials_final[i]
            active_production = production_form.save()

            active_production.button_mark_done()
            if i + 1 != nb_product_todo:  # If last MO, don't make a backorder
                action = active_production.button_mark_done()
                backorder = Form(
                    self.env['mrp.production.backorder'].with_context(
                        **action['context']))
                backorder.save().action_backorder()
            active_production = active_production.procurement_group_id.mrp_production_ids[
                -1]

        self.assertEqual(
            self.env['stock.quant']._get_available_quantity(
                p_final, self.stock_location), nb_product_todo,
            f'You should have the {nb_product_todo} final product in stock')
        self.assertEqual(
            len(production.procurement_group_id.mrp_production_ids),
            nb_product_todo)
Exemplo n.º 58
0
    def test_flow_2(self):
        """ Tick "Resupply Subcontractor on Order" on the components and trigger the creation of
        the subcontracting manufacturing order through a receipt picking. Checks if the resupplying
        actually works. Also set a different subcontracting location on the partner.
        """
        # Tick "resupply subconractor on order"
        resupply_sub_on_order_route = self.env['stock.location.route'].search([
            ('name', '=', 'Resupply Subcontractor on Order')
        ])
        (self.comp1 + self.comp2).write(
            {'route_ids': [(4, resupply_sub_on_order_route.id, None)]})
        # Create a different subcontract location
        partner_subcontract_location = self.env['stock.location'].create({
            'name':
            'Specific partner location',
            'location_id':
            self.env.ref('stock.stock_location_locations_partner').id,
            'usage':
            'internal',
            'company_id':
            self.env.company.id,
        })
        self.subcontractor_partner1.property_stock_subcontractor = partner_subcontract_location.id
        resupply_rule = resupply_sub_on_order_route.rule_ids.filtered(
            lambda l: l.location_id == self.comp1.property_stock_production and
            l.location_src_id == self.env.company.subcontracting_location_id)
        resupply_rule.copy(
            {'location_src_id': partner_subcontract_location.id})
        resupply_warehouse_rule = self.warehouse.route_ids.rule_ids.filtered(
            lambda l: l.location_id == self.env.company.
            subcontracting_location_id and l.location_src_id == self.warehouse.
            lot_stock_id)
        resupply_warehouse_rule.copy(
            {'location_id': partner_subcontract_location.id})

        # Create a receipt picking from the subcontractor
        picking_form = Form(self.env['stock.picking'])
        picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
        picking_form.partner_id = self.subcontractor_partner1
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = self.finished
            move.product_uom_qty = 1
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        # Nothing should be tracked
        self.assertFalse(picking_receipt.display_action_record_components)

        # Pickings should directly be created
        mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)])
        self.assertEqual(len(mo.picking_ids), 1)
        self.assertEqual(mo.state, 'confirmed')
        self.assertEqual(len(mo.picking_ids.move_lines), 2)

        picking = mo.picking_ids
        wh = picking.picking_type_id.warehouse_id

        # The picking should be a delivery order
        self.assertEqual(picking.picking_type_id, wh.out_type_id)

        self.assertEqual(mo.picking_type_id, wh.subcontracting_type_id)
        self.assertFalse(mo.picking_type_id.active)

        # No manufacturing order for `self.comp2`
        comp2mo = self.env['mrp.production'].search([('bom_id', '=',
                                                      self.comp2_bom.id)])
        self.assertEqual(len(comp2mo), 0)

        picking_receipt.move_lines.quantity_done = 1
        picking_receipt.button_validate()
        self.assertEqual(mo.state, 'done')

        # Available quantities should be negative at the subcontracting location for each components
        avail_qty_comp1 = self.env['stock.quant']._get_available_quantity(
            self.comp1,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_comp2 = self.env['stock.quant']._get_available_quantity(
            self.comp2,
            self.subcontractor_partner1.property_stock_subcontractor,
            allow_negative=True)
        avail_qty_finished = self.env['stock.quant']._get_available_quantity(
            self.finished, wh.lot_stock_id)
        self.assertEqual(avail_qty_comp1, -1)
        self.assertEqual(avail_qty_comp2, -1)
        self.assertEqual(avail_qty_finished, 1)

        avail_qty_comp1_in_global_location = self.env[
            'stock.quant']._get_available_quantity(
                self.comp1,
                self.env.company.subcontracting_location_id,
                allow_negative=True)
        avail_qty_comp2_in_global_location = self.env[
            'stock.quant']._get_available_quantity(
                self.comp2,
                self.env.company.subcontracting_location_id,
                allow_negative=True)
        self.assertEqual(avail_qty_comp1_in_global_location, 0.0)
        self.assertEqual(avail_qty_comp2_in_global_location, 0.0)
Exemplo n.º 59
0
    def test_product_produce_3(self):
        """ Check that line are created when the consumed products are
        tracked by serial and the lot proposed are correct. """
        self.stock_location = self.env.ref('stock.stock_location_stock')
        self.stock_shelf_1 = self.env.ref('stock.stock_location_components')
        self.stock_shelf_2 = self.env.ref('stock.stock_location_14')
        mo, _, p_final, p1, p2 = self.generate_mo(tracking_base_1='lot',
                                                  qty_base_1=10,
                                                  qty_final=1)
        self.assertEqual(len(mo), 1, 'MO should have been created')

        first_lot_for_p1 = self.env['stock.production.lot'].create({
            'name':
            'lot1',
            'product_id':
            p1.id,
        })
        second_lot_for_p1 = self.env['stock.production.lot'].create({
            'name':
            'lot2',
            'product_id':
            p1.id,
        })

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

        self.env['stock.quant']._update_available_quantity(
            p1, self.stock_shelf_1, 3, lot_id=first_lot_for_p1)
        self.env['stock.quant']._update_available_quantity(
            p1, self.stock_shelf_2, 3, lot_id=first_lot_for_p1)
        self.env['stock.quant']._update_available_quantity(
            p1, self.stock_location, 8, lot_id=second_lot_for_p1)
        self.env['stock.quant']._update_available_quantity(
            p2, self.stock_location, 5)

        mo.action_assign()
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.qty_producing = 1.0
        product_produce = produce_form.save()
        product_produce.final_lot_id = final_product_lot.id
        # product 1 lot 1 shelf1
        # product 1 lot 1 shelf2
        # product 1 lot 2
        self.assertEqual(
            len(product_produce.workorder_line_ids), 4,
            'You should have 4 produce lines. lot 1 shelf_1, lot 1 shelf_2, lot2 and for product which have tracking None'
        )

        for produce_line in product_produce.workorder_line_ids:
            produce_line.qty_done = produce_line.qty_to_consume + 1
        product_produce.do_produce()

        move_1 = mo.move_raw_ids.filtered(lambda m: m.product_id == p1)
        # qty_done/product_uom_qty lot
        # 3/3 lot 1 shelf 1
        # 1/1 lot 1 shelf 2
        # 2/2 lot 1 shelf 2
        # 2/0 lot 1 other
        # 5/4 lot 2
        ml_to_shelf_1 = move_1.move_line_ids.filtered(
            lambda ml: ml.lot_id == first_lot_for_p1 and ml.location_id == self
            .stock_shelf_1)
        ml_to_shelf_2 = move_1.move_line_ids.filtered(
            lambda ml: ml.lot_id == first_lot_for_p1 and ml.location_id == self
            .stock_shelf_2)

        self.assertEqual(sum(ml_to_shelf_1.mapped('qty_done')), 3.0,
                         '3 units should be took from shelf1 as reserved.')
        self.assertEqual(sum(ml_to_shelf_2.mapped('qty_done')), 3.0,
                         '3 units should be took from shelf2 as reserved.')
        self.assertEqual(move_1.quantity_done, 13,
                         'You should have used the tem units.')

        mo.button_mark_done()
        self.assertEqual(mo.state, 'done',
                         "Production order should be in done state.")
Exemplo n.º 60
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.")