Here is the code for the server action
# Available variables:
# - env: Odoo Environment on which the action is triggered
# - model: Odoo Model of the record on which the action is triggered; is a void recordset
# - record: record on which the action is triggered; may be void
# - records: recordset of all records on which the action is triggered in multi-mode; may be void
# - time, datetime, dateutil, timezone: useful Python libraries
# - log: log(message, level='info'): logging function to record debug information in ir.logging table
# - Warning: Warning Exception to use with raise
# To return an action, assign: action = {...}
# Available variables:
# - env: Odoo Environment on which the action is triggered
# - model: Odoo Model of the record on which the action is triggered; is a void recordset
# - record: record on which the action is triggered; may be void
# - records: recordset of all records on which the action is triggered in multi-mode; may be void
# - time, datetime, dateutil, timezone: useful Python libraries
# - log: log(message, level='info'): logging function to record debug information in ir.logging table
# - Warning: Warning Exception to use with raise
# To return an action, assign: action = {...}
quants = env["stock.quant"].search([])
move_line_ids = []
warning = ""
for quant in quants:
move_lines = env["stock.move.line"].search(
[
("product_id", "=", quant.product_id.id),
("location_id", "=", quant.location_id.id),
("lot_id", "=", quant.lot_id.id),
("package_id", "=", quant.package_id.id),
("owner_id", "=", quant.owner_id.id),
("product_qty", "!=", 0),
]
)
move_line_ids += move_lines.ids
reserved_on_move_lines = sum(move_lines.mapped("product_qty"))
move_line_str = str.join(
", ", [str(move_line_id) for move_line_id in move_lines.ids]
)
if quant.location_id.should_bypass_reservation():
# If a quant is in a location that should bypass the reservation, its `reserved_quantity` field
# should be 0.
if quant.reserved_quantity != 0:
quant.write({"reserved_quantity": 0})
else:
# If a quant is in a reservable location, its `reserved_quantity` should be exactly the sum
# of the `product_qty` of all the partially_available / assigned move lines with the same
# characteristics.
if quant.reserved_quantity == 0:
if move_lines:
move_lines.with_context(bypass_reservation_update=True).write(
{"product_uom_qty": 0}
)
elif quant.reserved_quantity < 0:
quant.write({"reserved_quantity": 0})
if move_lines:
move_lines.with_context(bypass_reservation_update=True).write(
{"product_uom_qty": 0}
)
else:
if reserved_on_move_lines != quant.reserved_quantity:
move_lines.with_context(bypass_reservation_update=True).write(
{"product_uom_qty": 0}
)
quant.write({"reserved_quantity": 0})
else:
if any(move_line.product_qty < 0 for move_line in move_lines):
move_lines.with_context(bypass_reservation_update=True).write(
{"product_uom_qty": 0}
)
quant.write({"reserved_quantity": 0})
move_lines = env["stock.move.line"].search(
[
("product_id.type", "=", "product"),
("product_qty", "!=", 0),
("id", "not in", move_line_ids),
]
)
move_lines_to_unreserve = []
for move_line in move_lines:
if not move_line.location_id.should_bypass_reservation():
move_lines_to_unreserve.append(move_line.id)
if len(move_lines_to_unreserve) > 1:
env.cr.execute(
"""
UPDATE stock_move_line SET product_uom_qty = 0, product_qty = 0 WHERE id in %s ;
"""
% (tuple(move_lines_to_unreserve),)
)
elif len(move_lines_to_unreserve) == 1:
env.cr.execute(
"""
UPDATE stock_move_line SET product_uom_qty = 0, product_qty = 0 WHERE id = %s ;
"""
% (move_lines_to_unreserve[0])
)
Wow. Thanks a lot! Worked like a charm
Thanks for the solution, worked like a charm.
Its excellent working fine and issue has been solved.... just add access right as mentioned above..
Thanks a lot
is it workable for v12
Hi.
It also worked for me in an Enterprise version, thanks so much @Julia van orsouw for sharing!!
Greetings from Spain.
Hello
I got anothor error when i do in step 11action/fix "fix unreserved qty",so odoo sent me a message " You are not allowed to modify 'Quants' (stock.quant) records.
No group currently allows this operation.
Contact your administrator to request access if necessary."
I don't know that reason about odoo version? because my odoo version is 14
That was really perfect as it immediately solved my problem.
The never ending story. V16. Manufacturing. MTO between semi finished product and top product. Operator made mistakes on confirm consumption on orders. Logistic responsible created extra transaction to the manufacturing order to correct this, but the consumed there lot numbers that was reserved to a new order. Reservations was not updated and the new order was blocked.
Solution: Update quant with qty on hand with the standard transaction for inventory. Then it was possible to delete the stock move line from the manufacturing order and the reservation was also deleted. 7 quants was involved.
Since this was MTO process, we also cancelled the manufacturing order and created a new independent.
Solved. But used about 6 hours to find the solution. Thanks to everybody that over the years has contributed on this tread.
Bedankt voor je mailtje. De rest van deze week ben ik vrij en zal ik dus niet reageren. Ik probeer je bericht komende maandag weer op te pakken. Bedankt voor het geduld en tot snel!