[FIX] stock: backorder base on initial demand

This reverts commit 656d8ace87.

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) <arm@odoo.com>
This commit is contained in:
Arnold Moyaux
2023-09-29 11:59:01 +00:00
parent e657831f5a
commit eff2c6edaa
12 changed files with 100 additions and 96 deletions
+4 -1
View File
@@ -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)
+3 -1
View File
@@ -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)
+3 -1
View File
@@ -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')
@@ -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()
+11 -4
View File
@@ -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}])
@@ -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()
@@ -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
+2 -4
View File
@@ -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
+23 -11
View File
@@ -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}']
+3 -1
View File
@@ -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.')
+16 -6
View File
@@ -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()
@@ -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)