- Mailing Lists
- Contributors
- stock: Retroactively removing lots from incompatible products in stock move history
Archives
- By thread 1419
-
By date
- August 2019 59
- September 2019 118
- October 2019 165
- November 2019 97
- December 2019 35
- January 2020 58
- February 2020 204
- March 2020 121
- April 2020 172
- May 2020 50
- June 2020 158
- July 2020 85
- August 2020 94
- September 2020 193
- October 2020 277
- November 2020 100
- December 2020 159
- January 2021 38
- February 2021 87
- March 2021 146
- April 2021 73
- May 2021 90
- June 2021 86
- July 2021 123
- August 2021 50
- September 2021 68
- October 2021 66
- November 2021 74
- December 2021 75
- January 2022 98
- February 2022 77
- March 2022 68
- April 2022 31
- May 2022 59
- June 2022 87
- July 2022 141
- August 2022 38
- September 2022 73
- October 2022 152
- November 2022 39
- December 2022 50
- January 2023 93
- February 2023 49
- March 2023 106
- April 2023 47
- May 2023 69
- June 2023 92
- July 2023 64
- August 2023 103
- September 2023 91
- October 2023 101
- November 2023 94
- December 2023 46
- January 2024 75
- February 2024 79
- March 2024 104
- April 2024 63
- May 2024 40
- June 2024 160
- July 2024 80
- August 2024 70
- September 2024 62
- October 2024 121
- November 2024 117
- December 2024 89
- January 2025 59
- February 2025 104
- March 2025 96
- April 2025 107
- May 2025 52
- June 2025 72
- July 2025 60
- August 2025 81
- September 2025 124
- October 2025 63
- November 2025 22
Contributors
stock: Retroactively removing lots from incompatible products in
stock move history
Hi all, I'm a little bit new to Odoo, so please bear with me if I don't get everything right, but I've been told that I have struck a difficult bug. TL:DR: Having removed the lot_id from certain rows (products that are incompatible with that lot) in stock_move_line and stock_quant, how do I know I haven't broken something? I have a database that was migrated from Odoo 9 to Odoo 12. Before the migration, there was a bug that assigned lots to by-products of a dismantling operation (in this case, empty bottles were assigned the lots of full bottles of wine). As a result, during inventory on Odoo 12, the error message from StockMoveLine._check_lot_product() shows up, correctly identifying that these various lots are incompatible with empty bottles, then aborting the validation. Because these lots were added in error, I want to remove them from all past stock moves. This cannot be done through the UI, so I've made these SQL statements to get it done: ``` update stock_move_line set lot_id = null, lot_name = null where product_id in (67, 38, 29) and lot_id is not null; update stock_quant set lot_id = null where product_id in (67, 38, 29) and lot_id is not null; ``` (the product_ids here are empty bottles) Having run the above on a test/staging database, I can now do the inventory without troubles. I have also verified that the quantities in the inventory have correctly added up (the quantities of bottles that previously had lots are added to the lot-less bottles). The quantities on the `product.product` view have remained the same, which makes sense to me. I have also triggered `_compute_quantities()` for 'product.product', and nothing has changed. Although everything works and my problems seem to have disappeared, the problem is that I do not know whether I have inadvertently corrupted the (test!) database. I've been reading the source code of the stock module to find interactions with lot_id and lot_name, but I've not really found anything troubling. Does my approach make sense? Is there anything I can do to verify the integrity of what I've done? Many thanks and best regards, Carmen Bianca Bakker Coop IT Easy
by Carmen Bianca Bakker - 10:46 - 7 Jan 2022
Follow-Ups
-
Re: stock: Retroactively removing lots from incompatible products in stock move history
Oh FYI,The inventory issue you've had I've had tens of times. What you've done is pretty much what I do.On Sat, Jan 8, 2022 at 11:42 AM Graeme Gellatly <gdgellatly@gmail.com> wrote:Personally if they are meant to have lots I wouldn't null them. Just create them new ones and set.Now as for quants there are 2 choices (these are v14) - first backport the Odoo way with a server action like this (if database is small) or the second is the same thing just specific to products.Model Server Actionquants = env['stock.quant'].sudo().search([])
move_line_ids = []
move_line_to_recompute_ids = []
logging = ''
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is not 0 while its location should bypass the reservation\n"
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
else:
logging += "no move lines are reserved on it, you can safely reset its `reserved_quantity` to 0\n"
logging += '******************\n'
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is 0 while these move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
elif quant.reserved_quantity < 0:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is negative while it should not happen\n"
quant.write({'reserved_quantity': 0})
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
logging += '******************\n'
else:
if reserved_on_move_lines != quant.reserved_quantity:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` does not reflect the move lines reservation\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
quant.write({'reserved_quantity': 0})
else:
if any(move_line.product_qty < 0 for move_line in
move_lines):
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` correctly reflects the move lines reservation but some are negatives\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
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():
logging += "Problematic move line found: %s (reserved_quantity: %s)\n" % (move_line.id, move_line.product_qty)
logging += "There is no exiting quants despite its `reserved_quantity`\n"
logging += '******************\n'
move_lines_to_unreserve.append(move_line.id)
move_line_to_recompute_ids.append(move_line.id)
if len(move_lines_to_unreserve) > 0:
env.cr.execute("""
UPDATE stock_move_line SET product_uom_qty = 0, product_qty = 0 WHERE id in %s ;
"""
% (tuple(move_lines_to_unreserve), ))
if logging:
env['ir.logging'].sudo().create({
'name': 'Unreserve stock.quant and stock.move.line',
'type': 'server',
'level': 'DEBUG',
'dbname': env.cr.dbname,
'message': logging,
'func': '_update_reserved_quantity',
'path': 'addons/stock/models/stock_quant.py',
'line': '0',
})
if move_line_to_recompute_ids:
env['stock.move.line'].browse(move_line_to_recompute_ids).move_id._recompute_state()Or if database is large/many users I create a Server Action on Product secured to inventory manager with an actionif records:
quants = env['stock.quant'].sudo().search([('product_id', 'in', records.ids)])
move_line_ids = []
move_line_to_recompute_ids = []
logging = ''
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is not 0 while its location should bypass the reservation\n"
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
else:
logging += "no move lines are reserved on it, you can safely reset its `reserved_quantity` to 0\n"
logging += '******************\n'
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is 0 while these move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
elif quant.reserved_quantity < 0:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is negative while it should not happen\n"
quant.write({'reserved_quantity': 0})
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
logging += '******************\n'
else:
if reserved_on_move_lines != quant.reserved_quantity:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` does not reflect the move lines reservation\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
quant.write({'reserved_quantity': 0})
else:
if any(move_line.product_qty < 0 for move_line in
move_lines):
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` correctly reflects the move lines reservation but some are negatives\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
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), ('product_id', 'in', records.ids)])
move_lines_to_unreserve = []
for move_line in move_lines:
if not move_line.location_id.should_bypass_reservation():
logging += "Problematic move line found: %s (reserved_quantity: %s)\n" % (move_line.id, move_line.product_qty)
logging += "There is no exiting quants despite its `reserved_quantity`\n"
logging += '******************\n'
move_lines_to_unreserve.append(move_line.id)
move_line_to_recompute_ids.append(move_line.id)
if len(move_lines_to_unreserve) > 0:
env.cr.execute("""
UPDATE stock_move_line SET product_uom_qty = 0, product_qty = 0 WHERE id in %s ;
"""
% (tuple(move_lines_to_unreserve), ))
if logging:
env['ir.logging'].sudo().create({
'name': 'Unreserve stock.quant and stock.move.line',
'type': 'server',
'level': 'INFO',
'dbname': env.cr.dbname,
'message': logging,
'func': '_update_reserved_quantity',
'path': 'addons/stock/models/stock_quant.py',
'line': '0',
})
if move_line_to_recompute_ids:
env['stock.move.line'].browse(move_line_to_recompute_ids).move_id._recompute_state()On Fri, 7 Jan 2022, 11:27 pm Carmen Bianca Bakker, <carmen@coopiteasy.be> wrote:Hello, Bedankt Tom, you are right. I have exclusively updated stock_quant from a previous backup, and I get effectively the same behaviour as I did when I updated both. That helps narrow down my research a lot---thank you. With kindness, Carmen
_______________________________________________
Mailing-List: https://odoo-community.org/groups/contributors-15
Post to: mailto:contributors@odoo-community.org
Unsubscribe: https://odoo-community.org/groups?unsubscribe
by Graeme Gellatly - 11:51 - 7 Jan 2022 -
Re: stock: Retroactively removing lots from incompatible products in stock move history
Personally if they are meant to have lots I wouldn't null them. Just create them new ones and set.Now as for quants there are 2 choices (these are v14) - first backport the Odoo way with a server action like this (if database is small) or the second is the same thing just specific to products.Model Server Actionquants = env['stock.quant'].sudo().search([])
move_line_ids = []
move_line_to_recompute_ids = []
logging = ''
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is not 0 while its location should bypass the reservation\n"
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
else:
logging += "no move lines are reserved on it, you can safely reset its `reserved_quantity` to 0\n"
logging += '******************\n'
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is 0 while these move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
elif quant.reserved_quantity < 0:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is negative while it should not happen\n"
quant.write({'reserved_quantity': 0})
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
logging += '******************\n'
else:
if reserved_on_move_lines != quant.reserved_quantity:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` does not reflect the move lines reservation\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
quant.write({'reserved_quantity': 0})
else:
if any(move_line.product_qty < 0 for move_line in
move_lines):
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` correctly reflects the move lines reservation but some are negatives\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
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():
logging += "Problematic move line found: %s (reserved_quantity: %s)\n" % (move_line.id, move_line.product_qty)
logging += "There is no exiting quants despite its `reserved_quantity`\n"
logging += '******************\n'
move_lines_to_unreserve.append(move_line.id)
move_line_to_recompute_ids.append(move_line.id)
if len(move_lines_to_unreserve) > 0:
env.cr.execute("""
UPDATE stock_move_line SET product_uom_qty = 0, product_qty = 0 WHERE id in %s ;
"""
% (tuple(move_lines_to_unreserve), ))
if logging:
env['ir.logging'].sudo().create({
'name': 'Unreserve stock.quant and stock.move.line',
'type': 'server',
'level': 'DEBUG',
'dbname': env.cr.dbname,
'message': logging,
'func': '_update_reserved_quantity',
'path': 'addons/stock/models/stock_quant.py',
'line': '0',
})
if move_line_to_recompute_ids:
env['stock.move.line'].browse(move_line_to_recompute_ids).move_id._recompute_state()Or if database is large/many users I create a Server Action on Product secured to inventory manager with an actionif records:
quants = env['stock.quant'].sudo().search([('product_id', 'in', records.ids)])
move_line_ids = []
move_line_to_recompute_ids = []
logging = ''
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is not 0 while its location should bypass the reservation\n"
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
else:
logging += "no move lines are reserved on it, you can safely reset its `reserved_quantity` to 0\n"
logging += '******************\n'
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:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is 0 while these move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
elif quant.reserved_quantity < 0:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` field is negative while it should not happen\n"
quant.write({'reserved_quantity': 0})
if move_lines:
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
logging += '******************\n'
else:
if reserved_on_move_lines != quant.reserved_quantity:
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` does not reflect the move lines reservation\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
quant.write({'reserved_quantity': 0})
else:
if any(move_line.product_qty < 0 for move_line in
move_lines):
logging += "Problematic quant found: %s (quantity: %s, reserved_quantity: %s)\n" % (quant.id, quant.quantity, quant.reserved_quantity)
logging += "its `reserved_quantity` correctly reflects the move lines reservation but some are negatives\n"
logging += "These move lines are reserved on it: %s (sum of the reservation: %s)\n" % (move_line_str, reserved_on_move_lines)
logging += '******************\n'
move_lines.with_context(bypass_reservation_update=True).sudo().write({'product_uom_qty': 0})
move_line_to_recompute_ids += move_lines.ids
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), ('product_id', 'in', records.ids)])
move_lines_to_unreserve = []
for move_line in move_lines:
if not move_line.location_id.should_bypass_reservation():
logging += "Problematic move line found: %s (reserved_quantity: %s)\n" % (move_line.id, move_line.product_qty)
logging += "There is no exiting quants despite its `reserved_quantity`\n"
logging += '******************\n'
move_lines_to_unreserve.append(move_line.id)
move_line_to_recompute_ids.append(move_line.id)
if len(move_lines_to_unreserve) > 0:
env.cr.execute("""
UPDATE stock_move_line SET product_uom_qty = 0, product_qty = 0 WHERE id in %s ;
"""
% (tuple(move_lines_to_unreserve), ))
if logging:
env['ir.logging'].sudo().create({
'name': 'Unreserve stock.quant and stock.move.line',
'type': 'server',
'level': 'INFO',
'dbname': env.cr.dbname,
'message': logging,
'func': '_update_reserved_quantity',
'path': 'addons/stock/models/stock_quant.py',
'line': '0',
})
if move_line_to_recompute_ids:
env['stock.move.line'].browse(move_line_to_recompute_ids).move_id._recompute_state()On Fri, 7 Jan 2022, 11:27 pm Carmen Bianca Bakker, <carmen@coopiteasy.be> wrote:Hello, Bedankt Tom, you are right. I have exclusively updated stock_quant from a previous backup, and I get effectively the same behaviour as I did when I updated both. That helps narrow down my research a lot---thank you. With kindness, Carmen
_______________________________________________
Mailing-List: https://odoo-community.org/groups/contributors-15
Post to: mailto:contributors@odoo-community.org
Unsubscribe: https://odoo-community.org/groups?unsubscribe
by Graeme Gellatly - 11:46 - 7 Jan 2022 -
Re: stock: Retroactively removing lots from incompatible products in stock move history
Hello, Bedankt Tom, you are right. I have exclusively updated stock_quant from a previous backup, and I get effectively the same behaviour as I did when I updated both. That helps narrow down my research a lot---thank you. With kindness, Carmen
by Carmen Bianca Bakker - 11:26 - 7 Jan 2022 -
Re: stock: Retroactively removing lots from incompatible products in stock move history
On 1/7/22 10:47 AM, Carmen Bianca Bakker wrote:
I have also verified that the quantities in the inventory have correctly added up (the quantities of bottles that previously had lots are added to the lot-less bottles).
I think at least for the stock_quant table, this is all you had to verify, and you have, so that's fine.
As for the modification that you did in "stock_move_line", I'm less sure - you're changing history there. I'm also not sure if doing that was really necessary to achieve your goal to make the inventory work again.
If you want to be sure, I would revert the stock move line table to a recent backup, and then do some more testing in a test database if that modification is really necessary.
by Tom Blauwendraat - 11:06 - 7 Jan 2022