001/*
002 * Copyright 2013 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 1.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl1.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.ole.select.document.service.impl;
017
018import org.kuali.ole.coa.businessobject.Account;
019import org.kuali.ole.gl.businessobject.Balance;
020import org.kuali.ole.module.purap.businessobject.PaymentRequestAccount;
021import org.kuali.ole.select.businessobject.OlePaymentRequestItem;
022import org.kuali.ole.select.businessobject.OleSufficientFundCheck;
023import org.kuali.ole.select.document.OlePaymentRequestDocument;
024import org.kuali.ole.select.document.service.OlePaymentRequestFundCheckService;
025import org.kuali.ole.sys.OLEConstants;
026import org.kuali.ole.sys.OLEPropertyConstants;
027import org.kuali.ole.sys.businessobject.SourceAccountingLine;
028import org.kuali.ole.sys.context.SpringContext;
029import org.kuali.ole.sys.service.UniversityDateService;
030import org.kuali.rice.core.api.util.type.KualiDecimal;
031import org.kuali.rice.krad.service.BusinessObjectService;
032
033import java.text.DateFormat;
034import java.text.SimpleDateFormat;
035import java.util.Date;
036import java.util.HashMap;
037import java.util.List;
038import java.util.Map;
039
040public class OlePaymentRequestFundCheckServiceImpl implements OlePaymentRequestFundCheckService {
041
042    @Override
043    public boolean hasSufficientFundCheckRequired(SourceAccountingLine accLine) {
044        boolean hasSufficientFundRequired = false;
045        Map searchMap = new HashMap();
046        Map<String, Object> key = new HashMap<String, Object>();
047        String chartCode = accLine.getChartOfAccountsCode();
048        String accNo = accLine.getAccountNumber();
049        String objectCd = accLine.getFinancialObjectCode();
050        String fundCodeType = getFundCode(chartCode, accNo);
051        KualiDecimal budgetAllocation = KualiDecimal.ZERO;
052        KualiDecimal expenseAmt = KualiDecimal.ZERO;
053        if (fundCodeType != null && fundCodeType.equals(OLEConstants.ACCOUNT_FUND_CODE)) {
054            budgetAllocation = getBudgetAllocationForAccount(chartCode, accNo, objectCd);
055            expenseAmt = getSumPaidInvoicesForAccount(chartCode, accNo, objectCd);
056            expenseAmt = expenseAmt.subtract(accLine.getAmount());
057            if (expenseAmt.isNegative()) {
058                budgetAllocation = budgetAllocation.subtract(expenseAmt.negated());
059            } else {
060                budgetAllocation = budgetAllocation.subtract(expenseAmt);
061            }
062            if (accLine.getAmount().isGreaterThan(budgetAllocation)) {
063                hasSufficientFundRequired = true;
064            } else {
065                hasSufficientFundRequired = false;
066            }
067        } else if (fundCodeType != null && fundCodeType.equals(OLEConstants.OBJECT_FUND_CODE)) {
068            budgetAllocation = getBudgetAllocationForObject(chartCode, accNo, objectCd);
069            expenseAmt = getSumPaidInvoicesForObject(chartCode, accNo, objectCd);
070            expenseAmt = expenseAmt.subtract(accLine.getAmount());
071            if (expenseAmt.isNegative()) {
072                budgetAllocation = budgetAllocation.subtract(expenseAmt.negated());
073            } else {
074                budgetAllocation = budgetAllocation.subtract(expenseAmt);
075            }
076            if (accLine.getAmount().isGreaterThan(budgetAllocation)) {
077                hasSufficientFundRequired = true;
078            } else {
079                hasSufficientFundRequired = false;
080            }
081        }
082        return hasSufficientFundRequired;
083    }
084
085    private String getFundCode(String chartCode, String accountNumber) {
086        Map accountMap = new HashMap();
087        accountMap.put("chartOfAccountsCode", chartCode);
088        accountMap.put("accountNumber", accountNumber);
089        Account account = SpringContext.getBean(BusinessObjectService.class)
090                .findByPrimaryKey(Account.class, accountMap);
091        boolean fundCheckIndication = false;
092        if (account != null) {
093            fundCheckIndication = account.isPendingAcctSufficientFundsIndicator();
094        }
095
096        if (fundCheckIndication) {
097            String fundCode = account.getAccountSufficientFundsCode();
098            return fundCode;
099        }
100        return null;
101    }
102
103    public KualiDecimal getSumPaidInvoicesForAccount(String chartCode, String accountNo, String objectCode) {
104        KualiDecimal paidInvoices = KualiDecimal.ZERO;
105        List<OlePaymentRequestDocument> payDocList = (List<OlePaymentRequestDocument>) SpringContext.getBean(
106                BusinessObjectService.class).findAll(OlePaymentRequestDocument.class);
107        if (payDocList.size() > 0) {
108            for (OlePaymentRequestDocument olePaymentRequestDocument : payDocList) {
109                Integer payReqId = olePaymentRequestDocument.getPurapDocumentIdentifier();
110                Map docMap = new HashMap();
111                docMap.put(OLEConstants.PUR_AP_IDEN, payReqId);
112                docMap.put(OLEConstants.ITM_TYP_CD_KEY, OLEConstants.ITM_TYP_CD);
113                List<OlePaymentRequestItem> itemList = (List<OlePaymentRequestItem>) SpringContext.getBean(
114                        BusinessObjectService.class).findMatching(OlePaymentRequestItem.class, docMap);
115                HashMap acctMap = new HashMap();
116                for (OlePaymentRequestItem olePaymentRequestItem : itemList) {
117                    Integer itemIdentifier = olePaymentRequestItem.getItemIdentifier();
118                    acctMap.put("itemIdentifier", olePaymentRequestItem.getItemIdentifier());
119                    acctMap.put("chartOfAccountsCode", chartCode);
120                    acctMap.put("accountNumber", accountNo);
121                    List<PaymentRequestAccount> olePaymentRequestAccount = (List<PaymentRequestAccount>) SpringContext
122                            .getBean(BusinessObjectService.class).findMatching(PaymentRequestAccount.class, acctMap);
123                    for (PaymentRequestAccount payReqAcct : olePaymentRequestAccount) {
124                        paidInvoices = paidInvoices.add(payReqAcct.getAmount());
125                    }
126                }
127            }
128        }
129        return paidInvoices;
130    }
131
132
133    public KualiDecimal getSumPaidInvoicesForObject(String chartCode, String accountNo, String objectCode) {
134        KualiDecimal paidInvoices = KualiDecimal.ZERO;
135        List<OlePaymentRequestDocument> payDocList = (List<OlePaymentRequestDocument>) SpringContext.getBean(
136                BusinessObjectService.class).findAll(OlePaymentRequestDocument.class);
137        if (payDocList.size() > 0) {
138            for (OlePaymentRequestDocument olePaymentRequestDocument : payDocList) {
139                Integer payReqId = olePaymentRequestDocument.getPurapDocumentIdentifier();
140                Map docMap = new HashMap();
141                docMap.put(OLEConstants.PUR_AP_IDEN, payReqId);
142                docMap.put(OLEConstants.ITM_TYP_CD_KEY, OLEConstants.ITM_TYP_CD);
143                List<OlePaymentRequestItem> itemList = (List<OlePaymentRequestItem>) SpringContext.getBean(
144                        BusinessObjectService.class).findMatching(OlePaymentRequestItem.class, docMap);
145                HashMap acctMap = new HashMap();
146                for (OlePaymentRequestItem olePaymentRequestItem : itemList) {
147                    acctMap.put("itemIdentifier", olePaymentRequestItem.getItemIdentifier());
148                    acctMap.put("chartOfAccountsCode", chartCode);
149                    acctMap.put("accountNumber", accountNo);
150                    acctMap.put("financialObjectCode", objectCode);
151                    List<PaymentRequestAccount> olePaymentRequestAccount = (List<PaymentRequestAccount>) SpringContext
152                            .getBean(BusinessObjectService.class).findMatching(PaymentRequestAccount.class, acctMap);
153                    for (PaymentRequestAccount payReqAcct : olePaymentRequestAccount) {
154                        paidInvoices = paidInvoices.add(payReqAcct.getAmount());
155                    }
156                }
157            }
158        }
159        return paidInvoices;
160    }
161
162    private KualiDecimal getBudgetAllocationForObject(String chartCode, String accountNumber, String objectCode) {
163        Map budgetMap = new HashMap();
164        Date date = new Date();
165        DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
166        String univFiscalYear = df.format(date);
167        UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class);
168        budgetMap.put("universityFiscalYear",
169                universityDateService.getCurrentUniversityDate().getUniversityFiscalYear());
170        budgetMap.put("chartOfAccountsCode", chartCode);
171        budgetMap.put("accountNumber", accountNumber);
172        budgetMap.put("objectCode", objectCode);
173        budgetMap.put(OLEPropertyConstants.BALANCE_TYPE_CODE, OLEPropertyConstants.BAL_TYP_CODE);
174        Balance balance = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(Balance.class, budgetMap);
175        KualiDecimal initialBudgetAmount = KualiDecimal.ZERO;
176        if (balance != null) {
177            initialBudgetAmount = balance.getAccountLineAnnualBalanceAmount();
178        }
179        Map encMap = new HashMap();
180        encMap.put("chartOfAccountsCode", chartCode);
181        encMap.put("accountNumber", accountNumber);
182        OleSufficientFundCheck oleSufficientFundCheck = SpringContext.getBean(BusinessObjectService.class)
183                .findByPrimaryKey(OleSufficientFundCheck.class, encMap);
184        KualiDecimal amount = KualiDecimal.ZERO;
185        if (oleSufficientFundCheck != null) {
186            if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_TYP_PERCENTAGE.equals(oleSufficientFundCheck
187                    .getEncumbExpenseConstraintType())) {
188                amount = new KualiDecimal(oleSufficientFundCheck.getExpenseAmount());
189                if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_OVER.equals(oleSufficientFundCheck
190                        .getEncumbExpenseMethod())) {
191                    initialBudgetAmount = initialBudgetAmount.add((initialBudgetAmount.multiply(amount))
192                            .divide(new KualiDecimal(100)));
193                } else if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_UNDER.equals(oleSufficientFundCheck
194                        .getEncumbExpenseMethod())) {
195                    initialBudgetAmount = initialBudgetAmount.subtract((initialBudgetAmount.multiply(amount))
196                            .divide(new KualiDecimal(100)));
197
198                }
199            } else if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_TYP_CASH.equals(oleSufficientFundCheck
200                    .getEncumbExpenseConstraintType())) {
201                amount = new KualiDecimal(oleSufficientFundCheck.getExpenseAmount());
202                if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_OVER.equals(oleSufficientFundCheck
203                        .getEncumbExpenseMethod())) {
204                    initialBudgetAmount = initialBudgetAmount.add(amount);
205                } else if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_UNDER.equals(oleSufficientFundCheck
206                        .getEncumbExpenseMethod())) {
207                    initialBudgetAmount = initialBudgetAmount.subtract(amount);
208                }
209            }
210        }
211        return initialBudgetAmount;
212    }
213
214    private KualiDecimal getBudgetAllocationForAccount(String chartCode, String accountNumber, String objectCode) {
215        Map budgetMap = new HashMap();
216        KualiDecimal initialBudgetAmount = KualiDecimal.ZERO;
217        UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class);
218        budgetMap.put("universityFiscalYear",
219                universityDateService.getCurrentUniversityDate().getUniversityFiscalYear());
220        budgetMap.put("chartOfAccountsCode", chartCode);
221        budgetMap.put("accountNumber", accountNumber);
222        budgetMap.put(OLEPropertyConstants.BALANCE_TYPE_CODE, OLEPropertyConstants.BAL_TYP_CODE);
223        List<Balance> balance = (List<Balance>) SpringContext.getBean(BusinessObjectService.class).findMatching(
224                Balance.class, budgetMap);
225        if (balance.size() > 0) {
226            for (Balance budgetBalance : balance) {
227                initialBudgetAmount = initialBudgetAmount.add(budgetBalance.getAccountLineAnnualBalanceAmount());
228            }
229        }
230        Map encMap = new HashMap();
231        encMap.put("chartOfAccountsCode", chartCode);
232        encMap.put("accountNumber", accountNumber);
233        OleSufficientFundCheck oleSufficientFundCheck = SpringContext.getBean(BusinessObjectService.class)
234                .findByPrimaryKey(OleSufficientFundCheck.class, encMap);
235        KualiDecimal amount = KualiDecimal.ZERO;
236        if (oleSufficientFundCheck != null) {
237            if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_TYP_PERCENTAGE.equals(oleSufficientFundCheck
238                    .getEncumbExpenseConstraintType())) {
239                amount = new KualiDecimal(oleSufficientFundCheck.getExpenseAmount());
240                if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_OVER.equals(oleSufficientFundCheck
241                        .getEncumbExpenseMethod())) {
242                    initialBudgetAmount = initialBudgetAmount.add((initialBudgetAmount.multiply(amount))
243                            .divide(new KualiDecimal(100)));
244                } else if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_UNDER.equals(oleSufficientFundCheck
245                        .getEncumbExpenseMethod())) {
246                    initialBudgetAmount = initialBudgetAmount.subtract((initialBudgetAmount.multiply(amount))
247                            .divide(new KualiDecimal(100)));
248
249                }
250            } else if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_TYP_CASH.equals(oleSufficientFundCheck
251                    .getEncumbExpenseConstraintType())) {
252                amount = new KualiDecimal(oleSufficientFundCheck.getExpenseAmount());
253                if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_OVER.equals(oleSufficientFundCheck
254                        .getEncumbExpenseMethod())) {
255                    initialBudgetAmount = initialBudgetAmount.add(amount);
256                } else if (OLEPropertyConstants.SUFFICIENT_FUND_ENC_UNDER.equals(oleSufficientFundCheck
257                        .getEncumbExpenseMethod())) {
258                    initialBudgetAmount = initialBudgetAmount.subtract(amount);
259                }
260            }
261        }
262        return initialBudgetAmount;
263    }
264
265
266}