From eff2c6edaa3f506a1704facae748592068c4be82 Mon Sep 17 00:00:00 2001 From: Arnold Moyaux Date: Fri, 22 Sep 2023 13:50:24 +0000 Subject: [PATCH] [FIX] stock: backorder base on initial demand This reverts commit 656d8ace871bf508668cd67927d06c381fcebd9f. The rational was: "If people don't have inventory, they will need a backorder anyway and it's logical to not display the popup even if the picking type has 'ask' for create backorder". Also for the barcode application in OE we only show the reserved lines and you could have the message if the picking was not fully reserve. Even if you completed all the lines. So we could have a single flow for backend and frontend. But it's difficult for poeple to understand that the backorder is base on the reservation and not on the initial demand. So we do a step back. On top of it, people usualy won't mix flow. So they could totaly use the "always create a BO" option on picking type when they use the barcode and "ask" when they use the backend. closes odoo/odoo#136725 X-original-commit: ed291c4d47783c5912ffb40db7893c321ccdb1e2 Related: odoo/enterprise#47959 Signed-off-by: Arnold Moyaux (arm) --- addons/mrp/tests/test_stock.py | 5 +- addons/pos_sale/tests/test_pos_sale_flow.py | 4 +- addons/sale_mrp/tests/test_sale_mrp_flow.py | 4 +- .../tests/test_anglo_saxon_valuation.py | 8 +- addons/sale_stock/tests/test_sale_stock.py | 15 +++- .../tests/test_sale_stock_report.py | 4 +- .../tests/test_sale_stock_margin.py | 4 +- addons/stock/models/stock_picking.py | 6 +- addons/stock/tests/test_move.py | 34 +++++--- addons/stock/tests/test_move2.py | 4 +- addons/stock/tests/test_stock_flow.py | 22 +++-- .../tests/test_batch_picking.py | 86 +++++-------------- 12 files changed, 100 insertions(+), 96 deletions(-) diff --git a/addons/mrp/tests/test_stock.py b/addons/mrp/tests/test_stock.py index 5416cbf3d3e..c4d6ae97ed0 100644 --- a/addons/mrp/tests/test_stock.py +++ b/addons/mrp/tests/test_stock.py @@ -305,7 +305,7 @@ class TestKitPicking(common.TestMrpCommon): 'partner_id': self.test_partner.id, 'picking_type_id': self.env.ref('stock.picking_type_in').id, }) - move_receipt_1 = self.env['stock.move'].create({ + self.env['stock.move'].create({ 'name': self.kit_parent.name, 'product_id': self.kit_parent.id, 'product_uom_qty': 3, @@ -316,6 +316,9 @@ class TestKitPicking(common.TestMrpCommon): 'location_dest_id': self.warehouse_1.wh_input_stock_loc_id.id, }) picking.button_validate() + backorder_wizard_dict = picking.button_validate() + backorder_wizard_form = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])) + backorder_wizard_form.save().process() # We check that the picking has the correct quantities after its move were splitted. self.assertEqual(len(picking.move_ids), 7) diff --git a/addons/pos_sale/tests/test_pos_sale_flow.py b/addons/pos_sale/tests/test_pos_sale_flow.py index ded2aa390ae..684f5bd8959 100644 --- a/addons/pos_sale/tests/test_pos_sale_flow.py +++ b/addons/pos_sale/tests/test_pos_sale_flow.py @@ -57,7 +57,9 @@ class TestPoSSale(TestPointOfSaleHttpCommon): sale_order.action_confirm() picking = sale_order.picking_ids picking.move_ids.quantity_done = 300 - picking.button_validate() + action = picking.button_validate() + wizard = Form(self.env[action['res_model']].with_context(action['context'])) + wizard.save().process() self.assertEqual(sale_order.order_line.qty_delivered, 1) diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py index f5a93130e21..85b50ee72c5 100644 --- a/addons/sale_mrp/tests/test_sale_mrp_flow.py +++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py @@ -550,7 +550,9 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon): # deliver partially (1 of each instead of 5), check the so's invoice_status and delivered quantities pick = so.picking_ids pick.move_ids.write({'quantity_done': 1}) - pick.button_validate() + wiz_act = pick.button_validate() + wiz = Form(self.env[wiz_act['res_model']].with_context(wiz_act['context'])).save() + wiz.process() self.assertEqual(so.invoice_status, 'no', 'Sale MRP: so invoice_status should be "no" after partial delivery of a kit') del_qty = sum(sol.qty_delivered for sol in so.order_line) self.assertEqual(del_qty, 0.0, 'Sale MRP: delivered quantity should be zero after partial delivery of a kit') diff --git a/addons/sale_stock/tests/test_anglo_saxon_valuation.py b/addons/sale_stock/tests/test_anglo_saxon_valuation.py index e4f498e777f..6edd7b75c4b 100644 --- a/addons/sale_stock/tests/test_anglo_saxon_valuation.py +++ b/addons/sale_stock/tests/test_anglo_saxon_valuation.py @@ -128,7 +128,9 @@ class TestAngloSaxonValuation(ValuationReconciliationTestCommon): # Deliver one. sale_order.picking_ids.move_ids.quantity_done = 1 - sale_order.picking_ids.button_validate() + wiz = sale_order.picking_ids.button_validate() + wiz = Form(self.env[wiz['res_model']].with_context(wiz['context'])).save() + wiz.process() # Invoice 1 invoice = sale_order._create_invoices() @@ -265,7 +267,9 @@ class TestAngloSaxonValuation(ValuationReconciliationTestCommon): # Deliver one. sale_order.picking_ids.move_ids.quantity_done = 1 - sale_order.picking_ids.button_validate() + wiz = sale_order.picking_ids.button_validate() + wiz = Form(self.env[wiz['res_model']].with_context(wiz['context'])).save() + wiz.process() # Invoice 1 invoice = sale_order._create_invoices() diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index e8b424c96e6..16d8634159d 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -267,15 +267,16 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): # deliver them # One of the move is for a consumable product, thus is assigned. The second one is for a # storable product, thus is unavailable. Hitting `button_validate` will first ask to - # process all the reserved quantities and, if the user chose to process, a backorder will - # be created for the unavailable product. + # process all the reserved quantities and, if the user chose to process, a second wizard + # will ask to create a backorder for the unavailable product. self.assertEqual(len(self.so.picking_ids), 1) res_dict = self.so.picking_ids.sorted()[0].button_validate() wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() self.assertEqual(wizard._name, 'stock.immediate.transfer') + res_dict = wizard.process() + wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() + self.assertEqual(wizard._name, 'stock.backorder.confirmation') wizard.process() - self.assertEqual(len(self.so.picking_ids), 2) - self.assertEqual(self.so.picking_ids[0].backorder_id.id, self.so.picking_ids[1].id) # Now, the original picking is done and there is a new one (the backorder). self.assertEqual(len(self.so.picking_ids), 2) @@ -1490,6 +1491,9 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): pack_picking.move_line_ids.result_package_id = False pack_picking.move_ids.quantity_done = 2 pack_picking.button_validate() + backorder_wizard_dict = pack_picking.button_validate() + backorder_wizard = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])).save() + backorder_wizard.process() self.assertEqual(out_picking.move_line_ids.package_id.id, False) self.assertEqual(out_picking.move_line_ids.result_package_id.id, False) @@ -1509,5 +1513,8 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): pack_picking_2.move_ids.quantity_done = 2 pack_picking_2.button_validate() + backorder_wizard_dict = pack_picking_2.button_validate() + backorder_wizard = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])).save() + backorder_wizard.process() self.assertRecordValues(out_picking.move_line_ids, [{'result_package_id': False}, {'result_package_id': package_2.id}]) diff --git a/addons/sale_stock/tests/test_sale_stock_report.py b/addons/sale_stock/tests/test_sale_stock_report.py index 2d8d565d409..d4c8c4d18f0 100644 --- a/addons/sale_stock/tests/test_sale_stock_report.py +++ b/addons/sale_stock/tests/test_sale_stock_report.py @@ -321,7 +321,9 @@ class TestSaleStockInvoices(TestSaleCommon): line.lot_id = lot02 line.qty_done = 3 move_form.save() - delivery02.button_validate() + action = delivery02.button_validate() + wizard = Form(self.env[action['res_model']].with_context(action['context'])).save() + wizard.process() # Invoice 2 x P invoice01 = so._create_invoices() diff --git a/addons/sale_stock_margin/tests/test_sale_stock_margin.py b/addons/sale_stock_margin/tests/test_sale_stock_margin.py index 5654893471c..8720ef2b95c 100644 --- a/addons/sale_stock_margin/tests/test_sale_stock_margin.py +++ b/addons/sale_stock_margin/tests/test_sale_stock_margin.py @@ -158,7 +158,9 @@ class TestSaleStockMargin(TestStockValuationCommon): sale_order.picking_ids.move_ids[0].quantity_done = 2 sale_order.picking_ids.move_ids[1].quantity_done = 3 - sale_order.picking_ids.button_validate() + + res = sale_order.picking_ids.button_validate() + Form(self.env[res['res_model']].with_context(res['context'])).save().process() self.assertAlmostEqual(order_line_1.purchase_price, 43) # (35 + 51) / 2 self.assertAlmostEqual(order_line_2.purchase_price, 12.5) # (17 + 11 + 11 + 11) / 4 diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 819dab0cf96..0017265dcf2 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -1247,12 +1247,10 @@ class Picking(models.Model): continue quantity_todo = {} quantity_done = {} - for move in picking.move_ids: - if move.state == "cancel": - continue + for move in picking.move_ids.filtered(lambda m: m.state != "cancel"): quantity_todo.setdefault(move.product_id.id, 0) quantity_done.setdefault(move.product_id.id, 0) - quantity_todo[move.product_id.id] += sum(move.move_line_ids.mapped('reserved_qty')) + quantity_todo[move.product_id.id] += move.product_uom._compute_quantity(move.product_uom_qty, move.product_id.uom_id, rounding_method='HALF-UP') quantity_done[move.product_id.id] += move.product_uom._compute_quantity(move.quantity_done, move.product_id.uom_id, rounding_method='HALF-UP') if any( float_compare(quantity_done[x], quantity_todo.get(x, 0), precision_digits=prec,) == -1 diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index a52e11c4714..2b6c94c5634 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -2727,8 +2727,10 @@ class StockMove(TransactionCase): # the quantity done on the move should not respect the rounding of the move line self.assertEqual(move_stock_pack.quantity_done, 0.5) - # Validate the picking should create a backorder in the uom of the quants. - picking_stock_pack.button_validate() + # create the backorder in the uom of the quants + backorder_wizard_dict = picking_stock_pack.button_validate() + backorder_wizard = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])).save() + backorder_wizard.process() self.assertEqual(move_stock_pack.state, 'done') self.assertEqual(move_stock_pack.quantity_done, 0.5) self.assertEqual(move_stock_pack.product_uom_qty, 0.5) @@ -4254,9 +4256,9 @@ class StockMove(TransactionCase): def test_immediate_validate_2(self): """ In a picking with a single partially available move, clicking on validate without filling any quantities should open a wizard asking to process all the reservation (so, only - a part of the initial demand). Validating this wizard should validate the picking and create - a backorder (the user's confirmation is asked only when the reservation is not fully - processed). The created backorder should contain the quantities not processed. + a part of the initial demand). Validating this wizard should open another one asking for + the creation of a backorder. If the backorder is created, it should contain the quantities + not processed. """ partner = self.env['res.partner'].create({'name': 'Jean'}) self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 5.0) @@ -4283,7 +4285,11 @@ class StockMove(TransactionCase): res_dict = picking.button_validate() self.assertEqual(res_dict.get('res_model'), 'stock.immediate.transfer') wizard = Form(self.env[res_dict['res_model']].with_context(res_dict['context'])).save() - wizard.process() + res_dict_for_back_order = wizard.process() + self.assertEqual(res_dict_for_back_order.get('res_model'), 'stock.backorder.confirmation') + backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context']) + # Chose to create a backorder. + backorder_wizard.process() # Only 5 products should be processed on the initial move. self.assertEqual(picking.move_ids.state, 'done') @@ -4299,8 +4305,9 @@ class StockMove(TransactionCase): def test_immediate_validate_3(self): """ In a picking with two moves, one partially available and one unavailable, clicking on validate without filling any quantities should open a wizard asking to process all the - reservation (so, only a part of one of the moves). Validating this wizard should confirm the - picking and create a backorder with the quantities not processed. + reservation (so, only a part of one of the moves). Validating this wizard should open + another one asking for the creation of a backorder. If the backorder is created, it should + contain the quantities not processed. """ product5 = self.env['product.product'].create({ 'name': 'Product 5', @@ -4346,6 +4353,10 @@ class StockMove(TransactionCase): action = picking.button_validate() self.assertEqual(action.get('res_model'), 'stock.immediate.transfer') wizard = Form(self.env[action['res_model']].with_context(action['context'])).save() + action = wizard.process() + self.assertTrue(isinstance(action, dict), 'Should open backorder wizard') + self.assertEqual(action.get('res_model'), 'stock.backorder.confirmation') + wizard = self.env[(action.get('res_model'))].browse(action.get('res_id')).with_context(action.get('context')) wizard.process() backorder = self.env['stock.picking'].search([('backorder_id', '=', picking.id)]) self.assertEqual(len(backorder), 1.0) @@ -5868,10 +5879,11 @@ class StockMove(TransactionCase): delivery_form = Form(picking) delivery = delivery_form.save() delivery.action_confirm() - delivery.button_validate() - backorder = self.env['stock.picking'].search([('backorder_id', '=', delivery.id)]) - backorder.action_cancel() # Cancels the automatically created backorder. + backorder_wizard_dict = delivery.button_validate() + backorder_wizard_form = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])) + backorder_wizard_form.save().process() + picking.backorder_ids.action_cancel() aggregate_values = picking.move_line_ids._get_aggregated_product_quantities() aggregated_val = aggregate_values[f'{self.product.id}_{self.product.name}__{self.product.uom_id.id}'] diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py index b1e57a67325..236af83a654 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -766,7 +766,9 @@ class TestPickShip(TestStockCommon): # make some stock self.env['stock.quant']._update_available_quantity(self.productA, location, 10.0) picking_pick.move_ids.quantity_done = 5.0 - picking_pick.button_validate() + backorder_wizard_values = picking_pick.button_validate() + backorder_wizard = self.env[(backorder_wizard_values.get('res_model'))].browse(backorder_wizard_values.get('res_id')).with_context(backorder_wizard_values['context']) + backorder_wizard.process() self.assertTrue(picking_client.move_line_ids, 'A move line should be created.') self.assertEqual(picking_client.move_line_ids.reserved_uom_qty, 5, 'The move line should have 5 unit reserved.') diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py index 55f98629271..cc6ab052f1d 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -664,7 +664,9 @@ class TestStockFlow(TestStockCommon): res_dict = picking_in_B.button_validate() wizard = Form(self.env[res_dict.get('res_model')].with_context(res_dict['context'])).save() - wizard.process() + res_dict_for_back_order = wizard.process() + backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context']) + backorder_wizard.process() # ----------------------------------------------------------------------- # Check incoming shipment @@ -983,7 +985,9 @@ class TestStockFlow(TestStockCommon): pack_opt.write({'reserved_uom_qty': 5}) res_dict = picking_out.button_validate() wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() - wizard.process() + res_dict_for_back_order = wizard.process() + backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context']) + backorder_wizard.process() quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)]) total_qty = [quant.quantity for quant in quants] # Check total quantity stock location. @@ -1005,7 +1009,9 @@ class TestStockFlow(TestStockCommon): pack_opt.write({'reserved_uom_qty': 5}) res_dict = bo_out_1.button_validate() wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() - wizard.process() + res_dict_for_back_order = wizard.process() + backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context']) + backorder_wizard.process() quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)]) total_qty = [quant.quantity for quant in quants] @@ -1027,7 +1033,9 @@ class TestStockFlow(TestStockCommon): pack_opt.write({'reserved_uom_qty': 5}) res_dict = bo_out_2.button_validate() wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() - wizard.process() + res_dict_for_back_order = wizard.process() + backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context']) + backorder_wizard.process() # Check total quantity stock location of product KG. quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)]) total_qty = [quant.quantity for quant in quants] @@ -1048,7 +1056,9 @@ class TestStockFlow(TestStockCommon): pack_opt.write({'reserved_uom_qty': 5}) res_dict = bo_out_3.button_validate() wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() - wizard.process() + res_dict_for_back_order = wizard.process() + backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context']) + backorder_wizard.process() quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)]) total_qty = [quant.quantity for quant in quants] self.assertEqual(sum(total_qty), 999.980, 'Expecting 999.980 kg , got %.4f kg on location stock!' % (sum(total_qty))) @@ -2248,7 +2258,7 @@ class TestStockFlow(TestStockCommon): 'location_id': stock_location.id, 'location_dest_id': self.customer_location }) - picking_out.action_confirm() + move_out.quantity_done = 7 action_dict = picking_out.button_validate() diff --git a/addons/stock_picking_batch/tests/test_batch_picking.py b/addons/stock_picking_batch/tests/test_batch_picking.py index 63c6f90a6ca..09b87b70e37 100644 --- a/addons/stock_picking_batch/tests/test_batch_picking.py +++ b/addons/stock_picking_batch/tests/test_batch_picking.py @@ -223,48 +223,9 @@ class TestBatchPicking(TransactionCase): self.assertFalse(sum(quant_B.mapped('quantity'))) def test_batch_with_backorder_wizard(self): - """ Test a simple batch picking with all quantities fully available but only one fully - processed. The user will set by himself the quantity reserved for each picking and - run the picking batch. There should be a wizard asking for a backorder. - """ - self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 10.0) - self.env['stock.quant']._update_available_quantity(self.productB, self.stock_location, 10.0) - - # Confirm batch, pickings should not be automatically assigned. - self.batch.action_confirm() - self.assertEqual(self.picking_client_1.state, 'confirmed', 'Picking 1 should be confirmed') - self.assertEqual(self.picking_client_2.state, 'confirmed', 'Picking 2 should be confirmed') - # Ask to assign, so pickings should be assigned now. - self.batch.action_assign() - self.assertEqual(self.picking_client_1.state, 'assigned', 'Picking 1 should be ready') - self.assertEqual(self.picking_client_2.state, 'assigned', 'Picking 2 should be ready') - - self.picking_client_1.move_ids.quantity_done = 6 - self.picking_client_2.move_ids.quantity_done = 10 - - # There should be a wizard asking to process picking without quantity done - back_order_wizard_dict = self.batch.action_done() - self.assertTrue(back_order_wizard_dict) - back_order_wizard = Form(self.env[(back_order_wizard_dict.get('res_model'))].with_context(back_order_wizard_dict['context'])).save() - self.assertEqual(len(back_order_wizard.pick_ids), 1) - back_order_wizard.process() - - self.assertEqual(self.picking_client_2.state, 'done', 'Picking 2 should be done') - self.assertEqual(self.picking_client_1.state, 'done', 'Picking 1 should be done') - self.assertEqual(self.picking_client_1.move_ids.product_uom_qty, 6, 'initial demand should be 6 after picking split') - self.assertTrue(self.env['stock.picking'].search([('backorder_id', '=', self.picking_client_1.id)]), 'no back order created') - - quant_A = self.env['stock.quant']._gather(self.productA, self.stock_location) - quant_B = self.env['stock.quant']._gather(self.productB, self.stock_location) - - # ensure that quantity for picking has been moved - self.assertEqual(sum(quant_A.mapped('quantity')), 4) - self.assertFalse(sum(quant_B.mapped('quantity'))) - - def test_batch_without_backorder_wizard(self): """ Test a simple batch picking with only one quantity fully available. The user will set by himself the quantity reserved for each picking and - run the picking batch. A backorder should be automatically created. + run the picking batch. There should be a wizard asking for a backorder. """ self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 5.0) self.env['stock.quant']._update_available_quantity(self.productB, self.stock_location, 10.0) @@ -280,12 +241,13 @@ class TestBatchPicking(TransactionCase): self.picking_client_1.move_ids.quantity_done = 5 self.picking_client_2.move_ids.quantity_done = 10 - self.batch.action_done() - # Checks a backorder was created for `picking_client_1`. - backorder = self.env['stock.picking'].search([('backorder_id', 'in', self.batch.picking_ids.ids)]) - self.assertEqual(len(backorder), 1) - self.assertEqual(backorder.backorder_id.id, self.picking_client_1.id) + # There should be a wizard asking to process picking without quantity done + back_order_wizard_dict = self.batch.action_done() + self.assertTrue(back_order_wizard_dict) + back_order_wizard = Form(self.env[(back_order_wizard_dict.get('res_model'))].with_context(back_order_wizard_dict['context'])).save() + self.assertEqual(len(back_order_wizard.pick_ids), 1) + back_order_wizard.process() self.assertEqual(self.picking_client_2.state, 'done', 'Picking 2 should be done') self.assertEqual(self.picking_client_1.state, 'done', 'Picking 1 should be done') @@ -299,11 +261,11 @@ class TestBatchPicking(TransactionCase): self.assertFalse(sum(quant_A.mapped('quantity'))) self.assertFalse(sum(quant_B.mapped('quantity'))) - def test_batch_with_immediate_transfer_and_backorder(self): + def test_batch_with_immediate_transfer_and_backorder_wizard(self): """ Test a simple batch picking with only one product fully available. - Everything should be automatically. The immediate transfer wizard should asking to set - quantity_done to reserved quantity. A backorder should be created without wizard as the - reserved quantity was fully processed. + Everything should be automatically. First one backorder in order to set quantity_done + to reserved quantity. After a second wizard asking for a backorder for the quantity that + has not been fully transfered. """ self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 5.0) self.env['stock.quant']._update_available_quantity(self.productB, self.stock_location, 10.0) @@ -322,12 +284,11 @@ class TestBatchPicking(TransactionCase): self.assertTrue(immediate_transfer_wizard_dict) immediate_transfer_wizard = Form(self.env[(immediate_transfer_wizard_dict.get('res_model'))].with_context(immediate_transfer_wizard_dict['context'])).save() self.assertEqual(len(immediate_transfer_wizard.pick_ids), 2) - immediate_transfer_wizard.process() - - # Checks a backorder was created for `picking_client_1`. - backorder = self.env['stock.picking'].search([('backorder_id', 'in', self.batch.picking_ids.ids)]) - self.assertEqual(len(backorder), 1) - self.assertEqual(backorder.backorder_id.id, self.picking_client_1.id) + back_order_wizard_dict = immediate_transfer_wizard.process() + self.assertTrue(back_order_wizard_dict) + back_order_wizard = Form(self.env[(back_order_wizard_dict.get('res_model'))].with_context(back_order_wizard_dict['context'])).save() + self.assertEqual(len(back_order_wizard.pick_ids), 1) + back_order_wizard.process() self.assertEqual(self.picking_client_1.state, 'done', 'Picking 1 should be done') self.assertEqual(self.picking_client_1.move_ids.product_uom_qty, 5, 'initial demand should be 5 after picking split') @@ -341,12 +302,12 @@ class TestBatchPicking(TransactionCase): self.assertFalse(sum(quant_B.mapped('quantity'))) def test_batch_with_immediate_transfer_and_backorder_wizard_with_manual_operations(self): - """ Test a simple batch picking with a quantity not fully processed. - The user set the quantity done only for the first picking. - The test should run the immediate transfer for the second picking and then - the backorder wizard for the first picking. + """ Test a simple batch picking with only one quantity fully available. + The user set the quantity done only for the partially available picking. + The test should run the immediate transfer for the first picking and then + the backorder wizard for the second picking. """ - self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 10.0) + self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 5.0) self.env['stock.quant']._update_available_quantity(self.productB, self.stock_location, 10.0) # Confirm batch, pickings should not be automatically assigned. @@ -358,7 +319,7 @@ class TestBatchPicking(TransactionCase): self.assertEqual(self.picking_client_1.state, 'assigned', 'Picking 1 should be ready') self.assertEqual(self.picking_client_2.state, 'assigned', 'Picking 2 should be ready') - self.picking_client_1.move_ids.quantity_done = 6 + self.picking_client_1.move_ids.quantity_done = 5 # There should be a wizard asking to make a backorder back_order_wizard_dict = self.batch.action_done() self.assertTrue(back_order_wizard_dict) @@ -369,9 +330,8 @@ class TestBatchPicking(TransactionCase): back_order_wizard.process() self.assertEqual(self.picking_client_1.state, 'done', 'Picking 1 should be done') - self.assertEqual(self.picking_client_1.move_ids.product_uom_qty, 6, 'initial demand should be 5 after picking split') + self.assertEqual(self.picking_client_1.move_ids.product_uom_qty, 5, 'initial demand should be 5 after picking split') self.assertFalse(self.picking_client_2.batch_id) - def test_put_in_pack(self): self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 10.0) self.env['stock.quant']._update_available_quantity(self.productB, self.stock_location, 10.0)