M_StorageOnHand Qty and Total M_Transaction Qty did not match


When we try to test multiple user to create transactions with same product and same material policy then COMPLETE all transaction simultaneuosly, M_StorageOnHand Qty and Total M_Transaction Qty did not match.

Replication Procedure:
1. Create Internal Use Inventory in PC1 using product1 and date current date.
2. Create Inventory Move in PC2 using same product and material policy in Internal Use Inventory.
3. Using 2 PC's COMPLETE both transaction at the same time.

This bug is intermitent and can only replicate using above replication.

Actual Results:
1. When we compute total Inventory OnHand Qty from M_StorageOnHand table the compute ending total movementqty from M_Transaction both table did no longer match.

Is there anyone who can help me regarding this issue? Thank you in advance.


Window 7 / Window Server 2012


Deepak Pansheriya
May 25, 2015, 12:50 PM

After making this fix live, We have noticed dead locks occurring. After 2 days of waiting we have reverted this code and system again worked fine.

I suggested in this case, we should move to update query with difference like
Update M_StorageOnHand set qtyOnhand=QtyOnhand-?, update=?, updatedby=? where M_StorageOnhand_UU=?

If this return 0 then we need to create M_StorageOnHand record.

Carlos Ruiz
May 25, 2015, 2:19 PM

thanks for the insights

Your suggestion seems correct - it must be made also on the reservation class.
And after the update we would need to reread the storage record from DB (po.load) and throw an exception if negative and the warehouse doesn't allow negatives

Carlos Ruiz
May 26, 2015, 11:36 PM

, analyzed again this issue.

In principle locking a record in a transaction and then re-reading from database within the same trx must not lead to deadlocks - as it must be guaranteed by database that another transaction cannot lock the same record.

But is possible if there are programs agressively locking many records then a race condition is created and deadlocks could happen - but I think those agressive locks are a bad practice here.

Analyzing the core code found 5 points where agressive locking was being forced - and not needed indeed.

So, the commit https://bitbucket.org/idempiere/idempiere/commits/82cca4a fixes that - but still is possible that plugins tries those agressive locks, maybe we could deprecate the getAll, getWarehouse and getWarehouseNegative methods with the forUpdate clause in favour of pushing people to use the non-locking approach.


Carlos Ruiz

Carlos Ruiz
June 24, 2015, 4:17 PM

reported prepaid order broken - after review seems it's caused by the approach I implemented on this ticket (refreshing values from DB when forUpdate is called) - reopening to think in a better approach

Carlos Ruiz
June 25, 2015, 1:30 AM

Thanks , I committed a different approach as per your suggestion with direct Update


Carlos Ruiz


Jhay Bentillo



Tested By



Affects versions