KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > order > finaccount > FinAccountHelper


1 /*
2  * $Id: $
3  *
4  * Copyright 2001-2006 The Apache Software Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7  * use this file except in compliance with the License. You may obtain a copy of
8  * the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations
16  * under the License.
17  */

18
19 package org.ofbiz.order.finaccount;
20
21 import java.math.BigDecimal JavaDoc;
22 import java.sql.Timestamp JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Random JavaDoc;
25 import java.util.regex.Pattern JavaDoc;
26
27 import org.ofbiz.base.util.Debug;
28 import org.ofbiz.base.util.UtilDateTime;
29 import org.ofbiz.base.util.UtilMisc;
30 import org.ofbiz.base.util.UtilNumber;
31 import org.ofbiz.entity.GenericDelegator;
32 import org.ofbiz.entity.GenericEntity;
33 import org.ofbiz.entity.GenericEntityException;
34 import org.ofbiz.entity.GenericValue;
35 import org.ofbiz.entity.condition.EntityConditionList;
36 import org.ofbiz.entity.condition.EntityExpr;
37 import org.ofbiz.entity.condition.EntityOperator;
38 import org.ofbiz.entity.model.ModelEntity;
39 import org.ofbiz.entity.util.EntityUtil;
40
41 /**
42  * A package of methods for improving efficiency of financial accounts services
43  * @author sichen
44  *
45  */

46 public class FinAccountHelper {
47     
48      public static final String JavaDoc module = FinAccountHelper.class.getName();
49      /**
50       * A word on precision: since we're just adding and subtracting, the interim figures should have one more decimal place of precision than the final numbers.
51       */

52      public static int decimals = UtilNumber.getBigDecimalScale("finaccount.decimals");
53      public static int rounding = UtilNumber.getBigDecimalRoundingMode("finaccount.rounding");
54      public static final BigDecimal JavaDoc ZERO = (new BigDecimal JavaDoc("0.0")).setScale(decimals, rounding);
55      
56      public static final String JavaDoc giftCertFinAccountTypeId = "GIFTCERT_ACCOUNT";
57      public static final boolean defaultPinRequired = false;
58      
59      // pool of available characters for account codes, here numbers plus uppercase characters
60
static char[] char_pool = new char[10+26];
61      static {
62          int j = 0;
63          for (int i = "0".charAt(0); i <= "9".charAt(0); i++) {
64              char_pool[j++] = (char) i;
65          }
66          for (int i = "A".charAt(0); i <= "Z".charAt(0); i++) {
67              char_pool[j++] = (char) i;
68          }
69      }
70      
71
72      /**
73       * A convenience method which adds transactions.get(0).get(fieldName) to initialValue, all done in BigDecimal to decimals and rounding
74       * @param initialValue
75       * @param transactions
76       * @param fieldName
77       * @param decimals
78       * @param rounding
79       * @return
80       * @throws GenericEntityException
81       */

82      public static BigDecimal JavaDoc addFirstEntryAmount(BigDecimal JavaDoc initialValue, List JavaDoc transactions, String JavaDoc fieldName, int decimals, int rounding) throws GenericEntityException {
83           if ((transactions != null) && (transactions.size() == 1)) {
84               GenericValue firstEntry = (GenericValue) transactions.get(0);
85               if (firstEntry.get(fieldName) != null) {
86                   BigDecimal JavaDoc valueToAdd = new BigDecimal JavaDoc(firstEntry.getDouble(fieldName).doubleValue());
87                   BigDecimal JavaDoc newValue = initialValue.add(valueToAdd).setScale(decimals, rounding);
88                   return newValue;
89               } else {
90                   return initialValue;
91               }
92           } else {
93               return initialValue;
94           }
95      }
96
97      /**
98       * Returns a unique randomly generated account code for FinAccount.finAccountCode composed of uppercase letters and numbers
99       * @param codeLength length of code in number of characters
100       * @param delegator
101       * @return
102       * @throws GenericEntityException
103       */

104      public static String JavaDoc getNewFinAccountCode(int codeLength, GenericDelegator delegator) throws GenericEntityException {
105
106          // keep generating new 12-digit account codes until a unique one is found
107
Random JavaDoc r = new Random JavaDoc();
108          boolean foundUniqueNewCode = false;
109          StringBuffer JavaDoc newAccountCode = null;
110             
111          while (!foundUniqueNewCode) {
112             newAccountCode = new StringBuffer JavaDoc(codeLength);
113             for (int i = 0; i < codeLength; i++) {
114                 newAccountCode.append(char_pool[(int) r.nextInt(char_pool.length)]);
115             }
116
117             List JavaDoc existingAccountsWithCode = delegator.findByAnd("FinAccount", UtilMisc.toMap("finAccountCode", newAccountCode.toString()));
118             if (existingAccountsWithCode.size() == 0) {
119                 foundUniqueNewCode = true;
120             }
121          }
122             
123          return newAccountCode.toString();
124      }
125      
126      /**
127       * Gets the first (and should be only) FinAccount based on finAccountCode, which will be cleaned up to be only uppercase and alphanumeric
128       * @param finAccountCode
129       * @param delegator
130       * @return
131       * @throws GenericEntityException
132       */

133      public static GenericValue getFinAccountFromCode(String JavaDoc finAccountCode, GenericDelegator delegator) throws GenericEntityException {
134          // regex magic to turn all letters in code to uppercase and then remove all non-alphanumeric letters
135
if (finAccountCode == null) {
136              return null;
137          }
138          
139          Pattern JavaDoc filterRegex = Pattern.compile("[^0-9A-Z]");
140          finAccountCode = finAccountCode.toUpperCase().replaceAll(filterRegex.pattern(), "");
141          
142          // now we need to get the encrypted version of the fin account code the user passed in to look up against FinAccount
143
// we do this by making a temporary generic entity with same finAccountCode and then doing a match
144
ModelEntity finAccountEntity = delegator.getModelEntity("FinAccount");
145          GenericEntity encryptedFinAccount = GenericEntity.createGenericEntity(finAccountEntity, UtilMisc.toMap("finAccountCode", finAccountCode));
146          delegator.encryptFields(encryptedFinAccount);
147          String JavaDoc encryptedFinAccountCode = encryptedFinAccount.getString("finAccountCode");
148          
149          // now look for the account
150
List JavaDoc accounts = delegator.findByAnd("FinAccount", UtilMisc.toMap("finAccountCode", encryptedFinAccountCode));
151          accounts = EntityUtil.filterByDate(accounts);
152          
153          if ((accounts == null) || (accounts.size() == 0)) {
154              // OK to display - not a code anyway
155
Debug.logWarning("No fin account found for account code [" + finAccountCode + "]", module);
156              return null;
157          } else if (accounts.size() > 1) {
158              // This should never happen, but don't display the code if it does -- it is supposed to be encrypted!
159
Debug.logError("Multiple fin accounts found", module);
160              return null;
161          } else {
162              return (GenericValue) accounts.get(0);
163          }
164      }
165      
166  
167      /**
168       * Sum of all DEPOSIT and ADJUSTMENT transactions minus all WITHDRAWAL transactions whose transactionDate is before asOfDateTime
169       * @param finAccountId
170       * @param currencyUomId
171       * @param asOfDateTime
172       * @param delegator
173       * @return
174       * @throws GenericEntityException
175       */

176      public static BigDecimal JavaDoc getBalance(String JavaDoc finAccountId, String JavaDoc currencyUomId, Timestamp JavaDoc asOfDateTime, GenericDelegator delegator) throws GenericEntityException {
177          BigDecimal JavaDoc incrementTotal = ZERO; // total amount of transactions which increase balance
178
BigDecimal JavaDoc decrementTotal = ZERO; // decrease balance
179

180          // find the sum of all transactions which increase the value
181
EntityConditionList incrementConditions = new EntityConditionList(UtilMisc.toList(
182                  new EntityExpr("finAccountId", EntityOperator.EQUALS, finAccountId),
183                  new EntityExpr("transactionDate", EntityOperator.LESS_THAN_EQUAL_TO, asOfDateTime),
184                  new EntityExpr("currencyUomId", EntityOperator.EQUALS, currencyUomId),
185                  new EntityConditionList(UtilMisc.toList(
186                          new EntityExpr("finAccountTransTypeId", EntityOperator.EQUALS, "DEPOSIT"),
187                          new EntityExpr("finAccountTransTypeId", EntityOperator.EQUALS, "ADJUSTMENT")),
188                      EntityOperator.OR)),
189                  EntityOperator.AND);
190          List JavaDoc transSums = delegator.findByCondition("FinAccountTransSum", incrementConditions, UtilMisc.toList("amount"), null);
191          incrementTotal = addFirstEntryAmount(incrementTotal, transSums, "amount", (decimals+1), rounding);
192
193          // now find sum of all transactions with decrease the value
194
EntityConditionList decrementConditions = new EntityConditionList(UtilMisc.toList(
195                  new EntityExpr("finAccountId", EntityOperator.EQUALS, finAccountId),
196                  new EntityExpr("transactionDate", EntityOperator.LESS_THAN_EQUAL_TO, asOfDateTime),
197                  new EntityExpr("currencyUomId", EntityOperator.EQUALS, currencyUomId),
198                  new EntityExpr("finAccountTransTypeId", EntityOperator.EQUALS, "WITHDRAWAL")),
199              EntityOperator.AND);
200          transSums = delegator.findByCondition("FinAccountTransSum", decrementConditions, UtilMisc.toList("amount"), null);
201          decrementTotal = addFirstEntryAmount(decrementTotal, transSums, "amount", (decimals+1), rounding);
202          
203          // the net balance is just the incrementTotal minus the decrementTotal
204
BigDecimal JavaDoc netBalance = incrementTotal.subtract(decrementTotal).setScale(decimals, rounding);
205          return netBalance;
206      }
207
208      /**
209       * Same as above for the current instant
210       * @param finAccountId
211       * @param currencyUomId
212       * @param delegator
213       * @return
214       * @throws GenericEntityException
215       */

216      public static BigDecimal JavaDoc getBalance(String JavaDoc finAccountId, String JavaDoc currencyUomId, GenericDelegator delegator) throws GenericEntityException {
217          return getBalance(finAccountId, currencyUomId, UtilDateTime.nowTimestamp(), delegator);
218      }
219      
220      /**
221       * Returns the net balance (see above) minus the sum of all authorization amounts which are not expired and were authorized by the as of date
222       * @param finAccountId
223       * @param currencyUomId
224       * @param asOfDateTime
225       * @param delegator
226       * @return
227       * @throws GenericEntityException
228       */

229      public static BigDecimal JavaDoc getAvailableBalance(String JavaDoc finAccountId, String JavaDoc currencyUomId, Timestamp JavaDoc asOfDateTime, GenericDelegator delegator) throws GenericEntityException {
230          BigDecimal JavaDoc netBalance = getBalance(finAccountId, currencyUomId, asOfDateTime, delegator);
231          
232          // find sum of all authorizations which are not expired and which were authorized before as of time
233
EntityConditionList authorizationConditions = new EntityConditionList(UtilMisc.toList(
234                  new EntityExpr("finAccountId", EntityOperator.EQUALS, finAccountId),
235                  new EntityExpr("authorizationDate", EntityOperator.LESS_THAN_EQUAL_TO, asOfDateTime),
236                  new EntityExpr("currencyUomId", EntityOperator.EQUALS, currencyUomId),
237                  EntityUtil.getFilterByDateExpr(asOfDateTime)),
238              EntityOperator.AND);
239          
240          List JavaDoc authSums = delegator.findByCondition("FinAccountAuthSum", authorizationConditions, UtilMisc.toList("amount"), null);
241          
242          BigDecimal JavaDoc authorizationsTotal = addFirstEntryAmount(ZERO, authSums, "amount", (decimals+1), rounding);
243          
244          // the total available balance is transactions total minus authorizations total
245
BigDecimal JavaDoc netAvailableBalance = netBalance.subtract(authorizationsTotal).setScale(decimals, rounding);
246          return netAvailableBalance;
247      }
248
249      /**
250       * Same as above for the current instant
251       * @param finAccountId
252       * @param currencyUomId
253       * @param delegator
254       * @return
255       * @throws GenericEntityException
256       */

257     public static BigDecimal JavaDoc getAvailableBalance(String JavaDoc finAccountId, String JavaDoc currencyUomId, GenericDelegator delegator) throws GenericEntityException {
258         return getAvailableBalance(finAccountId, currencyUomId, UtilDateTime.nowTimestamp(), delegator);
259     }
260 }
261
Popular Tags