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 }