001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.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/ecl2.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.kfs.module.endow.document.validation.impl; 017 018 import java.math.BigDecimal; 019 import java.util.List; 020 021 import org.apache.commons.lang.StringUtils; 022 import org.kuali.kfs.module.endow.EndowConstants; 023 import org.kuali.kfs.module.endow.EndowKeyConstants; 024 import org.kuali.kfs.module.endow.EndowPropertyConstants; 025 import org.kuali.kfs.module.endow.businessobject.ClassCode; 026 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionCode; 027 import org.kuali.kfs.module.endow.businessobject.FeeClassCode; 028 import org.kuali.kfs.module.endow.businessobject.FeeEndowmentTransactionCode; 029 import org.kuali.kfs.module.endow.businessobject.FeeMethod; 030 import org.kuali.kfs.module.endow.businessobject.FeePaymentType; 031 import org.kuali.kfs.module.endow.businessobject.FeeSecurity; 032 import org.kuali.kfs.module.endow.businessobject.FeeTransaction; 033 import org.kuali.kfs.module.endow.businessobject.Security; 034 import org.kuali.kfs.module.endow.document.service.ClassCodeService; 035 import org.kuali.kfs.module.endow.document.service.EndowmentTransactionCodeService; 036 import org.kuali.kfs.module.endow.document.service.FeeMethodService; 037 import org.kuali.kfs.module.endow.document.service.SecurityService; 038 import org.kuali.kfs.sys.context.SpringContext; 039 import org.kuali.rice.kns.bo.PersistableBusinessObject; 040 import org.kuali.rice.kns.document.Document; 041 import org.kuali.rice.kns.document.MaintenanceDocument; 042 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 043 import org.kuali.rice.kns.rule.event.ApproveDocumentEvent; 044 import org.kuali.rice.kns.util.GlobalVariables; 045 import org.kuali.rice.kns.util.KNSConstants; 046 import org.kuali.rice.kns.util.KualiDecimal; 047 import org.kuali.rice.kns.util.MessageMap; 048 import org.kuali.rice.kns.util.ObjectUtils; 049 050 public class FeeMethodRule extends MaintenanceDocumentRuleBase { 051 052 /** 053 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRule#processRouteDocument(org.kuali.rice.kns.document.Document) 054 */ 055 @Override 056 public boolean processRouteDocument(Document document) { 057 boolean isValid = true; 058 isValid &= super.processRouteDocument(document); 059 MessageMap errorMap = GlobalVariables.getMessageMap(); 060 isValid &= errorMap.hasNoErrors(); 061 062 if (!isValid) { 063 return isValid; 064 } 065 066 isValid &= validationRulesPassedForFeeMethod(document); 067 068 return isValid; 069 } 070 071 /** 072 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRule#processApproveDocument(ApproveDocumentEvent) 073 */ 074 @Override 075 public boolean processApproveDocument(ApproveDocumentEvent approveEvent) { 076 boolean isValid = true; 077 isValid &= super.processApproveDocument(approveEvent); 078 MessageMap errorMap = GlobalVariables.getMessageMap(); 079 isValid &= errorMap.hasNoErrors(); 080 081 if (!isValid) { 082 return isValid; 083 } 084 085 Document document = (Document) approveEvent.getDocument(); 086 isValid &= validationRulesPassedForFeeMethod(document); 087 088 return isValid; 089 } 090 091 /** 092 * This method will validate the custom business rules for fee method 093 * 094 * @param feeMethod 095 * @return true if rules are passed else return false 096 */ 097 private boolean validationRulesPassedForFeeMethod(Document document) { 098 boolean rulesPassed = true; 099 100 MaintenanceDocument maintenanceDocument = (MaintenanceDocument) document; 101 FeeMethod feeMethod = (FeeMethod) maintenanceDocument.getNewMaintainableObject().getBusinessObject(); 102 103 rulesPassed &= checkFeeTransactionTypeCodeValue(feeMethod); // rule #2 104 rulesPassed &= recordExistsInFeeTransactionType(feeMethod); // rule #3 105 rulesPassed &= recordExistsInFeeEndowmentTransactionType(feeMethod); // rule #4 106 rulesPassed &= checkFeeBalanceTypeCodeValue(feeMethod); // rule #5 107 rulesPassed &= recordExistsInFeeClassCode(feeMethod); // rule #6 108 rulesPassed &= recordExistsInFeeSecurity(feeMethod); // rule #7 109 rulesPassed &= checkFeePaymentTypeCodeValue(feeMethod); // rule #8 110 rulesPassed &= recordExistsInFeePaymentType(feeMethod); // rule #9 111 rulesPassed &= checkRateDefinitionAndFeeBalanceTypes(feeMethod); // rule #12 and rule#14 112 rulesPassed &= recordExistsInEndowmentTransactionCode(feeMethod); // rule #12 and rule#14 113 rulesPassed &= checkCorpusToMarketTolerance(feeMethod); // rule #16 114 rulesPassed &= checkFeeRateAndBreakpointAmounts(feeMethod); // rule #17, rule #18, rule #19 115 rulesPassed &= validFeeTransactionTypeEntered(feeMethod); // rule #20 116 rulesPassed &= checkFrequencyCodeNotChangedIfFeeMethodUsedOnAnyKemid(document); 117 rulesPassed &= validFeeExpenseETranCodeEntered(feeMethod); //new rule added by Norm. Per KULENDOW-564 118 119 return rulesPassed; 120 } 121 122 /** 123 * This method will check that if Fee By Transaction Type or Fee By ETran Code or both set to Y and Fee Type is set to T. 124 * 125 * @param feeMethod 126 * @return true if Fee By Transaction Type field or Fee By ETran Code field or both set to Y AND fee type code is T else return 127 * false 128 */ 129 private boolean checkFeeTransactionTypeCodeValue(FeeMethod feeMethod) { 130 boolean isValidTransactionCode = true; 131 132 if (feeMethod.getFeeByTransactionType() || feeMethod.getFeeByETranCode()) { 133 if (ObjectUtils.isNotNull(feeMethod.getFeeTypeCode()) && !EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_TRANSACTIONS.equalsIgnoreCase(feeMethod.getFeeTypeCode())) { 134 putFieldError(EndowPropertyConstants.FEE_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_TYPE_CODE_FOR_TRANSACTIONS_ENTERED); 135 return false; 136 } 137 } 138 139 return isValidTransactionCode; 140 } 141 142 /** 143 * This method will check that if Fee By Class Code or Fee By Security or both set to Yes and Fee Type is set to B. 144 * 145 * @param feeMethod 146 * @return true if Fee By Transaction Type field or Fee By ETran Code field or both set to Y AND fee type code is B else return 147 * false 148 */ 149 private boolean checkFeeBalanceTypeCodeValue(FeeMethod feeMethod) { 150 boolean isValidTransactionCode = true; 151 152 if (feeMethod.getFeeByClassCode() || feeMethod.getFeeBySecurityCode()) { 153 if (ObjectUtils.isNotNull(feeMethod.getFeeTypeCode()) && !EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_BALANCES.equalsIgnoreCase(feeMethod.getFeeTypeCode())) { 154 putFieldError(EndowPropertyConstants.FEE_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_TYPE_CODE_FOR_BALANCE_ENTERED); 155 return false; 156 } 157 } 158 159 return isValidTransactionCode; 160 } 161 162 /** 163 * This method will check that if Fee Type is set to value P then fee base code should be I 164 * 165 * @param feeMethod 166 * @return true if Fee Type is P and Fee Base code is I else return false 167 */ 168 private boolean checkFeePaymentTypeCodeValue(FeeMethod feeMethod) { 169 boolean isValidBaseCode = true; 170 171 if (ObjectUtils.isNotNull(feeMethod.getFeeTypeCode()) && EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_PAYMENTS.equalsIgnoreCase(feeMethod.getFeeTypeCode())) { 172 if (!EndowConstants.FeeMethod.FEE_BASE_CD_VALUE.equalsIgnoreCase(feeMethod.getFeeBaseCode())) { 173 putFieldError(EndowPropertyConstants.FEE_BASE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_BASE_CODE_FOR_PAYMENTS_ENTERED); 174 return false; 175 } 176 } 177 178 return isValidBaseCode; 179 } 180 181 /** 182 * This method will check if at least one record exists in Fee Transaction Type collection with INCL checked on when Fee 183 * Transaction Type Code is checked on 184 * 185 * @param feeMethod 186 * @return true if Fee Transaction Type code checked on and at least one record with INCL flag is checked on else return false 187 */ 188 private boolean recordExistsInFeeTransactionType(FeeMethod feeMethod) { 189 boolean recordExists = false; 190 191 List<FeeTransaction> feeTransactions = (List<FeeTransaction>) feeMethod.getFeeTransactions(); 192 193 for (FeeTransaction feeTransactionsRecord : feeTransactions) { 194 if (feeTransactionsRecord.getInclude()) { 195 recordExists = true; 196 break; 197 } 198 } 199 200 if (feeMethod.getFeeByTransactionType()) { 201 if (!recordExists) { 202 putFieldError(EndowPropertyConstants.FEE_BY_TRANSACTION_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_NO_RECORDS_WITH_YES_IN_FEE_TRANSACTION_TYPE); 203 return false; 204 } 205 } 206 //However, If Fee Transaction Type code is not checked, there can be no records in END_FEE_TRAN_DOC_TYP_T with the field INCL set to Yes 207 else { 208 if (recordExists) { 209 putFieldError(EndowPropertyConstants.FEE_BY_TRANSACTION_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_RECORDS_WITH_YES_IN_FEE_TRANSACTION_TYPE); 210 return false; 211 } 212 } 213 214 return true; 215 } 216 217 /** 218 * This method will check if at least one record exists in Fee Class Codes collection with INCL checked on when Fee Class code 219 * is checked on. 220 * 221 * @param feeMethod 222 * @return true if Fee Class code is checked on and at least one record with INCL flag is checked on else return false 223 */ 224 private boolean recordExistsInFeeClassCode(FeeMethod feeMethod) { 225 boolean recordExists = false; 226 227 List<FeeClassCode> feeClassCodes = (List<FeeClassCode>) feeMethod.getFeeClassCodes(); 228 229 for (FeeClassCode feeClassCodeRecord : feeClassCodes) { 230 if (feeClassCodeRecord.getInclude()) { 231 recordExists = true; 232 break; 233 } 234 } 235 236 if (feeMethod.getFeeByClassCode()) { 237 if (!recordExists) { 238 putFieldError(EndowPropertyConstants.FEE_BY_CLASS_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_NO_RECORDS_WITH_YES_IN_FEE_CLASS_CODE); 239 return false; 240 } 241 } 242 else { 243 if (recordExists) { 244 putFieldError(EndowPropertyConstants.FEE_BY_CLASS_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_RECORDS_WITH_YES_IN_FEE_CLASS_CODE); 245 return false; 246 } 247 } 248 249 return true; 250 } 251 252 /** 253 * This method will check if at least one record exists in Fee Endowment Transaction Codes collection with INCL checked on when 254 * Fee Endowment Transaction Code is checked on. 255 * 256 * @param feeMethod 257 * @return true if Fee EndowmentTransaction Type is checked on and at least one record with INCL flag is checked on else return 258 * false 259 */ 260 private boolean recordExistsInFeeEndowmentTransactionType(FeeMethod feeMethod) { 261 boolean recordExists = false; 262 263 List<FeeEndowmentTransactionCode> feeEndowmentTransactionCodes = (List<FeeEndowmentTransactionCode>) feeMethod.getFeeEndowmentTransactionCodes(); 264 265 for (FeeEndowmentTransactionCode feeEndowmentTransactionCodesRecord : feeEndowmentTransactionCodes) { 266 if (feeEndowmentTransactionCodesRecord.getInclude()) { 267 recordExists = true; 268 break; 269 } 270 } 271 272 if (feeMethod.getFeeByETranCode()) { 273 if (!recordExists) { 274 putFieldError(EndowPropertyConstants.FEE_BY_ENDOWMENT_TRANSACTION_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_NO_RECORDS_WITH_YES_IN_FEE_ENDOWMENT_TRANSACTION_CODE); 275 return false; 276 } 277 } 278 //However, If etran code is not checked, there can be no records in etrancode table with the field INCL set to Yes 279 else { 280 if (recordExists) { 281 putFieldError(EndowPropertyConstants.FEE_BY_ENDOWMENT_TRANSACTION_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_RECORDS_WITH_YES_IN_FEE_ENDOWMENT_TRANSACTION_CODE); 282 return false; 283 } 284 } 285 286 return true; 287 } 288 289 /** 290 * This method will check if at least one record exists in Fee Security collection with INCL checked on when Fee Class Code is 291 * checked on. 292 * 293 * @param feeMethod 294 * @return true if Fee Security Code is checked on and at least one record with INCL flag is checked on else return false 295 */ 296 private boolean recordExistsInFeeSecurity(FeeMethod feeMethod) { 297 boolean recordExists = false; 298 List<FeeSecurity> feeSecurity = (List<FeeSecurity>) feeMethod.getFeeSecurity(); 299 300 for (FeeSecurity feeSecurityRecord : feeSecurity) { 301 if (feeSecurityRecord.getInclude()) { 302 recordExists = true; 303 break; 304 } 305 } 306 307 if (feeMethod.getFeeBySecurityCode()) { 308 if (!recordExists) { 309 putFieldError(EndowPropertyConstants.FEE_BY_SECURITY_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_NO_RECORDS_WITH_YES_IN_FEE_SECURITY_CODE); 310 return false; 311 } 312 } 313 else { 314 if (recordExists) { 315 putFieldError(EndowPropertyConstants.FEE_BY_ENDOWMENT_TRANSACTION_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_RECORDS_WITH_YES_IN_FEE_SECURITY_CODE); 316 return false; 317 } 318 } 319 320 return true; 321 } 322 323 /** 324 * This method will check if at least one record exists in Fee Payment Type collection with INCL checked on when Fee Type Code 325 * is checked on. 326 * 327 * @param feeMethod 328 * @return true if at least one record with INCL flag is checked on else return false 329 */ 330 private boolean recordExistsInFeePaymentType(FeeMethod feeMethod) { 331 boolean recordExists = true; 332 333 if (ObjectUtils.isNotNull(feeMethod.getFeeTypeCode()) && EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_PAYMENTS.equalsIgnoreCase(feeMethod.getFeeTypeCode())) { 334 recordExists = false; 335 List<FeePaymentType> feePaymentTypes = (List<FeePaymentType>) feeMethod.getFeePaymentTypes(); 336 337 for (FeePaymentType feePaymentTypeRecord : feePaymentTypes) { 338 if (feePaymentTypeRecord.getInclude()) { 339 recordExists = true; 340 break; 341 } 342 } 343 344 if (!recordExists) { 345 putFieldError(EndowPropertyConstants.FEE_BASE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_NO_RECORDS_WITH_YES_IN_FEE_PAYMENT_TYPE); 346 } 347 } 348 349 return recordExists; 350 } 351 352 /** 353 * This method will check rate definition and fee balance types based on fee type code 354 * 355 * @param feeMethod 356 * @return true if ((rate definition is C AND fee type code is B AND fee balances types are AU or CU and/or MU) or (rate 357 * definition is V AND fee type code is B AND fee balances types are AMV or CMV and/or MMV)) else return false 358 */ 359 private boolean checkRateDefinitionAndFeeBalanceTypes(FeeMethod feeMethod) { 360 boolean isValid = true; 361 362 String feeRateDefinitionCode = feeMethod.getFeeRateDefinitionCode(); 363 364 if (ObjectUtils.isNotNull(feeRateDefinitionCode)) { 365 // if rate definition is C and type fee code is B 366 if (EndowConstants.FeeMethod.FEE_RATE_DEFINITION_CODE_FOR_COUNT.equalsIgnoreCase(feeRateDefinitionCode) && EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_BALANCES.equalsIgnoreCase(feeMethod.getFeeTypeCode())) { 367 String feeBalanceTypeCode = feeMethod.getFeeBalanceTypeCode(); 368 369 if (!EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_AVERAGE_UNITS.equalsIgnoreCase(feeBalanceTypeCode) && !EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_CURRENT_UNITS.equalsIgnoreCase(feeBalanceTypeCode) && !EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_MONTH_END_UNITS.equalsIgnoreCase(feeBalanceTypeCode)) { 370 putFieldError(EndowPropertyConstants.FEE_BALANCE_TYPES_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_BALANCE_TYPE_CODE_WHEN_COUNT_ENTERED); 371 return false; 372 } 373 } 374 375 // if rate definition is V and type fee code is B 376 if (EndowConstants.FeeMethod.FEE_RATE_DEFINITION_CODE_FOR_VALUE.equalsIgnoreCase(feeRateDefinitionCode) && EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_BALANCES.equalsIgnoreCase(feeMethod.getFeeTypeCode())) { 377 String feeBalanceTypeCode = feeMethod.getFeeBalanceTypeCode(); 378 379 if (!EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_AVERAGE_MARKET_VALUE.equalsIgnoreCase(feeBalanceTypeCode) && !EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_CURRENT_MARKET_VALUE.equalsIgnoreCase(feeBalanceTypeCode) && !EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_MONTH_END_MARKET_VALUE.equalsIgnoreCase(feeBalanceTypeCode)) { 380 putFieldError(EndowPropertyConstants.FEE_BALANCE_TYPES_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_BALANCE_TYPE_CODE_WHEN_VALUE_ENTERED); 381 return false; 382 } 383 } 384 } 385 386 return isValid; 387 } 388 389 /** 390 * This method will check if record exists in Endowment Transaction Code table 391 * 392 * @param feeMethod feeMethod object 393 * @return true if Fee Endowment Transaction code exists else return false 394 */ 395 private boolean recordExistsInEndowmentTransactionCode(FeeMethod feeMethod) { 396 boolean recordExists = true; 397 398 String endowmentTransactionCode = feeMethod.getFeeExpenseETranCode(); 399 400 EndowmentTransactionCodeService endowmentTransactionCodeService = SpringContext.getBean(EndowmentTransactionCodeService.class); 401 EndowmentTransactionCode endowmentTransaction = endowmentTransactionCodeService.getByPrimaryKey(endowmentTransactionCode.toUpperCase()); 402 403 if (ObjectUtils.isNull(endowmentTransaction)) { 404 putFieldError(EndowPropertyConstants.FEE_ENDOWMENT_TRANSACTION_TYPE_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_NO_RECORD_IN_ENDOWMENT_TRANSACTION_CODE); 405 return false; 406 } 407 408 return recordExists; 409 } 410 411 /** 412 * This method will check that if corpus to market tolerance is 0 or > 1 413 * 414 * @param feeMethod 415 * @return true if corpus to market tolerance is 0 (default) or > 1.00 else return false 416 */ 417 private boolean checkCorpusToMarketTolerance(FeeMethod feeMethod) { 418 boolean isValid = true; 419 420 if (ObjectUtils.isNotNull(feeMethod.getCorpusPctTolerance())) { 421 KualiDecimal corputPctToTolerance = feeMethod.getCorpusPctTolerance(); 422 if (corputPctToTolerance.isLessThan(KualiDecimal.ZERO)) { 423 putFieldError(EndowPropertyConstants.CORPUS_TO_PCT_TOLERANCE, EndowKeyConstants.FeeMethodConstants.ERROR_CORPUS_PCT_TO_TOLERANCE_NEGATIVE); 424 return false; 425 } 426 if (!corputPctToTolerance.isZero() && !corputPctToTolerance.isGreaterThan(new KualiDecimal("1.0"))) { 427 putFieldError(EndowPropertyConstants.CORPUS_TO_PCT_TOLERANCE, EndowKeyConstants.FeeMethodConstants.ERROR_CORPUS_PCT_TO_TOLERANCE_MUST_BE_GREATER_THAN_ONE); 428 return false; 429 } 430 } 431 432 return isValid; 433 } 434 435 /** 436 * This method will check the fee rate and fee rate breakpoints 437 * 438 * @param feeMethod 439 * @return true fee rate and fee rate breakpoints pass the validations else return false 440 */ 441 private boolean checkFeeRateAndBreakpointAmounts(FeeMethod feeMethod) { 442 boolean isValid = true; 443 444 // no negative values for first, second, and third rate fields 445 if (feeMethod.getFirstFeeRate().compareTo(BigDecimal.ZERO) == -1) { 446 putFieldError(EndowPropertyConstants.FIRST_FEE_RATE, EndowKeyConstants.FeeMethodConstants.ERROR_FIRST_FEE_RATE_CAN_NOT_BE_NEGATIVE); 447 return false; 448 } 449 if (feeMethod.getSecondFeeRate().compareTo(BigDecimal.ZERO) == -1) { 450 putFieldError(EndowPropertyConstants.SECOND_FEE_RATE, EndowKeyConstants.FeeMethodConstants.ERROR_SECOND_FEE_RATE_CAN_NOT_BE_NEGATIVE); 451 return false; 452 } 453 454 if (feeMethod.getThirdFeeRate().compareTo(BigDecimal.ZERO) == -1) { 455 putFieldError(EndowPropertyConstants.THIRD_FEE_RATE, EndowKeyConstants.FeeMethodConstants.ERROR_THIRD_FEE_RATE_CAN_NOT_BE_NEGATIVE); 456 return false; 457 } 458 459 // no negative values for first, second fee breakpoint values. 460 if (feeMethod.getFirstFeeBreakpoint().isLessThan(KualiDecimal.ZERO)) { 461 putFieldError(EndowPropertyConstants.FIRST_FEE_BREAK_POINT, EndowKeyConstants.FeeMethodConstants.ERROR_FIRST_FEE_BREAK_POINT_MUST_BE_GREATER_THAN_OR_ZERO); 462 return false; 463 } 464 465 if (feeMethod.getSecondFeeBreakpoint().isLessThan(KualiDecimal.ZERO)) { 466 putFieldError(EndowPropertyConstants.SECOND_FEE_BREAK_POINT, EndowKeyConstants.FeeMethodConstants.ERROR_SECOND_FEE_BREAK_POINT_MUST_BE_GREATER_THAN_OR_ZERO); 467 return false; 468 } 469 470 if (feeMethod.getFirstFeeBreakpoint().isLessThan(EndowConstants.FeeMethod.FEE_RATE_DEFAULT_VALUE) && feeMethod.getSecondFeeRate().compareTo(BigDecimal.ZERO) == 0) { 471 putFieldError(EndowPropertyConstants.SECOND_FEE_RATE, EndowKeyConstants.FeeMethodConstants.ERROR_SECOND_FEE_RATE_MUST_BE_GREATER_THAN_OR_ZERO); 472 return false; 473 } 474 475 if (feeMethod.getSecondFeeRate().compareTo(BigDecimal.ZERO) == 1 && feeMethod.getFirstFeeBreakpoint().isGreaterEqual(feeMethod.getSecondFeeBreakpoint())) { 476 putFieldError(EndowPropertyConstants.FIRST_FEE_BREAK_POINT, EndowKeyConstants.FeeMethodConstants.ERROR_FIRST_FEE_BREAK_POINT_MUST_BE_LESS_THAN_SECOND_FEE_BREAK_POINT); 477 return false; 478 } 479 480 if (feeMethod.getThirdFeeRate().compareTo(BigDecimal.ZERO) == 1 && feeMethod.getSecondFeeBreakpoint().isGreaterEqual(EndowConstants.FeeMethod.FEE_RATE_DEFAULT_VALUE)) { 481 putFieldError(EndowPropertyConstants.SECOND_FEE_BREAK_POINT, EndowKeyConstants.FeeMethodConstants.ERROR_SECOND_FEE_BREAK_POINT_MUST_BE_LESS_THAN_MAX_FEE_BREAK_POINT); 482 return false; 483 } 484 485 if (feeMethod.getSecondFeeBreakpoint().isLessThan(EndowConstants.FeeMethod.FEE_RATE_DEFAULT_VALUE) && (feeMethod.getThirdFeeRate().compareTo(BigDecimal.ZERO) == 0)) { 486 putFieldError(EndowPropertyConstants.THIRD_FEE_RATE, EndowKeyConstants.FeeMethodConstants.ERROR_THIRD_FEE_RATE_MUST_BE_GREATER_THAN_ZERO); 487 return false; 488 } 489 490 return isValid; 491 } 492 493 /** 494 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, 495 * java.lang.String, org.kuali.rice.kns.bo.PersistableBusinessObject) 496 */ 497 @Override 498 public boolean processAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject bo) { 499 boolean isValid = true; 500 isValid &= super.processCustomAddCollectionLineBusinessRules(document, collectionName, bo); 501 MessageMap errorMap = GlobalVariables.getMessageMap(); 502 isValid &= errorMap.hasNoErrors(); 503 504 if (!isValid) { 505 return isValid; 506 } 507 508 FeeMethod feeMethod = (FeeMethod) document.getNewMaintainableObject().getBusinessObject(); 509 510 // process add line for feeClassCodes collection 511 if (collectionName.equalsIgnoreCase(EndowPropertyConstants.FEE_CLASS_CODES_COLLECTION_NAME)) { 512 FeeClassCode feeClassCode = (FeeClassCode) bo; 513 bo.refreshReferenceObject(EndowPropertyConstants.FEE_CLASS_CODE_REF); 514 515 if (isEmptyFeeClassCode(bo)) { 516 return false; 517 } 518 if (duplicateFeeClassCodeEntered(feeMethod, bo)) { 519 return false; 520 } 521 if (!validateFeeClassCode(bo)) { 522 isValid = false; 523 } 524 } 525 526 // process add line for feeSecurity collection 527 if (collectionName.equalsIgnoreCase(EndowPropertyConstants.FEE_SECURITY_COLLECTION_NAME)) { 528 FeeSecurity feeSecurity = (FeeSecurity) bo; 529 bo.refreshReferenceObject(EndowPropertyConstants.FEE_SECURITY_REF); 530 531 if (isEmptyFeeSecurityCode(bo)) { 532 return false; 533 } 534 if (duplicateFeeSecurityCodeEntered(feeMethod, bo)) { 535 return false; 536 } 537 if (!validateFeeSecurityCode(bo)) { 538 isValid = false; 539 } 540 } 541 542 // process add line for feeTransaction collection 543 if (collectionName.equalsIgnoreCase(EndowPropertyConstants.FEE_TRANSACTION_TYPE_COLLECTION_NAME)) { 544 FeeTransaction feeTransaction = (FeeTransaction) bo; 545 // bo.refreshReferenceObject(EndowPropertyConstants.FEE_TRANSACTION_ARCHIVE_REF); 546 547 if (isEmptyFeeTransactionDocumentTypeName(bo)) { 548 return false; 549 } 550 if (duplicateFeeTransactionDocumentTypeName(feeMethod, bo)) { 551 return false; 552 } 553 } 554 555 // process add line for feeEndowmentTransaction collection 556 if (collectionName.equalsIgnoreCase(EndowPropertyConstants.FEE_ENDOWMENT_TRANSACTION_CODE_COLLECTION_NAME)) { 557 FeeEndowmentTransactionCode feeEndowmentTransactionCode = (FeeEndowmentTransactionCode) bo; 558 bo.refreshReferenceObject(EndowPropertyConstants.FEE_ENDOWMENT_TRANSACTION_CODE_REF); 559 560 if (isEmptyFeeEndowmentTransactionCode(bo)) { 561 return false; 562 } 563 if (duplicateFeeEndowmentTransactionCode(feeMethod, bo)) { 564 return false; 565 } 566 if (!validateFeeEndowmentTransactionCode(bo)) { 567 isValid = false; 568 } 569 } 570 571 // process add line for feePaymentType collection 572 if (collectionName.equalsIgnoreCase(EndowPropertyConstants.FEE_PAYMENT_TYPE_COLLECTION_NAME)) { 573 if (isEmptyFeePaymentTypeCode(bo)) { 574 return false; 575 } 576 if (duplicateFeePaymentTypeCode(feeMethod, bo)) { 577 return false; 578 } 579 } 580 581 return isValid; 582 } 583 584 /** 585 * This method checks to make sure that fee class code is not empty 586 * 587 * @param feeClassCode The object feeClassCode 588 * @return isValid is true if fee class code is empty else return false 589 */ 590 private boolean isEmptyFeeClassCode(PersistableBusinessObject bo) { 591 boolean isValid = false; 592 593 FeeClassCode feeClass = (FeeClassCode) bo; 594 595 String feeClassCode = feeClass.getFeeClassCode(); 596 if (ObjectUtils.isNull(feeClassCode)) { 597 putFieldError(EndowPropertyConstants.FEE_CLASS_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_BLANK_FEE_CLASS_CODE_ENTERED); 598 return true; 599 } 600 601 return isValid; 602 } 603 604 /** 605 * This method checks to make sure that fee class code exists in ClassCode 606 * 607 * @param feeClassCode The object feeClassCode 608 * @return isValid is true if fee class code exists in the database else return false 609 */ 610 private boolean validateFeeClassCode(PersistableBusinessObject bo) { 611 boolean isValid = true; 612 613 FeeClassCode feeClass = (FeeClassCode) bo; 614 String feeClassCode = feeClass.getFeeClassCode(); 615 616 ClassCodeService classCodeService = SpringContext.getBean(ClassCodeService.class); 617 ClassCode classCode = classCodeService.getByPrimaryKey(feeClassCode); 618 619 if (ObjectUtils.isNull(classCode)) { 620 putFieldError(EndowPropertyConstants.FEE_CLASS_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_CLASS_CODE_ENTERED); 621 return false; 622 } 623 624 return isValid; 625 } 626 627 /** 628 * This method checks to make sure that fee class code is not a duplicate in the collection list Compare the entered fee class 629 * code on the line to the fee class codes in the list to make sure it is not a duplicate. 630 * 631 * @param feeMethod, bo 632 * @return isDuplicate is true if fee class code is in the list already else return false 633 */ 634 private boolean duplicateFeeClassCodeEntered(FeeMethod feeMethod, PersistableBusinessObject bo) { 635 boolean isDuplicate = false; 636 637 FeeClassCode feeClass = (FeeClassCode) bo; 638 String feeClassCode = feeClass.getFeeClassCode(); 639 640 List<FeeClassCode> feeClassCodes = (List<FeeClassCode>) feeMethod.getFeeClassCodes(); 641 642 for (FeeClassCode feeClassCodeRecord : feeClassCodes) { 643 if (feeClassCodeRecord.getFeeClassCode().equalsIgnoreCase(feeClassCode)) { 644 isDuplicate = true; 645 putFieldError(EndowPropertyConstants.FEE_CLASS_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_DUPLICATE_FEE_CLASS_CODE_ENTERED); 646 } 647 } 648 649 return isDuplicate; 650 } 651 652 /** 653 * This method checks to make sure that fee security code is not empty 654 * 655 * @param bo 656 * @return isValid is true if fee security code is empty else return false 657 */ 658 private boolean isEmptyFeeSecurityCode(PersistableBusinessObject bo) { 659 boolean isValid = false; 660 661 FeeSecurity feeSecurity = (FeeSecurity) bo; 662 663 String feeSecurityCode = feeSecurity.getSecurityCode(); 664 if (ObjectUtils.isNull(feeSecurityCode)) { 665 putFieldError(EndowPropertyConstants.FEE_SECURITY_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_BLANK_FEE_SECURITY_CODE_ENTERED); 666 return true; 667 } 668 669 return isValid; 670 } 671 672 /** 673 * This method checks to make sure that fee security code exists in Security 674 * 675 * @param bo The bo to be mapped into feeSecurity 676 * @return isValid is true if fee security code is in the database else return false 677 */ 678 private boolean validateFeeSecurityCode(PersistableBusinessObject bo) { 679 boolean isValid = true; 680 681 FeeSecurity feeSecurity = (FeeSecurity) bo; 682 String securityCode = feeSecurity.getSecurityCode(); 683 684 SecurityService securityService = SpringContext.getBean(SecurityService.class); 685 Security security = securityService.getByPrimaryKey(securityCode); 686 687 if (ObjectUtils.isNull(security)) { 688 putFieldError(EndowPropertyConstants.FEE_SECURITY_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_FEE_SECURITY_CODE_ENTERED); 689 return false; 690 } 691 692 return isValid; 693 } 694 695 /** 696 * This method checks to make sure that fee security code is not a duplicate in the collection list Compare the entered fee 697 * security code on the line to the fee security codes in the list to make sure it is not a duplicate. 698 * 699 * @param feeMethod, bo 700 * @return isDuplicate is true if fee security code in the list else return false 701 */ 702 private boolean duplicateFeeSecurityCodeEntered(FeeMethod feeMethod, PersistableBusinessObject bo) { 703 boolean isDuplicate = false; 704 705 FeeSecurity feeSecurityCode = (FeeSecurity) bo; 706 String securityCode = feeSecurityCode.getSecurityCode(); 707 708 List<FeeSecurity> feeSecurity = (List<FeeSecurity>) feeMethod.getFeeSecurity(); 709 710 for (FeeSecurity feeSecurityRecord : feeSecurity) { 711 if (feeSecurityRecord.getSecurityCode().equalsIgnoreCase(securityCode)) { 712 isDuplicate = true; 713 putFieldError(EndowPropertyConstants.FEE_SECURITY_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_DUPLICATE_FEE_SECURITY_CODE_ENTERED); 714 } 715 } 716 717 return isDuplicate; 718 } 719 720 /** 721 * This method checks to make sure that fee transaction type code is not empty 722 * 723 * @param bo bo to be mapped into feeTransaction 724 * @return isValid is true if fee transaction document name is empty else return false 725 */ 726 private boolean isEmptyFeeTransactionDocumentTypeName(PersistableBusinessObject bo) { 727 boolean isValid = false; 728 729 FeeTransaction feeTransaction = (FeeTransaction) bo; 730 String feeTransactionTypeName = feeTransaction.getDocumentTypeName(); 731 732 if (ObjectUtils.isNull(feeTransactionTypeName)) { 733 putFieldError(EndowPropertyConstants.FEE_TRANSACTION_DOCUMENT_TYPE_NAME_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_BLANK_DOCUMENT_TYPE_NAME_ENTERED); 734 return true; 735 } 736 737 return isValid; 738 } 739 740 /** 741 * This method checks to make sure that fee class code is not a duplicate in the collection list Compare the entered fee 742 * transaction type code on the line to the fee transaction type codes in the list to make sure it is not a duplicate 743 * 744 * @param feeMethod, bo 745 * @return isDuplicate is true if fee transaction document type name is already in the list else return false 746 */ 747 private boolean duplicateFeeTransactionDocumentTypeName(FeeMethod feeMethod, PersistableBusinessObject bo) { 748 boolean isDuplicate = false; 749 750 FeeTransaction feeTransaction = (FeeTransaction) bo; 751 String feeTransactionDocumentTypeName = feeTransaction.getDocumentTypeName(); 752 753 List<FeeTransaction> feeTransactions = (List<FeeTransaction>) feeMethod.getFeeTransactions(); 754 755 for (FeeTransaction feeTransactionsRecord : feeTransactions) { 756 if (feeTransactionsRecord.getDocumentTypeName().equalsIgnoreCase(feeTransactionDocumentTypeName)) { 757 isDuplicate = true; 758 putFieldError(EndowPropertyConstants.FEE_TRANSACTION_DOCUMENT_TYPE_NAME_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_DUPLICATE_TRANSACTION_TYPE_NAME_ENTERED); 759 } 760 } 761 762 return isDuplicate; 763 } 764 765 /** 766 * This method checks to make sure that fee endowment transaction code is not empty 767 * 768 * @param bo bo will be mapped to feeEndowmentTransactionCode 769 * @return isValid is true if fee endowment transaction code is empty else return false 770 */ 771 private boolean isEmptyFeeEndowmentTransactionCode(PersistableBusinessObject bo) { 772 boolean isValid = false; 773 774 FeeEndowmentTransactionCode feeEndowmentTransactionCode = (FeeEndowmentTransactionCode) bo; 775 String feeEndowmentCode = feeEndowmentTransactionCode.getEndowmentTransactionCode(); 776 777 if (ObjectUtils.isNull(feeEndowmentCode)) { 778 putFieldError(EndowPropertyConstants.FEE_ENDOWMENT_TRANSACTION_TYPE_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_BLANK_ENDOWMENT_TRANSACTION_CODE_ENTERED); 779 return true; 780 } 781 782 return isValid; 783 } 784 785 /** 786 * This method checks to make sure that fee endowment transaction code exists in Endowment Transaction Code 787 * 788 * @param bo bo to be mapped into feeEndowmentTransactionCode 789 * @return isValid is true if fee endowment transaction code is in the database else return false 790 */ 791 private boolean validateFeeEndowmentTransactionCode(PersistableBusinessObject bo) { 792 boolean isValid = true; 793 794 FeeEndowmentTransactionCode feeEndowmentTransactionCode = (FeeEndowmentTransactionCode) bo; 795 String feeEndowmentCode = feeEndowmentTransactionCode.getEndowmentTransactionCode(); 796 797 EndowmentTransactionCodeService endowmentTransactionCodeService = SpringContext.getBean(EndowmentTransactionCodeService.class); 798 EndowmentTransactionCode endowmentTransactionCode = endowmentTransactionCodeService.getByPrimaryKey(feeEndowmentCode); 799 800 if (ObjectUtils.isNull(endowmentTransactionCode)) { 801 putFieldError(EndowPropertyConstants.FEE_ENDOWMENT_TRANSACTION_TYPE_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_ENDOWMENT_TRANSACTION_CODE_ENTERED); 802 return false; 803 } 804 805 return isValid; 806 } 807 808 /** 809 * This method checks to make sure that fee endowment transaction code is not a duplicate in the collection list Compare the 810 * entered fee endowment transaction code on the line to the fee endowment transaction codes in the list to make sure it is not 811 * a duplicate. 812 * 813 * @param feeMethod, bo 814 * @return isDuplicate is true if fee endowment transaction code in the list else return false 815 */ 816 private boolean duplicateFeeEndowmentTransactionCode(FeeMethod feeMethod, PersistableBusinessObject bo) { 817 boolean isDuplicate = false; 818 819 FeeEndowmentTransactionCode feeEndowmentTransactionCode = (FeeEndowmentTransactionCode) bo; 820 String feeEndowmentCode = feeEndowmentTransactionCode.getEndowmentTransactionCode(); 821 822 List<FeeEndowmentTransactionCode> feeEndowmentTransactionCodes = (List<FeeEndowmentTransactionCode>) feeMethod.getFeeEndowmentTransactionCodes(); 823 824 for (FeeEndowmentTransactionCode feeEndowmentTransactionCodesRecord : feeEndowmentTransactionCodes) { 825 if (feeEndowmentTransactionCodesRecord.getEndowmentTransactionCode().equalsIgnoreCase(feeEndowmentCode)) { 826 isDuplicate = true; 827 putFieldError(EndowPropertyConstants.FEE_ENDOWMENT_TRANSACTION_TYPE_CODE_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_DUPLICATE_ENDOWMENT_TRANSACTION_CODE_ENTERED); 828 } 829 } 830 831 return isDuplicate; 832 } 833 834 /** 835 * This method checks to make sure that fee payment type code is not empty 836 * 837 * @param bo bo to be mapped into feePaymentTypeCode 838 * @return isValid is true if fee payment type code is empty else return false 839 */ 840 private boolean isEmptyFeePaymentTypeCode(PersistableBusinessObject bo) { 841 boolean isValid = false; 842 843 FeePaymentType feePaymentType = (FeePaymentType) bo; 844 String feePaymentTypeCode = feePaymentType.getPaymentTypeCode(); 845 846 if (ObjectUtils.isNull(feePaymentTypeCode)) { 847 putFieldError(EndowPropertyConstants.FEE_PAYMENT_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_BLANK_PAYMENT_TYPE_CODE_ENTERED); 848 return true; 849 } 850 851 return isValid; 852 } 853 854 /** 855 * This method checks to make sure that fee payment type code is not a duplicate in the collection list Compare the entered fee 856 * payment type code on the line to the fee payment type codes in the list to make sure it is not a duplicate. 857 * 858 * @param feeMethod, bo 859 * @return isDuplicate is true if fee payment type code in the list else return false 860 */ 861 private boolean duplicateFeePaymentTypeCode(FeeMethod feeMethod, PersistableBusinessObject bo) { 862 boolean isDuplicate = false; 863 864 FeePaymentType feePaymentType = (FeePaymentType) bo; 865 String feePaymentTypeCode = feePaymentType.getPaymentTypeCode(); 866 867 List<FeePaymentType> feePaymentTypes = (List<FeePaymentType>) feeMethod.getFeePaymentTypes(); 868 869 for (FeePaymentType feePaymentTypesRecord : feePaymentTypes) { 870 if (feePaymentTypesRecord.getPaymentTypeCode().equalsIgnoreCase(feePaymentTypeCode)) { 871 isDuplicate = true; 872 putFieldError(EndowPropertyConstants.FEE_PAYMENT_TYPE_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_DUPLICATE_PAYMENT_TYPE_CODE_ENTERED); 873 } 874 } 875 876 return isDuplicate; 877 } 878 879 /** 880 * Check that the frequency code on the Fee Method did not change if the Fee Method is used on at least one KEMID. 881 * 882 * @param document 883 * @return true if valid, false otherwise 884 */ 885 private boolean checkFrequencyCodeNotChangedIfFeeMethodUsedOnAnyKemid(Document document) { 886 MaintenanceDocument maintenanceDocument = (MaintenanceDocument) document; 887 boolean isValid = true; 888 889 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceDocument.getNewMaintainableObject().getMaintenanceAction())) { 890 FeeMethod newFeeMethod = (FeeMethod) maintenanceDocument.getNewMaintainableObject().getBusinessObject(); 891 FeeMethod oldFeeMethod = (FeeMethod) maintenanceDocument.getOldMaintainableObject().getBusinessObject(); 892 String feeMethodCode = newFeeMethod.getCode(); 893 894 if (!StringUtils.equalsIgnoreCase(newFeeMethod.getFeeFrequencyCode(), oldFeeMethod.getFeeFrequencyCode())) { 895 FeeMethodService feeMethodService = SpringContext.getBean(FeeMethodService.class); 896 if (feeMethodService.isFeeMethodUsedOnAnyKemid(feeMethodCode)) { 897 putFieldError(EndowPropertyConstants.FEE_METHOD_FREQUENCY_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_FEE_MTHD_FREQ_CD_CANNOT_BE_CHANGED_IF_FEE_USED_ON_ANY_KEMID); 898 isValid = false; 899 } 900 } 901 } 902 903 return isValid; 904 } 905 906 /** 907 * This method will check if Fee Transaction Type collection does not have type as EHVA 908 * 909 * @param feeMethod 910 * @return true if Fee Transaction Type code is not EHVA else return false 911 */ 912 private boolean validFeeTransactionTypeEntered(FeeMethod feeMethod) { 913 boolean valid = true; 914 915 if (feeMethod.getFeeByTransactionType()) { 916 valid = true; 917 List<FeeTransaction> feeTransactions = (List<FeeTransaction>) feeMethod.getFeeTransactions(); 918 919 for (FeeTransaction feeTransactionsRecord : feeTransactions) { 920 if (feeTransactionsRecord.getDocumentTypeName().equals(EndowConstants.FeeMethod.ENDOWMENT_HISTORY_VALUE_ADJUSTMENT)) { 921 valid = false; 922 break; 923 } 924 } 925 if (!valid) { 926 putFieldError(EndowPropertyConstants.FEE_TRANSACTION_DOCUMENT_TYPE_NAME_ATTRIBUTE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_TRANSACTION_DOCUMENT_TYPE_CODE_ENTERED); 927 } 928 } 929 930 return valid; 931 } 932 933 /** 934 * Check to see if fee method etran code has a valiD expense etran code type = E 935 */ 936 private boolean validFeeExpenseETranCodeEntered(FeeMethod feeMethod) { 937 boolean valid = true; 938 939 if (!EndowConstants.EndowmentTransactionTypeCodes.EXPENSE_TYPE_CODE.equalsIgnoreCase(feeMethod.getEndowmentTransactionCode().getEndowmentTransactionTypeCode())) { 940 valid = false; 941 putFieldError(EndowPropertyConstants.FEE_EXPENSE_ENDOWMENT_TRANSACTION_CODE, EndowKeyConstants.FeeMethodConstants.ERROR_INVALID_TRANSACTION_TYPE_CODE_FOR_EXPENSE_ETRANCODE); 942 } 943 944 return valid; 945 } 946 }