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_flow_9(self): """Ensure that cancel the subcontract moves will also delete the components need for the subcontractor. """ 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)] }) 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_delivery = self.env['stock.move'].search([ ('product_id', 'in', (self.comp1 | self.comp2).ids) ]).picking_id self.assertTrue(picking_delivery) self.assertEqual(picking_delivery.state, 'confirmed') self.assertEqual(self.comp1.virtual_available, -5) self.assertEqual(self.comp2.virtual_available, -5) # action_cancel is not call on the picking in order # to test behavior from other source than picking (e.g. puchase). picking_receipt.move_lines._action_cancel() self.assertEqual(picking_delivery.state, 'cancel') self.assertEqual(self.comp1.virtual_available, 0.0) self.assertEqual(self.comp1.virtual_available, 0.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')
def test_read_purchase_order(self): """ Check that a purchase user can read all purchase order and 'in' invoices""" purchase_user_2 = self.purchase_user.copy({ 'name': 'Purchase user 2', 'login': '******', 'email': '*****@*****.**', }) purchase_order_form = Form(self.env['purchase.order'].with_user(purchase_user_2)) purchase_order_form.partner_id = self.vendor with purchase_order_form.order_line.new() as line: line.name = self.product.name line.product_id = self.product line.product_qty = 4 line.price_unit = 5 purchase_order_user2 = purchase_order_form.save() action = purchase_order_user2.with_user(purchase_user_2).action_view_invoice() invoice_form = Form(self.env['account.move'].with_user(purchase_user_2).with_context(action['context'])) vendor_bill_user2 = invoice_form.save() # open purchase_order_user2 and vendor_bill_user2 with `self.purchase_user` purchase_order_user1 = Form(purchase_order_user2.with_user(self.purchase_user)) purchase_order_user1 = purchase_order_user1.save() vendor_bill_user1 = Form(vendor_bill_user2.with_user(self.purchase_user)) vendor_bill_user1 = vendor_bill_user1.save()
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 _dropship_product1(self): # enable the dropship and MTO route on the product dropshipping_route = self.env.ref('stock_dropshipping.route_drop_shipping') mto_route = self.env.ref('stock.route_warehouse0_mto') self.product1.write({'route_ids': [(6, 0, [dropshipping_route.id, mto_route.id])]}) # add a vendor vendor1 = self.env['res.partner'].create({'name': 'vendor1'}) seller1 = self.env['product.supplierinfo'].create({ 'name': vendor1.id, 'price': 8, }) self.product1.write({'seller_ids': [(6, 0, [seller1.id])]}) # sell one unit of this product customer1 = self.env['res.partner'].create({'name': 'customer1'}) self.sale_order1 = self.env['sale.order'].create({ 'partner_id': customer1.id, 'partner_invoice_id': customer1.id, 'partner_shipping_id': customer1.id, 'order_line': [(0, 0, { 'name': self.product1.name, 'product_id': self.product1.id, 'product_uom_qty': 1, 'product_uom': self.product1.uom_id.id, 'price_unit': 12, })], 'pricelist_id': self.env.ref('product.list0').id, 'picking_policy': 'direct', }) self.sale_order1.action_confirm() # confirm the purchase order self.purchase_order1 = self.env['purchase.order'].search([('group_id', '=', self.sale_order1.procurement_group_id.id)]) self.purchase_order1.button_confirm() # validate the dropshipping picking self.assertEqual(len(self.sale_order1.picking_ids), 1) #self.assertEqual(self.sale_order1.picking_ids.move_lines._is_dropshipped(), True) wizard = self.sale_order1.picking_ids.button_validate() immediate_transfer = self.env[wizard['res_model']].browse(wizard['res_id']) immediate_transfer.process() self.assertEqual(self.sale_order1.picking_ids.state, 'done') # create the vendor bill move_form = Form(self.env['account.move'].with_context(default_type='in_invoice')) move_form.partner_id = vendor1 move_form.purchase_id = self.purchase_order1 self.vendor_bill1 = move_form.save() self.vendor_bill1.post() # create the customer invoice self.customer_invoice1 = self.sale_order1._create_invoices() self.customer_invoice1.post() all_amls = self.vendor_bill1.line_ids + self.customer_invoice1.line_ids if self.sale_order1.picking_ids.move_lines.account_move_ids: all_amls |= self.sale_order1.picking_ids.move_lines.account_move_ids.line_ids return all_amls
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_dropship(self): # Create a vendor supplier_dropship = self.env['res.partner'].create({'name': 'Vendor of Dropshipping test'}) # Create new product without any routes drop_shop_product = self.env['product.product'].create({ 'name': "Pen drive", 'type': "product", 'categ_id': self.env.ref('product.product_category_1').id, 'lst_price': 100.0, 'standard_price': 0.0, 'uom_id': self.env.ref('uom.product_uom_unit').id, 'uom_po_id': self.env.ref('uom.product_uom_unit').id, 'seller_ids': [(0, 0, { 'delay': 1, 'name': supplier_dropship.id, 'min_qty': 2.0 })] }) # Create a sales order with a line of 200 PCE incoming shipment, with route_id drop shipping so_form = Form(self.env['sale.order']) so_form.partner_id = self.env.ref('base.res_partner_2') so_form.payment_term_id = self.env.ref('account.account_payment_term_end_following_month') with mute_logger('harpiya.tests.common.onchange'): # otherwise complains that there's not enough inventory and # apparently that's normal according to @jco and @sle with so_form.order_line.new() as line: line.product_id = drop_shop_product line.product_uom_qty = 200 line.price_unit = 1.00 line.route_id = self.env.ref('stock_dropshipping.route_drop_shipping') sale_order_drp_shpng = so_form.save() # Confirm sales order sale_order_drp_shpng.action_confirm() # Check the sales order created a procurement group which has a procurement of 200 pieces self.assertTrue(sale_order_drp_shpng.procurement_group_id, 'SO should have procurement group') # Check a quotation was created to a certain vendor and confirm so it becomes a confirmed purchase order purchase = self.env['purchase.order'].search([('partner_id', '=', supplier_dropship.id)]) self.assertTrue(purchase, "an RFQ should have been created by the scheduler") purchase.button_confirm() self.assertEquals(purchase.state, 'purchase', 'Purchase order should be in the approved state') self.assertEquals(len(purchase.ids), 1, 'There should be one picking') # Send the 200 pieces purchase.picking_ids.move_lines.quantity_done = purchase.picking_ids.move_lines.product_qty purchase.picking_ids.button_validate() # Check one move line was created in Customers location with 200 pieces move_line = self.env['stock.move.line'].search([ ('location_dest_id', '=', self.env.ref('stock.stock_location_customers').id), ('product_id', '=', drop_shop_product.id)]) self.assertEquals(len(move_line.ids), 1, 'There should be exactly one move line')
def test_flow_6(self): """ Extra quantity on the move. """ # We create a second partner of type subcontractor main_partner_2 = self.env['res.partner'].create({'name': 'main_partner'}) subcontractor_partner2 = self.env['res.partner'].create({ 'name': 'subcontractor_partner', 'parent_id': main_partner_2.id, 'company_id': self.env.ref('base.main_company').id, }) self.env.cache.invalidate() # We create a different BoM for the same product comp3 = self.env['product.product'].create({ 'name': 'Component3', 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, }) bom_form = Form(self.env['mrp.bom']) bom_form.type = 'subcontract' bom_form.product_tmpl_id = self.finished.product_tmpl_id with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.comp1 bom_line.product_qty = 1 with bom_form.bom_line_ids.new() as bom_line: bom_line.product_id = comp3 bom_line.product_qty = 2 bom2 = bom_form.save() # We assign the second BoM to the new partner self.bom.write({'subcontractor_ids': [(4, self.subcontractor_partner1.id, None)]}) bom2.write({'subcontractor_ids': [(4, subcontractor_partner2.id, None)]}) # Create a receipt picking from the subcontractor1 picking_form = Form(self.env['stock.picking']) picking_form.picking_type_id = self.env.ref('stock.picking_type_in') picking_form.partner_id = subcontractor_partner2 with picking_form.move_ids_without_package.new() as move: move.product_id = self.finished move.product_uom_qty = 1 picking_receipt = picking_form.save() picking_receipt.action_confirm() picking_receipt.move_lines.quantity_done = 3.0 picking_receipt.action_done() mo = picking_receipt._get_subcontracted_productions() move_comp1 = mo.move_raw_ids.filtered(lambda m: m.product_id == self.comp1) move_comp3 = mo.move_raw_ids.filtered(lambda m: m.product_id == comp3) self.assertEqual(sum(move_comp1.mapped('product_uom_qty')), 3.0) self.assertEqual(sum(move_comp3.mapped('product_uom_qty')), 6.0) self.assertEqual(sum(move_comp1.mapped('quantity_done')), 3.0) self.assertEqual(sum(move_comp3.mapped('quantity_done')), 6.0) move_finished = mo.move_finished_ids self.assertEqual(sum(move_finished.mapped('product_uom_qty')), 3.0) self.assertEqual(sum(move_finished.mapped('quantity_done')), 3.0)
def test_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 test_vendor_bill_flow_anglo_saxon_2(self): """In anglo saxon accounting, receive 10@10 and invoice with the addition of 1@50 as a landed costs and create a linked landed costs record. """ self.env.company.anglo_saxon_accounting = True # Create an RFQ for self.product1, 10@10 rfq = Form(self.env['purchase.order']) rfq.partner_id = self.vendor1 with rfq.order_line.new() as po_line: po_line.product_id = self.product1 po_line.price_unit = 10 po_line.product_qty = 10 po_line.taxes_id.clear() rfq = rfq.save() rfq.button_confirm() # Process the receipt receipt = rfq.picking_ids wiz = receipt.button_validate() wiz = self.env['stock.immediate.transfer'].browse( wiz['res_id']).process() self.assertEqual(rfq.order_line.qty_received, 10) input_aml = self._get_stock_input_move_lines()[-1] self.assertEqual(input_aml.debit, 0) self.assertEqual(input_aml.credit, 100) valuation_aml = self._get_stock_valuation_move_lines()[-1] self.assertEqual(valuation_aml.debit, 100) self.assertEqual(valuation_aml.credit, 0) # Create a vebdor bill for the RFQ and add to it the landed cost action = rfq.action_view_invoice() vb = Form(self.env['account.move'].with_context(action['context'])) with vb.invoice_line_ids.new() as inv_line: inv_line.product_id = self.productlc1 inv_line.price_unit = 50 inv_line.is_landed_costs_line = True vb = vb.save() vb.post() action = vb.button_create_landed_costs() lc = Form(self.env[action['res_model']].browse(action['res_id'])) lc.picking_ids.add(receipt) lc = lc.save() lc.button_validate() # Check reconciliation of input aml of lc lc_input_aml = lc.account_move_id.line_ids.filtered( lambda aml: aml.account_id == self.stock_input_account) self.assertTrue(len(lc_input_aml.full_reconcile_id), 1)
def test_00_procurement_exception(self): # I create a product with no supplier define for it. product_form = Form(self.env['product.product']) product_form.name = 'product with no seller' product_form.lst_price = 20.00 product_form.categ_id = self.env.ref('product.product_category_1') product_with_no_seller = product_form.save() std_price_wiz = Form( self.env['stock.change.standard.price'].with_context( active_id=product_with_no_seller.id, active_model='product.product')) std_price_wiz.new_price = 70.0 std_price_wiz.save() # I create a sales order with this product with route dropship. so_form = Form(self.env['sale.order']) so_form.partner_id = self.env.ref('base.res_partner_2') so_form.partner_invoice_id = self.env.ref('base.res_partner_address_3') so_form.partner_shipping_id = self.env.ref( 'base.res_partner_address_3') so_form.payment_term_id = self.env.ref( 'account.account_payment_term_end_following_month') with so_form.order_line.new() as line: line.product_id = product_with_no_seller line.product_uom_qty = 3 line.route_id = self.env.ref( 'stock_dropshipping.route_drop_shipping') sale_order_route_dropship01 = so_form.save() # I confirm the sales order, but it will raise an error with self.assertRaises(Exception): sale_order_route_dropship01.action_confirm() # I set the at least one supplier on the product. with Form(product_with_no_seller) as f: with f.seller_ids.new() as seller: seller.delay = 1 seller.name = self.env.ref('base.res_partner_2') seller.min_qty = 2.0 # I confirm the sales order, no error this time sale_order_route_dropship01.action_confirm() # I check a purchase quotation was created. purchase = self.env['purchase.order.line'].search([ ('sale_line_id', '=', sale_order_route_dropship01.order_line.ids[0]) ]).order_id self.assertTrue(purchase, 'No Purchase Quotation is created')
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_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 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.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 test_create_purchase_order(self): """Check a purchase user can create a vendor bill from a purchase order but not post it""" purchase_order_form = Form(self.env['purchase.order'].with_user(self.purchase_user)) purchase_order_form.partner_id = self.vendor with purchase_order_form.order_line.new() as line: line.name = self.product.name line.product_id = self.product line.product_qty = 4 line.price_unit = 5 purchase_order = purchase_order_form.save() purchase_order.button_confirm() action = purchase_order.with_user(self.purchase_user).action_view_invoice() invoice_form = Form(self.env['account.move'].with_user(self.purchase_user).with_context( action['context'] )) invoice = invoice_form.save() with self.assertRaises(AccessError): invoice.post()
def test_flow_10(self): """Receipts from a children contact of a subcontractor are properly handled. """ # Create a children contact subcontractor_contact = self.env['res.partner'].create({ 'name': 'Test children subcontractor contact', 'parent_id': self.subcontractor_partner1.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 = subcontractor_contact 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() # Check that a manufacturing order is created mo = self.env['mrp.production'].search([('bom_id', '=', self.bom.id)]) self.assertEqual(len(mo), 1)
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_read_purchase_order_2(self): """ Check that a 2 purchase users with open the vendor bill the same way even with a 'own documents only' record rule. """ # edit the account.move record rule for purchase user in order to ensure # a user can only see his own invoices rule = self.env.ref('purchase.purchase_user_account_move_rule') rule.domain_force = "['&', ('type', 'in', ('in_invoice', 'in_refund', 'in_receipt')), ('invoice_user_id', '=', user.id)]" # create a purchase and make a vendor bill from it as purchase user 2 purchase_user_2 = self.purchase_user.copy({ 'name': 'Purchase user 2', 'login': '******', 'email': '*****@*****.**', }) purchase_order_form = Form(self.env['purchase.order'].with_user(purchase_user_2)) purchase_order_form.partner_id = self.vendor with purchase_order_form.order_line.new() as line: line.name = self.product.name line.product_id = self.product line.product_qty = 4 line.price_unit = 5 purchase_order_user2 = purchase_order_form.save() action = purchase_order_user2.with_user(purchase_user_2).action_view_invoice() invoice_form = Form(self.env['account.move'].with_user(purchase_user_2).with_context(action['context'])) vendor_bill_user2 = invoice_form.save() # check user 1 cannot read the invoice with self.assertRaises(AccessError): Form(vendor_bill_user2.with_user(self.purchase_user)) # Check that calling 'action_view_invoice' return the same action despite the record rule action_user_1 = purchase_order_user2.with_user(self.purchase_user).action_view_invoice() purchase_order_user2.invalidate_cache() action_user_2 = purchase_order_user2.with_user(purchase_user_2).action_view_invoice() self.assertEqual(action_user_1, action_user_2)
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_00_crossdock(self): # Create a supplier supplier_crossdock = self.env['res.partner'].create( {'name': "Crossdocking supplier"}) # I first create a warehouse with pick-pack-ship and reception in 2 steps wh_f = Form(self.env['stock.warehouse']) wh_f.name = 'WareHouse PickPackShip' wh_f.code = 'whpps' wh_f.reception_steps = 'two_steps' wh_f.delivery_steps = 'pick_pack_ship' wh_pps = wh_f.save() # Check that cross-dock route is active self.assertTrue( wh_pps.crossdock_route_id.active, "Crossdock route should be active when reception_steps is not in 'single_step'" ) p_f = Form(self.env['product.template']) p_f.name = 'PCE' p_f.type = 'product' p_f.categ_id = self.env.ref('product.product_category_1') p_f.list_price = 100.0 with p_f.seller_ids.new() as seller: seller.name = supplier_crossdock p_f.route_ids.add(wh_pps.crossdock_route_id) cross_shop_product = p_f.save() std_price_wiz = Form( self.env['stock.change.standard.price'].with_context( active_id=p_f.id, active_model='product.template')) std_price_wiz.new_price = 70.0 std_price_wiz.save() # Create a sales order with a line of 100 PCE incoming shipment with route_id crossdock shipping so_form = Form(self.env['sale.order']) so_form.partner_id = self.env.ref('base.res_partner_4') so_form.warehouse_id = wh_pps with mute_logger('harpiya.tests.common.onchange'): # otherwise complains that there's not enough inventory and # apparently that's normal according to @jco and @sle with so_form.order_line.new() as line: line.product_id = cross_shop_product.product_variant_ids line.product_uom_qty = 100.0 sale_order_crossdock = so_form.save() # Confirm sales order sale_order_crossdock.action_confirm() # Run the scheduler self.env['procurement.group'].run_scheduler() # Check a quotation was created for the created supplier and confirm it po = self.env['purchase.order'].search([('partner_id', '=', supplier_crossdock.id), ('state', '=', 'draft')]) self.assertTrue(po, "an RFQ should have been created by the scheduler") po.button_confirm()
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_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_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_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_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_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_invoice_after_lc(self): self.env.company.anglo_saxon_accounting = True self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' self.price_diff_account = self.env['account.account'].create({ 'name': 'price diff account', 'code': 'price diff account', 'user_type_id': self.env.ref('account.data_account_type_current_assets').id, }) self.product1.property_account_creditor_price_difference = self.price_diff_account # Create PO po_form = Form(self.env['purchase.order']) po_form.partner_id = self.env['res.partner'].create({'name': 'vendor'}) with po_form.order_line.new() as po_line: po_line.product_id = self.product1 po_line.product_qty = 1 po_line.price_unit = 455.0 order = po_form.save() order.button_confirm() # Receive the goods receipt = order.picking_ids[0] receipt.move_lines.quantity_done = 1 receipt.button_validate() # Check SVL and AML svl = self.env['stock.valuation.layer'].search([('stock_move_id', '=', receipt.move_lines.id)]) self.assertAlmostEqual(svl.value, 455) aml = self.env['account.move.line'].search([('account_id', '=', self.stock_valuation_account.id)]) self.assertAlmostEqual(aml.debit, 455) # Create and validate LC lc = self.env['stock.landed.cost'].create(dict( picking_ids=[(6, 0, [receipt.id])], account_journal_id=self.stock_journal.id, cost_lines=[ (0, 0, { 'name': 'equal split', 'split_method': 'equal', 'price_unit': 99, 'product_id': self.productlc1.id, }), ], )) lc.compute_landed_cost() lc.button_validate() # Check LC, SVL and AML self.assertAlmostEqual(lc.valuation_adjustment_lines.final_cost, 554) svl = self.env['stock.valuation.layer'].search([('stock_move_id', '=', receipt.move_lines.id)], order='id desc', limit=1) self.assertAlmostEqual(svl.value, 99) aml = self.env['account.move.line'].search([('account_id', '=', self.stock_valuation_account.id)], order='id desc', limit=1) self.assertAlmostEqual(aml.debit, 99) # Create an invoice with the same price move_form = Form(self.env['account.move'].with_context(default_type='in_invoice')) move_form.partner_id = order.partner_id move_form.purchase_id = order move = move_form.save() move.post() # Check nothing was posted in the price difference account price_diff_aml = self.env['account.move.line'].search([('account_id','=', self.price_diff_account.id), ('move_id', '=', move.id)]) self.assertEquals(len(price_diff_aml), 0, "No line should have been generated in the price difference account.")
def test_lifoprice(self): self._load('account', 'test', 'account_minimal_test.xml') self._load('stock_account', 'test', 'stock_valuation_account.xml') # Set product category removal strategy as LIFO product_category_001 = self.env['product.category'].create({ 'name': 'Lifo Category', 'removal_strategy_id': self.env.ref('stock.removal_lifo').id, 'property_valuation': 'real_time', 'property_cost_method': 'fifo', }) # Set a product as using lifo price product_form = Form(self.env['product.product']) product_form.default_code = 'LIFO' product_form.name = 'LIFO Ice Cream' product_form.type = 'product' product_form.categ_id = product_category_001 product_form.lst_price = 100.0 product_form.uom_id = self.env.ref('uom.product_uom_kgm') product_form.uom_po_id = self.env.ref('uom.product_uom_kgm') # these are not available (visible) in either product or variant # for views, apparently from the UI you can only set the product # category (or hand-assign the property_* version which seems...) # product_form.categ_id.valuation = 'real_time' # product_form.categ_id.property_cost_method = 'fifo' product_form.categ_id.property_stock_account_input_categ_id = self.env.ref( 'stock_dropshipping.o_expense') product_form.categ_id.property_stock_account_output_categ_id = self.env.ref( 'stock_dropshipping.o_income') product_lifo_icecream = product_form.save() std_price_wiz = Form( self.env['stock.change.standard.price'].with_context( active_id=product_lifo_icecream.id, active_model='product.product')) std_price_wiz.new_price = 70.0 std_price_wiz.save() # I create a draft Purchase Order for first in move for 10 pieces at 60 euro order_form = Form(self.env['purchase.order']) order_form.partner_id = self.env.ref('base.res_partner_3') with order_form.order_line.new() as line: line.product_id = product_lifo_icecream line.product_qty = 10.0 line.price_unit = 60.0 purchase_order_lifo1 = order_form.save() # I create a draft Purchase Order for second shipment for 30 pieces at 80 euro order2_form = Form(self.env['purchase.order']) order2_form.partner_id = self.env.ref('base.res_partner_3') with order2_form.order_line.new() as line: line.product_id = product_lifo_icecream line.product_qty = 30.0 line.price_unit = 80.0 purchase_order_lifo2 = order2_form.save() # I confirm the first purchase order purchase_order_lifo1.button_confirm() # I check the "Approved" status of purchase order 1 self.assertEqual(purchase_order_lifo1.state, 'purchase') # Process the receipt of purchase order 1 purchase_order_lifo1.picking_ids[ 0].move_lines.quantity_done = purchase_order_lifo1.picking_ids[ 0].move_lines.product_qty purchase_order_lifo1.picking_ids[0].button_validate() # I confirm the second purchase order purchase_order_lifo2.button_confirm() # Process the receipt of purchase order 2 purchase_order_lifo2.picking_ids[ 0].move_lines.quantity_done = purchase_order_lifo2.picking_ids[ 0].move_lines.product_qty purchase_order_lifo2.picking_ids[0].button_validate() # Let us send some goods out_form = Form(self.env['stock.picking']) out_form.picking_type_id = self.env.ref('stock.picking_type_out') out_form.immediate_transfer = True with out_form.move_ids_without_package.new() as move: move.product_id = product_lifo_icecream move.quantity_done = 20.0 move.date_expected = fields.Datetime.now() outgoing_lifo_shipment = out_form.save() # I assign this outgoing shipment outgoing_lifo_shipment.action_assign() # Process the delivery of the outgoing shipment outgoing_lifo_shipment.button_validate() # Check if the move value correctly reflects the fifo costing method self.assertEqual( outgoing_lifo_shipment.move_lines.stock_valuation_layer_ids.value, -1400.0, 'Stock move value should have been 1400 euro')