Fixes Issue 35137: Concurrency problem: current balance wrongly calculated
authorAtul Gaware <atul.gaware@openbravo.com>
Sat, 11 Mar 2017 00:46:09 +0530
changeset 31650 498699b38a5d
parent 31649 84ddadc11e41
child 31651 b886c29976bb
Fixes Issue 35137: Concurrency problem: current balance wrongly calculated
when 2 transactions are processed at same time

Lock added at database level for financial account being used while processing
or reactivating transaction.
modules/org.openbravo.advpaymentmngt/src/org/openbravo/advpaymentmngt/process/FIN_TransactionProcess.java
--- a/modules/org.openbravo.advpaymentmngt/src/org/openbravo/advpaymentmngt/process/FIN_TransactionProcess.java	Tue Mar 14 16:55:41 2017 +0100
+++ b/modules/org.openbravo.advpaymentmngt/src/org/openbravo/advpaymentmngt/process/FIN_TransactionProcess.java	Sat Mar 11 00:46:09 2017 +0530
@@ -11,7 +11,7 @@
  * under the License.
  * The Original Code is Openbravo ERP.
  * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2016 Openbravo SLU
+ * All portions are Copyright (C) 2010-2017 Openbravo SLU
  * All Rights Reserved.
  * Contributor(s):  ______________________________________.
  *************************************************************************
@@ -22,6 +22,9 @@
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
+import org.hibernate.LockOptions;
+import org.hibernate.Query;
+import org.hibernate.Session;
 import org.hibernate.criterion.Restrictions;
 import org.openbravo.advpaymentmngt.APRM_FinaccTransactionV;
 import org.openbravo.advpaymentmngt.dao.AdvPaymentMngtDao;
@@ -113,7 +116,7 @@
           throw new OBException(msg);
         }
 
-        final FIN_FinancialAccount financialAccount = transaction.getAccount();
+        final FIN_FinancialAccount financialAccount = lockFinAccount(transaction.getAccount());
         financialAccount.setCurrentBalance(financialAccount.getCurrentBalance().add(
             transaction.getDepositAmount().subtract(transaction.getPaymentAmount())));
         transaction.setProcessed(true);
@@ -218,7 +221,7 @@
           OBContext.restorePreviousMode();
         }
         transaction.setProcessed(false);
-        final FIN_FinancialAccount financialAccount = transaction.getAccount();
+        final FIN_FinancialAccount financialAccount = lockFinAccount(transaction.getAccount());
         financialAccount.setCurrentBalance(financialAccount.getCurrentBalance()
             .subtract(transaction.getDepositAmount()).add(transaction.getPaymentAmount()));
         OBDal.getInstance().save(financialAccount);
@@ -366,4 +369,15 @@
     return confirmation;
   }
 
+  private static FIN_FinancialAccount lockFinAccount(FIN_FinancialAccount account) {
+    StringBuilder queryStr = new StringBuilder("select a from FIN_Financial_Account a where id = :id");
+    final Session session = OBDal.getInstance().getSession();
+    final Query query = session.createQuery(queryStr.toString());
+    query.setParameter("id", account.getId());
+    query.setMaxResults(1);
+    query.setLockOptions(LockOptions.UPGRADE);
+    OBDal.getInstance().getSession().evict(account);
+    return (FIN_FinancialAccount) query.uniqueResult();
+  }
+
 }