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 020 import org.apache.commons.lang.StringUtils; 021 import org.kuali.kfs.module.endow.EndowConstants; 022 import org.kuali.kfs.module.endow.EndowKeyConstants; 023 import org.kuali.kfs.module.endow.EndowPropertyConstants; 024 import org.kuali.kfs.module.endow.businessobject.ClassCode; 025 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine; 026 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine; 027 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionSecurity; 028 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionTaxLotLine; 029 import org.kuali.kfs.module.endow.businessobject.RegistrationCode; 030 import org.kuali.kfs.module.endow.businessobject.Security; 031 import org.kuali.kfs.module.endow.document.EndowmentSecurityDetailsDocument; 032 import org.kuali.kfs.module.endow.document.EndowmentTransactionalDocument; 033 import org.kuali.kfs.module.endow.document.service.RegistrationCodeService; 034 import org.kuali.kfs.module.endow.document.service.SecurityService; 035 import org.kuali.kfs.sys.context.SpringContext; 036 import org.kuali.rice.kns.document.Document; 037 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 038 import org.kuali.rice.kns.rules.TransactionalDocumentRuleBase; 039 import org.kuali.rice.kns.util.GlobalVariables; 040 import org.kuali.rice.kns.util.KNSConstants; 041 import org.kuali.rice.kns.util.ObjectUtils; 042 043 public class EndowmentTransactionalDocumentBaseRule extends TransactionalDocumentRuleBase { 044 /** 045 * This method is a convenience method to easily add a Document level error (ie, one not tied to a specific field, but 046 * applicable to the whole document). 047 * 048 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 049 */ 050 protected void putGlobalError(String errorConstant) { 051 if (!errorAlreadyExists(KNSConstants.DOCUMENT_ERRORS, errorConstant)) { 052 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KNSConstants.DOCUMENT_ERRORS, errorConstant); 053 } 054 } 055 056 /** 057 * This method is a convenience method to easily add a Document level error (ie, one not tied to a specific field, but 058 * applicable to the whole document). 059 * 060 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 061 * @param parameter - Replacement value for part of the error message. 062 */ 063 protected void putGlobalError(String errorConstant, String parameter) { 064 if (!errorAlreadyExists(KNSConstants.DOCUMENT_ERRORS, errorConstant)) { 065 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KNSConstants.DOCUMENT_ERRORS, errorConstant, parameter); 066 } 067 } 068 069 /** 070 * This method is a convenience method to easily add a Document level error (ie, one not tied to a specific field, but 071 * applicable to the whole document). 072 * 073 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 074 * @param parameters - Array of replacement values for part of the error message. 075 */ 076 protected void putGlobalError(String errorConstant, String[] parameters) { 077 if (!errorAlreadyExists(KNSConstants.DOCUMENT_ERRORS, errorConstant)) { 078 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KNSConstants.DOCUMENT_ERRORS, errorConstant, parameters); 079 } 080 } 081 082 /** 083 * This method is a convenience method to add a property-specific error to the global errors list. This method makes sure that 084 * the correct prefix is added to the property name so that it will display correctly on maintenance documents. 085 * 086 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in 087 * the UI. 088 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 089 */ 090 protected void putFieldError(String propertyName, String errorConstant) { 091 if (!errorAlreadyExists(propertyName, errorConstant)) { 092 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant); 093 } 094 } 095 096 /** 097 * This method is a convenience method to add a property-specific error to the global errors list. This method makes sure that 098 * the correct prefix is added to the property name so that it will display correctly on maintenance documents. 099 * 100 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in 101 * the UI. 102 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 103 * @param parameter - Single parameter value that can be used in the message so that you can display specific values to the 104 * user. 105 */ 106 protected void putFieldError(String propertyName, String errorConstant, String parameter) { 107 if (!errorAlreadyExists(propertyName, errorConstant)) { 108 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant, parameter); 109 } 110 } 111 112 /** 113 * This method is a convenience method to add a property-specific error to the global errors list. This method makes sure that 114 * the correct prefix is added to the property name so that it will display correctly on maintenance documents. 115 * 116 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in 117 * the UI. 118 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 119 * @param parameters - Array of strings holding values that can be used in the message so that you can display specific values 120 * to the user. 121 */ 122 protected void putFieldError(String propertyName, String errorConstant, String[] parameters) { 123 if (!errorAlreadyExists(propertyName, errorConstant)) { 124 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant, parameters); 125 } 126 } 127 128 /** 129 * This method is a convenience method to add a property-specific document error to the global errors list. This method makes 130 * sure that the correct prefix is added to the property name so that it will display correctly on maintenance documents. 131 * 132 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in 133 * the UI. 134 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 135 * @param parameter - Single parameter value that can be used in the message so that you can display specific values to the 136 * user. 137 */ 138 protected void putDocumentError(String propertyName, String errorConstant, String parameter) { 139 if (!errorAlreadyExists(MaintenanceDocumentRuleBase.DOCUMENT_ERROR_PREFIX + propertyName, errorConstant)) { 140 GlobalVariables.getMessageMap().putError(MaintenanceDocumentRuleBase.DOCUMENT_ERROR_PREFIX + propertyName, errorConstant, parameter); 141 } 142 } 143 144 /** 145 * This method is a convenience method to add a property-specific document error to the global errors list. This method makes 146 * sure that the correct prefix is added to the property name so that it will display correctly on maintenance documents. 147 * 148 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in 149 * the UI. 150 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 151 * @param parameters - Array of String parameters that can be used in the message so that you can display specific values to the 152 * user. 153 */ 154 protected void putDocumentError(String propertyName, String errorConstant, String[] parameters) { 155 GlobalVariables.getMessageMap().putError(MaintenanceDocumentRuleBase.DOCUMENT_ERROR_PREFIX + propertyName, errorConstant, parameters); 156 } 157 158 /** 159 * Convenience method to determine whether the field already has the message indicated. This is useful if you want to suppress 160 * duplicate error messages on the same field. 161 * 162 * @param propertyName - propertyName you want to test on 163 * @param errorConstant - errorConstant you want to test 164 * @return returns True if the propertyName indicated already has the errorConstant indicated, false otherwise 165 */ 166 protected boolean errorAlreadyExists(String propertyName, String errorConstant) { 167 168 if (GlobalVariables.getMessageMap().fieldHasMessage(propertyName, errorConstant)) { 169 return true; 170 } 171 else { 172 return false; 173 } 174 } 175 176 /** 177 * This method specifically doesn't put any prefixes before the error so that the developer can do things specific to the 178 * globals errors (like newDelegateChangeDocument errors) 179 * 180 * @param propertyName 181 * @param errorConstant 182 */ 183 protected void putGlobalsError(String propertyName, String errorConstant) { 184 if (!errorAlreadyExists(propertyName, errorConstant)) { 185 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant); 186 } 187 } 188 189 /** 190 * This method specifically doesn't put any prefixes before the error so that the developer can do things specific to the 191 * globals errors (like newDelegateChangeDocument errors) 192 * 193 * @param propertyName 194 * @param errorConstant 195 * @param parameter 196 */ 197 protected void putGlobalsError(String propertyName, String errorConstant, String parameter) { 198 if (!errorAlreadyExists(propertyName, errorConstant)) { 199 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant, parameter); 200 } 201 } 202 203 204 /** 205 * This method obtains the Prefix for displaying errors on the UI for Source & Target lines. 206 * 207 * @param document 208 * @param isSource 209 * @return 210 */ 211 protected String getEndowmentTransactionSecurityPrefix(EndowmentTransactionalDocument document, boolean isSource) { 212 if (isSource) 213 return EndowPropertyConstants.TRANSACTION_SOURCE_SECURITY_PREFIX; 214 else 215 return EndowPropertyConstants.TRANSACTION_TARGET_SECURITY_PREFIX; 216 } 217 218 /** 219 * This method returns the Security line associated with a Transaction. 220 * 221 * @param document 222 * @param isSource 223 * @return 224 */ 225 protected EndowmentTransactionSecurity getEndowmentTransactionSecurity(EndowmentTransactionalDocument document, boolean isSource) { 226 if (isSource) 227 return ((EndowmentSecurityDetailsDocument) document).getSourceTransactionSecurity(); 228 else 229 return ((EndowmentSecurityDetailsDocument) document).getTargetTransactionSecurity(); 230 } 231 232 /** 233 * This method validate the Security code. 234 * 235 * @param tranSecurity 236 * @return 237 */ 238 protected boolean isSecurityCodeEmpty(EndowmentTransactionalDocument document, boolean isSource) { 239 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 240 241 if (StringUtils.isEmpty(tranSecurity.getSecurityID())) { 242 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_REQUIRED); 243 return true; 244 } 245 246 return false; 247 } 248 249 /** 250 * This method validates the Registration code. 251 * 252 * @param tranSecurity 253 * @return 254 */ 255 protected boolean isRegistrationCodeEmpty(EndowmentTransactionalDocument document, boolean isSource) { 256 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 257 258 if (StringUtils.isEmpty(tranSecurity.getRegistrationCode())) { 259 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_REGISTRATION_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_REGISTRATION_CODE_REQUIRED); 260 return true; 261 } 262 263 return false; 264 } 265 266 267 /** 268 * This method validates the Security code by trying to create a Security object from the code. 269 * 270 * @param document 271 * @param isSource 272 * @return 273 */ 274 protected boolean validateSecurityCode(EndowmentSecurityDetailsDocument document, boolean isSource) { 275 boolean success = true; 276 String prefix = null; 277 278 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 279 280 Security security = (Security) SpringContext.getBean(SecurityService.class).getByPrimaryKey(tranSecurity.getSecurityID()); 281 tranSecurity.setSecurity(security); 282 if (null == security) { 283 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_INVALID); 284 success = false; 285 } 286 287 return success; 288 } 289 290 /** 291 * This method validates the Registration code by trying to create a RegistrationCode object from the code. 292 * 293 * @param document 294 * @param isSource 295 * @return 296 */ 297 protected boolean validateRegistrationCode(EndowmentSecurityDetailsDocument document, boolean isSource) { 298 boolean success = true; 299 String prefix = null; 300 301 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 302 303 RegistrationCode registrationCode = (RegistrationCode) SpringContext.getBean(RegistrationCodeService.class).getByPrimaryKey(tranSecurity.getRegistrationCode()); 304 tranSecurity.setRegistrationCodeObj(registrationCode); 305 if (null == registrationCode) { 306 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_REGISTRATION_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_REGISTRATION_CODE_INVALID); 307 success = false; 308 } 309 310 return success; 311 } 312 313 /** 314 * This method checks if the Security is Active. 315 * 316 * @param document 317 * @param isSource 318 * @return 319 */ 320 protected boolean isSecurityActive(EndowmentSecurityDetailsDocument document, boolean isSource) { 321 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 322 323 if (tranSecurity.getSecurity().isActive()) 324 return true; 325 else { 326 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_INACTIVE); 327 return false; 328 } 329 } 330 331 /** 332 * Validates that the security class code type is not Liability. 333 * 334 * @param endowmentTransactionSecurity 335 * @return true is valid, false otherwise 336 */ 337 protected boolean validateSecurityClassCodeTypeNotLiability(EndowmentSecurityDetailsDocument document, boolean isSource) { 338 boolean isValid = true; 339 EndowmentTransactionSecurity endowmentTransactionSecurity = getEndowmentTransactionSecurity(document, isSource); 340 Security security = endowmentTransactionSecurity.getSecurity(); 341 if (ObjectUtils.isNotNull(security)) { 342 ClassCode classCode = security.getClassCode(); 343 if (ObjectUtils.isNotNull(classCode)) { 344 String classCodeType = classCode.getClassCodeType(); 345 if (EndowConstants.ClassCodeTypes.LIABILITY.equalsIgnoreCase(classCodeType)) { 346 isValid = false; 347 348 if (isSource) { 349 putFieldError(EndowPropertyConstants.TRANSACTION_SOURCE_SECURITY_PREFIX + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_NOT_LIABILITY); 350 } 351 else { 352 putFieldError(EndowPropertyConstants.TRANSACTION_TARGET_SECURITY_PREFIX + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_NOT_LIABILITY); 353 } 354 } 355 } 356 } 357 358 return isValid; 359 360 } 361 362 /** 363 * This method checks if the Registration Code is Active. 364 * 365 * @param document 366 * @param isSource 367 * @return 368 */ 369 protected boolean isRegistrationCodeActive(EndowmentSecurityDetailsDocument document, boolean isSource) { 370 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 371 372 if (tranSecurity.getRegistrationCodeObj().isActive()) 373 return true; 374 else { 375 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_REGISTRATION_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_REGISTRATION_CODE_INACTIVE); 376 return false; 377 } 378 } 379 380 /** 381 * This method validates the Security Class Type Code. 382 * 383 * @param document 384 * @param isSource 385 * @param classCodeType 386 * @return 387 */ 388 protected boolean validateSecurityClassTypeCode(EndowmentSecurityDetailsDocument document, boolean isSource, String classCodeType) { 389 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource); 390 tranSecurity.getSecurity().refreshNonUpdateableReferences(); 391 392 if (tranSecurity.getSecurity().getClassCode().getClassCodeType().equalsIgnoreCase(classCodeType)) 393 return true; 394 else { 395 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_CLASS_CODE_MISMATCH); 396 return false; 397 } 398 } 399 400 /** 401 * @see org.kuali.rice.kns.rules.DocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.Document) 402 */ 403 @Override 404 protected boolean processCustomRouteDocumentBusinessRules(Document document) { 405 boolean isValid = super.processCustomSaveDocumentBusinessRules(document); 406 isValid &= !GlobalVariables.getMessageMap().hasErrors(); 407 408 EndowmentTransactionalDocument endowmentTransactionalDocument = null; 409 410 if (isValid) { 411 endowmentTransactionalDocument = (EndowmentTransactionalDocument) document; 412 413 // Validates Tx Sub Type Code 414 isValid &= isSubTypeEmpty(endowmentTransactionalDocument); 415 } 416 417 return GlobalVariables.getMessageMap().getErrorCount() == 0; 418 } 419 420 /** 421 * This method validates the Sub Type Code. 422 * 423 * @param document 424 * @return 425 */ 426 protected boolean isSubTypeEmpty(EndowmentTransactionalDocument document) { 427 boolean success = true; 428 429 if (StringUtils.isEmpty(document.getTransactionSubTypeCode())) { 430 putFieldError(EndowConstants.TRANSACTION_DETAILS_ERRORS, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_DETAILS_SUB_TYPE_REQUIRED); 431 success = false; 432 } 433 434 return success; 435 } 436 437 }