diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 0e2c6d549c5..9efbf89089d 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -263,6 +263,34 @@ class StockQuant(models.Model): break return reserved_quants + @api.model + def _merge_quants(self): + """ In a situation where one transaction is updating a quant via + `_update_available_quantity` and another concurrent one calls this function with the same + argument, we’ll create a new quant in order for these transactions to not rollback. This + method will find and deduplicate these quants. + """ + query = """WITH + dupes AS ( + SELECT min(id) as to_update_quant_id, + (array_agg(id ORDER BY id))[2:array_length(array_agg(id), 1)] as to_delete_quant_ids, + SUM(reserved_quantity) as reserved_quantity, + SUM(quantity) as quantity + FROM stock_quant + GROUP BY product_id, company_id, location_id, lot_id, package_id, owner_id, in_date + HAVING count(id) > 1 + ), + _up AS ( + UPDATE stock_quant q + SET quantity = d.quantity, + reserved_quantity = d.reserved_quantity + FROM dupes d + WHERE d.to_update_quant_id = q.id + ) + DELETE FROM stock_quant WHERE id in (SELECT unnest(to_delete_quant_ids) from dupes) + """ + self.env.cr.execute(query) + class QuantPackage(models.Model): """ Packages containing quants and/or other packages """ diff --git a/addons/stock/views/stock_quant_views.xml b/addons/stock/views/stock_quant_views.xml index 792399b62d3..600793b5354 100644 --- a/addons/stock/views/stock_quant_views.xml +++ b/addons/stock/views/stock_quant_views.xml @@ -139,7 +139,17 @@ stock.quant - + + Merge duplicate quants + + code + +env['stock.quant']._merge_quants() +action = env.ref('stock.quantsact').read()[0] + + + + stock.quant.package.search