KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > accounting > payment > BillingAccountWorker


1 /*
2  * $Id: BillingAccountWorker.java 7251 2006-04-10 05:39:15Z jacopo $
3  *
4  * Copyright (c) 2003-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.accounting.payment;
25
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.TreeMap JavaDoc;
32 import java.math.BigDecimal JavaDoc;
33
34 import javolution.util.FastList;
35
36 import org.ofbiz.accounting.invoice.InvoiceWorker;
37 import org.ofbiz.base.util.Debug;
38 import org.ofbiz.base.util.GeneralException;
39 import org.ofbiz.base.util.UtilMisc;
40 import org.ofbiz.base.util.UtilNumber;
41 import org.ofbiz.entity.GenericDelegator;
42 import org.ofbiz.entity.GenericEntityException;
43 import org.ofbiz.entity.GenericEntity;
44 import org.ofbiz.entity.GenericValue;
45 import org.ofbiz.entity.condition.EntityCondition;
46 import org.ofbiz.entity.condition.EntityConditionList;
47 import org.ofbiz.entity.condition.EntityExpr;
48 import org.ofbiz.entity.condition.EntityOperator;
49 import org.ofbiz.entity.util.EntityUtil;
50 import org.ofbiz.order.order.OrderReadHelper;
51 import org.ofbiz.service.DispatchContext;
52 import org.ofbiz.service.LocalDispatcher;
53 import org.ofbiz.service.ServiceUtil;
54
55 /**
56  * Worker methods for BillingAccounts
57  *
58  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
59  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
60  * @version $Rev: 7251 $
61  * @since 2.1
62  */

63 public class BillingAccountWorker {
64     
65     public static final String JavaDoc module = BillingAccountWorker.class.getName();
66     private static BigDecimal JavaDoc ZERO = new BigDecimal JavaDoc("0");
67     private static int decimals = -1;
68     private static int rounding = -1;
69     static {
70         decimals = UtilNumber.getBigDecimalScale("order.decimals");
71         rounding = UtilNumber.getBigDecimalRoundingMode("order.rounding");
72
73         // set zero to the proper scale
74
if (decimals != -1) ZERO.setScale(decimals);
75     }
76
77     public static List JavaDoc makePartyBillingAccountList(GenericValue userLogin, String JavaDoc currencyUomId, String JavaDoc partyId, GenericDelegator delegator, LocalDispatcher dispatcher) throws GeneralException {
78         List JavaDoc billingAccountList = FastList.newInstance();
79
80         Map JavaDoc agentResult = dispatcher.runSync("getRelatedParties", UtilMisc.toMap("userLogin", userLogin, "partyIdFrom", partyId,
81                 "roleTypeIdFrom", "AGENT", "roleTypeIdTo", "CUSTOMER", "partyRelationshipTypeId", "AGENT", "includeFromToSwitched", "Y"));
82         if (ServiceUtil.isError(agentResult)) {
83             throw new GeneralException("Error while finding party BillingAccounts when getting Customers that this party is an agent of: " + ServiceUtil.getErrorMessage(agentResult));
84         }
85         List JavaDoc relatedPartyIdList = (List JavaDoc) agentResult.get("relatedPartyIdList");
86
87         EntityCondition barFindCond = new EntityConditionList(UtilMisc.toList(
88                 new EntityExpr("partyId", EntityOperator.IN, relatedPartyIdList),
89                 new EntityExpr("roleTypeId", EntityOperator.EQUALS, "BILL_TO_CUSTOMER")), EntityOperator.AND);
90         List JavaDoc billingAccountRoleList = delegator.findByCondition("BillingAccountRole", barFindCond, null, null);
91         billingAccountRoleList = EntityUtil.filterByDate(billingAccountRoleList);
92
93         if (billingAccountRoleList != null && billingAccountRoleList.size() > 0) {
94             double totalAvailable = 0.0;
95             TreeMap JavaDoc sortedAccounts = new TreeMap JavaDoc();
96             Iterator JavaDoc billingAcctIter = billingAccountRoleList.iterator();
97             while (billingAcctIter.hasNext()) {
98                 GenericValue billingAccountRole = (GenericValue) billingAcctIter.next();
99                 GenericValue billingAccountVO = billingAccountRole.getRelatedOne("BillingAccount");
100                 if (currencyUomId.equals(billingAccountVO.getString("accountCurrencyUomId"))) {
101                     double accountBalance = (BillingAccountWorker.getBillingAccountBalance(billingAccountVO)).doubleValue();
102                 
103                     Map JavaDoc billingAccount = new HashMap JavaDoc(billingAccountVO);
104                     double accountLimit = getAccountLimit(billingAccountVO).doubleValue();
105                 
106                     billingAccount.put("accountBalance", new Double JavaDoc(accountBalance));
107                     double accountAvailable = accountLimit - accountBalance;
108                     totalAvailable += accountAvailable;
109                     sortedAccounts.put(new Double JavaDoc(accountAvailable), billingAccount);
110                 }
111             }
112             
113             billingAccountList.addAll(sortedAccounts.values());
114         }
115         return billingAccountList;
116     }
117     
118     /**
119      * Returns the accountLimit of the BillingAccount or BigDecimal ZERO if it is null
120      * @param billingAccount
121      * @throws GenericEntityException
122      */

123     public static BigDecimal JavaDoc getAccountLimit(GenericValue billingAccount) throws GenericEntityException {
124         if (billingAccount.getBigDecimal("accountLimit") != null) {
125             return billingAccount.getBigDecimal("accountLimit");
126         } else {
127             Debug.logWarning("Billing Account [" + billingAccount.getString("billingAccountId") + "] does not have an account limit defined, assuming zero.", module);
128             return ZERO;
129         }
130     }
131     
132     /**
133      * Calculates the "available" balance of a billing account, which is net balance minus amount of pending (not canceled, rejected, or completed) orders.
134      * Available balance will not exceed billing account's accountLimit.
135      * When looking at using a billing account for a new order, you should use this method.
136      * @param delegator
137      * @param billingAccountId
138      * @return
139      * @throws GenericEntityException
140      */

141     public static BigDecimal JavaDoc getBillingAccountBalance(GenericValue billingAccount) throws GenericEntityException {
142         GenericDelegator delegator = billingAccount.getDelegator();
143         String JavaDoc billingAccountId = billingAccount.getString("billingAccountId");
144         
145         // first get the net balance of invoices - payments
146
BigDecimal JavaDoc balance = getBillingAccountNetBalance(delegator, billingAccountId);
147         
148         // now the amounts of all the pending orders (not cancelled, rejected or completed)
149
List JavaDoc orderHeaders = null;
150         List JavaDoc exprs1 = new LinkedList JavaDoc();
151         exprs1.add(new EntityExpr("billingAccountId", EntityOperator.EQUALS, billingAccountId));
152         exprs1.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_REJECTED"));
153         exprs1.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_CANCELLED"));
154         exprs1.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "ORDER_COMPLETED"));
155
156         orderHeaders = delegator.findByAnd("OrderHeader", exprs1);
157
158         if (orderHeaders != null) {
159             Iterator JavaDoc ohi = orderHeaders.iterator();
160             while (ohi.hasNext()) {
161                 GenericValue orderHeader = (GenericValue) ohi.next();
162                 OrderReadHelper orh = new OrderReadHelper(orderHeader);
163                 balance = balance.add(orh.getOrderGrandTotalBd());
164             }
165         }
166
167         // set the balance to BillingAccount.accountLimit if it is greater. This is necessary because nowhere do we track the amount of BillingAccount
168
// to be charged to an order, such as FinAccountAuth entity does for FinAccount. As a result, we must assume that the system is doing things correctly
169
// and use the accountLimit
170
BigDecimal JavaDoc accountLimit = new BigDecimal JavaDoc(billingAccount.getDouble("accountLimit").doubleValue());
171         if (balance.compareTo(accountLimit) == 1) {
172             balance = accountLimit;
173         } else {
174             balance = balance.setScale(decimals, rounding);
175         }
176         return balance;
177     }
178     
179     public static BigDecimal JavaDoc getBillingAccountBalance(GenericDelegator delegator, String JavaDoc billingAccountId) throws GenericEntityException {
180         GenericValue billingAccount = delegator.findByPrimaryKey("BillingAccount", UtilMisc.toMap("billingAccountId", billingAccountId));
181         return getBillingAccountBalance(billingAccount);
182     }
183     
184     /**
185      * Returns the amount which could be charged to a billing account, which is defined as the accountLimit minus account balance and minus the balance of outstanding orders
186      * When trying to figure out how much of a billing account can be used to pay for an outstanding order, use this method
187      * @param billingAccount
188      * @return
189      * @throws GenericEntityException
190      */

191     public static BigDecimal JavaDoc getBillingAccountAvailableBalance(GenericValue billingAccount) throws GenericEntityException {
192         if ((billingAccount != null) && (billingAccount.get("accountLimit") != null)) {
193             BigDecimal JavaDoc accountLimit = new BigDecimal JavaDoc(billingAccount.getDouble("accountLimit").doubleValue());
194             BigDecimal JavaDoc availableBalance = accountLimit.subtract(getBillingAccountBalance(billingAccount)).setScale(decimals, rounding);
195             return availableBalance;
196         } else {
197             return ZERO;
198         }
199     }
200     
201     /**
202      * Calculates the net balance of a billing account, which is sum of all amounts applied to invoices minus sum of all amounts applied from payments.
203      * When charging or capturing an invoice to a billing account, use this method
204      * @param delegator
205      * @param billingAccountId
206      * @return
207      * @throws GenericEntityException
208      */

209     public static BigDecimal JavaDoc getBillingAccountNetBalance(GenericDelegator delegator, String JavaDoc billingAccountId) throws GenericEntityException {
210         BigDecimal JavaDoc balance = ZERO;
211      
212         // search through all PaymentApplications and add the amount that was applied to invoice and subtract the amount applied from payments
213
List JavaDoc paymentAppls = delegator.findByAnd("PaymentApplication", UtilMisc.toMap("billingAccountId", billingAccountId));
214         if (paymentAppls != null) {
215             for (Iterator JavaDoc pAi = paymentAppls.iterator(); pAi.hasNext(); ) {
216                 GenericValue paymentAppl = (GenericValue) pAi.next();
217                 BigDecimal JavaDoc amountApplied = paymentAppl.getBigDecimal("amountApplied");
218                 if (paymentAppl.getString("invoiceId") != null) {
219                     // make sure the invoice has not been canceled
220
if (!"INVOICE_CANCELED".equals(paymentAppl.getRelatedOne("Invoice").getString("statusId"))) {
221                         balance = balance.add(amountApplied);
222                     }
223                 } else {
224                     balance = balance.subtract(amountApplied);
225                 }
226             }
227         }
228     
229         balance = balance.setScale(decimals, rounding);
230         return balance;
231     }
232     
233     /**
234      * Returns the amount of the billing account which could be captured, which is BillingAccount.accountLimit - net balance
235      * @param billingAccount
236      * @return
237      * @throws GenericEntityException
238      */

239     public static BigDecimal JavaDoc availableToCapture(GenericValue billingAccount) throws GenericEntityException {
240         BigDecimal JavaDoc netBalance = getBillingAccountNetBalance(billingAccount.getDelegator(), billingAccount.getString("billingAccountId"));
241         BigDecimal JavaDoc accountLimit = new BigDecimal JavaDoc(billingAccount.getDouble("accountLimit").doubleValue());
242         
243         return accountLimit.subtract(netBalance).setScale(decimals, rounding);
244     }
245     
246     public static Map JavaDoc calcBillingAccountBalance(DispatchContext dctx, Map JavaDoc context) {
247         GenericDelegator delegator = dctx.getDelegator();
248         String JavaDoc billingAccountId = (String JavaDoc) context.get("billingAccountId");
249         Map JavaDoc result = ServiceUtil.returnSuccess();
250         
251         try {
252             GenericValue billingAccount = delegator.findByPrimaryKey("BillingAccount", UtilMisc.toMap("billingAccountId", billingAccountId));
253             if (billingAccount == null) {
254                 return ServiceUtil.returnError("Unable to locate billing account #" + billingAccountId);
255             }
256             
257             result.put("billingAccount", billingAccount);
258             result.put("accountBalance", new Double JavaDoc((getBillingAccountBalance(delegator, billingAccountId)).doubleValue()));
259             result.put("netAccountBalance", new Double JavaDoc((getBillingAccountNetBalance(delegator, billingAccountId)).doubleValue()));
260             result.put("availableBalance", new Double JavaDoc(getBillingAccountAvailableBalance(billingAccount).doubleValue()));
261             result.put("availableToCapture", new Double JavaDoc(availableToCapture(billingAccount).doubleValue()));
262         
263             return result;
264         } catch (GenericEntityException e) {
265             Debug.logError(e, module);
266             return ServiceUtil.returnError("Error getting billing account or calculating balance for billing account #" + billingAccountId);
267         }
268         
269         
270     }
271 }
272
Popular Tags