001: /*
002: * Copyright 2005-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.KFSKeyConstants.ERROR_DOCUMENT_ACCOUNTING_LINE_INVALID_ACCT_OBJ_CD;
019:
020: import java.util.List;
021:
022: import org.apache.commons.lang.StringUtils;
023: import org.kuali.core.document.Document;
024: import org.kuali.core.service.DictionaryValidationService;
025: import org.kuali.core.util.GlobalVariables;
026: import org.kuali.core.workflow.service.KualiWorkflowDocument;
027: import org.kuali.kfs.KFSConstants;
028: import org.kuali.kfs.KFSKeyConstants;
029: import org.kuali.kfs.KFSPropertyConstants;
030: import org.kuali.kfs.bo.AccountingLine;
031: import org.kuali.kfs.context.SpringContext;
032: import org.kuali.kfs.document.AccountingDocument;
033: import org.kuali.kfs.service.ParameterEvaluator;
034: import org.kuali.kfs.service.ParameterService;
035: import org.kuali.kfs.service.impl.ParameterConstants;
036: import org.kuali.module.financial.bo.Check;
037: import org.kuali.module.financial.document.CashReceiptDocument;
038: import org.kuali.module.financial.document.CashReceiptFamilyBase;
039: import org.kuali.module.financial.rule.AddCheckRule;
040: import org.kuali.module.financial.rule.DeleteCheckRule;
041: import org.kuali.module.financial.rule.UpdateCheckRule;
042:
043: /**
044: * Business rule(s) applicable to CashReceipt documents.
045: */
046: public class CashReceiptDocumentRule extends CashReceiptFamilyRule
047: implements AddCheckRule, DeleteCheckRule, UpdateCheckRule {
048: /**
049: * Implements Cash Receipt specific rule checks for the cash reconciliation section, to make sure that the cash, check, and coin
050: * totals are not negative.
051: *
052: * @param document submitted cash receipt document
053: * @return true if cash, check, and coin totals are not negative
054: *
055: * @see org.kuali.core.rule.DocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.core.document.Document)
056: */
057: @Override
058: protected boolean processCustomSaveDocumentBusinessRules(
059: Document document) {
060: boolean isValid = super
061: .processCustomSaveDocumentBusinessRules(document);
062:
063: if (isValid) {
064: isValid &= validateAccountingLineTotal((CashReceiptFamilyBase) document);
065: isValid &= !CashReceiptDocumentRuleUtil
066: .areCashTotalsInvalid((CashReceiptDocument) document);
067: isValid &= validateAccountAndObjectCodeAllLines((CashReceiptFamilyBase) document);
068: }
069:
070: return isValid;
071: }
072:
073: /**
074: * Returns true if account and object code are valid in an accounting line.
075: *
076: * @param financialDocument submitted accounting document
077: * @param accountingLine
078: * @return true if account and object code are valid in an accounting line.
079: *
080: * @see org.kuali.kfs.rules.AccountingDocumentRuleBase#processCustomAddAccountingLineBusinessRules(org.kuali.kfs.document.AccountingDocument,
081: * org.kuali.kfs.bo.AccountingLine)
082: */
083: @Override
084: protected boolean processCustomAddAccountingLineBusinessRules(
085: AccountingDocument financialDocument,
086: AccountingLine accountingLine) {
087: boolean isValid = true;
088: isValid &= validateAccountAndObjectCode(accountingLine,
089: accountingLine.isSourceAccountingLine(), true, 0);
090: return isValid;
091: }
092:
093: /**
094: * Checks to make sure that the check passed in passes all data dictionary validation and that the amount is positive.
095: *
096: * @param financialDocument submitted financial document
097: * @param check check added to cash receipt document
098: * @return true if check is valid (i.e. non-zero and not negative)
099: *
100: * @see org.kuali.core.rule.AddCheckRule#processAddCheckBusinessRules(org.kuali.core.document.FinancialDocument,
101: * org.kuali.module.financial.bo.Check)
102: */
103: public boolean processAddCheckBusinessRules(
104: AccountingDocument financialDocument, Check check) {
105: boolean isValid = validateCheck(check);
106:
107: return isValid;
108: }
109:
110: /**
111: * Default implementation does nothing now.
112: *
113: * @param financialDocument submitted financial document
114: * @param check check deleted from cash receipt document
115: * @return true
116: *
117: * @see org.kuali.core.rule.DeleteCheckRule#processDeleteCheckBusinessRules(org.kuali.core.document.FinancialDocument,
118: * org.kuali.module.financial.bo.Check)
119: */
120: public boolean processDeleteCheckBusinessRules(
121: AccountingDocument financialDocument, Check check) {
122: boolean processed = true;
123:
124: return processed;
125: }
126:
127: /**
128: * Checks to make sure that the check passed in passes all data dictionary validation and that the amount is positive.
129: *
130: * @param financialDocument submitted financial document
131: * @param check check updated from cash receipt document
132: * @return true if updated check is valid (i.e. non-zero and not negative)
133: *
134: * @see org.kuali.core.rule.UpdateCheckRule#processUpdateCheckRule(org.kuali.core.document.FinancialDocument,
135: * org.kuali.module.financial.bo.Check)
136: */
137: public boolean processUpdateCheckRule(
138: AccountingDocument financialDocument, Check check) {
139: boolean isValid = validateCheck(check);
140:
141: return isValid;
142: }
143:
144: /**
145: * This method validates checks for a CR document.
146: *
147: * @param check validated check
148: * @return true if check is non-zero and not negative
149: */
150: private boolean validateCheck(Check check) {
151: // validate the specific check coming in
152: SpringContext.getBean(DictionaryValidationService.class)
153: .validateBusinessObject(check);
154:
155: boolean isValid = GlobalVariables.getErrorMap().isEmpty();
156:
157: // check to make sure the amount is also valid
158: if (check.getAmount().isZero()) {
159: GlobalVariables
160: .getErrorMap()
161: .putError(
162: KFSPropertyConstants.CHECK_AMOUNT,
163: KFSKeyConstants.CashReceipt.ERROR_ZERO_CHECK_AMOUNT,
164: KFSPropertyConstants.CHECKS);
165: isValid = false;
166: } else if (check.getAmount().isNegative()) {
167: GlobalVariables
168: .getErrorMap()
169: .putError(
170: KFSPropertyConstants.CHECK_AMOUNT,
171: KFSKeyConstants.CashReceipt.ERROR_NEGATIVE_CHECK_AMOUNT,
172: KFSPropertyConstants.CHECKS);
173: isValid = false;
174: }
175:
176: return isValid;
177: }
178:
179: /**
180: * Method used by <code>{@link org.kuali.module.financial.service.CashReceiptCoverSheetService}</code> to determine of the
181: * <code>{@link CashReceiptDocument}</code> validates business rules for generating a cover page. <br/> <br/> Rule is the
182: * <code>{@link Document}</code> must be ENROUTE.
183: *
184: * @param document submitted cash receipt document
185: * @return true if state is not cancelled, initiated, disapproved, saved, or exception
186: */
187: public boolean isCoverSheetPrintable(CashReceiptFamilyBase document) {
188: KualiWorkflowDocument workflowDocument = document
189: .getDocumentHeader().getWorkflowDocument();
190: return !(workflowDocument.stateIsCanceled()
191: || workflowDocument.stateIsInitiated()
192: || workflowDocument.stateIsDisapproved()
193: || workflowDocument.stateIsException()
194: || workflowDocument.stateIsDisapproved() || workflowDocument
195: .stateIsSaved());
196: }
197:
198: /**
199: * This method validates all the accounting lines for the right account/object code pairings, if the account is a sales tax
200: * account
201: *
202: * @param document submitted cash receipt document
203: * @return true if all accounting lines have valid account and object codes
204: */
205: private boolean validateAccountAndObjectCodeAllLines(
206: AccountingDocument document) {
207: boolean isValid = true;
208: List<AccountingLine> sourceLines = document
209: .getSourceAccountingLines();
210: List<AccountingLine> targetLines = document
211: .getTargetAccountingLines();
212: int index = 0;
213: for (AccountingLine accountingLine : sourceLines) {
214: boolean source = false;
215: source = accountingLine.isSourceAccountingLine();
216: validateAccountAndObjectCode(accountingLine, source, false,
217: index);
218: index++;
219: }
220:
221: return isValid;
222: }
223:
224: /**
225: * This method processes the accounting line to make sure if a sales tax account is used the right object code is used with it
226: *
227: * @param accountingLine accounting line from accounting document
228: * @param source true if accounting line is a source line
229: * @param newLine true if new line
230: * @param index index of accounting line
231: * @return true if accounting line has a non-empty sales tax account account and a corresponding non-empty object code
232: */
233: private boolean validateAccountAndObjectCode(
234: AccountingLine accountingLine, boolean source,
235: boolean newLine, int index) {
236: boolean isValid = true;
237: // not evaluating, just want to retrieve the evaluator to get the values of the parameter
238: // get the object code and account
239: String objCd = accountingLine.getFinancialObjectCode();
240: String account = accountingLine.getAccountNumber();
241: if (!StringUtils.isEmpty(objCd)
242: && !StringUtils.isEmpty(account)) {
243: String[] params = SpringContext
244: .getBean(ParameterService.class)
245: .getParameterValues(
246: ParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class,
247: APPLICATION_PARAMETER.SALES_TAX_APPLICABLE_ACCOUNTS_AND_OBJECT_CODES)
248: .toArray(new String[] {});
249: boolean acctsMatched = false;
250: for (int i = 0; i < params.length; i++) {
251: String paramAcct = params[i].split(":")[0];
252: if (account.equalsIgnoreCase(paramAcct)) {
253: acctsMatched = true;
254: }
255: }
256: if (acctsMatched) {
257: String compare = account + ":" + objCd;
258: ParameterEvaluator evaluator = SpringContext
259: .getBean(ParameterService.class)
260: .getParameterEvaluator(
261: ParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class,
262: APPLICATION_PARAMETER.SALES_TAX_APPLICABLE_ACCOUNTS_AND_OBJECT_CODES,
263: compare);
264: if (!evaluator.evaluationSucceeds()) {
265: isValid = false;
266: }
267: }
268:
269: }
270: if (!isValid) {
271: String pathPrefix = "";
272: if (source && !newLine) {
273: pathPrefix = "document."
274: + KFSConstants.EXISTING_SOURCE_ACCT_LINE_PROPERTY_NAME
275: + "[" + index + "]";
276: } else if (!source && !newLine) {
277: pathPrefix = "document."
278: + KFSConstants.EXISTING_TARGET_ACCT_LINE_PROPERTY_NAME
279: + "[" + index + "]";
280: } else if (source && newLine) {
281: pathPrefix = KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME;
282: } else if (!source && newLine) {
283: pathPrefix = KFSConstants.NEW_TARGET_ACCT_LINE_PROPERTY_NAME;
284: }
285: GlobalVariables.getErrorMap().addToErrorPath(pathPrefix);
286:
287: GlobalVariables.getErrorMap().putError("accountNumber",
288: ERROR_DOCUMENT_ACCOUNTING_LINE_INVALID_ACCT_OBJ_CD,
289: account, objCd);
290:
291: GlobalVariables.getErrorMap().removeFromErrorPath(
292: pathPrefix);
293: }
294: return isValid;
295: }
296: }
|