Пример #1
0
    def test_pricelist_application(self):
        """ Test different prices are correctly applied based on dates """
        support_product = self.env.ref('product.product_product_2')
        support_product.list_price = 100
        partner = self.res_partner_model.create(dict(name="George"))

        christmas_pricelist = self.env['product.pricelist'].create({
            'name':
            'Christmas pricelist',
            'item_ids': [(0, 0, {
                'date_start': "2017-12-01",
                'date_end': "2017-12-24",
                'compute_price': 'percentage',
                'base': 'list_price',
                'percent_price': 20,
                'applied_on': '3_global',
                'name': 'Pre-Christmas discount'
            }),
                         (0, 0, {
                             'date_start': "2017-12-25",
                             'date_end': "2017-12-31",
                             'compute_price': 'percentage',
                             'base': 'list_price',
                             'percent_price': 50,
                             'applied_on': '3_global',
                             'name': 'Post-Christmas super-discount'
                         })]
        })

        # Create the SO with pricelist based on date
        order_form = Form(
            self.env['sale.order'].with_context(tracking_disable=True))
        order_form.partner_id = partner
        order_form.date_order = '2017-12-20'
        order_form.pricelist_id = christmas_pricelist
        with order_form.order_line.new() as line:
            line.product_id = support_product
        so = order_form.save()
        # Check the unit price and subtotal of SO line
        self.assertEqual(so.order_line[0].price_unit, 80,
                         "First date pricelist rule not applied")
        self.assertEquals(
            so.order_line[0].price_subtotal,
            so.order_line[0].price_unit * so.order_line[0].product_uom_qty,
            'Total of SO line should be a multiplication of unit price and ordered quantity'
        )

        # Change order date of the SO and check the unit price and subtotal of SO line
        with Form(so) as order:
            order.date_order = '2017-12-30'
            with order.order_line.edit(0) as line:
                line.product_id = support_product

        self.assertEqual(so.order_line[0].price_unit, 50,
                         "Second date pricelist rule not applied")
        self.assertEquals(
            so.order_line[0].price_subtotal,
            so.order_line[0].price_unit * so.order_line[0].product_uom_qty,
            'Total of SO line should be a multiplication of unit price and ordered quantity'
        )
Пример #2
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.move'].with_context(default_type='in_invoice'))
        f.partner_id = po.partner_id
        f.purchase_id = po
        invoice = f.save()
        invoice.post()
        po.flush()

        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')
Пример #3
0
    def test_reordering_rule(self):
        """
            - Receive products in 2 steps
            - The product has a reordering rule
            - On the po generated, the source document should be the name of the reordering rule
        """
        warehouse_1 = self.env['stock.warehouse'].search(
            [('company_id', '=', self.env.user.id)], limit=1)
        warehouse_1.write({'reception_steps': 'two_steps'})

        # Create a supplier
        partner = self.env['res.partner'].create({'name': 'Smith'})

        # create product and set the vendor
        product_form = Form(self.env['product.product'])
        product_form.name = 'Product A'
        product_form.type = 'product'
        with product_form.seller_ids.new() as seller:
            seller.name = partner
        product_form.route_ids.add(
            self.env.ref('purchase_stock.route_warehouse0_buy'))
        product_01 = product_form.save()

        # create reordering rule
        orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
        orderpoint_form.warehouse_id = warehouse_1
        orderpoint_form.location_id = warehouse_1.lot_stock_id
        orderpoint_form.product_id = product_01
        orderpoint_form.product_min_qty = 0.000
        orderpoint_form.product_max_qty = 0.000
        order_point = orderpoint_form.save()

        # Create Delivery Order of 10 product
        picking_form = Form(self.env['stock.picking'])
        picking_form.partner_id = partner
        picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
        with picking_form.move_ids_without_package.new() as move:
            move.product_id = product_01
            move.product_uom_qty = 10.0
        customer_picking = picking_form.save()

        # picking confirm
        customer_picking.action_confirm()

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

        # Check purchase order created or not
        purchase_order = self.env['purchase.order'].search([('partner_id', '=',
                                                             partner.id)])
        self.assertTrue(purchase_order, 'No purchase order created.')

        # On the po generated, the source document should be the name of the reordering rule
        self.assertEqual(
            order_point.name, purchase_order.origin,
            'Source document on purchase order should be the name of the reordering rule.'
        )
Пример #4
0
    def test_00_product_company_level_delays(self):
        """ In order to check schedule date, set product's Manufacturing Lead Time
            and Customer Lead Time and also set company's Manufacturing Lead Time
            and Sales Safety Days."""

        company = self.env.ref('base.main_company')

        # Update company with Manufacturing Lead Time and Sales Safety Days
        company.write({'manufacturing_lead': 3.0, 'security_lead': 3.0})

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

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

        # Check schedule date of picking
        out_date = fields.Datetime.from_string(order.date_order) + timedelta(
            days=self.product_1.sale_delay) - timedelta(
                days=company.security_lead)
        min_date = fields.Datetime.from_string(
            order.picking_ids[0].scheduled_date)
        self.assertAlmostEqual(
            min_date,
            out_date,
            delta=timedelta(seconds=1),
            msg=
            'Schedule date of picking should be equal to: Order date + Customer Lead Time - Sales Safety Days.'
        )

        # Check schedule date of manufacturing order
        mo_date = out_date - timedelta(
            days=self.product_1.produce_delay) - timedelta(
                days=company.manufacturing_lead)
        date_deadline = fields.Datetime.from_string(
            manufacturing_order.date_deadline)
        self.assertAlmostEqual(
            date_deadline,
            mo_date,
            delta=timedelta(seconds=1),
            msg=
            "Schedule date of manufacturing order should be equal to: Schedule date of picking - product's Manufacturing Lead Time - company's Manufacturing Lead Time."
        )
    def setUp(self):
        super(TestMultistepManufacturing, self).setUp()

        self.MrpProduction = self.env['mrp.production']
        # Create warehouse
        warehouse_form = Form(self.env['stock.warehouse'])
        warehouse_form.name = 'Test'
        warehouse_form.code = 'Test'
        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.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.product_manu = product_form.save()

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

        # Create bom for manufactured product
        bom_product_form = Form(self.env['mrp.bom'])
        bom_product_form.product_id = self.product_manu
        bom_product_form.product_tmpl_id = self.product_manu.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.product_raw
            bom_line.product_qty = 2.0
        self.bom_prod_manu = bom_product_form.save()

        # Create sale order
        sale_form = Form(self.env['sale.order'])
        sale_form.partner_id = self.env.ref('base.res_partner_1')
        sale_form.picking_policy = 'direct'
        sale_form.warehouse_id = self.warehouse
        with sale_form.order_line.new() as line:
            line.name = self.product_manu.name
            line.product_id = self.product_manu
            line.product_uom_qty = 1.0
            line.product_uom = self.uom_unit
            line.price_unit = 10.0
        self.sale_order = sale_form.save()
Пример #6
0
    def test_onchange_product_id(self):

        uom_id = self.product_uom_model.search([('name', '=', 'Units')])[0]
        pricelist = self.pricelist_model.search([('name', '=',
                                                  'Public Pricelist')])[0]

        partner_id = self.res_partner_model.create(dict(name="George"))
        tax_include_id = self.tax_model.create(
            dict(name="Include tax",
                 amount='21.00',
                 price_include=True,
                 type_tax_use='sale'))
        tax_exclude_id = self.tax_model.create(
            dict(name="Exclude tax", amount='0.00', type_tax_use='sale'))

        product_tmpl_id = self.product_tmpl_model.create(
            dict(name="Voiture",
                 list_price=121,
                 taxes_id=[(6, 0, [tax_include_id.id])]))

        product_id = product_tmpl_id.product_variant_id

        fp_id = self.fiscal_position_model.create(
            dict(name="fiscal position", sequence=1))

        fp_tax_id = self.fiscal_position_tax_model.create(
            dict(position_id=fp_id.id,
                 tax_src_id=tax_include_id.id,
                 tax_dest_id=tax_exclude_id.id))

        # Create the SO with one SO line and apply a pricelist and fiscal position on it
        order_form = Form(
            self.env['sale.order'].with_context(tracking_disable=True))
        order_form.partner_id = partner_id
        order_form.pricelist_id = pricelist
        order_form.fiscal_position_id = fp_id
        with order_form.order_line.new() as line:
            line.name = product_id.name
            line.product_id = product_id
            line.product_uom_qty = 1.0
            line.product_uom = uom_id
        sale_order = order_form.save()

        # Check the unit price of SO line
        self.assertEquals(100, sale_order.order_line[0].price_unit,
                          "The included tax must be subtracted to the price")
Пример #7
0
    def test_no_expense(self):
        """ Test invoicing vendor bill with no policy. Check nothing happen. """
        # confirm SO
        sale_order_line = self.env['sale.order.line'].create({
            'name':
            self.product_no_expense.name,
            'product_id':
            self.product_no_expense.id,
            'product_uom_qty':
            2,
            'qty_delivered':
            1,
            'product_uom':
            self.product_no_expense.uom_id.id,
            'price_unit':
            self.product_no_expense.list_price,
            'order_id':
            self.sale_order.id,
        })
        self.sale_order._compute_tax_id()
        self.sale_order.action_confirm()

        # create invoice lines and validate it
        move_form = Form(self.AccountMove)
        move_form.partner_id = self.partner_customer_usd
        move_form.journal_id = self.journal_purchase
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_no_expense
            line_form.quantity = 3.0
            line_form.analytic_account_id = self.analytic_account
        invoice_a = move_form.save()
        invoice_a.post()

        self.assertEquals(
            len(self.sale_order.order_line), 1,
            "No SO line should have been created (or removed) when validating vendor bill"
        )
        self.assertEquals(
            sale_order_line.qty_delivered, 1,
            "The delivered quantity of SO line should not have been incremented"
        )
        self.assertTrue(invoice_a.mapped('line_ids.analytic_line_ids'),
                        "Analytic lines should be generated")
Пример #8
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.move'].with_context(default_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.post()
        return invoice
Пример #9
0
    def test_no_expense(self):
        """ Test invoicing vendor bill with no policy. Check nothing happen. """
        # confirm SO
        sale_order_line = self.env['sale.order.line'].create({
            'name': self.product_no_expense.name,
            'product_id': self.product_no_expense.id,
            'product_uom_qty': 2,
            'qty_delivered': 1,
            'product_uom': self.product_no_expense.uom_id.id,
            'price_unit': self.product_no_expense.list_price,
            'order_id': self.sale_order.id,
        })
        self.sale_order._compute_tax_id()
        self.sale_order.action_confirm()

        # create invoice lines and validate it
        move_form = Form(self.env['account.move'].with_context(default_type='in_invoice'))
        move_form.partner_id = self.partner_customer_usd
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_no_expense
            line_form.quantity = 3.0
            line_form.analytic_account_id = self.analytic_account
        invoice_a = move_form.save()
        invoice_a.post()

        # let's log some timesheets (on the project created by sale_order_line1)
        task_sol1 = sale_order_line.task_id
        self.env['account.analytic.line'].create({
            'name': 'Test Line',
            'project_id': task_sol1.project_id.id,
            'task_id': task_sol1.id,
            'unit_amount': 1,
            'employee_id': self.employee_user.id,
        })

        self.assertEquals(len(self.sale_order.order_line), 1, "No SO line should have been created (or removed) when validating vendor bill")
        self.assertEquals(sale_order_line.qty_delivered, 1, "The delivered quantity of SO line should not have been incremented")
        self.assertTrue(invoice_a.mapped('line_ids.analytic_line_ids'), "Analytic lines should be generated")
Пример #10
0
    def test_flow_8(self):
        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 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 = 5
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()

        picking_receipt.move_lines.quantity_done = 3
        backorder_wiz = picking_receipt.button_validate()
        backorder_wiz = self.env['stock.backorder.confirmation'].browse(
            backorder_wiz['res_id'])
        backorder_wiz.process()

        backorder = self.env['stock.picking'].search([('backorder_id', '=',
                                                       picking_receipt.id)])
        self.assertTrue(backorder)
        self.assertEqual(backorder.move_lines.product_uom_qty, 2)
        subcontract_order = backorder.move_lines.move_orig_ids.production_id.filtered(
            lambda p: p.state != 'done')
        self.assertTrue(subcontract_order)
        self.assertEqual(subcontract_order.product_uom_qty, 5)
        self.assertEqual(subcontract_order.qty_produced, 3)
        backorder.move_lines.quantity_done = 2
        backorder.action_done()
        self.assertTrue(picking_receipt.move_lines.move_orig_ids.production_id.
                        state == 'done')
Пример #11
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.assertEquals(len(mo_pick1), 1)
        self.assertEquals(len(mo_pick2), 1)
        self.assertEquals(mo_pick1.bom_id, self.bom)
        self.assertEquals(mo_pick2.bom_id, bom2)
Пример #12
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_type='in_invoice'))
        move_form.partner_id = self.partner_id
        move_form.purchase_id = self.po
        self.invoice = move_form.save()
        self.invoice.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_type='in_refund'))
        move_form.partner_id = self.partner_id
        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.post()

        self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [3.0, 3.0],
                         'Purchase: Billed quantity should be 3.0')
Пример #13
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=10),
            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=10),
            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=10),
            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_deadline = fields.Datetime.from_string(
            manufacturing_order.date_deadline)
        self.assertAlmostEqual(
            date_deadline,
            mo_date,
            delta=timedelta(seconds=10),
            msg=
            "Schedule date of manufacturing order should be equal to: Schedule date of pack type picking - product's Manufacturing Lead Time."
        )
Пример #14
0
    def test_00_purchase_order_flow(self):
        # Ensure product_id_2 doesn't have res_partner_1 as supplier
        if self.partner_id 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_id
            ).ids[0] if self.product_id_2.seller_ids.filtered(
                lambda r: r.name == self.partner_id) 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_id),
            'Purchase: the partner should not be in the list of the product suppliers'
        )

        self.po = self.PurchaseOrder.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_id),
            'Purchase: the partner should be in the list of the product suppliers'
        )

        seller = self.product_id_2._select_seller(
            partner_id=self.partner_id,
            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_type='in_invoice'))
        move_form.partner_id = self.partner_id
        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"')
Пример #15
0
    def test_at_cost(self):
        """ Test vendor bill at cost for product based on ordered and delivered quantities. """
        # create SO line and confirm SO (with only one line)
        sale_order_line1 = self.env['sale.order.line'].create({
            'name':
            self.product_ordered_cost.name,
            'product_id':
            self.product_ordered_cost.id,
            'product_uom_qty':
            2,
            'qty_delivered':
            1,
            'product_uom':
            self.product_ordered_cost.uom_id.id,
            'price_unit':
            self.product_ordered_cost.list_price,
            'order_id':
            self.sale_order.id,
        })
        sale_order_line1.product_id_change()
        sale_order_line2 = self.env['sale.order.line'].create({
            'name':
            self.product_deliver_cost.name,
            'product_id':
            self.product_deliver_cost.id,
            'product_uom_qty':
            4,
            'qty_delivered':
            1,
            'product_uom':
            self.product_deliver_cost.uom_id.id,
            'price_unit':
            self.product_deliver_cost.list_price,
            'order_id':
            self.sale_order.id,
        })
        sale_order_line2.product_id_change()

        self.sale_order.onchange_partner_id()
        self.sale_order._compute_tax_id()
        self.sale_order.action_confirm()

        # create invoice lines and validate it
        move_form = Form(self.AccountMove)
        move_form.partner_id = self.partner_customer_usd
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_ordered_cost
            line_form.quantity = 3.0
            line_form.analytic_account_id = self.analytic_account
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_deliver_cost
            line_form.quantity = 3.0
            line_form.analytic_account_id = self.analytic_account
        invoice_a = move_form.save()
        invoice_a.post()

        sale_order_line3 = self.sale_order.order_line.filtered(
            lambda sol: sol != sale_order_line1 and sol.product_id == self.
            product_ordered_cost)
        sale_order_line4 = self.sale_order.order_line.filtered(
            lambda sol: sol != sale_order_line2 and sol.product_id == self.
            product_deliver_cost)

        self.assertTrue(
            sale_order_line3,
            "A new sale line should have been created with ordered product")
        self.assertTrue(
            sale_order_line4,
            "A new sale line should have been created with delivered product")
        self.assertEquals(
            len(self.sale_order.order_line), 4,
            "There should be 4 lines on the SO (2 vendor bill lines created)")
        self.assertEquals(
            len(self.sale_order.order_line.filtered(
                lambda sol: sol.is_expense)), 2,
            "There should be 4 lines on the SO (2 vendor bill lines created)")

        self.assertEquals(
            sale_order_line1.qty_delivered, 1,
            "Exising SO line 1 should not be impacted by reinvoicing product at cost"
        )
        self.assertEquals(
            sale_order_line2.qty_delivered, 1,
            "Exising SO line 2 should not be impacted by reinvoicing product at cost"
        )

        self.assertEquals(
            (sale_order_line3.price_unit, sale_order_line3.qty_delivered,
             sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced),
            (self.product_ordered_cost.standard_price, 3, 0, 0),
            'Sale line is wrong after confirming vendor invoice')
        self.assertEquals(
            (sale_order_line4.price_unit, sale_order_line4.qty_delivered,
             sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced),
            (self.product_deliver_cost.standard_price, 3, 0, 0),
            'Sale line is wrong after confirming vendor invoice')

        self.assertEquals(
            sale_order_line3.qty_delivered_method, 'analytic',
            "Delivered quantity of 'expense' SO line should be computed by analytic amount"
        )
        self.assertEquals(
            sale_order_line4.qty_delivered_method, 'analytic',
            "Delivered quantity of 'expense' SO line should be computed by analytic amount"
        )

        # create second invoice lines and validate it
        move_form = Form(self.AccountMove)
        move_form.partner_id = self.partner_customer_usd
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_ordered_cost
            line_form.quantity = 2.0
            line_form.analytic_account_id = self.analytic_account
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_deliver_cost
            line_form.quantity = 2.0
            line_form.analytic_account_id = self.analytic_account
        invoice_b = move_form.save()
        invoice_b.post()

        sale_order_line5 = self.sale_order.order_line.filtered(
            lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and
            sol.product_id == self.product_ordered_cost)
        sale_order_line6 = self.sale_order.order_line.filtered(
            lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and
            sol.product_id == self.product_deliver_cost)

        self.assertTrue(
            sale_order_line5,
            "A new sale line should have been created with ordered product")
        self.assertTrue(
            sale_order_line6,
            "A new sale line should have been created with delivered product")

        self.assertEquals(
            len(self.sale_order.order_line), 6,
            "There should be still 4 lines on the SO, no new created")
        self.assertEquals(
            len(self.sale_order.order_line.filtered(
                lambda sol: sol.is_expense)), 4,
            "There should be still 2 expenses lines on the SO")

        self.assertEquals(
            (sale_order_line5.price_unit, sale_order_line5.qty_delivered,
             sale_order_line5.product_uom_qty, sale_order_line5.qty_invoiced),
            (self.product_ordered_cost.standard_price, 2, 0, 0),
            'Sale line 5 is wrong after confirming 2e vendor invoice')
        self.assertEquals(
            (sale_order_line6.price_unit, sale_order_line6.qty_delivered,
             sale_order_line6.product_uom_qty, sale_order_line6.qty_invoiced),
            (self.product_deliver_cost.standard_price, 2, 0, 0),
            'Sale line 6 is wrong after confirming 2e vendor invoice')
Пример #16
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.assertEquals(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.assertEquals(picking.picking_type_id, wh.out_type_id)

        self.assertEquals(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.assertEquals(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.assertEquals(avail_qty_comp1, -1)
        self.assertEquals(avail_qty_comp2, -1)
        self.assertEquals(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)
Пример #17
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)

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

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

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

        # 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.assertEquals(avail_qty_comp1, -1)
        self.assertEquals(avail_qty_comp2, -1)
        self.assertEquals(avail_qty_finished, 1)
Пример #18
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_lot
            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.assertEquals(mo.state, 'confirmed')
        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_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.assertEquals(picking.picking_type_id, wh.out_type_id)

        lot_id = self.env['stock.production.lot'].create({
            'name':
            'lot1',
            'product_id':
            self.finished_lot.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,
        })
        produce_form = Form(self.env['mrp.product.produce'].with_context({
            'active_id':
            mo.id,
            'active_ids': [mo.id],
        }))
        produce_form.finished_lot_id = lot_id
        produce_form.raw_workorder_line_ids._records[0][
            'lot_id'] = serial_id.id
        wiz_produce = produce_form.save()
        wiz_produce.do_produce()

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

        picking_receipt.move_lines.quantity_done = 1
        picking_receipt.move_lines.move_line_ids.lot_id = lot_id.id
        picking_receipt.button_validate()
        self.assertEquals(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_lot, wh.lot_stock_id)
        self.assertEquals(avail_qty_comp1, -1)
        self.assertEquals(avail_qty_comp2, -1)
        self.assertEquals(avail_qty_finished, 1)
Пример #19
0
    def test_flow_7(self):
        """ Process a subcontracting receipt with tracked component and
        finished product. Simulate the regiter components button.
        Once the components are registered, try to do a correction on exisiting
        move lines and check that the subcontracting document is updated.
        """
        # Create a receipt picking from the subcontractor
        (self.comp1 | self.comp2 | self.finished).write({'tracking': 'lot'})
        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 = 5
        picking_receipt = picking_form.save()
        picking_receipt.action_confirm()
        mo = picking_receipt.move_lines.move_orig_ids.production_id
        move_comp1 = mo.move_raw_ids.filtered(
            lambda m: m.product_id == self.comp1)
        move_comp2 = mo.move_raw_ids.filtered(
            lambda m: m.product_id == self.comp2)
        # move_finished is linked to receipt and not MO finished move.
        move_finished = picking_receipt.move_lines

        self.assertEqual(move_comp1.quantity_done, 0)
        self.assertEqual(move_comp2.quantity_done, 0)

        lot_c1 = self.env['stock.production.lot'].create({
            'name':
            'LOT C1',
            'product_id':
            self.comp1.id,
            'company_id':
            self.env.company.id,
        })
        lot_c2 = self.env['stock.production.lot'].create({
            'name':
            'LOT C2',
            'product_id':
            self.comp2.id,
            'company_id':
            self.env.company.id,
        })
        lot_f1 = self.env['stock.production.lot'].create({
            'name':
            'LOT F1',
            'product_id':
            self.finished.id,
            'company_id':
            self.env.company.id,
        })

        register_form = Form(self.env['mrp.product.produce'].with_context(
            active_id=picking_receipt._get_subcontracted_productions().id,
            default_subcontract_move_id=picking_receipt.move_lines.id))
        register_form.qty_producing = 3.0
        self.assertEqual(
            len(register_form._values['raw_workorder_line_ids']), 2,
            'Register Components Form should contains one line per component.')
        self.assertTrue(
            all(p[2]['product_id'] in (self.comp1 | self.comp2).ids
                for p in register_form._values['raw_workorder_line_ids']),
            'Register Components Form should contains component.')
        with register_form.raw_workorder_line_ids.edit(0) as pl:
            pl.lot_id = lot_c1
        with register_form.raw_workorder_line_ids.edit(1) as pl:
            pl.lot_id = lot_c2
        register_form.finished_lot_id = lot_f1
        register_wizard = register_form.save()
        action = register_wizard.continue_production()
        register_form = Form(
            self.env['mrp.product.produce'].with_context(**action['context']))
        with register_form.raw_workorder_line_ids.edit(0) as pl:
            pl.lot_id = lot_c1
        with register_form.raw_workorder_line_ids.edit(1) as pl:
            pl.lot_id = lot_c2
        register_form.finished_lot_id = lot_f1
        register_wizard = register_form.save()
        register_wizard.do_produce()

        self.assertEqual(move_comp1.quantity_done, 5.0)
        self.assertEqual(
            move_comp1.move_line_ids.filtered(
                lambda ml: not ml.product_uom_qty).lot_id.name, 'LOT C1')
        self.assertEqual(move_comp2.quantity_done, 5.0)
        self.assertEqual(
            move_comp2.move_line_ids.filtered(
                lambda ml: not ml.product_uom_qty).lot_id.name, 'LOT C2')
        self.assertEqual(move_finished.quantity_done, 5.0)
        self.assertEqual(
            move_finished.move_line_ids.filtered(
                lambda ml: ml.product_uom_qty).lot_id.name, 'LOT F1')

        corrected_final_lot = self.env['stock.production.lot'].create({
            'name':
            'LOT F2',
            'product_id':
            self.finished.id,
            'company_id':
            self.env.company.id,
        })

        details_operation_form = Form(
            picking_receipt.move_lines,
            view=self.env.ref('stock.view_stock_move_operations'))
        for i in range(len(details_operation_form._values['move_line_ids'])):
            with details_operation_form.move_line_ids.edit(i) as ml:
                if ml._values['qty_done']:
                    ml.lot_id = corrected_final_lot
        details_operation_form.save()
        move_raw_comp_1 = picking_receipt.move_lines.move_orig_ids.production_id.move_raw_ids.filtered(
            lambda m: m.product_id == self.comp1)
        move_raw_comp_2 = picking_receipt.move_lines.move_orig_ids.production_id.move_raw_ids.filtered(
            lambda m: m.product_id == self.comp2)

        details_subcontract_moves_form = Form(
            move_raw_comp_1,
            view=self.env.ref(
                'mrp_subcontracting.mrp_subcontracting_move_form_view'))
        for i in range(
                len(details_subcontract_moves_form._values['move_line_ids'])):
            with details_subcontract_moves_form.move_line_ids.edit(i) as sc:
                if sc._values['qty_done']:
                    sc.lot_produced_ids.remove(index=0)
                    sc.lot_produced_ids.add(corrected_final_lot)
        details_subcontract_moves_form.save()
        details_subcontract_moves_form = Form(
            move_raw_comp_2,
            view=self.env.ref(
                'mrp_subcontracting.mrp_subcontracting_move_form_view'))
        for i in range(
                len(details_subcontract_moves_form._values['move_line_ids'])):
            with details_subcontract_moves_form.move_line_ids.edit(i) as sc:
                if sc._values['qty_done']:
                    sc.lot_produced_ids.remove(index=0)
                    sc.lot_produced_ids.add(corrected_final_lot)
        details_subcontract_moves_form.save()

        self.assertEqual(
            move_comp1.move_line_ids.filtered(
                lambda ml: not ml.product_uom_qty).lot_produced_ids.name,
            'LOT F2')
        self.assertEqual(
            move_comp2.move_line_ids.filtered(
                lambda ml: not ml.product_uom_qty).lot_produced_ids.name,
            'LOT F2')
Пример #20
0
    def test_at_cost(self):
        """ Test vendor bill at cost for product based on ordered and delivered quantities. """
        # create SO line and confirm SO (with only one line)
        sale_order_line1 = self.env['sale.order.line'].create({
            'name': self.product_ordered_cost.name,
            'product_id': self.product_ordered_cost.id,
            'product_uom_qty': 2,
            'product_uom': self.product_ordered_cost.uom_id.id,
            'price_unit': self.product_ordered_cost.list_price,
            'order_id': self.sale_order.id,
        })
        sale_order_line1.product_id_change()
        sale_order_line2 = self.env['sale.order.line'].create({
            'name': self.product_deliver_cost.name,
            'product_id': self.product_deliver_cost.id,
            'product_uom_qty': 4,
            'product_uom': self.product_deliver_cost.uom_id.id,
            'price_unit': self.product_deliver_cost.list_price,
            'order_id': self.sale_order.id,
        })
        sale_order_line2.product_id_change()

        self.sale_order.onchange_partner_id()
        self.sale_order._compute_tax_id()
        self.sale_order.action_confirm()

        self.assertEquals(sale_order_line1.qty_delivered_method, 'timesheet', "Delivered quantity of 'service' SO line should be computed by timesheet amount")
        self.assertEquals(sale_order_line2.qty_delivered_method, 'timesheet', "Delivered quantity of 'service' SO line should be computed by timesheet amount")

        # let's log some timesheets (on the project created by sale_order_line1)
        task_sol1 = sale_order_line1.task_id
        self.env['account.analytic.line'].create({
            'name': 'Test Line',
            'project_id': task_sol1.project_id.id,
            'task_id': task_sol1.id,
            'unit_amount': 1,
            'employee_id': self.employee_user.id,
        })

        move_form = Form(self.env['account.move'].with_context(default_type='in_invoice'))
        move_form.partner_id = self.partner_customer_usd
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_ordered_cost
            line_form.quantity = 3.0
            line_form.analytic_account_id = self.analytic_account
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_deliver_cost
            line_form.quantity = 3.0
            line_form.analytic_account_id = self.analytic_account
        invoice_a = move_form.save()
        invoice_a.post()

        sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.product_ordered_cost)
        sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.product_deliver_cost)

        self.assertTrue(sale_order_line3, "A new sale line should have been created with ordered product")
        self.assertTrue(sale_order_line4, "A new sale line should have been created with delivered product")
        self.assertEquals(len(self.sale_order.order_line), 4, "There should be 4 lines on the SO (2 vendor bill lines created)")
        self.assertEquals(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 2, "There should be 4 lines on the SO (2 vendor bill lines created)")

        self.assertEquals(sale_order_line1.qty_delivered, 1, "Exising SO line 1 should not be impacted by reinvoicing product at cost")
        self.assertEquals(sale_order_line2.qty_delivered, 0, "Exising SO line 2 should not be impacted by reinvoicing product at cost")

        self.assertFalse(sale_order_line3.task_id, "Adding a new expense SO line should not create a task (sol3)")
        self.assertFalse(sale_order_line4.task_id, "Adding a new expense SO line should not create a task (sol4)")
        self.assertEquals(len(self.sale_order.project_ids), 1, "SO create only one project with its service line. Adding new expense SO line should not impact that")

        self.assertEquals((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.product_ordered_cost.standard_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
        self.assertEquals((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.product_deliver_cost.standard_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')

        self.assertEquals(sale_order_line3.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")
        self.assertEquals(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")

        # create second invoice lines and validate it
        move_form = Form(self.env['account.move'].with_context(default_type='in_invoice'))
        move_form.partner_id = self.partner_customer_usd
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_ordered_cost
            line_form.quantity = 2.0
            line_form.analytic_account_id = self.analytic_account
        with move_form.line_ids.new() as line_form:
            line_form.product_id = self.product_deliver_cost
            line_form.quantity = 2.0
            line_form.analytic_account_id = self.analytic_account
        invoice_b = move_form.save()
        invoice_b.post()

        sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.product_ordered_cost)
        sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.product_deliver_cost)

        self.assertTrue(sale_order_line5, "A new sale line should have been created with ordered product")
        self.assertTrue(sale_order_line6, "A new sale line should have been created with delivered product")

        self.assertEquals(len(self.sale_order.order_line), 6, "There should be still 4 lines on the SO, no new created")
        self.assertEquals(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 4, "There should be still 2 expenses lines on the SO")

        self.assertEquals((sale_order_line5.price_unit, sale_order_line5.qty_delivered, sale_order_line5.product_uom_qty, sale_order_line5.qty_invoiced), (self.product_ordered_cost.standard_price, 2.0, 0, 0), 'Sale line 5 is wrong after confirming 2e vendor invoice')
        self.assertEquals((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line6.product_uom_qty, sale_order_line6.qty_invoiced), (self.product_deliver_cost.standard_price, 2.0, 0, 0), 'Sale line 6 is wrong after confirming 2e vendor invoice')
Пример #21
0
    def test_date_planned_1(self):
        """Set a date planned on a PO, see that it is set on the PO lines. Try to edit the date
        planned of the PO line, see that it is not possible. Unset the date planned on the PO and
        edit the date planned on the PO lines. Validate the PO and see that it isn't possible to
        set the date planned on the PO nor on the PO lines.
        """
        po = Form(self.env['purchase.order'])
        po.partner_id = self.vendor
        with po.order_line.new() as po_line:
            po_line.product_id = self.product_consu
            po_line.product_qty = 1
            po_line.price_unit = 100
        with po.order_line.new() as po_line:
            po_line.product_id = self.product_consu2
            po_line.product_qty = 10
            po_line.price_unit = 200
        po = po.save()

        # Check there is no date planned on the PO and the same date planned on both PO lines.
        self.assertEqual(po.date_planned, False)
        self.assertNotEqual(po.order_line[0].date_planned, False)
        self.assertAlmostEqual(po.order_line[0].date_planned,
                               po.order_line[1].date_planned,
                               delta=timedelta(seconds=10))

        orig_date_planned = po.order_line[0].date_planned

        # Set a date planned on a PO, see that it is set on the PO lines.
        new_date_planned = orig_date_planned + timedelta(hours=1)
        po.date_planned = new_date_planned
        self.assertAlmostEqual(po.order_line[0].date_planned,
                               new_date_planned,
                               delta=timedelta(seconds=10))
        self.assertAlmostEqual(po.order_line[1].date_planned,
                               new_date_planned,
                               delta=timedelta(seconds=10))

        # Try to edit the date planned of the PO line, see that it is not possible
        po = Form(po)
        with self.assertRaises(AssertionError):
            po.order_line.edit(0).date_planned = orig_date_planned
        with self.assertRaises(AssertionError):
            po.order_line.edit(1).date_planned = orig_date_planned
        po = po.save()

        self.assertAlmostEqual(po.order_line[0].date_planned,
                               new_date_planned,
                               delta=timedelta(seconds=10))
        self.assertAlmostEqual(po.order_line[1].date_planned,
                               new_date_planned,
                               delta=timedelta(seconds=10))

        # Unset the date planned on the PO and edit the date planned on the PO line.
        po = Form(po)
        po.date_planned = False
        with po.order_line.edit(0) as po_line:
            po_line.date_planned = orig_date_planned
        with po.order_line.edit(1) as po_line:
            po_line.date_planned = orig_date_planned
        po = po.save()

        self.assertAlmostEqual(po.order_line[0].date_planned,
                               orig_date_planned,
                               delta=timedelta(seconds=10))
        self.assertAlmostEqual(po.order_line[1].date_planned,
                               orig_date_planned,
                               delta=timedelta(seconds=10))

        # Validate the PO and see that it isn't possible to set the date planned on the PO
        # nor on the PO lines.
        po.button_confirm()
        po.button_done()

        po = Form(po)
        with self.assertRaises(AssertionError):
            po.date_planned = new_date_planned
        with self.assertRaises(AssertionError):
            with po.order_line.edit(0) as po_line:
                po_line.date_planned = orig_date_planned
        with self.assertRaises(AssertionError):
            with po.order_line.edit(1) as po_line:
                po_line.date_planned = orig_date_planned
        po.save()
Пример #22
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 to the subcontractor is not created
        at the receipt creation. Then run the scheduler and check that
        the delivery and MO exist.
        """
        # 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)]})

        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_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.assertEquals(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.assertFalse(move)

        self.env['procurement.group'].run_scheduler(
            company_id=self.env.company.id)

        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)
Пример #23
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.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')

        # 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.assertEquals(avail_qty_comp1, -1)
        self.assertEquals(avail_qty_comp2, -1)
        self.assertEquals(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)
Пример #24
0
    def test_mrp_subcontracting_dropshipping_1(self):
        """ Mark the subcontracted product with the route dropship and add the
        subcontractor as seller. The component has the routes 'MTO', 'Replenish
        on order' and 'Buy'. Also another partner is set as vendor on the comp.
        Create a SO and check that:
        - Delivery between subcontractor and customer for subcontracted product.
        - Delivery for the component to the subcontractor for the specified wh.
        - Po created for the component.
        """
        mto_route = self.env['stock.location.route'].search([
            ('name', '=', 'Replenish on Order (MTO)')
        ])
        resupply_route = self.env['stock.location.route'].search([
            ('name', '=', 'Resupply Subcontractor on Order')
        ])
        buy_route = self.env['stock.location.route'].search([('name', '=',
                                                              'Buy')])
        dropship_route = self.env['stock.location.route'].search([
            ('name', '=', 'Dropship')
        ])
        self.comp2.write({
            'route_ids': [(4, buy_route.id), (4, mto_route.id),
                          (4, resupply_route.id)]
        })
        self.finished.write({'route_ids': [(4, dropship_route.id)]})

        warehouse = self.env['stock.warehouse'].create({
            'name': 'Warehouse For subcontract',
            'code': 'WFS'
        })

        self.env['product.supplierinfo'].create({
            'product_tmpl_id':
            self.finished.product_tmpl_id.id,
            'name':
            self.subcontractor_partner1.id
        })

        partner = self.env['res.partner'].create({'name': 'Toto'})
        self.env['product.supplierinfo'].create({
            'product_tmpl_id':
            self.comp2.product_tmpl_id.id,
            'name':
            partner.id
        })

        # Create a receipt picking from the subcontractor
        so_form = Form(self.env['sale.order'])
        so_form.partner_id = partner
        so_form.warehouse_id = warehouse
        with so_form.order_line.new() as line:
            line.product_id = self.finished
            line.product_uom_qty = 1
        so = so_form.save()
        so.action_confirm()

        # Pickings should directly be created
        po = self.env['purchase.order'].search([('origin', 'ilike', so.name)])
        self.assertTrue(po)

        po.button_approve()

        picking_finished = po.picking_ids
        self.assertEqual(len(picking_finished), 1.0)
        self.assertEqual(picking_finished.location_dest_id,
                         partner.property_stock_customer)
        self.assertEqual(picking_finished.location_id,
                         self.subcontractor_partner1.property_stock_supplier)
        self.assertEqual(picking_finished.state, 'assigned')

        picking_delivery = self.env['stock.move'].search([
            ('product_id', '=', self.comp2.id),
            ('location_id', '=', warehouse.lot_stock_id.id),
            ('location_dest_id', '=',
             self.subcontractor_partner1.property_stock_subcontractor.id),
        ]).picking_id
        self.assertTrue(picking_delivery)
        self.assertEqual(picking_delivery.state, 'waiting')

        po = self.env['purchase.order.line'].search([
            ('product_id', '=', self.comp2.id),
            ('partner_id', '=', partner.id),
        ]).order_id
        self.assertTrue(po)
Пример #25
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)