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.service.impl; 017 018 import java.util.ArrayList; 019 import java.util.Arrays; 020 import java.util.Collection; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Map; 025 026 import org.apache.commons.lang.StringUtils; 027 import org.kuali.kfs.module.cam.CamsConstants; 028 import org.kuali.kfs.module.cam.CamsPropertyConstants; 029 import org.kuali.kfs.module.cam.businessobject.Asset; 030 import org.kuali.kfs.module.cam.businessobject.AssetGlobal; 031 import org.kuali.kfs.module.cam.businessobject.AssetGlobalDetail; 032 import org.kuali.kfs.module.cam.businessobject.AssetLocation; 033 import org.kuali.kfs.module.cam.businessobject.AssetPayment; 034 import org.kuali.kfs.module.cam.businessobject.AssetType; 035 import org.kuali.kfs.module.cam.document.service.AssetService; 036 import org.kuali.kfs.module.cam.document.service.PaymentSummaryService; 037 import org.kuali.kfs.sys.KFSPropertyConstants; 038 import org.kuali.kfs.sys.KFSConstants.DocumentStatusCodes; 039 import org.kuali.kfs.sys.businessobject.UniversityDate; 040 import org.kuali.kfs.sys.context.SpringContext; 041 import org.kuali.kfs.sys.service.UniversityDateService; 042 import org.kuali.rice.kew.exception.WorkflowException; 043 import org.kuali.rice.kns.document.Document; 044 import org.kuali.rice.kns.document.MaintenanceDocument; 045 import org.kuali.rice.kns.exception.ValidationException; 046 import org.kuali.rice.kns.service.BusinessObjectService; 047 import org.kuali.rice.kns.service.ParameterService; 048 import org.kuali.rice.kns.util.ObjectUtils; 049 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 050 051 public class AssetServiceImpl implements AssetService { 052 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetServiceImpl.class); 053 054 private ParameterService parameterService; 055 private PaymentSummaryService paymentSummaryService; 056 private BusinessObjectService businessObjectService; 057 058 public ParameterService getParameterService() { 059 return parameterService; 060 } 061 062 public void setParameterService(ParameterService parameterService) { 063 this.parameterService = parameterService; 064 } 065 066 public boolean isAssetMovableCheckByAsset(Asset asset) { 067 asset.refreshReferenceObject(CamsPropertyConstants.Asset.CAPITAL_ASSET_TYPE); 068 return asset.getCapitalAssetType().isMovingIndicator(); 069 } 070 071 072 /** 073 * @see org.kuali.kfs.module.cam.document.service.AssetService#isAssetDepreciationStarted(org.kuali.kfs.module.cam.businessobject.Asset) 074 */ 075 public boolean isAssetDepreciationStarted(Asset asset) { 076 // check non-persistent field accumulatedDepreciation first since it's the sum of 077 // assetPayment.accumulatedPrimaryDepreciationAmount. If it's not set yet, we'll check assetPayment one by one. 078 if (ObjectUtils.isNotNull(asset.getAccumulatedDepreciation()) && asset.getAccumulatedDepreciation().isPositive()) { 079 return true; 080 } 081 else { 082 for (AssetPayment assetPayment : asset.getAssetPayments()) { 083 if (ObjectUtils.isNotNull(assetPayment.getAccumulatedPrimaryDepreciationAmount()) && assetPayment.getAccumulatedPrimaryDepreciationAmount().isPositive()) { 084 return true; 085 } 086 } 087 } 088 return false; 089 } 090 091 public boolean isCapitalAsset(Asset asset) { 092 return parameterService.getParameterValues(Asset.class, CamsConstants.Parameters.CAPITAL_ASSET_STATUS_CODES).contains(asset.getInventoryStatusCode()); 093 } 094 095 public boolean isAssetRetired(Asset asset) { 096 return parameterService.getParameterValues(Asset.class, CamsConstants.Parameters.RETIRED_STATUS_CODES).contains(asset.getInventoryStatusCode()); 097 } 098 099 public boolean isInServiceDateChanged(Asset oldAsset, Asset newAsset) { 100 return !(ObjectUtils.isNull(oldAsset.getCapitalAssetInServiceDate()) ? ObjectUtils.isNull(newAsset.getCapitalAssetInServiceDate()) : oldAsset.getCapitalAssetInServiceDate().equals(newAsset.getCapitalAssetInServiceDate())); 101 } 102 103 /** 104 * @see org.kuali.kfs.module.cam.document.service.AssetService#isAssetFabrication(org.kuali.rice.kns.document.MaintenanceDocument) 105 */ 106 public boolean isAssetFabrication(MaintenanceDocument maintenanceDocument) { 107 return maintenanceDocument.getNewMaintainableObject().getBusinessObject() instanceof Asset && maintenanceDocument.isNew(); 108 } 109 110 /** 111 * @see org.kuali.kfs.module.cam.document.service.AssetService#isAssetLoaned(org.kuali.kfs.module.cam.businessobject.Asset) 112 */ 113 public boolean isAssetLoaned(Asset asset) { 114 return ObjectUtils.isNotNull(asset.getExpectedReturnDate()) && ObjectUtils.isNull(asset.getLoanReturnDate()); 115 } 116 117 /** 118 * @see org.kuali.kfs.module.cam.document.service.AssetService#isAssetTaggedInPriorFiscalYear(org.kuali.kfs.module.cam.businessobject.Asset) 119 */ 120 public boolean isAssetTaggedInPriorFiscalYear(Asset asset) { 121 UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class); 122 123 return StringUtils.isNotBlank(asset.getCampusTagNumber()) && ObjectUtils.isNotNull(asset.getFinancialDocumentPostingYear()) && !universityDateService.getCurrentFiscalYear().equals(asset.getFinancialDocumentPostingYear()); 124 } 125 126 /** 127 * @see org.kuali.kfs.module.cam.document.service.AssetService#isTagNumberCheckExclude(org.kuali.kfs.module.cam.businessobject.Asset) 128 */ 129 public boolean isTagNumberCheckExclude(Asset asset) { 130 String status = asset.getInventoryStatusCode(); 131 132 return StringUtils.equalsIgnoreCase(status, CamsConstants.InventoryStatusCode.CAPITAL_ASSET_RETIRED) || StringUtils.equalsIgnoreCase(status, CamsConstants.InventoryStatusCode.NON_CAPITAL_ASSET_RETIRED) || StringUtils.equalsIgnoreCase(asset.getCampusTagNumber(), CamsConstants.Asset.NON_TAGGABLE_ASSET); 133 } 134 135 /** 136 * @see org.kuali.kfs.module.cam.document.service.AssetService#isOffCampusLocationEntered(org.kuali.kfs.module.cam.businessobject.Asset) 137 */ 138 public boolean isOffCampusLocationEntered(Asset asset) { 139 AssetLocation offCampus = asset.getOffCampusLocation(); 140 return StringUtils.isNotBlank(offCampus.getAssetLocationContactName()) || StringUtils.isNotBlank(offCampus.getAssetLocationStreetAddress()) || StringUtils.isNotBlank(offCampus.getAssetLocationCityName()) || StringUtils.isNotBlank(offCampus.getAssetLocationStateCode()) || StringUtils.isNotBlank(offCampus.getAssetLocationZipCode()) || StringUtils.isNotBlank(offCampus.getAssetLocationCountryCode()); 141 } 142 143 /** 144 * @see org.kuali.kfs.module.cam.document.service.AssetService#isFinancialObjectSubTypeCodeChanged(org.kuali.kfs.module.cam.businessobject.Asset, 145 * org.kuali.kfs.module.cam.businessobject.Asset) 146 */ 147 public boolean isFinancialObjectSubTypeCodeChanged(Asset oldAsset, Asset newAsset) { 148 return !StringUtils.equalsIgnoreCase(oldAsset.getFinancialObjectSubTypeCode(), newAsset.getFinancialObjectSubTypeCode()); 149 } 150 151 /** 152 * @see org.kuali.kfs.module.cam.document.service.AssetService#isAssetTypeCodeChanged(org.kuali.kfs.module.cam.businessobject.Asset, 153 * org.kuali.kfs.module.cam.businessobject.Asset) 154 */ 155 public boolean isAssetTypeCodeChanged(Asset oldAsset, Asset newAsset) { 156 return !StringUtils.equalsIgnoreCase(oldAsset.getCapitalAssetTypeCode(), newAsset.getCapitalAssetTypeCode()); 157 } 158 159 public boolean isAssetDepreciableLifeLimitZero(Asset asset) { 160 asset.refreshReferenceObject(CamsPropertyConstants.Asset.CAPITAL_ASSET_TYPE); 161 AssetType capitalAssetType = asset.getCapitalAssetType(); 162 if (ObjectUtils.isNotNull(capitalAssetType)) { 163 return Integer.valueOf(0).equals(capitalAssetType.getDepreciableLifeLimit()); 164 } 165 return false; 166 } 167 168 /** 169 * @see org.kuali.kfs.module.cam.document.service.AssetService#isCapitalAssetNumberDuplicate(java.lang.Long, java.lang.Long) 170 */ 171 public boolean isCapitalAssetNumberDuplicate(Long capitalAssetNumber1, Long capitalAssetNumber2) { 172 if (capitalAssetNumber1 != null && capitalAssetNumber2 != null && capitalAssetNumber1.compareTo(capitalAssetNumber2) == 0) { 173 return true; 174 } 175 return false; 176 } 177 178 179 /** 180 * This method calls the service codes to calculate the summary fields for each asset 181 * 182 * @param asset 183 */ 184 public void setAssetSummaryFields(Asset asset) { 185 if (ObjectUtils.isNotNull(asset)) { 186 asset.setFederalContribution(paymentSummaryService.calculateFederalContribution(asset)); 187 asset.setAccumulatedDepreciation(paymentSummaryService.calculatePrimaryAccumulatedDepreciation(asset)); 188 asset.setBookValue(paymentSummaryService.calculatePrimaryBookValue(asset)); 189 } 190 } 191 192 public PaymentSummaryService getPaymentSummaryService() { 193 return paymentSummaryService; 194 } 195 196 public void setPaymentSummaryService(PaymentSummaryService paymentSummaryService) { 197 this.paymentSummaryService = paymentSummaryService; 198 } 199 200 /** 201 * @see org.kuali.kfs.module.cam.document.service.AssetService#isMovableFinancialObjectSubtypeCode(java.lang.String) 202 */ 203 public boolean isAssetMovableCheckByPayment(String financialObjectSubTypeCode) { 204 if (parameterService.getParameterValues(Asset.class, CamsConstants.Parameters.MOVABLE_EQUIPMENT_OBJECT_SUB_TYPES).contains(financialObjectSubTypeCode)) { 205 return true; 206 } 207 else if (parameterService.getParameterValues(Asset.class, CamsConstants.Parameters.NON_MOVABLE_EQUIPMENT_OBJECT_SUB_TYPES).contains(financialObjectSubTypeCode)) { 208 return false; 209 } 210 else { 211 throw new ValidationException("Cound not determine movable or non-movable for this object sub-type code " + financialObjectSubTypeCode); 212 } 213 } 214 215 public List<Asset> findActiveAssetsMatchingTagNumber(String campusTagNumber) { 216 List<Asset> activeMatches = new ArrayList<Asset>(); 217 // find all assets matching this tag number 218 Map<String, String> params = new HashMap<String, String>(); 219 params.put(CamsPropertyConstants.Asset.CAMPUS_TAG_NUMBER, campusTagNumber); 220 Collection<Asset> tagMatches = SpringContext.getBean(BusinessObjectService.class).findMatching(Asset.class, params); 221 if (tagMatches != null && !tagMatches.isEmpty()) { 222 for (Asset asset : tagMatches) { 223 // if found matching, check if status is not retired 224 if (!isAssetRetired(asset)) { 225 activeMatches.add(asset); 226 } 227 } 228 } 229 return activeMatches; 230 } 231 232 233 /** 234 * @see org.kuali.kfs.module.cam.document.service.AssetService#findAssetsMatchingTagNumber(java.lang.String) 235 */ 236 public Collection<Asset> findAssetsMatchingTagNumber(String campusTagNumber) { 237 // find all assets matching this tag number 238 Map<String, String> params = new HashMap<String, String>(); 239 params.put(CamsPropertyConstants.Asset.CAMPUS_TAG_NUMBER, campusTagNumber); 240 Collection<Asset> tagMatches = SpringContext.getBean(BusinessObjectService.class).findMatching(Asset.class, params); 241 242 return tagMatches; 243 } 244 245 /** 246 * @see org.kuali.kfs.module.cam.document.service.AssetService#isObjectSubTypeCompatible(java.util.List) 247 */ 248 public boolean isObjectSubTypeCompatible(List<String> financialObjectSubTypeCode) { 249 if (financialObjectSubTypeCode == null || financialObjectSubTypeCode.size() <= 1) { 250 return true; 251 } 252 253 List<String> subTypes = parameterService.getParameterValues(Asset.class, CamsConstants.Parameters.OBJECT_SUB_TYPE_GROUPS); 254 String firstObjectSubType = (String) financialObjectSubTypeCode.get(0); 255 List<String> validObjectSubTypes = new ArrayList<String>(); 256 257 // Get the set for compatible object sub type code by the first financial object sub type code 258 for (String subType : subTypes) { 259 if (subType.contains(firstObjectSubType)) { 260 validObjectSubTypes = Arrays.asList(StringUtils.split(subType, ",")); 261 break; 262 } 263 } 264 265 if (validObjectSubTypes.isEmpty()) { 266 validObjectSubTypes.add(firstObjectSubType); 267 } 268 269 // Check in the whole list if all object sub type code are compatible. 270 for (String subTypeCode : financialObjectSubTypeCode) { 271 if (!validObjectSubTypes.contains(subTypeCode)) { 272 return false; 273 } 274 } 275 276 return true; 277 } 278 279 /** 280 * @see org.kuali.kfs.module.cam.document.service.AssetService#setSeparateHistory(org.kuali.kfs.module.cam.businessobject.Asset) 281 */ 282 public void setSeparateHistory(Asset asset) { 283 // Find the asset this was separated from. It should only be one, error if more 284 Map<String, String> paramsAssetGlobalDetail = new HashMap<String, String>(); 285 paramsAssetGlobalDetail.put(CamsPropertyConstants.AssetGlobalDetail.CAPITAL_ASSET_NUMBER, asset.getCapitalAssetNumber().toString()); 286 Collection<AssetGlobalDetail> assetGlobalDetails = SpringContext.getBean(BusinessObjectService.class).findMatching(AssetGlobalDetail.class, paramsAssetGlobalDetail); 287 288 if (assetGlobalDetails.size() > 1) { 289 throw new IllegalStateException("Asset #" + asset.getCapitalAssetNumber().toString() + " was created from more then one asset document."); 290 } 291 else if (assetGlobalDetails.size() == 1) { 292 // Find the document associated to that 293 Map<String, String> paramsAssetGlobal = new HashMap<String, String>(); 294 paramsAssetGlobal.put(CamsPropertyConstants.AssetGlobal.DOCUMENT_NUMBER, assetGlobalDetails.iterator().next().getDocumentNumber()); 295 AssetGlobal assetGlobal = (AssetGlobal) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(AssetGlobal.class, paramsAssetGlobal); 296 297 // Only set it if it is in status approved 298 if (DocumentStatusCodes.APPROVED.equals((assetGlobal.getDocumentHeader().getFinancialDocumentStatusCode()))) { 299 asset.setSeparateHistory(assetGlobal); 300 } 301 } 302 303 // Else no history, just return 304 } 305 306 /** 307 * @see org.kuali.kfs.module.cam.document.service.AssetService#getDocumentNumberThatSeparatedThisAsset(java.lang.Long) 308 */ 309 public List<String> getDocumentNumbersThatSeparatedThisAsset(Long capitalAssetNumber) { 310 Map<String, String> paramsAssetGlobal = new HashMap<String, String>(); 311 paramsAssetGlobal.put(CamsPropertyConstants.AssetGlobal.SEPARATE_SOURCE_CAPITAL_ASSET_NUMBER, capitalAssetNumber.toString()); 312 Collection<AssetGlobal> assetGlobals = SpringContext.getBean(BusinessObjectService.class).findMatching(AssetGlobal.class, paramsAssetGlobal); 313 314 List<String> separateDocumentNumbers = new ArrayList<String>(); 315 for (Iterator<AssetGlobal> assetGlobalIter = assetGlobals.iterator(); assetGlobalIter.hasNext();) { 316 AssetGlobal assetGlobal = assetGlobalIter.next(); 317 318 if (DocumentStatusCodes.APPROVED.equals(assetGlobal.getDocumentHeader().getFinancialDocumentStatusCode())) { 319 separateDocumentNumbers.add(assetGlobal.getDocumentNumber()); 320 } 321 } 322 323 return separateDocumentNumbers; 324 } 325 326 /** 327 * sets the posting year and posting month based on the asset creation date 328 * 329 * @param asset 330 * @return none 331 */ 332 public void setFiscalPeriod(Asset asset) { 333 if (asset.getCreateDate() == null) 334 return; 335 336 Map<String, Object> primaryKeys = new HashMap<String, Object>(); 337 primaryKeys.put(KFSPropertyConstants.UNIVERSITY_DATE, asset.getCreateDate()); 338 UniversityDate universityDate = (UniversityDate) businessObjectService.findByPrimaryKey(UniversityDate.class, primaryKeys); 339 if (universityDate != null) { 340 asset.setFinancialDocumentPostingYear(universityDate.getUniversityFiscalYear()); 341 asset.setFinancialDocumentPostingPeriodCode(universityDate.getUniversityFiscalAccountingPeriod()); 342 } 343 } 344 345 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 346 this.businessObjectService = businessObjectService; 347 } 348 349 350 /** 351 * @see org.kuali.kfs.module.cam.document.service.AssetService#getCurrentRouteLevels(org.kuali.rice.kns.workflow.service.KualiWorkflowDocument) 352 */ 353 public List<String> getCurrentRouteLevels(KualiWorkflowDocument workflowDocument) { 354 try { 355 return Arrays.asList(workflowDocument.getNodeNames()); 356 } 357 catch (WorkflowException e) { 358 throw new RuntimeException(e); 359 } 360 } 361 362 /** 363 * @see org.kuali.kfs.module.cam.document.service.AssetService#isMaintenanceDocumentEnroute(org.kuali.rice.kns.document.MaintenanceDocument) 364 */ 365 public boolean isDocumentEnrouting(Document document) { 366 return document.getDocumentHeader().getWorkflowDocument().stateIsEnroute(); 367 } 368 369 }