[FIX] stock_picking_batch: remove empty pickings
If a picking is totally empty (no move line with quantity recorded) in a batch at validation. This one will be ignored by the immediate transfer mechanism as well as the backorder creation. It is simply remove from the batch. closes odoo/odoo#63291 Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
This commit is contained in:
@@ -195,14 +195,25 @@ class StockPickingBatch(models.Model):
|
||||
if any(picking.state not in ('assigned', 'confirmed') for picking in pickings):
|
||||
raise UserError(_('Some transfers are still waiting for goods. Please check or force their availability before setting this batch to done.'))
|
||||
|
||||
empty_pickings = set()
|
||||
for picking in pickings:
|
||||
if all(float_is_zero(line.qty_done, precision_rounding=line.product_uom_id.rounding) for line in picking.move_line_ids if line.state not in ('done', 'cancel')):
|
||||
empty_pickings.add(picking.id)
|
||||
picking.message_post(
|
||||
body="<b>%s:</b> %s <a href=#id=%s&view_type=form&model=stock.picking.batch>%s</a>" % (
|
||||
_("Transferred by"),
|
||||
_("Batch Transfer"),
|
||||
picking.batch_id.id,
|
||||
picking.batch_id.name))
|
||||
return pickings.button_validate()
|
||||
|
||||
if len(empty_pickings) == len(pickings):
|
||||
return pickings.button_validate()
|
||||
else:
|
||||
res = pickings.with_context(skip_immediate=True).button_validate()
|
||||
if empty_pickings and res.get('context'):
|
||||
res['context']['pickings_to_detach'] = list(empty_pickings)
|
||||
return res
|
||||
|
||||
|
||||
def action_assign(self):
|
||||
self.ensure_one()
|
||||
|
||||
@@ -309,28 +309,17 @@ class TestBatchPicking(TransactionCase):
|
||||
self.assertEqual(self.picking_client_2.state, 'assigned', 'Picking 2 should be ready')
|
||||
|
||||
self.picking_client_1.move_lines.quantity_done = 5
|
||||
# There should be a wizard asking to process picking without quantity done
|
||||
immediate_transfer_wizard_dict = self.batch.action_done()
|
||||
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), 1)
|
||||
back_order_wizard_dict = immediate_transfer_wizard.process()
|
||||
# There should be a wizard asking to make a backorder
|
||||
back_order_wizard_dict = self.batch.action_done()
|
||||
self.assertTrue(back_order_wizard_dict)
|
||||
self.assertEqual(back_order_wizard_dict.get('res_model'), 'stock.backorder.confirmation')
|
||||
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)
|
||||
self.assertEqual(len(back_order_wizard.pick_ids), 2)
|
||||
back_order_wizard.process()
|
||||
|
||||
self.assertEqual(self.picking_client_1.state, 'done', 'Picking 1 should be done')
|
||||
self.assertEqual(self.picking_client_1.move_lines.product_uom_qty, 5, 'initial demand should be 5 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.assertFalse(sum(quant_A.mapped('quantity')))
|
||||
self.assertFalse(sum(quant_B.mapped('quantity')))
|
||||
|
||||
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)
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
from . import stock_picking_to_batch
|
||||
from . import stock_add_to_wave
|
||||
from . import stock_package_destination
|
||||
from . import stock_backorder_confirmation
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class StockBackorderConfirmation(models.TransientModel):
|
||||
_inherit = 'stock.backorder.confirmation'
|
||||
|
||||
def process(self):
|
||||
res = super().process()
|
||||
if self.env.context.get('pickings_to_detach'):
|
||||
self.env['stock.picking'].browse(self.env.context['pickings_to_detach']).batch_id = False
|
||||
return res
|
||||
|
||||
def process_cancel_backorder(self):
|
||||
res = super().process_cancel_backorder()
|
||||
if self.env.context.get('pickings_to_detach'):
|
||||
self.env['stock.picking'].browse(self.env.context['pickings_to_detach']).batch_id = False
|
||||
return res
|
||||
Reference in New Issue
Block a user