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.coa.document.validation.impl; 017 018 import java.util.List; 019 020 import org.apache.commons.lang.StringUtils; 021 import org.kuali.kfs.coa.businessobject.AccountDelegateGlobal; 022 import org.kuali.kfs.coa.businessobject.AccountDelegateGlobalDetail; 023 import org.kuali.kfs.coa.businessobject.AccountGlobalDetail; 024 import org.kuali.kfs.sys.KFSConstants; 025 import org.kuali.kfs.sys.KFSKeyConstants; 026 import org.kuali.kfs.sys.KFSPropertyConstants; 027 import org.kuali.kfs.sys.context.SpringContext; 028 import org.kuali.kfs.sys.document.service.FinancialSystemDocumentService; 029 import org.kuali.kfs.sys.document.service.FinancialSystemDocumentTypeService; 030 import org.kuali.rice.kim.bo.Person; 031 import org.kuali.rice.kns.bo.PersistableBusinessObject; 032 import org.kuali.rice.kns.document.MaintenanceDocument; 033 import org.kuali.rice.kns.util.GlobalVariables; 034 import org.kuali.rice.kns.util.KualiDecimal; 035 import org.kuali.rice.kns.util.ObjectUtils; 036 037 /** 038 * This class executes specific rules for the {@link DelegateGlobalMaintenanceDocument} 039 */ 040 public class DelegateGlobalRule extends GlobalDocumentRuleBase { 041 042 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DelegateGlobalRule.class); 043 044 protected static final KualiDecimal ZERO = KualiDecimal.ZERO; 045 protected AccountDelegateGlobal newDelegateGlobal; 046 protected static final String DELEGATE_GLOBALS_PREFIX = "delegateGlobals"; 047 048 public DelegateGlobalRule() { 049 super(); 050 } 051 052 /** 053 * This method sets the convenience objects like newAccount and oldAccount, so you have short and easy handles to the new and 054 * old objects contained in the maintenance document. It also calls the BusinessObjectBase.refresh(), which will attempt to load 055 * all sub-objects from the DB by their primary keys, if available. 056 */ 057 @Override 058 public void setupConvenienceObjects() { 059 060 // setup newDelegateGlobal convenience objects, 061 // make sure all possible sub-objects are populated 062 newDelegateGlobal = (AccountDelegateGlobal) super.getNewBo(); 063 064 // forces refreshes on all the sub-objects in the lists 065 for (AccountDelegateGlobalDetail delegateGlobal : newDelegateGlobal.getDelegateGlobals()) { 066 delegateGlobal.refreshNonUpdateableReferences(); 067 } 068 for (AccountGlobalDetail accountGlobalDetail : newDelegateGlobal.getAccountGlobalDetails()) { 069 accountGlobalDetail.refreshNonUpdateableReferences(); 070 } 071 } 072 073 /** 074 * This checks some basic rules for document approval Specifically it calls the following: 075 * <ul> 076 * <li>{@link DelegateGlobalRule#checkSimpleRulesAllLines()}</li> 077 * <li>{@link DelegateGlobalRule#checkOnlyOneChartErrorWrapper(List)}</li> 078 * <li>{@link DelegateGlobalRule#checkForPrimaryDelegateAllLines()}</li> 079 * </ul> 080 * fails if any rules fail 081 * 082 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) 083 */ 084 @Override 085 protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) { 086 boolean success = true; 087 setupConvenienceObjects(); 088 // check simple rules 089 success &= checkSimpleRulesAllLines(document); 090 091 success &= checkOnlyOneChartErrorWrapper(newDelegateGlobal.getAccountGlobalDetails()); 092 093 // check for primary routing 094 success &= checkForPrimaryDelegateAllLines(); 095 return success; 096 } 097 098 /** 099 * This checks some basic rules for document routing Specifically it calls the following: 100 * <ul> 101 * <li>{@link DelegateGlobalRule#checkSimpleRulesAllLines()}</li> 102 * <li>{@link DelegateGlobalRule#checkAccountDetails(List)}</li> 103 * <li>{@link DelegateGlobalRule#checkForPrimaryDelegateAllLines()}</li> 104 * </ul> 105 * fails if any rules fail 106 * 107 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) 108 */ 109 @Override 110 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { 111 boolean success = true; 112 setupConvenienceObjects(); 113 // check simple rules 114 success &= checkSimpleRulesAllLines(document); 115 116 success &= checkAccountDetails(newDelegateGlobal.getAccountGlobalDetails()); 117 118 // check for primary routing 119 success &= checkForPrimaryDelegateAllLines(); 120 return success; 121 } 122 123 /** 124 * This checks some basic rules for document saving Specifically it calls the following: 125 * <ul> 126 * <li>{@link DelegateGlobalRule#checkSimpleRulesAllLines()}</li> 127 * <li>{@link DelegateGlobalRule#checkOnlyOneChartErrorWrapper(List)}</li> 128 * <li>{@link DelegateGlobalRule#checkForPrimaryDelegateAllLines()}</li> 129 * </ul> 130 * fails if any rules fail 131 * 132 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) 133 */ 134 @Override 135 protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) { 136 setupConvenienceObjects(); 137 // check simple rules 138 checkSimpleRulesAllLines(document); 139 140 checkOnlyOneChartErrorWrapper(newDelegateGlobal.getAccountGlobalDetails()); 141 142 // check for primary routing 143 checkForPrimaryDelegateAllLines(); 144 return true; 145 } 146 147 /** 148 * This checks to see if there are any accounts in the details collection if there are then it calls 149 * {@link DelegateGlobalRule#checkAccountDetails(AccountGlobalDetail)} 150 * 151 * @param details - collection of {@link AccountGlobalDetail}s 152 * @return false if there are no objects in the collection or any one of the {@link AccountGlobalDetail} fail 153 */ 154 public boolean checkAccountDetails(List<AccountGlobalDetail> details) { 155 boolean success = true; 156 157 // check if there are any accounts 158 if (details.size() == 0) { 159 putFieldError(KFSConstants.MAINTENANCE_ADD_PREFIX + "accountGlobalDetails.accountNumber", KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_NO_ACCOUNTS); 160 success = false; 161 } 162 else { 163 // check each account 164 int index = 0; 165 for (AccountGlobalDetail dtl : details) { 166 String errorPath = MAINTAINABLE_ERROR_PREFIX + "accountGlobalDetails[" + index + "]"; 167 GlobalVariables.getMessageMap().addToErrorPath(errorPath); 168 success &= checkAccountDetails(dtl); 169 GlobalVariables.getMessageMap().removeFromErrorPath(errorPath); 170 index++; 171 } 172 success &= checkOnlyOneChartErrorWrapper(details); 173 } 174 175 return success; 176 } 177 178 /** 179 * This checks to make sure that each {@link AccountGlobalDetail} has a valid {@link Account} 180 * 181 * @param dtl - the {@link AccountGlobalDetail} 182 * @return false if it does not have a valid {@link Account} 183 */ 184 public boolean checkAccountDetails(AccountGlobalDetail dtl) { 185 boolean success = true; 186 int originalErrorCount = GlobalVariables.getMessageMap().getErrorCount(); 187 getDictionaryValidationService().validateBusinessObject(dtl); 188 if (StringUtils.isNotBlank(dtl.getAccountNumber()) && StringUtils.isNotBlank(dtl.getChartOfAccountsCode())) { 189 dtl.refreshReferenceObject("account"); 190 if (ObjectUtils.isNull(dtl.getAccount())) { 191 GlobalVariables.getMessageMap().putError("accountNumber", KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_INVALID_ACCOUNT, new String[] { dtl.getChartOfAccountsCode(), dtl.getAccountNumber() }); 192 } 193 } 194 success &= GlobalVariables.getMessageMap().getErrorCount() == originalErrorCount; 195 196 return success; 197 } 198 199 /** 200 * This method checks the simple rules for all lines at once and gets called on save, submit, etc. but not on add Specifically 201 * it calls the following: 202 * <ul> 203 * <li>{@link DelegateGlobalRule#checkDelegateUserRules(DelegateGlobalDetail, int, boolean)}</li> 204 * <li>{@link DelegateGlobalRule#checkDelegateForNullToAmount(KualiDecimal, KualiDecimal, int, boolean)}</li> 205 * <li>{@link DelegateGlobalRule#checkDelegateToAmtGreaterThanFromAmt(KualiDecimal, KualiDecimal, int, boolean)}</li> 206 * <li>{@link DelegateGlobalRule#checkDelegateFromAmtGreaterThanEqualZero(KualiDecimal, int, boolean)}</li> 207 * <li>{@link DelegateGlobalRule#checkPrimaryRouteRules(List, DelegateGlobalDetail, Integer, boolean)}</li> 208 * </ul> 209 * 210 * @return 211 */ 212 protected boolean checkSimpleRulesAllLines(MaintenanceDocument document) { 213 214 boolean success = true; 215 // check if there are any accounts 216 if (newDelegateGlobal.getDelegateGlobals().size() == 0) { 217 putFieldError(KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.DELEGATE_GLOBALS + "." + KFSPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE, KFSKeyConstants.ERROR_DOCUMENT_DELEGATE_CHANGE_NO_DELEGATE); 218 success = false; 219 } 220 else { 221 // check each delegate 222 int i = 0; 223 final FinancialSystemDocumentTypeService documentService = SpringContext.getBean(FinancialSystemDocumentTypeService.class); 224 for (AccountDelegateGlobalDetail newDelegateGlobalDetail : newDelegateGlobal.getDelegateGlobals()) { 225 KualiDecimal fromAmount = newDelegateGlobalDetail.getApprovalFromThisAmount(); 226 KualiDecimal toAmount = newDelegateGlobalDetail.getApprovalToThisAmount(); 227 228 success &= checkDelegateUserRules(document, newDelegateGlobalDetail, i, false); 229 230 // FROM amount must be >= 0 (may not be negative) 231 success &= checkDelegateFromAmtGreaterThanEqualZero(fromAmount, i, false); 232 233 // TO amount must be >= FROM amount or Zero 234 success &= checkDelegateToAmtGreaterThanFromAmt(fromAmount, toAmount, i, false); 235 236 success &= checkDelegateDocumentTypeCode(newDelegateGlobalDetail.getFinancialDocumentTypeCode(), documentService); 237 238 // increment counter for delegate changes list 239 i++; 240 } 241 } 242 return success; 243 } 244 245 246 /** 247 * This method will check through each delegate referenced in the DelegateGlobal to ensure that there is one and only primary 248 * for each account and doctype 249 * 250 * @return false if there is more than one primary delegate 251 */ 252 protected boolean checkForPrimaryDelegateAllLines() { 253 boolean success = true; 254 int i = 0; 255 for (AccountDelegateGlobalDetail newDelegateGlobalDetail : newDelegateGlobal.getDelegateGlobals()) { 256 success &= checkPrimaryRouteRules(newDelegateGlobal.getDelegateGlobals(), newDelegateGlobalDetail, new Integer(i), false); 257 i++; 258 } 259 return success; 260 } 261 262 /** 263 * This method checks to see if the from amount is greater than zero 264 * 265 * @param fromAmount 266 * @param lineNum 267 * @return false if from amount less than zero 268 */ 269 protected boolean checkDelegateFromAmtGreaterThanEqualZero(KualiDecimal fromAmount, int lineNum, boolean add) { 270 boolean success = true; 271 if (ObjectUtils.isNotNull(fromAmount)) { 272 if (fromAmount.isLessThan(ZERO)) { 273 String errorPath = KFSConstants.EMPTY_STRING; 274 if (add) { 275 errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + "approvalFromThisAmount"; 276 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_FROM_AMOUNT_NONNEGATIVE); 277 } 278 else { 279 errorPath = DELEGATE_GLOBALS_PREFIX + "[" + lineNum + "]." + "approvalFromThisAmount"; 280 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_FROM_AMOUNT_NONNEGATIVE); 281 } 282 success &= false; 283 } 284 } 285 return success; 286 } 287 288 /** 289 * This method checks to see if the to Amount is greater than the from amount 290 * 291 * @param fromAmount 292 * @param toAmount 293 * @param lineNum 294 * @return false if to amount less than from amount 295 */ 296 protected boolean checkDelegateToAmtGreaterThanFromAmt(KualiDecimal fromAmount, KualiDecimal toAmount, int lineNum, boolean add) { 297 boolean success = true; 298 if (ObjectUtils.isNotNull(toAmount)) { 299 300 if (!ObjectUtils.isNull(fromAmount)) { 301 // case if FROM amount is non-null and positive, disallow TO amount being less if it is not ZERO (another indicator 302 // of infinity) 303 if (!toAmount.equals(ZERO) && toAmount.isLessThan(fromAmount)) { 304 String errorPath = KFSConstants.EMPTY_STRING; 305 if (add) { 306 errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + "approvalToThisAmount"; 307 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_TO_AMOUNT_MORE_THAN_FROM_OR_ZERO); 308 } 309 else { 310 errorPath = DELEGATE_GLOBALS_PREFIX + "[" + lineNum + "]." + "approvalToThisAmount"; 311 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_TO_AMOUNT_MORE_THAN_FROM_OR_ZERO); 312 } 313 success &= false; 314 } 315 } 316 317 if (toAmount.isLessThan(KualiDecimal.ZERO)) { 318 String errorPath = KFSConstants.EMPTY_STRING; 319 if (add) { 320 errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + "approvalToThisAmount"; 321 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_TO_AMOUNT_MORE_THAN_FROM_OR_ZERO); 322 } 323 else { 324 errorPath = DELEGATE_GLOBALS_PREFIX + "[" + lineNum + "]." + "approvalToThisAmount"; 325 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_TO_AMOUNT_MORE_THAN_FROM_OR_ZERO); 326 } 327 success &= false; 328 } 329 } 330 return success; 331 } 332 333 /** 334 * Validates the document type code for the delegate, to make sure it is a Financial System document type code 335 * 336 * @param documentTypeCode the document type code to check 337 * @param delegateService a helpful instance of the delegate service, so new ones don't have to be created all the time 338 * @return true if the document type code is valid, false otherwise 339 */ 340 protected boolean checkDelegateDocumentTypeCode(String documentTypeCode, FinancialSystemDocumentTypeService documentService) { 341 if (!documentService.isFinancialSystemDocumentType(documentTypeCode)) { 342 String errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + KFSPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE; 343 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_INVALID_DOC_TYPE, new String[] { documentTypeCode, KFSConstants.ROOT_DOCUMENT_TYPE }); 344 345 return false; 346 } 347 return true; 348 } 349 350 /** 351 * This method validates the rule that says there can be only one PrimaryRoute delegate for each given docType. It checks the 352 * delegateGlobalToTest against the list, to determine whether adding this new delegateGlobalToTest would violate any 353 * PrimaryRoute business rule violations. If any of the incoming variables is null or empty, the method will do nothing, and 354 * return Null. It will only process the business rules if there is sufficient data to do so. 355 * 356 * @param delegateGlobalToTest A delegateGlobal line that you want to test against the list. 357 * @param delegateGlobals A List of delegateGlobal items that is being tested against. 358 * @return Null if the business rule passes, or an Integer value greater than zero, representing the line that the new line is 359 * conflicting with 360 */ 361 protected Integer checkPrimaryRoutePerDocType(AccountDelegateGlobalDetail delegateGlobalToTest, List<AccountDelegateGlobalDetail> delegateGlobals, Integer testLineNum) { 362 363 // exit immediately if the adding line isnt a Primary routing 364 if (delegateGlobalToTest == null || delegateGlobals == null || delegateGlobals.isEmpty()) { 365 return null; 366 } 367 if (!delegateGlobalToTest.getAccountDelegatePrimaryRoutingIndicator()) { 368 return null; 369 } 370 if (StringUtils.isBlank(delegateGlobalToTest.getFinancialDocumentTypeCode())) { 371 return null; 372 } 373 374 // at this point, the delegateGlobal being added is a Primary for ALL docTypes, so we need to 375 // test whether any in the existing list are also Primary, regardless of docType 376 String docType = delegateGlobalToTest.getFinancialDocumentTypeCode(); 377 AccountDelegateGlobalDetail delegateGlobal = null; 378 for (int lineNumber = 0; lineNumber < delegateGlobals.size(); lineNumber++) { 379 delegateGlobal = delegateGlobals.get(lineNumber); 380 if (delegateGlobal.getAccountDelegatePrimaryRoutingIndicator()) { 381 if (docType.equalsIgnoreCase(delegateGlobal.getFinancialDocumentTypeCode())) { 382 if (testLineNum == null) { 383 return new Integer(lineNumber); 384 } 385 else if (!(testLineNum.intValue() == lineNumber)) { 386 return new Integer(lineNumber); 387 } 388 } 389 } 390 } 391 392 return null; 393 } 394 395 /** 396 * This checks that the primary routing for delegates is correct, specifically that - there is not already a primary route 397 * delegate setup for this {@link Account} 398 * 399 * @param delegateGlobals 400 * @param delegateGlobalToTest 401 * @param lineNum 402 * @param add 403 * @return 404 */ 405 protected boolean checkPrimaryRouteRules(List<AccountDelegateGlobalDetail> delegateGlobals, AccountDelegateGlobalDetail delegateGlobalToTest, Integer lineNum, boolean add) { 406 boolean success = true; 407 408 String errorPath = ""; 409 Integer result = null; 410 for (AccountDelegateGlobalDetail delegateGlobal : delegateGlobals) { 411 412 result = checkPrimaryRoutePerDocType(delegateGlobalToTest, delegateGlobals, lineNum); 413 if (result != null) { 414 if (add) { 415 errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + "financialDocumentTypeCode"; 416 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_DELEGATEMAINT_PRIMARY_ROUTE_ALREADY_EXISTS_FOR_DOCTYPE); 417 } 418 else { 419 errorPath = DELEGATE_GLOBALS_PREFIX + "[" + lineNum.toString() + "]." + "financialDocumentTypeCode"; 420 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_DELEGATEMAINT_PRIMARY_ROUTE_ALREADY_EXISTS_FOR_DOCTYPE); 421 } 422 success &= false; 423 } 424 } 425 return success; 426 } 427 428 /** 429 * This checks that the delegate for this {@link Account} exists and is valid (active and a professional) 430 * 431 * @param delegateGlobal 432 * @param lineNum 433 * @param add 434 * @return false if the delegate for the {@link Account} doesn't exist or isn't valid 435 */ 436 protected boolean checkDelegateUserRules(MaintenanceDocument document, AccountDelegateGlobalDetail delegateGlobal, int lineNum, boolean add) { 437 boolean success = true; 438 String errorPath = KFSConstants.EMPTY_STRING; 439 440 Person accountDelegate = delegateGlobal.getAccountDelegate(); 441 if (StringUtils.isBlank(delegateGlobal.getAccountDelegateUniversalId()) || ObjectUtils.isNull(accountDelegate)) { 442 if (add) { 443 errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + "accountDelegate.principalName"; 444 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_USER_DOESNT_EXIST); 445 } 446 else { 447 errorPath = DELEGATE_GLOBALS_PREFIX + "[" + lineNum + "]." + "accountDelegate.principalName"; 448 putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_USER_DOESNT_EXIST); 449 } 450 451 success &= false; 452 } 453 else if (!getDocumentHelperService().getDocumentAuthorizer(document).isAuthorized(document, KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER_DELEGATE, accountDelegate.getPrincipalId())) { 454 if (add) { 455 errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + DELEGATE_GLOBALS_PREFIX + "." + "accountDelegate.principalName"; 456 putFieldError(errorPath, KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] { accountDelegate.getName(), KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER_DELEGATE }); 457 } 458 else { 459 errorPath = DELEGATE_GLOBALS_PREFIX + "[" + lineNum + "]." + "accountDelegate.principalName"; 460 putFieldError(errorPath, KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] { accountDelegate.getName(), KFSConstants.ParameterNamespaces.CHART, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER_DELEGATE }); 461 } 462 463 success &= false; 464 } 465 466 return success; 467 } 468 469 /** 470 * This checks that when a new line is added (either {@link AccountGlobalDetail} or {@link DelegateGlobalDetail}) that the 471 * appropriate rules are run on the new lines being added on {@link AccountGlobalDetail}: - make sure that the account number 472 * and chart are entered 473 * <ul> 474 * <li>{@link DelegateGlobalRule#checkAccountDetails(AccountGlobalDetail)}</li> 475 * </ul> 476 * on {@link DelegateGlobalDetail} 477 * <ul> 478 * <li>{@link DelegateGlobalRule#checkDelegateFromAmtGreaterThanEqualZero(KualiDecimal, int, boolean)}</li> 479 * <li>{@link DelegateGlobalRule#checkDelegateForNullToAmount(KualiDecimal, KualiDecimal, int, boolean)}</li> 480 * <li>{@link DelegateGlobalRule#checkDelegateToAmtGreaterThanFromAmt(KualiDecimal, KualiDecimal, int, boolean)}</li> 481 * <li>{@link DelegateGlobalRule#checkDelegateUserRules(DelegateGlobalDetail, int, boolean)}</li> 482 * <li>{@link DelegateGlobalRule#checkPrimaryRouteRules(List, DelegateGlobalDetail, Integer, boolean)}</li> 483 * </ul> 484 * 485 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, 486 * java.lang.String, org.kuali.rice.kns.bo.PersistableBusinessObject) 487 */ 488 public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject bo) { 489 boolean success = true; 490 if (bo instanceof AccountGlobalDetail) { 491 AccountGlobalDetail detail = (AccountGlobalDetail) bo; 492 // make sure that both primary keys are available for this object 493 if (!checkEmptyValue(detail.getAccountNumber())) { 494 // put an error about accountnumber 495 GlobalVariables.getMessageMap().putError("accountNumber", KFSKeyConstants.ERROR_REQUIRED, "Account Number"); 496 success &= false; 497 } 498 if (!checkEmptyValue(detail.getChartOfAccountsCode())) { 499 // put an error about chart code 500 GlobalVariables.getMessageMap().putError("chartOfAccountsCode", KFSKeyConstants.ERROR_REQUIRED, "Chart of Accounts Code"); 501 success &= false; 502 } 503 success &= checkAccountDetails(detail); 504 } 505 else if (bo instanceof AccountDelegateGlobalDetail) { 506 AccountDelegateGlobalDetail detail = (AccountDelegateGlobalDetail) bo; 507 detail.refreshNonUpdateableReferences(); 508 KualiDecimal fromAmount = detail.getApprovalFromThisAmount(); 509 KualiDecimal toAmount = detail.getApprovalToThisAmount(); 510 511 // FROM amount must be >= 0 (may not be negative) 512 success &= checkDelegateFromAmtGreaterThanEqualZero(fromAmount, 0, true); 513 514 // TO amount must be >= FROM amount or Zero 515 success &= checkDelegateToAmtGreaterThanFromAmt(fromAmount, toAmount, 0, true); 516 517 // check the user that is being added 518 // TODO: add back in once the user issues have been fixed 519 success &= checkDelegateUserRules(document, detail, 0, true); 520 521 // check the routing 522 success &= checkPrimaryRouteRules(newDelegateGlobal.getDelegateGlobals(), detail, null, true); 523 524 final FinancialSystemDocumentTypeService documentService = SpringContext.getBean(FinancialSystemDocumentTypeService.class); 525 success &= checkDelegateDocumentTypeCode(detail.getFinancialDocumentTypeCode(), documentService); 526 527 } 528 return success; 529 } 530 531 }