001: /*
002: * Copyright 2006-2007 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: */
016: package org.kuali.module.financial.rules;
017:
018: import static org.kuali.kfs.rules.AccountingDocumentRuleBaseConstants.ERROR_PATH.DOCUMENT_ERROR_PREFIX;
019:
020: import org.apache.commons.lang.StringUtils;
021: import org.kuali.core.rule.event.ApproveDocumentEvent;
022: import org.kuali.core.util.GlobalVariables;
023: import org.kuali.core.util.KualiDecimal;
024: import org.kuali.kfs.KFSConstants;
025: import org.kuali.kfs.KFSKeyConstants;
026: import org.kuali.kfs.KFSPropertyConstants;
027: import org.kuali.kfs.KFSKeyConstants.CashReceipt;
028: import org.kuali.kfs.bo.AccountingLine;
029: import org.kuali.kfs.bo.GeneralLedgerPendingEntry;
030: import org.kuali.kfs.context.SpringContext;
031: import org.kuali.kfs.document.AccountingDocument;
032: import org.kuali.kfs.rules.AccountingDocumentRuleBase;
033: import org.kuali.module.financial.bo.CashDrawer;
034: import org.kuali.module.financial.document.CashReceiptFamilyBase;
035: import org.kuali.module.financial.service.CashDrawerService;
036: import org.kuali.module.financial.service.CashReceiptService;
037:
038: /**
039: * Business rule(s) shared amongst to CashReceipt-related documents.
040: */
041: public class CashReceiptFamilyRule extends AccountingDocumentRuleBase
042: implements CashReceiptDocumentRuleConstants {
043:
044: /**
045: * Cash Receipt documents allow both positive and negative values, so we only need to check for zero amounts.
046: *
047: * @param document submitted accounting document
048: * @param accountingLine accounting line in accounting doducment
049: * @return true if amount is non-zero
050: *
051: * @see org.kuali.core.rule.AccountingLineRule#isAmountValid(org.kuali.core.document.FinancialDocument,
052: * org.kuali.core.bo.AccountingLine)
053: */
054: @Override
055: public boolean isAmountValid(AccountingDocument document,
056: AccountingLine accountingLine) {
057: KualiDecimal amount = accountingLine.getAmount();
058:
059: if (KFSConstants.ZERO.compareTo(amount) == 0) { // amount == 0
060: GlobalVariables.getErrorMap().putError(
061: KFSConstants.AMOUNT_PROPERTY_NAME,
062: KFSKeyConstants.ERROR_ZERO_AMOUNT,
063: "an accounting line");
064: return false;
065: }
066:
067: return true;
068: }
069:
070: /**
071: * This overrides to call super, then to make sure that the cash drawer for the verification unit associated with this CR doc is
072: * open. If it's not, the the rule fails.
073: *
074: * @param approveEvent event fired when approving a document
075: * @return true if verification unit associated with cash receipt is open
076: *
077: * @see org.kuali.core.rule.DocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.core.rule.event.ApproveDocumentEvent)
078: */
079: @Override
080: protected boolean processCustomApproveDocumentBusinessRules(
081: ApproveDocumentEvent approveEvent) {
082: boolean valid = super
083: .processCustomApproveDocumentBusinessRules(approveEvent);
084:
085: if (valid) {
086: CashReceiptFamilyBase crd = (CashReceiptFamilyBase) approveEvent
087: .getDocument();
088:
089: String unitName = SpringContext.getBean(
090: CashReceiptService.class)
091: .getCashReceiptVerificationUnitForCampusCode(
092: crd.getCampusLocationCode());
093: CashDrawer cd = SpringContext.getBean(
094: CashDrawerService.class).getByWorkgroupName(
095: unitName, false);
096: if (cd == null) {
097: throw new IllegalStateException(
098: "There is no cash drawer associated with unitName '"
099: + unitName + "' from cash receipt "
100: + crd.getDocumentNumber());
101: } else if (cd.isClosed()) {
102: GlobalVariables
103: .getErrorMap()
104: .putError(
105: KFSConstants.GLOBAL_ERRORS,
106: KFSKeyConstants.CashReceipt.MSG_CASH_DRAWER_CLOSED_VERIFICATION_NOT_ALLOWED,
107: cd.getWorkgroupName());
108: valid = false;
109: }
110: }
111:
112: return valid;
113: }
114:
115: /**
116: * For Cash Receipt documents, the document is balanced if the sum total of checks and cash and coin equals the sum total of the
117: * accounting lines. In addition, the sum total of checks and cash and coin must be greater than zero.
118: *
119: * @param financialDocument submitted accounting document
120: * @return true if cash and check total matches the total of all the accounting lines and cash and check totals are greater than zero
121: *
122: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isDocumentBalanceValid(org.kuali.core.document.FinancialDocument)
123: */
124: @Override
125: protected boolean isDocumentBalanceValid(
126: AccountingDocument financialDocument) {
127: CashReceiptFamilyBase cr = (CashReceiptFamilyBase) financialDocument;
128:
129: // make sure that cash reconciliation total is greater than zero
130: boolean isValid = cr.getTotalDollarAmount().compareTo(
131: KFSConstants.ZERO) > 0;
132: if (!isValid) {
133: GlobalVariables
134: .getErrorMap()
135: .putError(
136: DOCUMENT_ERROR_PREFIX
137: + KFSPropertyConstants.SUM_TOTAL_AMOUNT,
138: KFSKeyConstants.CashReceipt.ERROR_DOCUMENT_CASH_RECEIPT_NO_CASH_RECONCILIATION_TOTAL);
139: }
140:
141: if (isValid) {
142: // make sure the document is in balance
143: isValid = cr.getSourceTotal().compareTo(
144: cr.getTotalDollarAmount()) == 0;
145:
146: if (!isValid) {
147: GlobalVariables
148: .getErrorMap()
149: .putError(
150: DOCUMENT_ERROR_PREFIX
151: + KFSPropertyConstants.SUM_TOTAL_AMOUNT,
152: KFSKeyConstants.CashReceipt.ERROR_DOCUMENT_CASH_RECEIPT_BALANCE);
153: }
154: }
155:
156: return isValid;
157: }
158:
159: /**
160: * Cash receipt documents do not utilize the target accounting line list. A CR doc is one sided, so this method should always
161: * return true.
162: *
163: * @param financialDocument submitted financial document
164: * @return true
165: *
166: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isTargetAccountingLinesRequiredNumberForRoutingMet(org.kuali.core.document.FinancialDocument)
167: */
168: @Override
169: protected boolean isTargetAccountingLinesRequiredNumberForRoutingMet(
170: AccountingDocument financialDocument) {
171: return true;
172: }
173:
174: /**
175: * Cash receipt documents need at least one accounting line. Had to override to supply a Cash Receipt specific method.
176: *
177: * @param financialDocument submitted financial document
178: * @return true if there is at least one accounting line
179: *
180: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isSourceAccountingLinesRequiredNumberForRoutingMet(org.kuali.core.document.FinancialDocument)
181: */
182: @Override
183: protected boolean isSourceAccountingLinesRequiredNumberForRoutingMet(
184: AccountingDocument financialDocument) {
185: if (0 == financialDocument.getSourceAccountingLines().size()) {
186: GlobalVariables
187: .getErrorMap()
188: .putError(
189: DOCUMENT_ERROR_PREFIX
190: + KFSPropertyConstants.SOURCE_ACCOUNTING_LINES,
191: KFSKeyConstants.ERROR_DOCUMENT_SINGLE_SECTION_NO_ACCOUNTING_LINES);
192: return false;
193: } else {
194: return true;
195: }
196: }
197:
198: /**
199: * Overrides to set the entry's description to the description from the accounting line, if a value exists.
200: *
201: * @param financialDocument submitted accounting document
202: * @param accountingLine accounting line in accounting document
203: * @param explicitEntry general ledger pending entry
204: *
205: * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.core.document.FinancialDocument,
206: * org.kuali.core.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
207: */
208: protected void customizeExplicitGeneralLedgerPendingEntry(
209: AccountingDocument financialDocument,
210: AccountingLine accountingLine,
211: GeneralLedgerPendingEntry explicitEntry) {
212: String accountingLineDescription = accountingLine
213: .getFinancialDocumentLineDescription();
214: if (StringUtils.isNotBlank(accountingLineDescription)) {
215: explicitEntry
216: .setTransactionLedgerEntryDescription(accountingLineDescription);
217: }
218: }
219:
220: /**
221: * Returns true if accounting line is debit
222: *
223: * @param financialDocument
224: * @param accountingLine
225: * @param true if accountline line
226: *
227: * @see IsDebitUtils#isDebitConsideringType(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
228: * @see org.kuali.core.rule.AccountingLineRule#isDebit(org.kuali.core.document.FinancialDocument,
229: * org.kuali.core.bo.AccountingLine)
230: */
231: public boolean isDebit(AccountingDocument financialDocument,
232: AccountingLine accountingLine) {
233: // error corrections are not allowed
234: IsDebitUtils.disallowErrorCorrectionDocumentCheck(this ,
235: financialDocument);
236: return IsDebitUtils.isDebitConsideringType(this ,
237: financialDocument, accountingLine);
238: }
239:
240: /**
241: * Return true if source total is non-zero
242: *
243: * @param crdoc cash receipt family base document
244: * @return true if the sum of the accountingLine values is non-zero
245: */
246: protected boolean validateAccountingLineTotal(
247: CashReceiptFamilyBase crdoc) {
248: boolean isValid = true;
249:
250: if (crdoc.getSourceTotal().isZero()) {
251: String errorProperty = DOCUMENT_ERROR_PREFIX
252: + KFSPropertyConstants.SOURCE_ACCOUNTING_LINES;
253:
254: isValid = false;
255: GlobalVariables.getErrorMap().putError(errorProperty,
256: CashReceipt.ERROR_ZERO_TOTAL,
257: "Accounting Line Total");
258: }
259:
260: return isValid;
261: }
262: }
|