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.cam.document.validation.impl; 017 018 import java.util.ArrayList; 019 import java.util.HashMap; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.commons.lang.StringUtils; 024 import org.kuali.kfs.coa.businessobject.ObjectCode; 025 import org.kuali.kfs.coa.service.ObjectCodeService; 026 import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService; 027 import org.kuali.kfs.module.cam.CamsConstants; 028 import org.kuali.kfs.module.cam.CamsKeyConstants; 029 import org.kuali.kfs.module.cam.CamsPropertyConstants; 030 import org.kuali.kfs.module.cam.CamsConstants.DocumentTypeName; 031 import org.kuali.kfs.module.cam.businessobject.Asset; 032 import org.kuali.kfs.module.cam.businessobject.AssetObjectCode; 033 import org.kuali.kfs.module.cam.businessobject.AssetPayment; 034 import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal; 035 import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobalDetail; 036 import org.kuali.kfs.module.cam.document.gl.AssetRetirementGeneralLedgerPendingEntrySource; 037 import org.kuali.kfs.module.cam.document.service.AssetObjectCodeService; 038 import org.kuali.kfs.module.cam.document.service.AssetPaymentService; 039 import org.kuali.kfs.module.cam.document.service.AssetRetirementService; 040 import org.kuali.kfs.module.cam.document.service.AssetService; 041 import org.kuali.kfs.sys.KFSKeyConstants; 042 import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader; 043 import org.kuali.kfs.sys.context.SpringContext; 044 import org.kuali.kfs.sys.document.authorization.FinancialSystemMaintenanceDocumentAuthorizerBase; 045 import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService; 046 import org.kuali.rice.kns.bo.PersistableBusinessObject; 047 import org.kuali.rice.kns.document.MaintenanceDocument; 048 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 049 import org.kuali.rice.kns.service.BusinessObjectService; 050 import org.kuali.rice.kns.service.DataDictionaryService; 051 import org.kuali.rice.kns.service.DocumentHelperService; 052 import org.kuali.rice.kns.service.ParameterService; 053 import org.kuali.rice.kns.util.GlobalVariables; 054 import org.kuali.rice.kns.util.ObjectUtils; 055 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 056 057 /** 058 * Business rules applicable to AssetLocationGlobal documents. 059 */ 060 public class AssetRetirementGlobalRule extends MaintenanceDocumentRuleBase { 061 062 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetRetirementGlobalRule.class); 063 064 protected PersistableBusinessObject bo; 065 066 067 /** 068 * Constructs a AssetLocationGlobalRule 069 */ 070 public AssetRetirementGlobalRule() { 071 } 072 073 /** 074 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects() 075 */ 076 @Override 077 public void setupConvenienceObjects() { 078 AssetRetirementGlobal newRetirementGlobal = (AssetRetirementGlobal) super.getNewBo(); 079 newRetirementGlobal.refreshNonUpdateableReferences(); 080 for (AssetRetirementGlobalDetail detail : newRetirementGlobal.getAssetRetirementGlobalDetails()) { 081 detail.refreshNonUpdateableReferences(); 082 } 083 } 084 085 /** 086 * Forces the processing of rules when saving. 087 * 088 * @param document MaintenanceDocument 089 * @return boolean true when valid; Namely we need to enforce foreign key constraints else 090 * processCustomSaveDocumentBusinessRules does not force user back to the document for error correction. 091 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#isDocumentValidForSave(org.kuali.rice.kns.document.MaintenanceDocument) 092 */ 093 @Override 094 protected boolean isDocumentValidForSave(MaintenanceDocument document) { 095 boolean valid = super.isDocumentValidForSave(document); 096 097 if (valid) { 098 AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getNewMaintainableObject().getBusinessObject(); 099 100 setupConvenienceObjects(); 101 valid &= assetRetirementValidation(assetRetirementGlobal, document); 102 } 103 104 return valid; 105 } 106 107 108 /** 109 * Processes rules when saving this global. 110 * 111 * @param document MaintenanceDocument type of document to be processed. 112 * @return boolean true when success 113 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) 114 */ 115 @Override 116 protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) { 117 boolean valid = true; 118 AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getNewMaintainableObject().getBusinessObject(); 119 120 setupConvenienceObjects(); 121 valid &= assetRetirementValidation(assetRetirementGlobal, document); 122 123 if ((valid && super.processCustomSaveDocumentBusinessRules(document)) && !getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal) && !allPaymentsFederalOwned(assetRetirementGlobal)) { 124 // Check if Asset Object Code and Object code exists and active. 125 if (valid &= validateObjectCodesForGLPosting(assetRetirementGlobal)) { 126 // create poster 127 AssetRetirementGeneralLedgerPendingEntrySource assetRetirementGlPoster = new AssetRetirementGeneralLedgerPendingEntrySource((FinancialSystemDocumentHeader) document.getDocumentHeader()); 128 // create postables 129 getAssetRetirementService().createGLPostables(assetRetirementGlobal, assetRetirementGlPoster); 130 131 if (SpringContext.getBean(GeneralLedgerPendingEntryService.class).generateGeneralLedgerPendingEntries(assetRetirementGlPoster)) { 132 assetRetirementGlobal.setGeneralLedgerPendingEntries(assetRetirementGlPoster.getPendingEntries()); 133 } 134 else { 135 assetRetirementGlPoster.getPendingEntries().clear(); 136 } 137 } 138 } 139 140 // add doc header description if retirement reason is "MERGED" 141 if (CamsConstants.AssetRetirementReasonCode.MERGED.equals(assetRetirementGlobal.getRetirementReasonCode())) { 142 if (!document.getDocumentHeader().getDocumentDescription().toLowerCase().contains(CamsConstants.AssetRetirementGlobal.MERGE_AN_ASSET_DESCRIPTION.toLowerCase())) { 143 document.getDocumentHeader().setDocumentDescription(CamsConstants.AssetRetirementGlobal.MERGE_AN_ASSET_DESCRIPTION + " " + document.getDocumentHeader().getDocumentDescription()); 144 } 145 } 146 // get asset locks 147 List<Long> capitalAssetNumbers = retrieveAssetNumbersForLocking(assetRetirementGlobal); 148 valid &= !this.getCapitalAssetManagementModuleService().isAssetLocked(capitalAssetNumbers, DocumentTypeName.ASSET_RETIREMENT_GLOBAL, document.getDocumentNumber()); 149 150 return valid; 151 } 152 153 protected List<Long> retrieveAssetNumbersForLocking(AssetRetirementGlobal assetRetirementGlobal) { 154 List<Long> capitalAssetNumbers = new ArrayList<Long>(); 155 if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal) && assetRetirementGlobal.getMergedTargetCapitalAssetNumber() != null) { 156 capitalAssetNumbers.add(assetRetirementGlobal.getMergedTargetCapitalAssetNumber()); 157 } 158 159 for (AssetRetirementGlobalDetail retirementDetail : assetRetirementGlobal.getAssetRetirementGlobalDetails()) { 160 if (retirementDetail.getCapitalAssetNumber() != null) { 161 capitalAssetNumbers.add(retirementDetail.getCapitalAssetNumber()); 162 } 163 } 164 return capitalAssetNumbers; 165 } 166 167 @Override 168 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { 169 boolean valid = super.processCustomRouteDocumentBusinessRules(document); 170 171 KualiWorkflowDocument workflowDoc = document.getDocumentHeader().getWorkflowDocument(); 172 // adding asset locks 173 if (!GlobalVariables.getMessageMap().hasErrors() && (workflowDoc.stateIsInitiated() || workflowDoc.stateIsSaved())) { 174 valid &= setAssetLocks(document); 175 176 } 177 return valid; 178 } 179 180 protected boolean setAssetLocks(MaintenanceDocument document) { 181 AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getNewMaintainableObject().getBusinessObject(); 182 // get asset locks 183 return this.getCapitalAssetManagementModuleService().storeAssetLocks(retrieveAssetNumbersForLocking(assetRetirementGlobal), document.getDocumentNumber(), DocumentTypeName.ASSET_RETIREMENT_GLOBAL, null); 184 } 185 186 protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() { 187 return SpringContext.getBean(CapitalAssetManagementModuleService.class); 188 } 189 190 191 /** 192 * Check if all asset payments are federal owned. 193 * 194 * @param assetRetirementGlobal 195 * @return 196 */ 197 protected boolean allPaymentsFederalOwned(AssetRetirementGlobal assetRetirementGlobal) { 198 List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); 199 for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) { 200 for (AssetPayment assetPayment : assetRetirementGlobalDetail.getAsset().getAssetPayments()) { 201 if (!getAssetPaymentService().isPaymentFederalOwned(assetPayment)) { 202 return false; 203 } 204 } 205 } 206 return true; 207 } 208 209 /** 210 * Validate Asset Object Codes and Fin Object Codes eligible for GL Posting. 211 * 212 * @param assetRetirementGlobal 213 * @return 214 */ 215 protected boolean validateObjectCodesForGLPosting(AssetRetirementGlobal assetRetirementGlobal) { 216 boolean valid = true; 217 List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); 218 Asset asset = null; 219 List<AssetPayment> assetPayments = null; 220 221 for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) { 222 asset = assetRetirementGlobalDetail.getAsset(); 223 assetPayments = asset.getAssetPayments(); 224 for (AssetPayment assetPayment : assetPayments) { 225 if (!getAssetPaymentService().isPaymentFederalOwned(assetPayment)) { 226 // validate Asset Object Code and Financial Object Codes respectively 227 if (valid &= validateAssetObjectCode(asset, assetPayment)) { 228 valid &= validateFinancialObjectCodes(asset, assetPayment); 229 } 230 } 231 } 232 } 233 234 return valid; 235 } 236 237 /** 238 * Check Financial Object Code for GLPE. 239 * 240 * @param asset 241 * @param assetPayment 242 * @return 243 */ 244 protected boolean validateFinancialObjectCodes(Asset asset, AssetPayment assetPayment) { 245 AssetPaymentService assetPaymentService = getAssetPaymentService(); 246 boolean valid = true; 247 ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class); 248 ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(assetPayment.getChartOfAccountsCode(), assetPayment.getFinancialObjectCode()); 249 250 AssetObjectCode assetObjectCode = getAssetObjectCodeService().findAssetObjectCode(asset.getOrganizationOwnerChartOfAccountsCode(), objectCode.getFinancialObjectSubTypeCode()); 251 if (assetPaymentService.isPaymentEligibleForCapitalizationGLPosting(assetPayment)) { 252 // check for capitalization financial object code existing. 253 assetObjectCode.refreshReferenceObject(CamsPropertyConstants.AssetObjectCode.CAPITALIZATION_FINANCIAL_OBJECT); 254 valid &= validateFinObjectCodeForGLPosting(asset.getOrganizationOwnerChartOfAccountsCode(), assetObjectCode.getCapitalizationFinancialObjectCode(), assetObjectCode.getCapitalizationFinancialObject(), CamsConstants.GLPostingObjectCodeType.CAPITALIZATION); 255 } 256 if (assetPaymentService.isPaymentEligibleForAccumDeprGLPosting(assetPayment)) { 257 // check for accumulate depreciation financial Object Code existing 258 assetObjectCode.refreshReferenceObject(CamsPropertyConstants.AssetObjectCode.ACCUMULATED_DEPRECIATION_FINANCIAL_OBJECT); 259 valid &= validateFinObjectCodeForGLPosting(asset.getOrganizationOwnerChartOfAccountsCode(), assetObjectCode.getAccumulatedDepreciationFinancialObjectCode(), assetObjectCode.getAccumulatedDepreciationFinancialObject(), CamsConstants.GLPostingObjectCodeType.ACCUMMULATE_DEPRECIATION); 260 } 261 if (assetPaymentService.isPaymentEligibleForOffsetGLPosting(assetPayment)) { 262 // check for offset financial object code existing. 263 valid &= validateFinObjectCodeForGLPosting(asset.getOrganizationOwnerChartOfAccountsCode(), SpringContext.getBean(ParameterService.class).getParameterValue(AssetRetirementGlobal.class, CamsConstants.Parameters.DEFAULT_GAIN_LOSS_DISPOSITION_OBJECT_CODE), getAssetRetirementService().getOffsetFinancialObject(asset.getOrganizationOwnerChartOfAccountsCode()), CamsConstants.GLPostingObjectCodeType.OFFSET_AMOUNT); 264 } 265 return valid; 266 } 267 268 /** 269 * check existence and active status for given financial Object Code BO. 270 * 271 * @param chartCode 272 * @param finObjectCode 273 * @param finObject 274 * @return 275 */ 276 protected boolean validateFinObjectCodeForGLPosting(String chartOfAccountsCode, String finObjectCode, ObjectCode finObject, String glPostingType) { 277 boolean valid = true; 278 // not defined in Asset Object Code table 279 if (StringUtils.isBlank(finObjectCode)) { 280 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.GLPosting.ERROR_OBJECT_CODE_FROM_ASSET_OBJECT_CODE_NOT_FOUND, new String[] { glPostingType, chartOfAccountsCode }); 281 valid = false; 282 } 283 // check Object Code existing 284 else if (ObjectUtils.isNull(finObject)) { 285 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.GLPosting.ERROR_OBJECT_CODE_FROM_ASSET_OBJECT_CODE_INVALID, new String[] { glPostingType, finObjectCode, chartOfAccountsCode }); 286 valid = false; 287 } 288 // check Object Code active 289 else if (!finObject.isActive()) { 290 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.GLPosting.ERROR_OBJECT_CODE_FROM_ASSET_OBJECT_CODE_INACTIVE, new String[] { glPostingType, finObjectCode, chartOfAccountsCode }); 291 valid = false; 292 } 293 return valid; 294 } 295 296 /** 297 * Asset Object Code must exist as an active status. 298 * 299 * @param asset 300 * @param assetPayment 301 * @return 302 */ 303 protected boolean validateAssetObjectCode(Asset asset, AssetPayment assetPayment) { 304 boolean valid = true; 305 ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class); 306 ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(assetPayment.getChartOfAccountsCode(), assetPayment.getFinancialObjectCode()); 307 308 AssetObjectCode assetObjectCode = getAssetObjectCodeService().findAssetObjectCode(asset.getOrganizationOwnerChartOfAccountsCode(), objectCode.getFinancialObjectSubTypeCode()); 309 // check Asset Object Code existing. 310 if (ObjectUtils.isNull(assetObjectCode)) { 311 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.GLPosting.ERROR_ASSET_OBJECT_CODE_NOT_FOUND, new String[] { asset.getOrganizationOwnerChartOfAccountsCode(), objectCode.getFinancialObjectSubTypeCode() }); 312 valid = false; 313 } 314 // check Asset Object Code active 315 else if (!assetObjectCode.isActive()) { 316 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.GLPosting.ERROR_ASSET_OBJECT_CODE_INACTIVE, new String[] { asset.getOrganizationOwnerChartOfAccountsCode(), objectCode.getFinancialObjectSubTypeCode() }); 317 valid = false; 318 } 319 320 return valid; 321 } 322 323 /** 324 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, 325 * java.lang.String, org.kuali.rice.kns.bo.PersistableBusinessObject) 326 */ 327 @Override 328 public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) { 329 boolean success = true; 330 AssetRetirementGlobalDetail assetRetirementGlobalDetail = (AssetRetirementGlobalDetail) line; 331 AssetRetirementGlobal assetRetirementGlobal = (AssetRetirementGlobal) document.getDocumentBusinessObject(); 332 333 if (!checkEmptyValue(assetRetirementGlobalDetail.getCapitalAssetNumber())) { 334 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_BLANK_CAPITAL_ASSET_NUMBER); 335 return false; 336 } 337 assetRetirementGlobalDetail.refreshReferenceObject(CamsPropertyConstants.AssetLocationGlobalDetail.ASSET); 338 339 if (ObjectUtils.isNull(assetRetirementGlobalDetail.getAsset())) { 340 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_INVALID_CAPITAL_ASSET_NUMBER, assetRetirementGlobalDetail.getCapitalAssetNumber().toString()); 341 return false; 342 } 343 344 if (this.getAssetService().isAssetLoaned(assetRetirementGlobalDetail.getAsset())) { 345 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_LOANED_ASSET_CANNOT_RETIRED); 346 success = false; 347 } 348 else if (!getAssetService().isDocumentEnrouting(document)) { 349 success &= checkRetirementDetailOneLine(assetRetirementGlobalDetail, assetRetirementGlobal, document); 350 success &= checkRetireMultipleAssets(assetRetirementGlobal.getRetirementReasonCode(), assetRetirementGlobal.getAssetRetirementGlobalDetails(), new Integer(0), document); 351 } 352 353 // Calculate summary fields in order to show the values even though add new line fails. 354 for (AssetRetirementGlobalDetail detail : assetRetirementGlobal.getAssetRetirementGlobalDetails()) { 355 getAssetService().setAssetSummaryFields(detail.getAsset()); 356 } 357 return success & super.processCustomAddCollectionLineBusinessRules(document, collectionName, line); 358 } 359 360 /** 361 * Check if only single asset is allowed to retire. 362 * 363 * @param retirementReasonCode 364 * @param assetRetirementDetails 365 * @param maxNumber 366 * @param maintenanceDocument 367 * @return 368 */ 369 protected boolean checkRetireMultipleAssets(String retirementReasonCode, List<AssetRetirementGlobalDetail> assetRetirementDetails, Integer maxNumber, MaintenanceDocument maintenanceDocument) { 370 boolean success = true; 371 372 if (assetRetirementDetails.size() > maxNumber && !getAssetRetirementService().isAllowedRetireMultipleAssets(maintenanceDocument)) { 373 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_MULTIPLE_ASSET_RETIRED); 374 success = false; 375 } 376 377 return success; 378 } 379 380 /** 381 * This method validates each asset to be retired. 382 * 383 * @param assetRetirementGlobalDetails 384 * @param maintenanceDocument 385 * @return 386 */ 387 protected boolean validateRetirementDetails(AssetRetirementGlobal assetRetirementGlobal, MaintenanceDocument maintenanceDocument) { 388 boolean success = true; 389 390 List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails(); 391 392 if (assetRetirementGlobalDetails.size() == 0) { 393 success = false; 394 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_ASSET_RETIREMENT_GLOBAL_NO_ASSET); 395 } 396 else { 397 // validate each asset retirement detail 398 int index = 0; 399 for (AssetRetirementGlobalDetail detail : assetRetirementGlobalDetails) { 400 String errorPath = MAINTAINABLE_ERROR_PREFIX + CamsPropertyConstants.AssetRetirementGlobal.ASSET_RETIREMENT_GLOBAL_DETAILS + "[" + index++ + "]"; 401 GlobalVariables.getMessageMap().addToErrorPath(errorPath); 402 403 success &= checkRetirementDetailOneLine(detail, assetRetirementGlobal, maintenanceDocument); 404 405 GlobalVariables.getMessageMap().removeFromErrorPath(errorPath); 406 } 407 } 408 return success; 409 } 410 411 412 /** 413 * This method validates one asset is a valid asset and no duplicate with target asset when merge. 414 * 415 * @param assetRetirementGlobalDetail 416 * @param assetRetirementGlobal 417 * @param maintenanceDocument 418 * @return 419 */ 420 protected boolean checkRetirementDetailOneLine(AssetRetirementGlobalDetail assetRetirementGlobalDetail, AssetRetirementGlobal assetRetirementGlobal, MaintenanceDocument maintenanceDocument) { 421 boolean success = true; 422 423 assetRetirementGlobalDetail.refreshReferenceObject(CamsPropertyConstants.AssetRetirementGlobalDetail.ASSET); 424 425 Asset asset = assetRetirementGlobalDetail.getAsset(); 426 427 if (ObjectUtils.isNull(asset)) { 428 success = false; 429 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_INVALID_CAPITAL_ASSET_NUMBER, assetRetirementGlobalDetail.getCapitalAssetNumber().toString()); 430 } 431 else { 432 success &= validateActiveCapitalAsset(asset); 433 success &= validateNonMoveableAsset(asset, maintenanceDocument); 434 435 if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) { 436 success &= validateDuplicateAssetNumber(assetRetirementGlobal.getMergedTargetCapitalAssetNumber(), assetRetirementGlobalDetail.getCapitalAssetNumber()); 437 } 438 439 // Set asset non persistent fields 440 getAssetService().setAssetSummaryFields(asset); 441 } 442 443 return success; 444 } 445 446 /** 447 * Check for Merge Asset, no duplicate capitalAssetNumber between "from" and "to". 448 * 449 * @param targetAssetNumber 450 * @param sourceAssetNumber 451 * @return 452 */ 453 protected boolean validateDuplicateAssetNumber(Long targetAssetNumber, Long sourceAssetNumber) { 454 boolean success = true; 455 456 if (getAssetService().isCapitalAssetNumberDuplicate(targetAssetNumber, sourceAssetNumber)) { 457 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_DUPLICATE_CAPITAL_ASSET_NUMBER_WITH_TARGET, sourceAssetNumber.toString()); 458 success = false; 459 } 460 461 return success; 462 } 463 464 /** 465 * User must be in work group CM_SUPER_USERS to retire a non-moveable asset. 466 * 467 * @param asset 468 * @param maintenanceDocument 469 * @return 470 */ 471 protected boolean validateNonMoveableAsset(Asset asset, MaintenanceDocument maintenanceDocument) { 472 boolean success = true; 473 474 FinancialSystemMaintenanceDocumentAuthorizerBase documentAuthorizer = (FinancialSystemMaintenanceDocumentAuthorizerBase) SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(maintenanceDocument); 475 boolean isAuthorized = documentAuthorizer.isAuthorized(maintenanceDocument, CamsConstants.CAM_MODULE_CODE, CamsConstants.PermissionNames.RETIRE_NON_MOVABLE_ASSETS, GlobalVariables.getUserSession().getPerson().getPrincipalId()); 476 477 if (!getAssetService().isAssetMovableCheckByAsset(asset) && !isAuthorized) { 478 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_INVALID_USER_GROUP_FOR_NON_MOVEABLE_ASSET, asset.getCapitalAssetNumber().toString()); 479 success = false; 480 } 481 482 return success; 483 } 484 485 486 /** 487 * Validate Asset Retirement Global and Details. 488 * 489 * @param assetRetirementGlobal 490 * @param maintenanceDocument 491 * @return 492 */ 493 protected boolean assetRetirementValidation(AssetRetirementGlobal assetRetirementGlobal, MaintenanceDocument maintenanceDocument) { 494 boolean valid = true; 495 496 valid &= validateRequiredGlobalFields(assetRetirementGlobal); 497 if (getAssetRetirementService().isAssetRetiredByMerged(assetRetirementGlobal)) { 498 valid &= validateMergeTargetAsset(assetRetirementGlobal); 499 } 500 501 if (!getAssetService().isDocumentEnrouting(maintenanceDocument)) { 502 valid &= validateRetirementDetails(assetRetirementGlobal, maintenanceDocument); 503 valid &= checkRetireMultipleAssets(assetRetirementGlobal.getRetirementReasonCode(), assetRetirementGlobal.getAssetRetirementGlobalDetails(), new Integer(1), maintenanceDocument); 504 } 505 return valid; 506 } 507 508 509 /** 510 * Validate mergedTargetCapitalAsset. Only valid and active capital asset is allowed. 511 * 512 * @param assetRetirementGlobal 513 * @return 514 */ 515 protected boolean validateMergeTargetAsset(AssetRetirementGlobal assetRetirementGlobal) { 516 boolean valid = true; 517 Asset targetAsset = assetRetirementGlobal.getMergedTargetCapitalAsset(); 518 Long targetAssetNumber = assetRetirementGlobal.getMergedTargetCapitalAssetNumber(); 519 520 if (!checkEmptyValue(targetAssetNumber)) { 521 putFieldError(CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_BLANK_CAPITAL_ASSET_NUMBER); 522 valid = false; 523 } 524 else if (ObjectUtils.isNull(targetAsset)) { 525 putFieldError(CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_INVALID_MERGED_TARGET_ASSET_NUMBER, targetAssetNumber.toString()); 526 valid = false; 527 } 528 else { 529 // Check asset of capital and active 530 if (!getAssetService().isCapitalAsset(targetAsset)) { 531 putFieldError(CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_NON_CAPITAL_ASSET_RETIREMENT, targetAssetNumber.toString()); 532 valid = false; 533 } 534 if (getAssetService().isAssetRetired(targetAsset)) { 535 putFieldError(CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_NON_ACTIVE_ASSET_RETIREMENT, targetAssetNumber.toString()); 536 valid = false; 537 } 538 } 539 540 // Validating the mergeAssetDescription is not blank 541 if (!checkEmptyValue(assetRetirementGlobal.getMergedTargetCapitalAssetDescription())) { 542 String label = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(AssetRetirementGlobal.class.getName()).getAttributeDefinition(CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET_DESC).getLabel(); 543 putFieldError(CamsPropertyConstants.AssetRetirementGlobal.MERGED_TARGET_CAPITAL_ASSET_DESC, KFSKeyConstants.ERROR_REQUIRED, label); 544 valid = false; 545 } 546 547 return valid; 548 } 549 550 551 /** 552 * Only active capital equipment can be retired using the asset retirement document. 553 * 554 * @param valid 555 * @param detail 556 * @return 557 */ 558 protected boolean validateActiveCapitalAsset(Asset asset) { 559 boolean valid = true; 560 561 if (!getAssetService().isCapitalAsset(asset)) { 562 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_NON_CAPITAL_ASSET_RETIREMENT, asset.getCapitalAssetNumber().toString()); 563 valid = false; 564 } 565 else if (getAssetService().isAssetRetired(asset)) { 566 GlobalVariables.getMessageMap().putError(CamsPropertyConstants.AssetRetirementGlobalDetail.CAPITAL_ASSET_NUMBER, CamsKeyConstants.Retirement.ERROR_NON_ACTIVE_ASSET_RETIREMENT, asset.getCapitalAssetNumber().toString()); 567 valid = false; 568 } 569 else if (!this.validateAssetOnLoan(asset)) { 570 valid = false; 571 } 572 573 return valid; 574 } 575 576 577 /** 578 * Validate required fields for given retirement reason code 579 * 580 * @param assetRetirementGlobal 581 * @return 582 */ 583 protected boolean validateRequiredGlobalFields(AssetRetirementGlobal assetRetirementGlobal) { 584 boolean valid = true; 585 586 if (getAssetRetirementService().isAssetRetiredBySold(assetRetirementGlobal)) { 587 if (StringUtils.isBlank(assetRetirementGlobal.getBuyerDescription())) { 588 putFieldError(CamsPropertyConstants.AssetRetirementGlobalDetail.BUYER_DESCRIPTION, CamsKeyConstants.Retirement.ERROR_RETIREMENT_DETAIL_INFO_NULL, new String[] { CamsConstants.RetirementLabel.BUYER_DESCRIPTION, getAssetRetirementService().getAssetRetirementReasonName(assetRetirementGlobal) }); 589 valid = false; 590 } 591 if (assetRetirementGlobal.getSalePrice() == null) { 592 putFieldError(CamsPropertyConstants.AssetRetirementGlobalDetail.SALE_PRICE, CamsKeyConstants.Retirement.ERROR_RETIREMENT_DETAIL_INFO_NULL, new String[] { CamsConstants.RetirementLabel.SALE_PRICE, getAssetRetirementService().getAssetRetirementReasonName(assetRetirementGlobal) }); 593 valid = false; 594 } 595 valid &= validateCashReceiptFinancialDocumentNumber(assetRetirementGlobal.getCashReceiptFinancialDocumentNumber()); 596 } 597 else if (getAssetRetirementService().isAssetRetiredByAuction(assetRetirementGlobal)) { 598 valid = validateCashReceiptFinancialDocumentNumber(assetRetirementGlobal.getCashReceiptFinancialDocumentNumber()); 599 } 600 else if (getAssetRetirementService().isAssetRetiredByExternalTransferOrGift(assetRetirementGlobal) && StringUtils.isBlank(assetRetirementGlobal.getRetirementInstitutionName())) { 601 putFieldError(CamsPropertyConstants.AssetRetirementGlobalDetail.RETIREMENT_INSTITUTION_NAME, CamsKeyConstants.Retirement.ERROR_RETIREMENT_DETAIL_INFO_NULL, new String[] { CamsConstants.RetirementLabel.RETIREMENT_INSTITUTION_NAME, getAssetRetirementService().getAssetRetirementReasonName(assetRetirementGlobal) }); 602 valid = false; 603 } 604 else if (getAssetRetirementService().isAssetRetiredByTheft(assetRetirementGlobal) && StringUtils.isBlank(assetRetirementGlobal.getPaidCaseNumber())) { 605 putFieldError(CamsPropertyConstants.AssetRetirementGlobalDetail.PAID_CASE_NUMBER, CamsKeyConstants.Retirement.ERROR_RETIREMENT_DETAIL_INFO_NULL, new String[] { CamsConstants.RetirementLabel.PAID_CASE_NUMBER, getAssetRetirementService().getAssetRetirementReasonName(assetRetirementGlobal) }); 606 valid = false; 607 } 608 return valid; 609 } 610 611 /** 612 * validates Cash Receipt Financial Document Number 613 * 614 * @param sharedRetirementInfo 615 * @return boolean 616 */ 617 protected boolean validateCashReceiptFinancialDocumentNumber(String documentNumber) { 618 boolean valid = true; 619 if (StringUtils.isNotBlank(documentNumber)) { 620 Map retirementInfoMap = new HashMap(); 621 retirementInfoMap.put(CamsPropertyConstants.AssetGlobal.DOCUMENT_NUMBER, documentNumber); 622 bo = (FinancialSystemDocumentHeader) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(FinancialSystemDocumentHeader.class, retirementInfoMap); 623 if (ObjectUtils.isNull(bo)) { 624 putFieldError(CamsPropertyConstants.AssetRetirementGlobalDetail.CASH_RECEIPT_FINANCIAL_DOCUMENT_NUMBER, CamsKeyConstants.Retirement.ERROR_INVALID_RETIREMENT_DETAIL_INFO, new String[] { CamsConstants.RetirementLabel.CASH_RECEIPT_FINANCIAL_DOCUMENT_NUMBER, documentNumber }); 625 valid = false; 626 } 627 } 628 return valid; 629 } 630 631 632 /** 633 * Validates whether or not asset is on loan status 634 * 635 * @param assetRetirementGlobalDetail 636 * @return boolean 637 */ 638 protected boolean validateAssetOnLoan(Asset asset) { 639 boolean success = true; 640 if (this.getAssetService().isAssetLoaned(asset)) { 641 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.AssetRetirementGlobal.SECTION_ID_ASSET_DETAIL_INFORMATION, CamsKeyConstants.Retirement.ERROR_LOANED_ASSET_CANNOT_RETIRED); 642 success = false; 643 } 644 return success; 645 } 646 647 648 protected AssetService getAssetService() { 649 return SpringContext.getBean(AssetService.class); 650 } 651 652 protected AssetRetirementService getAssetRetirementService() { 653 return SpringContext.getBean(AssetRetirementService.class); 654 } 655 656 protected AssetPaymentService getAssetPaymentService() { 657 return SpringContext.getBean(AssetPaymentService.class); 658 } 659 660 protected AssetObjectCodeService getAssetObjectCodeService() { 661 return SpringContext.getBean(AssetObjectCodeService.class); 662 } 663 }