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' )
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')
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.' )
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()
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")
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")
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
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")
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')
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)
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')
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." )
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"')
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')
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)
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)
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)
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')
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')
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()
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)
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)
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)
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)