From 656d8ace871bf508668cd67927d06c381fcebd9f Mon Sep 17 00:00:00 2001 From: svs-odoo Date: Tue, 10 Jan 2023 16:46:48 +0000 Subject: [PATCH] [IMP] stock: backorder confirmation In `_check_backorder`, changes the condition so it checks if the qty done is enough compared to the actual reserved quantity (instead of the demand). Also, removes an unused bloack of code and makes minor visual changes. task-3076044 Part-of: odoo/odoo#109511 --- 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 | 9 +- .../tests/test_sale_stock_report.py | 4 +- .../tests/test_sale_stock_margin.py | 4 +- addons/stock/models/stock_picking.py | 14 +-- addons/stock/tests/test_move.py | 33 +++---- addons/stock/tests/test_move2.py | 4 +- addons/stock/tests/test_stock_flow.py | 22 ++--- .../stock_backorder_confirmation_views.xml | 4 +- .../tests/test_batch_picking.py | 86 ++++++++++++++----- 12 files changed, 97 insertions(+), 99 deletions(-) diff --git a/addons/pos_sale/tests/test_pos_sale_flow.py b/addons/pos_sale/tests/test_pos_sale_flow.py index c1ca4a642fc..9c9a7225510 100644 --- a/addons/pos_sale/tests/test_pos_sale_flow.py +++ b/addons/pos_sale/tests/test_pos_sale_flow.py @@ -57,9 +57,7 @@ class TestPoSSale(TestPointOfSaleHttpCommon): sale_order.action_confirm() picking = sale_order.picking_ids picking.move_ids.quantity_done = 300 - action = picking.button_validate() - wizard = Form(self.env[action['res_model']].with_context(action['context'])) - wizard.save().process() + picking.button_validate() 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 48e7e79f6f4..1d4dea1e30a 100644 --- a/addons/sale_mrp/tests/test_sale_mrp_flow.py +++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py @@ -550,9 +550,7 @@ 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}) - wiz_act = pick.button_validate() - wiz = Form(self.env[wiz_act['res_model']].with_context(wiz_act['context'])).save() - wiz.process() + pick.button_validate() 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 49168e916c4..e7767ecc0d1 100644 --- a/addons/sale_stock/tests/test_anglo_saxon_valuation.py +++ b/addons/sale_stock/tests/test_anglo_saxon_valuation.py @@ -127,9 +127,7 @@ class TestAngloSaxonValuation(ValuationReconciliationTestCommon): # Deliver one. sale_order.picking_ids.move_ids.quantity_done = 1 - wiz = sale_order.picking_ids.button_validate() - wiz = Form(self.env[wiz['res_model']].with_context(wiz['context'])).save() - wiz.process() + sale_order.picking_ids.button_validate() # Invoice 1 invoice = sale_order._create_invoices() @@ -266,9 +264,7 @@ class TestAngloSaxonValuation(ValuationReconciliationTestCommon): # Deliver one. sale_order.picking_ids.move_ids.quantity_done = 1 - wiz = sale_order.picking_ids.button_validate() - wiz = Form(self.env[wiz['res_model']].with_context(wiz['context'])).save() - wiz.process() + sale_order.picking_ids.button_validate() # 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 431aabe02c6..5b83158a843 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -316,16 +316,15 @@ 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 second wizard - # will ask to create a backorder for the unavailable product. + # process all the reserved quantities and, if the user chose to process, a backorder will + # be created 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) diff --git a/addons/sale_stock/tests/test_sale_stock_report.py b/addons/sale_stock/tests/test_sale_stock_report.py index 27dd8b32ef0..1fcf9c0886c 100644 --- a/addons/sale_stock/tests/test_sale_stock_report.py +++ b/addons/sale_stock/tests/test_sale_stock_report.py @@ -321,9 +321,7 @@ class TestSaleStockInvoices(TestSaleCommon): line.lot_id = lot02 line.qty_done = 3 move_form.save() - action = delivery02.button_validate() - wizard = Form(self.env[action['res_model']].with_context(action['context'])).save() - wizard.process() + delivery02.button_validate() # 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 4cd1572ac33..009d9086278 100644 --- a/addons/sale_stock_margin/tests/test_sale_stock_margin.py +++ b/addons/sale_stock_margin/tests/test_sale_stock_margin.py @@ -158,9 +158,7 @@ class TestSaleStockMargin(TestStockValuationCommon): sale_order.picking_ids.move_ids[0].quantity_done = 2 sale_order.picking_ids.move_ids[1].quantity_done = 3 - - res = sale_order.picking_ids.button_validate() - Form(self.env[res['res_model']].with_context(res['context'])).save().process() + sale_order.picking_ids.button_validate() 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 62f9e7bf3b5..dbd1069b429 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -1176,19 +1176,13 @@ class Picking(models.Model): continue quantity_todo = {} quantity_done = {} - for move in picking.move_ids.filtered(lambda m: m.state != "cancel"): + for move in picking.move_ids: + if move.state == "cancel": + continue quantity_todo.setdefault(move.product_id.id, 0) quantity_done.setdefault(move.product_id.id, 0) - 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_todo[move.product_id.id] += sum(move.move_line_ids.mapped('reserved_qty')) quantity_done[move.product_id.id] += move.product_uom._compute_quantity(move.quantity_done, move.product_id.uom_id, rounding_method='HALF-UP') - # FIXME: the next block doesn't seem nor should be used. - for ops in picking.mapped('move_line_ids').filtered(lambda x: x.package_id and not x.product_id and not x.move_id): - for quant in ops.package_id.quant_ids: - quantity_done.setdefault(quant.product_id.id, 0) - quantity_done[quant.product_id.id] += quant.qty - for pack in picking.mapped('move_line_ids').filtered(lambda x: x.product_id and not x.move_id): - quantity_done.setdefault(pack.product_id.id, 0) - quantity_done[pack.product_id.id] += pack.product_uom_id._compute_quantity(pack.qty_done, pack.product_id.uom_id) if any( float_compare(quantity_done[x], quantity_todo.get(x, 0), precision_digits=prec,) == -1 for x in quantity_done diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index 3d4ae8e363b..481310c0e0a 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -2719,10 +2719,8 @@ 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) - # 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() + # Validate the picking should create a backorder in the uom of the quants. + picking_stock_pack.button_validate() 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) @@ -4234,9 +4232,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 open another one asking for - the creation of a backorder. If the backorder is created, it should contain the quantities - not processed. + 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. """ partner = self.env['res.partner'].create({'name': 'Jean'}) self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 5.0) @@ -4261,11 +4259,7 @@ 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() - 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() + wizard.process() # Only 5 products should be processed on the initial move. self.assertEqual(picking.move_ids.state, 'done') @@ -4281,9 +4275,8 @@ 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 open - another one asking for the creation of a backorder. If the backorder is created, it should - contain the quantities not processed. + 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. """ product5 = self.env['product.product'].create({ 'name': 'Product 5', @@ -4327,10 +4320,6 @@ 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) @@ -5750,10 +5739,10 @@ class StockMove(TransactionCase): delivery_form = Form(picking) delivery = delivery_form.save() delivery.action_confirm() + delivery.button_validate() - 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_cancel_backorder() # Don't create a backorder + backorder = self.env['stock.picking'].search([('backorder_id', '=', delivery.id)]) + backorder.action_cancel() # Cancels the automatically created backorder. 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 b6c18882045..e239513df14 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -644,9 +644,7 @@ 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 - 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() + picking_pick.button_validate() 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 d8e295ef520..8a3c5d7ab57 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -656,9 +656,7 @@ 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() - 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() + wizard.process() # ----------------------------------------------------------------------- # Check incoming shipment @@ -969,9 +967,7 @@ 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() - 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() + 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. @@ -993,9 +989,7 @@ 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() - 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() + wizard.process() quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)]) total_qty = [quant.quantity for quant in quants] @@ -1017,9 +1011,7 @@ 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() - 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() + 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] @@ -1040,9 +1032,7 @@ 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() - 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() + 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))) @@ -2161,7 +2151,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/wizard/stock_backorder_confirmation_views.xml b/addons/stock/wizard/stock_backorder_confirmation_views.xml index 5824fd4de0a..42b4162680e 100644 --- a/addons/stock/wizard/stock_backorder_confirmation_views.xml +++ b/addons/stock/wizard/stock_backorder_confirmation_views.xml @@ -40,8 +40,8 @@ diff --git a/addons/stock_picking_batch/tests/test_batch_picking.py b/addons/stock_picking_batch/tests/test_batch_picking.py index 1ff175cdd6f..fdff1b30136 100644 --- a/addons/stock_picking_batch/tests/test_batch_picking.py +++ b/addons/stock_picking_batch/tests/test_batch_picking.py @@ -217,9 +217,48 @@ 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. There should be a wizard asking for a backorder. + run the picking batch. A backorder should be automatically created. """ 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) @@ -235,13 +274,12 @@ 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() - # 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() + # 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) 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') @@ -255,11 +293,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_wizard(self): + def test_batch_with_immediate_transfer_and_backorder(self): """ Test a simple batch picking with only one product fully available. - 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. + 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. """ 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) @@ -278,11 +316,12 @@ 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) - 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() + 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) 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') @@ -296,12 +335,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 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. + """ 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. """ - self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 5.0) + 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. @@ -313,7 +352,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 = 5 + self.picking_client_1.move_ids.quantity_done = 6 # There should be a wizard asking to make a backorder back_order_wizard_dict = self.batch.action_done() self.assertTrue(back_order_wizard_dict) @@ -324,8 +363,9 @@ 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, 5, 'initial demand should be 5 after picking split') + self.assertEqual(self.picking_client_1.move_ids.product_uom_qty, 6, '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)