/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.fp.document; import java.util.ArrayList; import java.util.List; import org.kuali.kfs.fp.businessobject.CreditCardDetail; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.KFSParameterKeyConstants; import org.kuali.kfs.sys.businessobject.Bank; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.AmountTotaling; import org.kuali.kfs.sys.document.Correctable; import org.kuali.kfs.sys.document.service.AccountingDocumentRuleHelperService; import org.kuali.kfs.sys.service.BankService; import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.core.web.format.CurrencyFormatter; import org.kuali.rice.kew.api.exception.WorkflowException; import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange; import org.kuali.rice.kns.service.DataDictionaryService; import org.kuali.rice.krad.document.Copyable; import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent; import org.kuali.rice.krad.rules.rule.event.SaveDocumentEvent; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; /** * This is the business object that represents the CreditCardReceipt document in Kuali. This is a transactional document that will * eventually post transactions to the G/L. It integrates with workflow. Since a Credit Card Receipt is a one sided transactional * document, only accepting funds into the university, the accounting line data will be held in the source accounting line data * structure only. */ public class CreditCardReceiptDocument extends CashReceiptFamilyBase implements Copyable, AmountTotaling, Correctable { public static final String CREDIT_CARD_RECEIPT_DOCUMENT_TYPE_CODE = "CCR"; // holds details about each credit card receipt protected List<CreditCardDetail> creditCardReceipts = new ArrayList<CreditCardDetail>(); // incrementers for detail lines protected Integer nextCcCrLineNumber = new Integer(1); // monetary attributes protected KualiDecimal totalCreditCardAmount = KualiDecimal.ZERO; protected String creditCardReceiptBankCode; protected Bank bank; /** * Default constructor that calls super. */ public CreditCardReceiptDocument() { super(); bank = new Bank(); } /** * Sets the bank code for a new document to the setup default for the Non Check Disbursement document. */ public void setDefaultBankCode() { Bank defaultBank = SpringContext.getBean(BankService.class).getDefaultBankByDocType(this.getClass()); if (defaultBank != null) { this.creditCardReceiptBankCode = defaultBank.getBankCode(); this.bank = defaultBank; } } @Override public boolean documentPerformsSufficientFundsCheck() { return false; } /** * Gets the total credit card amount. * * @return KualiDecimal */ public KualiDecimal getTotalCreditCardAmount() { return totalCreditCardAmount; } /** * This method returns the credit card total amount as a currency formatted string. * * @return String */ public String getCurrencyFormattedTotalCreditCardAmount() { return (String) new CurrencyFormatter().format(totalCreditCardAmount); } /** * Sets the total credit card amount which is the sum of all credit card receipts on this document. * * @param creditCardAmount */ public void setTotalCreditCardAmount(KualiDecimal creditCardAmount) { this.totalCreditCardAmount = creditCardAmount; } /** * Gets the list of credit card receipts which is a list of CreditCardDetail business objects. * * @return List */ public List<CreditCardDetail> getCreditCardReceipts() { return creditCardReceipts; } /** * Sets the credit card receipts list. * * @param creditCardReceipts */ public void setCreditCardReceipts(List<CreditCardDetail> creditCardReceipts) { this.creditCardReceipts = creditCardReceipts; } /** * Adds a new credit card receipt to the list. * * @param creditCardReceiptDetail */ public void addCreditCardReceipt(CreditCardDetail creditCardReceiptDetail) { // these three make up the primary key for a credit card detail record prepareNewCreditCardReceipt(creditCardReceiptDetail); // add the new detail record to the list this.creditCardReceipts.add(creditCardReceiptDetail); // increment line number this.nextCcCrLineNumber = new Integer(this.nextCcCrLineNumber.intValue() + 1); // update the overall amount this.totalCreditCardAmount = this.totalCreditCardAmount.add(creditCardReceiptDetail.getCreditCardAdvanceDepositAmount()); } /** * This is a helper method that automatically populates document specfic information into the credit card receipt * (CreditCardDetail) instance. * * @param creditCardReceiptDetail */ public final void prepareNewCreditCardReceipt(CreditCardDetail creditCardReceiptDetail) { creditCardReceiptDetail.setFinancialDocumentLineNumber(this.nextCcCrLineNumber); creditCardReceiptDetail.setDocumentNumber(this.getDocumentNumber()); creditCardReceiptDetail.setFinancialDocumentTypeCode(SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass())); } /** * Retrieve a particular credit card receipt at a given index in the list of credit card receipts. * * @param index * @return CreditCardReceiptDetail */ public CreditCardDetail getCreditCardReceipt(int index) { while (this.creditCardReceipts.size() <= index) { creditCardReceipts.add(new CreditCardDetail()); } return creditCardReceipts.get(index); } /** * This method removes a credit card receipt from the list and updates the total appropriately. * * @param index */ public void removeCreditCardReceipt(int index) { CreditCardDetail creditCardReceiptDetail = creditCardReceipts.remove(index); this.totalCreditCardAmount = this.totalCreditCardAmount.subtract(creditCardReceiptDetail.getCreditCardAdvanceDepositAmount()); } /** * @return Integer */ public Integer getNextCcCrLineNumber() { return nextCcCrLineNumber; } /** * @param nextCcCrLineNumber */ public void setNextCcCrLineNumber(Integer nextCcCrLineNumber) { this.nextCcCrLineNumber = nextCcCrLineNumber; } /** * This method returns the overall total of the document - the credit card total. * * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getTotalDollarAmount() * @return KualiDecimal */ @Override public KualiDecimal getTotalDollarAmount() { return this.totalCreditCardAmount; } /** * This method returns the sum of all of the credit card receipts for this document. * * @return KualiDecimal */ public KualiDecimal calculateCreditCardReceiptTotal() { KualiDecimal total = KualiDecimal.ZERO; for (CreditCardDetail detail : getCreditCardReceipts()) { if (null != detail.getCreditCardAdvanceDepositAmount()) { total = total.add(detail.getCreditCardAdvanceDepositAmount()); } } return total; } /** * Overrides super to call super and then also add in the new list of credit card receipts that have to be managed. * * @see org.kuali.rice.krad.document.TransactionalDocumentBase#buildListOfDeletionAwareLists() */ @Override public List buildListOfDeletionAwareLists() { List managedLists = super.buildListOfDeletionAwareLists(); managedLists.add(getCreditCardReceipts()); return managedLists; } /** * Generates bank offset GLPEs for deposits, if enabled. * * @param financialDocument submitted accounting document * @param sequenceHelper helper class for keep track of sequence for GLPEs * @return true if generation of GLPE's is successful for credit card receipt document * * @see org.kuali.rice.krad.rule.GenerateGeneralLedgerDocumentPendingEntriesRule#processGenerateDocumentGeneralLedgerPendingEntries(org.kuali.rice.krad.document.FinancialDocument,org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper) */ @Override public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) { boolean success = true; GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class); if (SpringContext.getBean(BankService.class).isBankSpecificationEnabled()) { final KualiDecimal bankOffsetAmount = glpeService.getOffsetToCashAmount(this).negated(); GeneralLedgerPendingEntry bankOffsetEntry = new GeneralLedgerPendingEntry(); Bank offsetBank = getOffsetBank(); if (ObjectUtils.isNull(offsetBank)) { success = false; GlobalVariables.getMessageMap().putError("newCreditCardReceipt.financialDocumentCreditCardTypeCode", KFSKeyConstants.CreditCardReceipt.ERROR_DOCUMENT_CREDIT_CARD_BANK_MUST_EXIST_WHEN_BANK_ENHANCEMENT_ENABLED, new String[] { KFSParameterKeyConstants.ENABLE_BANK_SPECIFICATION_IND, KFSParameterKeyConstants.DEFAULT_BANK_BY_DOCUMENT_TYPE }); } else { success &= glpeService.populateBankOffsetGeneralLedgerPendingEntry(offsetBank, bankOffsetAmount, this, getPostingYear(), sequenceHelper, bankOffsetEntry, KFSConstants.CREDIT_CARD_RECEIPTS_LINE_ERRORS); // An unsuccessfully populated bank offset entry may contain invalid relations, so don't add it if (success) { AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class); bankOffsetEntry.setTransactionLedgerEntryDescription(accountingDocumentRuleUtil.formatProperty(KFSKeyConstants.Bank.DESCRIPTION_GLPE_BANK_OFFSET)); getGeneralLedgerPendingEntries().add(bankOffsetEntry); sequenceHelper.increment(); GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(bankOffsetEntry); success &= glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), bankOffsetEntry, sequenceHelper, offsetEntry); getGeneralLedgerPendingEntries().add(offsetEntry); sequenceHelper.increment(); } } } return success; } /** * Assigns default bank code */ public void initiateDocument() { // default bank code Bank defaultBank = SpringContext.getBean(BankService.class).getDefaultBankByDocType(this.getClass()); if (defaultBank != null) { this.creditCardReceiptBankCode = defaultBank.getBankCode(); this.bank = defaultBank; } } /** * Returns the default bank code for Credit Card Receipt documents. */ protected Bank getOffsetBank() { return SpringContext.getBean(BankService.class).getByPrimaryId(creditCardReceiptBankCode); } /** * Gets the creditCardReceiptBankCode attribute. * @return Returns the creditCardReceiptBankCode. */ public String getCreditCardReceiptBankCode() { return creditCardReceiptBankCode; } /** * Sets the creditCardReceiptBankCode attribute value. * @param creditCardReceiptBankCode The creditCardReceiptBankCode to set. */ public void setCreditCardReceiptBankCode(String creditCardReceiptBankCode) { this.creditCardReceiptBankCode = creditCardReceiptBankCode; } /** * Gets the bank attribute. * @return Returns the bank. */ public Bank getBank() { return bank; } /** * Sets the bank attribute value. * @param bank The bank to set. */ public void setBank(Bank bank) { this.bank = bank; } @Override public void postProcessSave(KualiDocumentEvent event) { super.postProcessSave(event); if (!(event instanceof SaveDocumentEvent)) { // don't lock until they route String documentTypeName = SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass()); this.getCapitalAssetManagementModuleService().generateCapitalAssetLock(this,documentTypeName); } } @Override public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) { super.doRouteStatusChange(statusChangeEvent); this.getCapitalAssetManagementModuleService().deleteDocumentAssetLocks(this); } /** * @see org.kuali.kfs.sys.document.AccountingDocumentBase#toErrorCorrection() */ @Override public void toErrorCorrection() throws WorkflowException { super.toErrorCorrection(); correctCreditCardReceipts(); correctCapitalAccountingLines(); } /** * Upon error correction, negates amount in each credit card receipt, and updates the documentNumber to point to the new document. */ protected void correctCreditCardReceipts() { for (CreditCardDetail receipt: creditCardReceipts) { receipt.setVersionNumber(new Long(1)); receipt.setDocumentNumber(documentNumber); receipt.setCreditCardAdvanceDepositAmount(receipt.getCreditCardAdvanceDepositAmount().negated()); } } }