def _create_invoice_for_po(self, purchase_order, date): move_form = Form( self.env['account.move'].with_context(default_type='in_invoice')) move_form.invoice_date = date move_form.partner_id = self.test_partner move_form.currency_id = self.currency_two move_form.purchase_id = purchase_order return move_form.save()
def _init_payment(cls, payment_type, partner_type=None): payment_form = Form(cls.env['account.payment']) payment_form.journal_id = cls.bank_journal payment_form.payment_date = fields.Date.from_string('2019-01-01') payment_form.amount = 100 if payment_type == 'transfer': payment_form.destination_journal_id = cls.cash_journal else: payment_form.partner_type = partner_type payment_form.partner_id = cls.partner_a payment_form.payment_type = payment_type return payment_form.save()
def test_subcontracting_account_flow_1(self): self.stock_location = self.env.ref('stock.stock_location_stock') self.customer_location = self.env.ref('stock.stock_location_customers') self.supplier_location = self.env.ref('stock.stock_location_suppliers') self.uom_unit = self.env.ref('uom.product_uom_unit') self.env.ref('product.product_category_all').property_cost_method = 'fifo' # IN 10@10 comp1 10@20 comp2 move1 = self.env['stock.move'].create({ 'name': 'IN 10 units @ 10.00 per unit', 'location_id': self.supplier_location.id, 'location_dest_id': self.env.company.subcontracting_location_id.id, 'product_id': self.comp1.id, 'product_uom': self.uom_unit.id, 'product_uom_qty': 10.0, 'price_unit': 10.0, }) move1._action_confirm() move1._action_assign() move1.move_line_ids.qty_done = 10.0 move1._action_done() move2 = self.env['stock.move'].create({ 'name': 'IN 10 units @ 20.00 per unit', 'location_id': self.supplier_location.id, 'location_dest_id': self.env.company.subcontracting_location_id.id, 'product_id': self.comp2.id, 'product_uom': self.uom_unit.id, 'product_uom_qty': 10.0, 'price_unit': 20.0, }) move2._action_confirm() move2._action_assign() move2.move_line_ids.qty_done = 10.0 move2._action_done() 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.move_lines.price_unit = 30.0 picking_receipt.action_confirm() picking_receipt.move_lines.quantity_done = 1.0 picking_receipt.action_done() mo = picking_receipt._get_subcontracted_productions() self.assertEqual(mo.move_finished_ids.stock_valuation_layer_ids.value, 60) self.assertEqual(mo.move_finished_ids.product_id.value_svl, 60)
def _create_invoice_line(cls, amount, partner, type): ''' Create an invoice on the fly.''' invoice_form = Form( cls.env['account.move'].with_context(default_type=type)) invoice_form.invoice_date = fields.Date.from_string('2019-09-01') invoice_form.partner_id = partner with invoice_form.invoice_line_ids.new() as invoice_line_form: invoice_line_form.name = 'xxxx' invoice_line_form.quantity = 1 invoice_line_form.price_unit = amount invoice_line_form.tax_ids.clear() invoice = invoice_form.save() invoice.post() lines = invoice.line_ids return lines.filtered(lambda l: l.account_id.user_type_id.type in ('receivable', 'payable'))
def test_06_differed_schedule_date(self): warehouse = self.env['stock.warehouse'].search([], limit=1) # mark all rules as propagate_date so that push rules will use it self.env['stock.rule'].search([]).write({ 'propagate_date': True, 'propagate_date_minimum_delta': 5, }) with Form(warehouse) as w: w.reception_steps = 'three_steps' po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner_id with po_form.order_line.new() as line: line.product_id = self.product_id_1 line.date_planned = datetime.today() line.product_qty = 1.0 with po_form.order_line.new() as line: line.product_id = self.product_id_1 line.date_planned = datetime.today() + timedelta(days=7) line.product_qty = 1.0 po = po_form.save() # mark the po line as propagate_date so that the created moves will use it po.order_line.write({ 'propagate_date': True, 'propagate_date_minimum_delta': 5, }) po.button_approve() po.picking_ids.move_line_ids.write({ 'qty_done': 1.0 }) po.picking_ids.button_validate() pickings = self.env['stock.picking'].search([('group_id', '=', po.group_id.id)]) for picking in pickings: self.assertEqual(picking.scheduled_date.date(), date.today())
def test_sale_mrp_pickings(self): """ Test sale of multiple mrp products in MTO to avoid generating multiple deliveries to the customer location """ # Create warehouse self.customer_location = self.env['ir.model.data'].xmlid_to_res_id( 'stock.stock_location_customers') warehouse_form = Form(self.env['stock.warehouse']) warehouse_form.name = 'Test Warehouse' warehouse_form.code = 'TWH' self.warehouse = warehouse_form.save() self.uom_unit = self.env.ref('uom.product_uom_unit') # Create raw product for manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Raw Stick' product_form.type = 'product' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit self.raw_product = product_form.save() # Create manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Stick' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit product_form.type = 'product' product_form.route_ids.clear() product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id) product_form.route_ids.add(self.warehouse.mto_pull_id.route_id) self.finished_product = product_form.save() # Create manifactured product which uses another manifactured product_form = Form(self.env['product.product']) product_form.name = 'Arrow' product_form.type = 'product' product_form.route_ids.clear() product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id) product_form.route_ids.add(self.warehouse.mto_pull_id.route_id) self.complex_product = product_form.save() ## Create raw product for manufactured product product_form = Form(self.env['product.product']) product_form.name = 'Raw Iron' product_form.type = 'product' product_form.uom_id = self.uom_unit product_form.uom_po_id = self.uom_unit self.raw_product_2 = product_form.save() # Create bom for manufactured product bom_product_form = Form(self.env['mrp.bom']) bom_product_form.product_id = self.finished_product bom_product_form.product_tmpl_id = self.finished_product.product_tmpl_id bom_product_form.product_qty = 1.0 bom_product_form.type = 'normal' with bom_product_form.bom_line_ids.new() as bom_line: bom_line.product_id = self.raw_product bom_line.product_qty = 2.0 self.bom = bom_product_form.save() ## Create bom for manufactured product bom_product_form = Form(self.env['mrp.bom']) bom_product_form.product_id = self.complex_product bom_product_form.product_tmpl_id = self.complex_product.product_tmpl_id with bom_product_form.bom_line_ids.new() as line: line.product_id = self.finished_product line.product_qty = 1.0 with bom_product_form.bom_line_ids.new() as line: line.product_id = self.raw_product_2 line.product_qty = 1.0 self.complex_bom = bom_product_form.save() with Form(self.warehouse) as warehouse: warehouse.manufacture_steps = 'pbm_sam' so_form = Form(self.env['sale.order']) so_form.partner_id = self.env.ref('base.res_partner_4') with so_form.order_line.new() as line: line.product_id = self.complex_product line.price_unit = 1 line.product_uom_qty = 1 with so_form.order_line.new() as line: line.product_id = self.finished_product line.price_unit = 1 line.product_uom_qty = 1 sale_order_so0 = so_form.save() sale_order_so0.action_confirm() pickings = sale_order_so0.picking_ids # One delivery... self.assertEqual(len(pickings), 1) # ...with two products move_lines = pickings[0].move_lines self.assertEqual(len(move_lines), 2)
def test_sale_mrp(self): warehouse0 = self.env.ref('stock.warehouse0') # In order to test the sale_mrp module in OpenERP, I start by creating a new product 'Slider Mobile' # I define product category Mobile Products Sellable. with mute_logger('harpiya.tests.common.onchange'): # Suppress warning on "Changing your cost method" when creating a # product category pc = Form(self.env['product.category']) pc.name = 'Mobile Products Sellable' product_category_allproductssellable0 = pc.save() uom_unit = self.env.ref('uom.product_uom_unit') self.assertIn("seller_ids", self.env['product.template'].fields_get()) # I define product for Slider Mobile. product = Form(self.env['product.template']) product.categ_id = product_category_allproductssellable0 product.list_price = 200.0 product.name = 'Slider Mobile' product.type = 'product' product.uom_id = uom_unit product.uom_po_id = uom_unit product.route_ids.clear() product.route_ids.add(warehouse0.manufacture_pull_id.route_id) product.route_ids.add(warehouse0.mto_pull_id.route_id) product_template_slidermobile0 = product.save() std_price_wiz = Form( self.env['stock.change.standard.price'].with_context( active_id=product_template_slidermobile0.id, active_model='product.template')) std_price_wiz.new_price = 189 std_price_wiz.save() product_component = Form(self.env['product.product']) product_component.name = 'Battery' product_product_bettery = product_component.save() with Form(self.env['mrp.bom']) as bom: bom.product_tmpl_id = product_template_slidermobile0 with bom.bom_line_ids.new() as line: line.product_id = product_product_bettery line.product_qty = 4 # I create a sale order for product Slider mobile so_form = Form(self.env['sale.order']) so_form.partner_id = self.env.ref('base.res_partner_4') with so_form.order_line.new() as line: line.product_id = product_template_slidermobile0.product_variant_ids line.price_unit = 200 line.product_uom_qty = 500.0 line.customer_lead = 7.0 sale_order_so0 = so_form.save() # I confirm the sale order sale_order_so0.action_confirm() # I verify that a manufacturing order has been generated, and that its name and reference are correct mo = self.env['mrp.production'].search( [('origin', 'like', sale_order_so0.name)], limit=1) self.assertTrue(mo, 'Manufacturing order has not been generated')
def test_in_refund_line_onchange_partner_1(self): move_form = Form(self.invoice) move_form.partner_id = self.partner_b move_form.invoice_payment_ref = 'turlututu' move_form.save() self.assertInvoiceValues( self.invoice, [ { **self.product_line_vals_1, 'partner_id': self.partner_b.id, }, { **self.product_line_vals_2, 'partner_id': self.partner_b.id, }, { **self.tax_line_vals_1, 'partner_id': self.partner_b.id, }, { **self.tax_line_vals_2, 'partner_id': self.partner_b.id, }, { **self.term_line_vals_1, 'name': 'turlututu', 'partner_id': self.partner_b.id, 'account_id': self.partner_b.property_account_payable_id.id, 'price_unit': -338.4, 'price_subtotal': -338.4, 'price_total': -338.4, 'debit': 338.4, }, { **self.term_line_vals_1, 'name': 'turlututu', 'partner_id': self.partner_b.id, 'account_id': self.partner_b.property_account_payable_id.id, 'price_unit': -789.6, 'price_subtotal': -789.6, 'price_total': -789.6, 'debit': 789.6, 'date_maturity': fields.Date.from_string('2019-02-28'), }, ], { **self.move_vals, 'partner_id': self.partner_b.id, 'invoice_payment_ref': 'turlututu', 'fiscal_position_id': self.fiscal_pos_a.id, 'invoice_payment_term_id': self.pay_terms_b.id, 'amount_untaxed': 960.0, 'amount_tax': 168.0, 'amount_total': 1128.0, }) # Remove lines and recreate them to apply the fiscal position. move_form = Form(self.invoice) move_form.invoice_line_ids.remove(0) move_form.invoice_line_ids.remove(0) with move_form.invoice_line_ids.new() as line_form: line_form.product_id = self.product_a with move_form.invoice_line_ids.new() as line_form: line_form.product_id = self.product_b move_form.save() self.assertInvoiceValues( self.invoice, [ { **self.product_line_vals_1, 'account_id': self.product_b.property_account_expense_id.id, 'partner_id': self.partner_b.id, 'tax_ids': self.tax_purchase_b.ids, }, { **self.product_line_vals_2, 'partner_id': self.partner_b.id, 'price_total': 184.0, 'tax_ids': self.tax_purchase_b.ids, }, { **self.tax_line_vals_1, 'name': self.tax_purchase_b.name, 'partner_id': self.partner_b.id, 'tax_line_id': self.tax_purchase_b.id, }, { **self.term_line_vals_1, 'name': 'turlututu', 'account_id': self.partner_b.property_account_payable_id.id, 'partner_id': self.partner_b.id, 'price_unit': -331.2, 'price_subtotal': -331.2, 'price_total': -331.2, 'debit': 331.2, }, { **self.term_line_vals_1, 'name': 'turlututu', 'account_id': self.partner_b.property_account_payable_id.id, 'partner_id': self.partner_b.id, 'price_unit': -772.8, 'price_subtotal': -772.8, 'price_total': -772.8, 'debit': 772.8, 'date_maturity': fields.Date.from_string('2019-02-28'), }, ], { **self.move_vals, 'partner_id': self.partner_b.id, 'invoice_payment_ref': 'turlututu', 'fiscal_position_id': self.fiscal_pos_a.id, 'invoice_payment_term_id': self.pay_terms_b.id, 'amount_untaxed': 960.0, 'amount_tax': 144.0, 'amount_total': 1104.0, })
def test_out_refund_line_onchange_partner_1(self): move_form = Form(self.invoice) move_form.partner_id = self.partner_b move_form.invoice_payment_ref = 'turlututu' move_form.save() self.assertInvoiceValues( self.invoice, [ { **self.product_line_vals_1, 'partner_id': self.partner_b.id, }, { **self.product_line_vals_2, 'partner_id': self.partner_b.id, }, { **self.tax_line_vals_1, 'partner_id': self.partner_b.id, }, { **self.tax_line_vals_2, 'partner_id': self.partner_b.id, }, { **self.term_line_vals_1, 'name': 'turlututu', 'partner_id': self.partner_b.id, 'account_id': self.partner_b.property_account_receivable_id.id, 'price_unit': -987.0, 'price_subtotal': -987.0, 'price_total': -987.0, 'credit': 987.0, 'date_maturity': fields.Date.from_string('2019-02-28'), }, { **self.term_line_vals_1, 'name': 'turlututu', 'partner_id': self.partner_b.id, 'account_id': self.partner_b.property_account_receivable_id.id, 'price_unit': -423.0, 'price_subtotal': -423.0, 'price_total': -423.0, 'credit': 423.0, }, ], { **self.move_vals, 'partner_id': self.partner_b.id, 'invoice_payment_ref': 'turlututu', 'fiscal_position_id': self.fiscal_pos_a.id, 'invoice_payment_term_id': self.pay_terms_b.id, 'amount_untaxed': 1200.0, 'amount_tax': 210.0, 'amount_total': 1410.0, }) # Remove lines and recreate them to apply the fiscal position. move_form = Form(self.invoice) move_form.invoice_line_ids.remove(0) move_form.invoice_line_ids.remove(0) with move_form.invoice_line_ids.new() as line_form: line_form.product_id = self.product_a with move_form.invoice_line_ids.new() as line_form: line_form.product_id = self.product_b move_form.save() self.assertInvoiceValues( self.invoice, [ { **self.product_line_vals_1, 'account_id': self.product_b.property_account_income_id.id, 'partner_id': self.partner_b.id, 'tax_ids': self.tax_sale_b.ids, }, { **self.product_line_vals_2, 'partner_id': self.partner_b.id, 'price_total': 230.0, 'tax_ids': self.tax_sale_b.ids, }, { **self.tax_line_vals_1, 'name': self.tax_sale_b.name, 'partner_id': self.partner_b.id, 'tax_line_id': self.tax_sale_b.id, }, { **self.term_line_vals_1, 'name': 'turlututu', 'account_id': self.partner_b.property_account_receivable_id.id, 'partner_id': self.partner_b.id, 'price_unit': -966.0, 'price_subtotal': -966.0, 'price_total': -966.0, 'credit': 966.0, 'date_maturity': fields.Date.from_string('2019-02-28'), }, { **self.term_line_vals_1, 'name': 'turlututu', 'account_id': self.partner_b.property_account_receivable_id.id, 'partner_id': self.partner_b.id, 'price_unit': -414.0, 'price_subtotal': -414.0, 'price_total': -414.0, 'credit': 414.0, }, ], { **self.move_vals, 'partner_id': self.partner_b.id, 'invoice_payment_ref': 'turlututu', 'fiscal_position_id': self.fiscal_pos_a.id, 'invoice_payment_term_id': self.pay_terms_b.id, 'amount_untaxed': 1200.0, 'amount_tax': 180.0, 'amount_total': 1380.0, })
def test_01_sale_mrp_kit_qty_delivered(self): """ Test that the quantities delivered are correct when a kit with subkits is ordered with multiple backorders and returns """ # 'kit_parent' structure: # --------------------------- # # kit_parent --|- kit_2 x2 --|- component_d x1 # | |- kit_1 x2 -------|- component_a x2 # | |- component_b x1 # | |- component_c x3 # | # |- kit_3 x1 --|- component_f x1 # | |- component_g x2 # | # |- component_e x1 # Creation of a sale order for x7 kit_parent partner = self.env.ref('base.res_partner_1') f = Form(self.env['purchase.order']) f.partner_id = partner with f.order_line.new() as line: line.product_id = self.kit_parent line.product_qty = 7.0 line.price_unit = 10 po = f.save() po.button_confirm() # Check picking creation, its move lines should concern # only components. Also checks that the quantities are corresponding # to the PO self.assertEquals(len(po.picking_ids), 1) order_line = po.order_line[0] picking_original = po.picking_ids[0] move_lines = picking_original.move_lines products = move_lines.mapped('product_id') kits = [self.kit_parent, self.kit_3, self.kit_2, self.kit_1] components = [self.component_a, self.component_b, self.component_c, self.component_d, self.component_e, self.component_f, self.component_g] expected_quantities = { self.component_a: 56.0, self.component_b: 28.0, self.component_c: 84.0, self.component_d: 14.0, self.component_e: 7.0, self.component_f: 14.0, self.component_g: 28.0 } self.assertEquals(len(move_lines), 7) self.assertTrue(not any(kit in products for kit in kits)) self.assertTrue(all(component in products for component in components)) self._assert_quantities(move_lines, expected_quantities) # Process only 7 units of each component qty_to_process = 7 move_lines.write({'quantity_done': qty_to_process}) # Create a backorder for the missing componenents backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, po.picking_ids[0].id)]}) backorder_wizard.process() # Check that a backorded is created self.assertEquals(len(po.picking_ids), 2) backorder_1 = po.picking_ids - picking_original self.assertEquals(backorder_1.backorder_id.id, picking_original.id) # Even if some components are received completely, # no KitParent should be received self.assertEquals(order_line.qty_received, 0) # Process just enough components to make 1 kit_parent qty_to_process = { self.component_a: 1, self.component_c: 5, } self._process_quantities(backorder_1.move_lines, qty_to_process) # Create a backorder for the missing componenents backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_1.id)]}) backorder_wizard.process() # Only 1 kit_parent should be received at this point self.assertEquals(order_line.qty_received, 1) # Check that the second backorder is created self.assertEquals(len(po.picking_ids), 3) backorder_2 = po.picking_ids - picking_original - backorder_1 self.assertEquals(backorder_2.backorder_id.id, backorder_1.id) # Set the components quantities that backorder_2 should have expected_quantities = { self.component_a: 48, self.component_b: 21, self.component_c: 72, self.component_d: 7, self.component_f: 7, self.component_g: 21 } # Check that the computed quantities are matching the theorical ones. # Since component_e was totally processed, this componenent shouldn't be # present in backorder_2 self.assertEquals(len(backorder_2.move_lines), 6) move_comp_e = backorder_2.move_lines.filtered(lambda m: m.product_id.id == self.component_e.id) self.assertFalse(move_comp_e) self._assert_quantities(backorder_2.move_lines, expected_quantities) # Process enough components to make x3 kit_parents qty_to_process = { self.component_a: 16, self.component_b: 5, self.component_c: 24, self.component_g: 5 } self._process_quantities(backorder_2.move_lines, qty_to_process) # Create a backorder for the missing componenents backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_2.id)]}) backorder_wizard.process() # Check that x3 kit_parents are indeed received self.assertEquals(order_line.qty_received, 3) # Check that the third backorder is created self.assertEquals(len(po.picking_ids), 4) backorder_3 = po.picking_ids - (picking_original + backorder_1 + backorder_2) self.assertEquals(backorder_3.backorder_id.id, backorder_2.id) # Check the components quantities that backorder_3 should have expected_quantities = { self.component_a: 32, self.component_b: 16, self.component_c: 48, self.component_d: 7, self.component_f: 7, self.component_g: 16 } self._assert_quantities(backorder_3.move_lines, expected_quantities) # Process all missing components self._process_quantities(backorder_3.move_lines, expected_quantities) # Validating the last backorder now it's complete. # All kits should be received backorder_3.button_validate() self.assertEquals(order_line.qty_received, 7.0) # Return all components processed by backorder_3 stock_return_picking_form = Form(self.env['stock.return.picking'] .with_context(active_ids=backorder_3.ids, active_id=backorder_3.ids[0], active_model='stock.picking')) return_wiz = stock_return_picking_form.save() for return_move in return_wiz.product_return_moves: return_move.write({ 'quantity': expected_quantities[return_move.product_id], 'to_refund': True }) res = return_wiz.create_returns() return_pick = self.env['stock.picking'].browse(res['res_id']) # Process all components and validate the picking wiz_act = return_pick.button_validate() wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']) wiz.process() # Now quantity received should be 3 again self.assertEquals(order_line.qty_received, 3) stock_return_picking_form = Form(self.env['stock.return.picking'] .with_context(active_ids=return_pick.ids, active_id=return_pick.ids[0], active_model='stock.picking')) return_wiz = stock_return_picking_form.save() for move in return_wiz.product_return_moves: move.quantity = expected_quantities[move.product_id] res = return_wiz.create_returns() return_of_return_pick = self.env['stock.picking'].browse(res['res_id']) # Process all components except one of each for move in return_of_return_pick.move_lines: move.write({ 'quantity_done': expected_quantities[move.product_id] - 1, 'to_refund': True }) backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, return_of_return_pick.id)]}) backorder_wizard.process() # As one of each component is missing, only 6 kit_parents should be received self.assertEquals(order_line.qty_received, 6) # Check that the 4th backorder is created. self.assertEquals(len(po.picking_ids), 7) backorder_4 = po.picking_ids - ( picking_original + backorder_1 + backorder_2 + backorder_3 + return_of_return_pick + return_pick) self.assertEquals(backorder_4.backorder_id.id, return_of_return_pick.id) # Check the components quantities that backorder_4 should have for move in backorder_4.move_lines: self.assertEquals(move.product_qty, 1)