From 9477257b58fee42a52336e007fb9d643c708e939 Mon Sep 17 00:00:00 2001 From: Mylyna Hy Date: Thu, 27 Apr 2023 18:12:27 +0000 Subject: [PATCH] [FIX] stock: show exception log when cancel backorders Steps to Reproduce Issue for single picking: 1. Install Sales, Inventory 2. Create an SO and confirm 3. Go to the transfer, assign the done value to be less than demanded 4. Validate the transfer and cancel the backorder Current Behavior: There is no exception error on the SO chatter Expected Behavior: An exception error should be logged on the SO chatter Other Info: When cancelling a backorder for a single picking, the exception error about less quantity than expected is not logged on the SO. "process_cancel_backorder" does not call _log_less_quantities_than_expected. As defined in "process", the exception is only logged when validating multiple pickings at once but one is to backorder but the other is not. opw-3222508 closes odoo/odoo#121331 X-original-commit: a1dfc58eebd1badc3eea501b23861748b3762d75 Signed-off-by: Mylyna Hy (myhy) Signed-off-by: Tiffany Chang --- addons/sale_stock/tests/test_sale_stock.py | 31 +++++++++++++++++++ .../wizard/stock_backorder_confirmation.py | 31 ++++++++++--------- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index 2857f3caf6f..2b6679a2868 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -279,6 +279,10 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() wizard.process_cancel_backorder() + #Check Exception error is logged on SO + activity = self.env['mail.activity'].search([('res_id', '=', self.so.id), ('res_model', '=', 'sale.order')]) + self.assertEqual(len(activity), 1, 'When no backorder is created for a partial delivery, a warning error should be logged in its origin SO') + # Check quantity delivered del_qty = sum(sol.qty_delivered for sol in self.so.order_line) self.assertEqual(del_qty, 4.0, 'Sale Stock: delivered quantity should be 4.0 after partial delivery') @@ -1408,3 +1412,30 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): ]) self.assertEqual(ship01.move_ids.move_orig_ids, (pick01 | pick02).move_ids) self.assertEqual(ship02.move_ids.move_orig_ids, (pick01 | pick02).move_ids) + + def test_exception_delivery_partial_multi(self): + """ + When a backorder is cancelled for a picking in multi-picking, + the related SO should have an exception logged + """ + #Create 2 sale orders + so_1 = self._get_new_sale_order() + so_1.action_confirm() + picking_1 = so_1.picking_ids + picking_1.move_ids.write({'quantity_done': 1}) + + so_2 = self._get_new_sale_order() + so_2.action_confirm() + picking_2 = so_2.picking_ids + picking_2.move_ids.write({'quantity_done': 2}) + + #multi-picking validation + pick = picking_1 | picking_2 + res_dict = pick.button_validate() + wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save() + wizard.backorder_confirmation_line_ids[1].write({'to_backorder': False}) + wizard.process() + + #Check Exception error is logged on so_2 + activity = self.env['mail.activity'].search([('res_id', '=', so_2.id), ('res_model', '=', 'sale.order')]) + self.assertEqual(len(activity), 1, 'When no backorder is created for a partial delivery, a warning error should be logged in its origin SO') diff --git a/addons/stock/wizard/stock_backorder_confirmation.py b/addons/stock/wizard/stock_backorder_confirmation.py index 0fc5491e41f..755ac27256b 100644 --- a/addons/stock/wizard/stock_backorder_confirmation.py +++ b/addons/stock/wizard/stock_backorder_confirmation.py @@ -37,6 +37,16 @@ class StockBackorderConfirmation(models.TransientModel): # because of webclient limitations return res + def _check_less_quantities_than_expected(self, pickings): + for pick_id in pickings: + moves_to_log = {} + for move in pick_id.move_ids: + if float_compare(move.product_uom_qty, + move.quantity_done, + precision_rounding=move.product_uom.rounding) > 0: + moves_to_log[move] = (move.quantity_done, move.product_uom_qty) + pick_id._log_less_quantities_than_expected(moves_to_log) + def process(self): pickings_to_do = self.env['stock.picking'] pickings_not_to_do = self.env['stock.picking'] @@ -46,28 +56,21 @@ class StockBackorderConfirmation(models.TransientModel): else: pickings_not_to_do |= line.picking_id - for pick_id in pickings_not_to_do: - moves_to_log = {} - for move in pick_id.move_ids: - if float_compare(move.product_uom_qty, - move.quantity_done, - precision_rounding=move.product_uom.rounding) > 0: - moves_to_log[move] = (move.quantity_done, move.product_uom_qty) - pick_id._log_less_quantities_than_expected(moves_to_log) - pickings_to_validate = self.env.context.get('button_validate_picking_ids') if pickings_to_validate: pickings_to_validate = self.env['stock.picking'].browse(pickings_to_validate).with_context(skip_backorder=True) if pickings_not_to_do: + self._check_less_quantities_than_expected(pickings_not_to_do) pickings_to_validate = pickings_to_validate.with_context(picking_ids_not_to_backorder=pickings_not_to_do.ids) return pickings_to_validate.button_validate() return True def process_cancel_backorder(self): - pickings_to_validate = self.env.context.get('button_validate_picking_ids') - if pickings_to_validate: - return self.env['stock.picking']\ - .browse(pickings_to_validate)\ - .with_context(skip_backorder=True, picking_ids_not_to_backorder=pickings_to_validate)\ + pickings_to_validate_ids = self.env.context.get('button_validate_picking_ids') + if pickings_to_validate_ids: + pickings_to_validate = self.env['stock.picking'].browse(pickings_to_validate_ids) + self._check_less_quantities_than_expected(pickings_to_validate) + return pickings_to_validate\ + .with_context(skip_backorder=True, picking_ids_not_to_backorder=self.pick_ids.ids)\ .button_validate() return True