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 }