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 java.text.MessageFormat;
019: import java.util.List;
020:
021: import org.apache.commons.lang.StringUtils;
022: import org.kuali.core.document.Document;
023: import org.kuali.core.rules.PreRulesContinuationBase;
024: import org.kuali.core.service.KualiConfigurationService;
025: import org.kuali.core.util.ObjectUtils;
026: import org.kuali.core.web.ui.KeyLabelPair;
027: import org.kuali.kfs.KFSConstants;
028: import org.kuali.kfs.KFSKeyConstants;
029: import org.kuali.kfs.context.SpringContext;
030: import org.kuali.kfs.service.ParameterEvaluator;
031: import org.kuali.kfs.service.ParameterService;
032: import org.kuali.module.financial.bo.DisbursementVoucherNonEmployeeTravel;
033: import org.kuali.module.financial.bo.DisbursementVoucherWireTransfer;
034: import org.kuali.module.financial.document.DisbursementVoucherDocument;
035: import org.kuali.module.financial.lookup.keyvalues.PaymentReasonValuesFinder;
036:
037: /**
038: * Checks warnings and prompt conditions for dv document.
039: */
040: public class DisbursementVoucherDocumentPreRules extends
041: PreRulesContinuationBase implements
042: DisbursementVoucherRuleConstants {
043: private KualiConfigurationService kualiConfiguration;
044:
045: /**
046: * Executes pre-rules for Disbursement Voucher Document
047: *
048: * @param document submitted document
049: * @return true if pre-rules execute successfully
050: *
051: * @see org.kuali.core.rules.PreRulesContinuationBase#doRules(org.kuali.core.document.MaintenanceDocument)
052: */
053: public boolean doRules(Document document) {
054: boolean preRulesOK = true;
055:
056: DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) document;
057: checkSpecialHandlingIndicator(dvDocument);
058:
059: preRulesOK &= checkNonEmployeeTravelTabState(dvDocument);
060:
061: preRulesOK &= checkWireTransferTabState(dvDocument);
062:
063: preRulesOK &= checkForeignDraftTabState(dvDocument);
064:
065: return preRulesOK;
066: }
067:
068: /**
069: * If the special handling name and address 1 fields have value, this will mark the special handling indicator for the user.
070: *
071: * @param dvDocument submitted disbursement voucher document
072: */
073: private void checkSpecialHandlingIndicator(
074: DisbursementVoucherDocument dvDocument) {
075: if (StringUtils.isNotBlank(dvDocument.getDvPayeeDetail()
076: .getDisbVchrRemitPersonName())
077: && StringUtils.isNotBlank(dvDocument.getDvPayeeDetail()
078: .getDisbVchrRemitLine1Addr())) {
079: dvDocument.setDisbVchrSpecialHandlingCode(true);
080: }
081: }
082:
083: /**
084: * This method checks non-employee travel tab state is valid
085: *
086: * @param dvDocument submitted disbursement voucher document
087: * @return true if the state of all the tabs is valid, false otherwise.
088: */
089: private boolean checkNonEmployeeTravelTabState(
090: DisbursementVoucherDocument dvDocument) {
091: boolean tabStatesOK = true;
092:
093: DisbursementVoucherNonEmployeeTravel dvNonEmplTrav = dvDocument
094: .getDvNonEmployeeTravel();
095:
096: String paymentReasonCode = dvDocument.getDvPayeeDetail()
097: .getDisbVchrPaymentReasonCode();
098: ParameterEvaluator travelNonEmplPaymentReasonEvaluator = SpringContext
099: .getBean(ParameterService.class).getParameterEvaluator(
100: DisbursementVoucherDocument.class,
101: NONEMPLOYEE_TRAVEL_PAY_REASONS_PARM_NM,
102: paymentReasonCode);
103: if (hasNonEmployeeTravelValues(dvNonEmplTrav)
104: && !travelNonEmplPaymentReasonEvaluator
105: .evaluationSucceeds()) {
106: String questionText = SpringContext.getBean(
107: KualiConfigurationService.class).getPropertyString(
108: KFSKeyConstants.QUESTION_CLEAR_UNNEEDED_TAB);
109:
110: PaymentReasonValuesFinder payReasonValues = new PaymentReasonValuesFinder();
111: List<KeyLabelPair> reasons = payReasonValues.getKeyValues();
112: String nonEmplTravReasonStr = dvDocument.getDvPayeeDetail()
113: .getDisbVchrPaymentReasonCode();
114:
115: List<String> travelNonEmplPaymentReasonCodes = SpringContext
116: .getBean(ParameterService.class)
117: .getParameterValues(
118: DisbursementVoucherDocument.class,
119: NONEMPLOYEE_TRAVEL_PAY_REASONS_PARM_NM,
120: paymentReasonCode);
121:
122: for (KeyLabelPair r : reasons) {
123: // TODO: warren: what if there are multiple codes?, I think this code's under the assumption that there's only one
124: // non-employee travel payment reason
125: if (r.getKey().equals(
126: travelNonEmplPaymentReasonCodes.get(0))) {
127: nonEmplTravReasonStr = r.getLabel();
128: }
129: }
130:
131: Object[] args = {
132: "payment reason",
133: "'"
134: + dvDocument.getDvPayeeDetail()
135: .getDisbVchrPaymentReasonName()
136: + "'", "Non-Employee Travel",
137: "'" + nonEmplTravReasonStr + "'" };
138: questionText = MessageFormat.format(questionText, args);
139:
140: boolean clearTab = super
141: .askOrAnalyzeYesNoQuestion(
142: KFSConstants.DisbursementVoucherDocumentConstants.CLEAR_NON_EMPLOYEE_TAB_QUESTION_ID,
143: questionText);
144: if (clearTab) {
145: DisbursementVoucherNonEmployeeTravel blankDvNonEmplTrav = new DisbursementVoucherNonEmployeeTravel();
146: blankDvNonEmplTrav.setDocumentNumber(dvNonEmplTrav
147: .getDocumentNumber());
148: blankDvNonEmplTrav.setVersionNumber(dvNonEmplTrav
149: .getVersionNumber());
150: dvDocument.setDvNonEmployeeTravel(blankDvNonEmplTrav);
151: } else {
152: // return to document if the user doesn't want to clear the Non Employee Travel tab
153: super .event
154: .setActionForwardName(KFSConstants.MAPPING_BASIC);
155: tabStatesOK = false;
156: }
157: }
158:
159: return tabStatesOK;
160: }
161:
162: /**
163: * Returns true if non-employee travel tab contains any data in any of its fields
164: *
165: * @param dvNonEmplTrav disbursement voucher non employee travel object
166: * @return True if non employee travel tab contains any data in any fields.
167: */
168: private boolean hasNonEmployeeTravelValues(
169: DisbursementVoucherNonEmployeeTravel dvNonEmplTrav) {
170: boolean hasValues = false;
171:
172: // Checks each explicit field in the tab for user entered values
173: hasValues = hasNonEmployeeTravelGeneralValues(dvNonEmplTrav);
174:
175: // Checks per diem section for values
176: if (!hasValues) {
177: hasValues = hasNonEmployeeTravelPerDiemValues(dvNonEmplTrav);
178: }
179:
180: if (!hasValues) {
181: hasValues = hasNonEmployeeTravelPersonalVehicleValues(dvNonEmplTrav);
182: }
183:
184: if (!hasValues) {
185: hasValues = dvNonEmplTrav.getDvNonEmployeeExpenses().size() > 0;
186: }
187:
188: if (!hasValues) {
189: hasValues = dvNonEmplTrav.getDvPrePaidEmployeeExpenses()
190: .size() > 0;
191: }
192:
193: return hasValues;
194: }
195:
196: /**
197: * Returns true if any values are not blank on non employee travel tab
198: *
199: * @param dvNonEmplTrav disbursement voucher non employee travel object
200: * @return True if any values are found in the non employee travel tab
201: */
202: private boolean hasNonEmployeeTravelGeneralValues(
203: DisbursementVoucherNonEmployeeTravel dvNonEmplTrav) {
204: return StringUtils.isNotBlank(dvNonEmplTrav
205: .getDisbVchrNonEmpTravelerName())
206: || StringUtils.isNotBlank(dvNonEmplTrav
207: .getDisbVchrServicePerformedDesc())
208: || StringUtils.isNotBlank(dvNonEmplTrav
209: .getDvServicePerformedLocName())
210: || StringUtils.isNotBlank(dvNonEmplTrav
211: .getDvServiceRegularEmprName())
212: || StringUtils.isNotBlank(dvNonEmplTrav
213: .getDisbVchrTravelFromCityName())
214: || StringUtils.isNotBlank(dvNonEmplTrav
215: .getDisbVchrTravelFromStateCode())
216: || StringUtils.isNotBlank(dvNonEmplTrav
217: .getDvTravelFromCountryCode())
218: || ObjectUtils.isNotNull(dvNonEmplTrav
219: .getDvPerdiemStartDttmStamp())
220: || StringUtils.isNotBlank(dvNonEmplTrav
221: .getDisbVchrTravelToCityName())
222: || StringUtils.isNotBlank(dvNonEmplTrav
223: .getDisbVchrTravelToStateCode())
224: || StringUtils.isNotBlank(dvNonEmplTrav
225: .getDisbVchrTravelToCountryCode())
226: || ObjectUtils.isNotNull(dvNonEmplTrav
227: .getDvPerdiemEndDttmStamp());
228: }
229:
230: /**
231: * Returns true if non employee travel tab contains data in any of the fields in the per diem section
232: *
233: * @param dvNonEmplTrav disbursement voucher non employee travel object
234: * @return True if non employee travel tab contains data in any of the fields in the per diem section
235: */
236: private boolean hasNonEmployeeTravelPerDiemValues(
237: DisbursementVoucherNonEmployeeTravel dvNonEmplTrav) {
238: return StringUtils.isNotBlank(dvNonEmplTrav
239: .getDisbVchrPerdiemCategoryName())
240: || ObjectUtils.isNotNull(dvNonEmplTrav
241: .getDisbVchrPerdiemRate())
242: || ObjectUtils.isNotNull(dvNonEmplTrav
243: .getDisbVchrPerdiemCalculatedAmt())
244: || ObjectUtils.isNotNull(dvNonEmplTrav
245: .getDisbVchrPerdiemActualAmount())
246: || StringUtils.isNotBlank(dvNonEmplTrav
247: .getDvPerdiemChangeReasonText());
248: }
249:
250: /**
251: * Returns true if non employee travel tab contains data in any of the fields in the personal vehicle section
252: *
253: * @param dvNonEmplTrav disbursement voucher non employee travel object
254: * @return True if non employee travel tab contains data in any of the fields in the personal vehicle section
255: */
256: private boolean hasNonEmployeeTravelPersonalVehicleValues(
257: DisbursementVoucherNonEmployeeTravel dvNonEmplTrav) {
258: return StringUtils.isNotBlank(dvNonEmplTrav
259: .getDisbVchrAutoFromCityName())
260: || StringUtils.isNotBlank(dvNonEmplTrav
261: .getDisbVchrAutoFromStateCode())
262: || StringUtils.isNotBlank(dvNonEmplTrav
263: .getDisbVchrAutoToCityName())
264: || StringUtils.isNotBlank(dvNonEmplTrav
265: .getDisbVchrAutoToStateCode())
266: || ObjectUtils.isNotNull(dvNonEmplTrav
267: .getDisbVchrMileageCalculatedAmt())
268: || ObjectUtils.isNotNull(dvNonEmplTrav
269: .getDisbVchrPersonalCarAmount());
270: }
271:
272: /**
273: * Returns true if the state of all the tabs is valid, false otherwise.
274: *
275: * @param dvDocument submitted disbursemtn voucher document
276: * @return true if the state of all the tabs is valid, false otherwise.
277: */
278: private boolean checkForeignDraftTabState(
279: DisbursementVoucherDocument dvDocument) {
280: boolean tabStatesOK = true;
281:
282: DisbursementVoucherWireTransfer dvForeignDraft = dvDocument
283: .getDvWireTransfer();
284:
285: // if payment method is CHECK and wire tab contains data, ask user to clear tab
286: if ((StringUtils.equals(
287: DisbursementVoucherRuleConstants.PAYMENT_METHOD_CHECK,
288: dvDocument.getDisbVchrPaymentMethodCode()) || StringUtils
289: .equals(
290: DisbursementVoucherRuleConstants.PAYMENT_METHOD_WIRE,
291: dvDocument.getDisbVchrPaymentMethodCode()))
292: && hasForeignDraftValues(dvForeignDraft)) {
293: String questionText = SpringContext.getBean(
294: KualiConfigurationService.class).getPropertyString(
295: KFSKeyConstants.QUESTION_CLEAR_UNNEEDED_TAB);
296:
297: Object[] args = {
298: "payment method",
299: dvDocument.getDisbVchrPaymentMethodCode(),
300: "Foreign Draft",
301: DisbursementVoucherRuleConstants.PAYMENT_METHOD_DRAFT };
302: questionText = MessageFormat.format(questionText, args);
303:
304: boolean clearTab = super
305: .askOrAnalyzeYesNoQuestion(
306: KFSConstants.DisbursementVoucherDocumentConstants.CLEAR_FOREIGN_DRAFT_TAB_QUESTION_ID,
307: questionText);
308: if (clearTab) {
309: // NOTE: Can't replace with new instance because Wire Transfer uses same object
310: clearForeignDraftValues(dvForeignDraft);
311: } else {
312: // return to document if the user doesn't want to clear the Wire Transfer tab
313: super .event
314: .setActionForwardName(KFSConstants.MAPPING_BASIC);
315: tabStatesOK = false;
316: }
317: }
318:
319: return tabStatesOK;
320: }
321:
322: /**
323: * Returns true if foreign draft tab contains any data in any fields.
324: * NOTE: Currently does not validate based on only required fields. Checks all fields within tab for data.
325: *
326: * @param dvForeignDraft disbursement foreign draft object
327: * @return True if foreign draft tab contains any data in any fields.
328: */
329: private boolean hasForeignDraftValues(
330: DisbursementVoucherWireTransfer dvForeignDraft) {
331: boolean hasValues = false;
332:
333: // Checks each explicit field in the tab for user entered values
334: hasValues |= StringUtils.isNotBlank(dvForeignDraft
335: .getDisbursementVoucherForeignCurrencyTypeCode());
336: hasValues |= StringUtils.isNotBlank(dvForeignDraft
337: .getDisbursementVoucherForeignCurrencyTypeName());
338:
339: return hasValues;
340: }
341:
342: /**
343: * This method sets foreign currency type code and name to null for passed in disbursement foreign draft object
344: *
345: * @param dvForeignDraft disbursement foreign draft object
346: */
347: private void clearForeignDraftValues(
348: DisbursementVoucherWireTransfer dvForeignDraft) {
349: dvForeignDraft
350: .setDisbursementVoucherForeignCurrencyTypeCode(null);
351: dvForeignDraft
352: .setDisbursementVoucherForeignCurrencyTypeName(null);
353: }
354:
355: /**
356: * This method returns true if the state of all the tabs is valid, false otherwise.
357: *
358: * @param dvDocument submitted disbursement voucher document
359: * @return Returns true if the state of all the tabs is valid, false otherwise.
360: */
361: private boolean checkWireTransferTabState(
362: DisbursementVoucherDocument dvDocument) {
363: boolean tabStatesOK = true;
364:
365: DisbursementVoucherWireTransfer dvWireTransfer = dvDocument
366: .getDvWireTransfer();
367:
368: // if payment method is CHECK and wire tab contains data, ask user to clear tab
369: if ((StringUtils.equals(
370: DisbursementVoucherRuleConstants.PAYMENT_METHOD_CHECK,
371: dvDocument.getDisbVchrPaymentMethodCode()) || StringUtils
372: .equals(
373: DisbursementVoucherRuleConstants.PAYMENT_METHOD_DRAFT,
374: dvDocument.getDisbVchrPaymentMethodCode()))
375: && hasWireTransferValues(dvWireTransfer)) {
376: String questionText = SpringContext.getBean(
377: KualiConfigurationService.class).getPropertyString(
378: KFSKeyConstants.QUESTION_CLEAR_UNNEEDED_TAB);
379:
380: Object[] args = {
381: "payment method",
382: dvDocument.getDisbVchrPaymentMethodCode(),
383: "Wire Transfer",
384: DisbursementVoucherRuleConstants.PAYMENT_METHOD_WIRE };
385: questionText = MessageFormat.format(questionText, args);
386:
387: boolean clearTab = super
388: .askOrAnalyzeYesNoQuestion(
389: KFSConstants.DisbursementVoucherDocumentConstants.CLEAR_WIRE_TRANSFER_TAB_QUESTION_ID,
390: questionText);
391: if (clearTab) {
392: // NOTE: Can't replace with new instance because Foreign Draft uses same object
393: clearWireTransferValues(dvWireTransfer);
394: } else {
395: // return to document if the user doesn't want to clear the Wire Transfer tab
396: super .event
397: .setActionForwardName(KFSConstants.MAPPING_BASIC);
398: tabStatesOK = false;
399: }
400: }
401:
402: return tabStatesOK;
403: }
404:
405: /**
406: * Returns true if wire transfer tab contains any data in any fields.
407: *
408: * @param dvWireTransfer disbursement voucher wire transfer
409: * @return true if wire transfer tab contains any data in any fields.
410: */
411: private boolean hasWireTransferValues(
412: DisbursementVoucherWireTransfer dvWireTransfer) {
413: boolean hasValues = false;
414:
415: // Checks each explicit field in the tab for user entered values
416: hasValues |= StringUtils
417: .isNotBlank(dvWireTransfer
418: .getDisbursementVoucherAutomatedClearingHouseProfileNumber());
419: hasValues |= StringUtils.isNotBlank(dvWireTransfer
420: .getDisbursementVoucherBankName());
421: hasValues |= StringUtils.isNotBlank(dvWireTransfer
422: .getDisbVchrBankRoutingNumber());
423: hasValues |= StringUtils.isNotBlank(dvWireTransfer
424: .getDisbVchrBankCityName());
425: hasValues |= StringUtils.isNotBlank(dvWireTransfer
426: .getDisbVchrBankStateCode());
427: hasValues |= StringUtils.isNotBlank(dvWireTransfer
428: .getDisbVchrBankCountryCode());
429: hasValues |= StringUtils.isNotBlank(dvWireTransfer
430: .getDisbVchrPayeeAccountNumber());
431: hasValues |= StringUtils.isNotBlank(dvWireTransfer
432: .getDisbVchrAttentionLineText());
433: hasValues |= StringUtils.isNotBlank(dvWireTransfer
434: .getDisbVchrCurrencyTypeName());
435: hasValues |= StringUtils.isNotBlank(dvWireTransfer
436: .getDisbVchrAdditionalWireText());
437: hasValues |= StringUtils.isNotBlank(dvWireTransfer
438: .getDisbursementVoucherPayeeAccountName());
439:
440: return hasValues;
441: }
442:
443: /**
444: * This method sets all values in the passed in disbursement wire transfer object to null
445: *
446: * @param dvWireTransfer
447: */
448: private void clearWireTransferValues(
449: DisbursementVoucherWireTransfer dvWireTransfer) {
450: dvWireTransfer
451: .setDisbursementVoucherAutomatedClearingHouseProfileNumber(null);
452: dvWireTransfer.setDisbursementVoucherBankName(null);
453: dvWireTransfer.setDisbVchrBankRoutingNumber(null);
454: dvWireTransfer.setDisbVchrBankCityName(null);
455: dvWireTransfer.setDisbVchrBankStateCode(null);
456: dvWireTransfer.setDisbVchrBankCountryCode(null);
457: dvWireTransfer.setDisbVchrPayeeAccountNumber(null);
458: dvWireTransfer.setDisbVchrAttentionLineText(null);
459: dvWireTransfer.setDisbVchrCurrencyTypeName(null);
460: dvWireTransfer.setDisbVchrAdditionalWireText(null);
461: dvWireTransfer.setDisbursementVoucherPayeeAccountName(null);
462: }
463:
464: }
|