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.sql.Date;
019    import java.sql.Timestamp;
020    import java.util.ArrayList;
021    import java.util.Arrays;
022    import java.util.Iterator;
023    import java.util.List;
024    
025    import org.apache.commons.lang.StringUtils;
026    import org.apache.log4j.Logger;
027    import org.kuali.kfs.coa.businessobject.ObjectCode;
028    import org.kuali.kfs.coa.businessobject.OffsetDefinition;
029    import org.kuali.kfs.coa.service.ObjectCodeService;
030    import org.kuali.kfs.coa.service.OffsetDefinitionService;
031    import org.kuali.kfs.module.cam.CamsConstants;
032    import org.kuali.kfs.module.cam.CamsPropertyConstants;
033    import org.kuali.kfs.module.cam.businessobject.Asset;
034    import org.kuali.kfs.module.cam.businessobject.AssetAcquisitionType;
035    import org.kuali.kfs.module.cam.businessobject.AssetGlobal;
036    import org.kuali.kfs.module.cam.businessobject.AssetGlobalDetail;
037    import org.kuali.kfs.module.cam.businessobject.AssetGlpeSourceDetail;
038    import org.kuali.kfs.module.cam.businessobject.AssetLocation;
039    import org.kuali.kfs.module.cam.businessobject.AssetObjectCode;
040    import org.kuali.kfs.module.cam.businessobject.AssetPayment;
041    import org.kuali.kfs.module.cam.businessobject.AssetPaymentDetail;
042    import org.kuali.kfs.module.cam.document.gl.CamsGeneralLedgerPendingEntrySourceBase;
043    import org.kuali.kfs.module.cam.document.service.AssetGlobalService;
044    import org.kuali.kfs.module.cam.document.service.AssetObjectCodeService;
045    import org.kuali.kfs.module.cam.document.service.AssetPaymentService;
046    import org.kuali.kfs.module.cam.document.service.AssetService;
047    import org.kuali.kfs.module.cam.document.service.PaymentSummaryService;
048    import org.kuali.kfs.module.cam.util.AssetSeparatePaymentDistributor;
049    import org.kuali.kfs.module.cam.util.KualiDecimalUtils;
050    import org.kuali.kfs.sys.context.SpringContext;
051    import org.kuali.kfs.sys.service.UniversityDateService;
052    import org.kuali.kfs.sys.service.impl.KfsParameterConstants.CAPITAL_ASSETS_BATCH;
053    import org.kuali.rice.kns.bo.PersistableBusinessObject;
054    import org.kuali.rice.kns.service.BusinessObjectService;
055    import org.kuali.rice.kns.service.ParameterService;
056    import org.kuali.rice.kns.util.KualiDecimal;
057    import org.kuali.rice.kns.util.ObjectUtils;
058    
059    public class AssetGlobalServiceImpl implements AssetGlobalService {
060    
061        protected enum AmountCategory {
062    
063            PAYMENT {
064                void setParams(AssetGlpeSourceDetail postable, AssetPaymentDetail assetPaymentDetail, AssetObjectCode assetObjectCode, OffsetDefinition offsetDefinition, AssetAcquisitionType acquisitionType) {
065                    postable.setPayment(true);
066                    postable.setFinancialDocumentLineDescription(CamsConstants.AssetGlobal.LINE_DESCRIPTION_PAYMENT);
067                    postable.setFinancialObjectCode(assetPaymentDetail.getFinancialObjectCode());
068                    postable.setObjectCode(assetPaymentDetail.getObjectCode());
069                };
070    
071            },
072            PAYMENT_OFFSET {
073                void setParams(AssetGlpeSourceDetail postable, AssetPaymentDetail assetPaymentDetail, AssetObjectCode assetObjectCode, OffsetDefinition offsetDefinition, AssetAcquisitionType acquisitionType) {
074                    postable.setPaymentOffset(true);
075                    postable.setFinancialDocumentLineDescription(CamsConstants.AssetGlobal.LINE_DESCRIPTION_PAYMENT_OFFSET);
076                    postable.setFinancialObjectCode(acquisitionType.getIncomeAssetObjectCode());
077                    postable.setObjectCode(SpringContext.getBean(ObjectCodeService.class).getByPrimaryId(assetPaymentDetail.getPostingYear(), assetPaymentDetail.getChartOfAccountsCode(), acquisitionType.getIncomeAssetObjectCode()));
078                };
079    
080            };
081    
082            abstract void setParams(AssetGlpeSourceDetail postable, AssetPaymentDetail assetPaymentDetail, AssetObjectCode assetObjectCode, OffsetDefinition offsetDefinition, AssetAcquisitionType acquisitionType);
083        }
084    
085        private ParameterService parameterService;
086        private AssetService assetService;
087        private UniversityDateService universityDateService;
088        private AssetObjectCodeService assetObjectCodeService;
089        private BusinessObjectService businessObjectService;
090        private AssetPaymentService assetPaymentService;
091        private PaymentSummaryService paymentSummaryService;
092    
093        private static final Logger LOG = Logger.getLogger(AssetGlobalServiceImpl.class);
094    
095        /**
096         * Creates an instance of AssetGlpeSourceDetail depending on the source flag
097         * 
098         * @param universityDateService University Date Service
099         * @param assetPayment Payment record for which postable is created
100         * @param isSource Indicates if postable is for source organization
101         * @return GL Postable source detail
102         */
103        protected AssetGlpeSourceDetail createAssetGlpePostable(AssetGlobal document, AssetPaymentDetail assetPaymentDetail, AmountCategory amountCategory) {
104            LOG.debug("Start - createAssetGlpePostable (" + document.getDocumentNumber() + "-" + assetPaymentDetail.getAccountNumber() + ")");
105            AssetGlpeSourceDetail postable = new AssetGlpeSourceDetail();
106    
107            assetPaymentDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDetail.ACCOUNT);
108            postable.setAccount(assetPaymentDetail.getAccount());
109    
110            postable.setAmount(assetPaymentDetail.getAmount());
111            postable.setAccountNumber(assetPaymentDetail.getAccountNumber());
112            postable.setBalanceTypeCode(CamsConstants.Postable.GL_BALANCE_TYPE_CODE_AC);
113            postable.setChartOfAccountsCode(assetPaymentDetail.getChartOfAccountsCode());
114            postable.setDocumentNumber(document.getDocumentNumber());
115            postable.setFinancialSubObjectCode(assetPaymentDetail.getFinancialSubObjectCode());
116            postable.setPostingYear(getUniversityDateService().getCurrentUniversityDate().getUniversityFiscalYear());
117            postable.setProjectCode(assetPaymentDetail.getProjectCode());
118            postable.setSubAccountNumber(assetPaymentDetail.getSubAccountNumber());
119            postable.setOrganizationReferenceId(assetPaymentDetail.getOrganizationReferenceId());
120    
121            assetPaymentDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentDetail.OBJECT_CODE);
122            ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class);
123            ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(assetPaymentDetail.getChartOfAccountsCode(), assetPaymentDetail.getFinancialObjectCode());
124    
125            AssetObjectCode assetObjectCode = getAssetObjectCodeService().findAssetObjectCode(assetPaymentDetail.getChartOfAccountsCode(), objectCode.getFinancialObjectSubTypeCode());
126    
127            OffsetDefinition offsetDefinition = SpringContext.getBean(OffsetDefinitionService.class).getByPrimaryId(getUniversityDateService().getCurrentFiscalYear(), assetPaymentDetail.getChartOfAccountsCode(), CamsConstants.AssetTransfer.DOCUMENT_TYPE_CODE, CamsConstants.Postable.GL_BALANCE_TYPE_CODE_AC);
128            document.refreshReferenceObject(CamsPropertyConstants.AssetGlobal.ACQUISITION_TYPE);
129            amountCategory.setParams(postable, assetPaymentDetail, assetObjectCode, offsetDefinition, document.getAcquisitionType());
130    
131            LOG.debug("End - createAssetGlpePostable(" + document.getDocumentNumber() + "-" + assetPaymentDetail.getAccountNumber() + "-" + ")");
132            return postable;
133        }
134    
135        /**
136         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#createGLPostables(org.kuali.module.cams.document.AssetGlobal)
137         */
138        public void createGLPostables(AssetGlobal assetGlobal, CamsGeneralLedgerPendingEntrySourceBase assetGlobalGlPoster) {
139            List<AssetPaymentDetail> assetPaymentDetails = assetGlobal.getAssetPaymentDetails();
140    
141            for (AssetPaymentDetail assetPaymentDetail : assetPaymentDetails) {
142                if (isPaymentFinancialObjectActive(assetPaymentDetail)) {
143                    KualiDecimal accountChargeAmount = assetPaymentDetail.getAmount();
144                    if (accountChargeAmount != null && !accountChargeAmount.isZero()) {
145                        assetGlobalGlPoster.getGeneralLedgerPendingEntrySourceDetails().add(createAssetGlpePostable(assetGlobal, assetPaymentDetail, AmountCategory.PAYMENT));
146                        assetGlobalGlPoster.getGeneralLedgerPendingEntrySourceDetails().add(createAssetGlpePostable(assetGlobal, assetPaymentDetail, AmountCategory.PAYMENT_OFFSET));
147                    }
148                }
149            }
150        }
151    
152    
153        public ParameterService getParameterService() {
154            return parameterService;
155        }
156    
157    
158        public void setParameterService(ParameterService parameterService) {
159            this.parameterService = parameterService;
160        }
161    
162    
163        /**
164         * Gets the assetObjectCodeService attribute.
165         * 
166         * @return Returns the assetObjectCodeService.
167         */
168        public AssetObjectCodeService getAssetObjectCodeService() {
169            return assetObjectCodeService;
170        }
171    
172    
173        /**
174         * Sets the assetObjectCodeService attribute value.
175         * 
176         * @param assetObjectCodeService The assetObjectCodeService to set.
177         */
178        public void setAssetObjectCodeService(AssetObjectCodeService assetObjectCodeService) {
179            this.assetObjectCodeService = assetObjectCodeService;
180        }
181    
182    
183        /**
184         * Gets the assetPaymentService attribute.
185         * 
186         * @return Returns the assetPaymentService.
187         */
188        public AssetPaymentService getAssetPaymentService() {
189            return assetPaymentService;
190        }
191    
192    
193        /**
194         * Sets the assetPaymentService attribute value.
195         * 
196         * @param assetPaymentService The assetPaymentService to set.
197         */
198        public void setAssetPaymentService(AssetPaymentService assetPaymentService) {
199            this.assetPaymentService = assetPaymentService;
200        }
201    
202        /**
203         * Gets the businessObjectService attribute.
204         * 
205         * @return Returns the businessObjectService.
206         */
207        public BusinessObjectService getBusinessObjectService() {
208            return businessObjectService;
209        }
210    
211    
212        /**
213         * Sets the businessObjectService attribute value.
214         * 
215         * @param businessObjectService The businessObjectService to set.
216         */
217        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
218            this.businessObjectService = businessObjectService;
219        }
220    
221    
222        /**
223         * Gets the universityDateService attribute.
224         * 
225         * @return Returns the universityDateService.
226         */
227        public UniversityDateService getUniversityDateService() {
228            return universityDateService;
229        }
230    
231    
232        /**
233         * Sets the universityDateService attribute value.
234         * 
235         * @param universityDateService The universityDateService to set.
236         */
237        public void setUniversityDateService(UniversityDateService universityDateService) {
238            this.universityDateService = universityDateService;
239        }
240    
241        /**
242         * We need to calculate asset total amount from the sum of its payments. Otherwise, the asset total amount could mismatch with
243         * the sum of payments.
244         * 
245         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#totalPaymentByAsset(org.kuali.kfs.module.cam.businessobject.AssetGlobal)
246         */
247        public KualiDecimal totalPaymentByAsset(AssetGlobal assetGlobal, boolean lastEntry) {
248            KualiDecimal assetTotalAmount = KualiDecimal.ZERO;
249            List<AssetPaymentDetail> assetPaymentDetails = assetGlobal.getAssetPaymentDetails();
250            int numberOfTotalAsset = assetGlobal.getAssetGlobalDetails().size();
251            if (numberOfTotalAsset > 0) {
252                for (AssetPaymentDetail assetPaymentDetail : assetPaymentDetails) {
253                    KualiDecimal assetPaymentUnitCost = assetPaymentDetail.getAmount().divide(new KualiDecimal(numberOfTotalAsset));
254                    if (lastEntry) {
255                        assetPaymentUnitCost = assetPaymentDetail.getAmount().subtract(assetPaymentUnitCost.multiply(new KualiDecimal(numberOfTotalAsset - 1)));
256                    }
257                    assetTotalAmount = assetTotalAmount.add(assetPaymentUnitCost);
258                }
259            }
260    
261            return assetTotalAmount;
262        }
263    
264        /**
265         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#existsInGroup(java.lang.String, java.lang.String)
266         */
267        public boolean existsInGroup(String groupName, String memberName) {
268            if (StringUtils.isBlank(groupName) || StringUtils.isBlank(memberName)) {
269                return false;
270            }
271            return Arrays.asList(groupName.split(";")).contains(memberName);
272        }
273    
274        protected boolean isPaymentFinancialObjectActive(AssetPaymentDetail assetPayment) {
275            ObjectCode financialObjectCode = new ObjectCode();
276            financialObjectCode.setUniversityFiscalYear(getUniversityDateService().getCurrentFiscalYear());
277            financialObjectCode.setChartOfAccountsCode(assetPayment.getChartOfAccountsCode());
278            financialObjectCode.setFinancialObjectCode(assetPayment.getFinancialObjectCode());
279            financialObjectCode = (ObjectCode) getBusinessObjectService().retrieve(financialObjectCode);
280            if (ObjectUtils.isNotNull(financialObjectCode)) {
281                return financialObjectCode.isActive();
282            }
283            return false;
284        }
285    
286        /**
287         * Gets the assetService attribute.
288         * 
289         * @return Returns the assetService.
290         */
291        public AssetService getAssetService() {
292            return assetService;
293        }
294    
295        /**
296         * Sets the assetService attribute value.
297         * 
298         * @param assetService The assetService to set.
299         */
300        public void setAssetService(AssetService assetService) {
301            this.assetService = assetService;
302        }
303    
304        /**
305         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#isAssetSeparate(org.kuali.kfs.module.cam.businessobject.AssetGlobal)
306         */
307        public boolean isAssetSeparate(AssetGlobal assetGlobal) {
308            if (ObjectUtils.isNotNull(assetGlobal.getFinancialDocumentTypeCode()) && assetGlobal.getFinancialDocumentTypeCode().equals(CamsConstants.PaymentDocumentTypeCodes.ASSET_GLOBAL_SEPARATE)) {
309                return true;
310            }
311            return false;
312        }
313    
314        /**
315         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#isAssetSeparateByPayment(org.kuali.kfs.module.cam.businessobject.AssetGlobal)
316         */
317        public boolean isAssetSeparateByPayment(AssetGlobal assetGlobal) {
318            if (this.isAssetSeparate(assetGlobal) && ObjectUtils.isNotNull(assetGlobal.getSeparateSourcePaymentSequenceNumber())) {
319                return true;
320            }
321            return false;
322        }
323    
324        /**
325         * Add and return the total amount for all unique assets created.
326         * 
327         * @param assetGlobal
328         * @return Returns the total separate source amount
329         */
330        public KualiDecimal getUniqueAssetsTotalAmount(AssetGlobal assetGlobal) {
331            KualiDecimal totalAmount = KualiDecimal.ZERO;
332            // add new asset location
333            for (AssetGlobalDetail assetSharedDetail : assetGlobal.getAssetSharedDetails()) {
334                // existing
335                for (AssetGlobalDetail assetGlobalUniqueDetail : assetSharedDetail.getAssetGlobalUniqueDetails()) {
336                    KualiDecimal separateSourceAmount = assetGlobalUniqueDetail.getSeparateSourceAmount();
337                    if (separateSourceAmount != null) {
338                        totalAmount = totalAmount.add(separateSourceAmount);
339                    }
340                }
341            }
342            return totalAmount;
343        }
344    
345        /**
346         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#getCreateNewAssets(org.kuali.kfs.module.cam.businessobject.AssetGlobal)
347         */
348        public List<PersistableBusinessObject> getCreateNewAssets(AssetGlobal assetGlobal) {
349            List<PersistableBusinessObject> persistables = new ArrayList<PersistableBusinessObject>();
350    
351            // create new assets with inner loop handling payments
352            Iterator<AssetGlobalDetail> assetGlobalDetailsIterator = assetGlobal.getAssetGlobalDetails().iterator();
353            for (int assetGlobalDetailsIndex = 0; assetGlobalDetailsIterator.hasNext(); assetGlobalDetailsIndex++) {
354                AssetGlobalDetail assetGlobalDetail = (AssetGlobalDetail) assetGlobalDetailsIterator.next();
355    
356                // Create the asset with most fields set as required
357                Asset asset = setupAsset(assetGlobal, assetGlobalDetail, false);
358    
359                // track total cost of all payments for this assetGlobalDetail
360                KualiDecimal paymentsAccountChargeAmount = new KualiDecimal(0);
361    
362                // take care of all the payments for this asset
363                for (AssetPaymentDetail assetPaymentDetail : assetGlobal.getAssetPaymentDetails()) {
364                    AssetPayment assetPayment = setupCreateNewAssetPayment(assetGlobalDetail.getCapitalAssetNumber(), assetGlobal.getAcquisitionTypeCode(), assetGlobal.getAssetGlobalDetails().size(), assetGlobalDetailsIndex, assetPaymentDetail);
365    
366                    paymentsAccountChargeAmount = paymentsAccountChargeAmount.add(assetPayment.getAccountChargeAmount());
367    
368                    asset.getAssetPayments().add(assetPayment);
369                }
370    
371                // set the amount generically. Note for separate this should equal assetGlobalDetail.getSeparateSourceAmount()
372                asset.setTotalCostAmount(paymentsAccountChargeAmount);
373    
374                persistables.add(asset);
375            }
376    
377            return persistables;
378        }
379    
380        /**
381         * @see org.kuali.kfs.module.cam.document.service.AssetGlobalService#getSeparateAssets(org.kuali.kfs.module.cam.businessobject.AssetGlobal)
382         */
383        public List<PersistableBusinessObject> getSeparateAssets(AssetGlobal assetGlobal) {
384    
385            // set the source asset amounts properly
386            Asset separateSourceCapitalAsset = assetGlobal.getSeparateSourceCapitalAsset();
387            List<AssetPayment> sourcePayments = new ArrayList<AssetPayment>();
388    
389            for (AssetPayment assetPayment : separateSourceCapitalAsset.getAssetPayments()) {
390                if (!this.isAssetSeparateByPayment(assetGlobal)) {
391                    sourcePayments.add(assetPayment);
392                }
393                else if (assetPayment.getPaymentSequenceNumber().equals(assetGlobal.getSeparateSourcePaymentSequenceNumber())) {
394                    // If this is separate by payment, then only add the payment that we are interested in
395                    sourcePayments.add(assetPayment);
396                    break;
397                }
398            }
399    
400            List<Asset> newAssets = new ArrayList<Asset>();
401            // create new assets with inner loop handling payments
402            for (AssetGlobalDetail assetGlobalDetail : assetGlobal.getAssetGlobalDetails()) {
403                newAssets.add(setupAsset(assetGlobal, assetGlobalDetail, true));
404            }
405            // adjust source asset amounts
406            KualiDecimalUtils kualiDecimalUtils = new KualiDecimalUtils();
407            double separateRatio = 1 - (assetGlobal.getSeparateSourceTotalAmount().doubleValue() / assetGlobal.getSeparateSourceCapitalAsset().getTotalCostAmount().doubleValue());
408            separateSourceCapitalAsset.setSalvageAmount(kualiDecimalUtils.safeMultiply(assetGlobal.getSeparateSourceCapitalAsset().getSalvageAmount(), separateRatio));
409            separateSourceCapitalAsset.setReplacementAmount(kualiDecimalUtils.safeMultiply(assetGlobal.getSeparateSourceCapitalAsset().getReplacementAmount(), separateRatio));
410            separateSourceCapitalAsset.setFabricationEstimatedTotalAmount(kualiDecimalUtils.safeMultiply(assetGlobal.getSeparateSourceCapitalAsset().getFabricationEstimatedTotalAmount(), separateRatio));
411    
412            Integer maxSequenceNumber = SpringContext.getBean(AssetPaymentService.class).getMaxSequenceNumber(separateSourceCapitalAsset.getCapitalAssetNumber());
413            // Add to the save list
414            AssetSeparatePaymentDistributor distributor = new AssetSeparatePaymentDistributor(separateSourceCapitalAsset, sourcePayments, maxSequenceNumber, assetGlobal, newAssets);
415            distributor.distribute();
416            // re-compute the source total cost amount after split
417            separateSourceCapitalAsset.setTotalCostAmount(getPaymentSummaryService().calculatePaymentTotalCost(separateSourceCapitalAsset));
418            List<PersistableBusinessObject> persistables = new ArrayList<PersistableBusinessObject>();
419            persistables.add(separateSourceCapitalAsset);
420            persistables.addAll(newAssets);
421            return persistables;
422        }
423    
424        /**
425         * Creates a new Asset appropriate for either create new or separate. This does not create the payments for this asset.
426         * 
427         * @param assetGlobal containing data for the asset to be created
428         * @param assetGlobalDetail containing data for the asset to be created
429         * @param separate indicating whether this is a separate and asset or not
430         * @return set of assets appropriate for this creation without payments
431         */
432        protected Asset setupAsset(AssetGlobal assetGlobal, AssetGlobalDetail assetGlobalDetail, boolean separate) {
433            Asset asset = new Asset(assetGlobal, assetGlobalDetail, separate);
434            KualiDecimalUtils kualiDecimalUtils = new KualiDecimalUtils();
435    
436            // set financialObjectSubTypeCode per first payment entry if one exists
437            if (!assetGlobal.getAssetPaymentDetails().isEmpty() && ObjectUtils.isNotNull(assetGlobal.getAssetPaymentDetails().get(0).getObjectCode())) {
438                ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class);
439                AssetPaymentDetail assetPaymentDetail = assetGlobal.getAssetPaymentDetails().get(0);
440                
441                ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(assetPaymentDetail.getChartOfAccountsCode(), assetPaymentDetail.getFinancialObjectCode());
442    
443                asset.setFinancialObjectSubTypeCode(objectCode.getFinancialObjectSubTypeCode());
444            }
445    
446            // create off campus location for each asset only if it was filled in
447            boolean offCampus = StringUtils.isNotBlank(assetGlobalDetail.getOffCampusName()) || StringUtils.isNotBlank(assetGlobalDetail.getOffCampusAddress()) || StringUtils.isNotBlank(assetGlobalDetail.getOffCampusCityName()) || StringUtils.isNotBlank(assetGlobalDetail.getOffCampusStateCode()) || StringUtils.isNotBlank(assetGlobalDetail.getOffCampusZipCode()) || StringUtils.isNotBlank(assetGlobalDetail.getOffCampusCountryCode());
448            if (offCampus) {
449                setupAssetLocationOffCampus(assetGlobalDetail, asset);
450            }
451    
452            // set specific values for new assets if document is Asset Separate
453            if (separate) {
454                double separateRatio = assetGlobalDetail.getSeparateSourceAmount().doubleValue() / assetGlobal.getSeparateSourceCapitalAsset().getTotalCostAmount().doubleValue();
455                asset.setSalvageAmount(kualiDecimalUtils.safeMultiply(assetGlobal.getSeparateSourceCapitalAsset().getSalvageAmount(), separateRatio));
456                asset.setReplacementAmount(kualiDecimalUtils.safeMultiply(assetGlobal.getSeparateSourceCapitalAsset().getReplacementAmount(), separateRatio));
457                asset.setFabricationEstimatedTotalAmount(kualiDecimalUtils.safeMultiply(assetGlobal.getSeparateSourceCapitalAsset().getFabricationEstimatedTotalAmount(), separateRatio));
458                Date lastInventoryDate = assetGlobal.getLastInventoryDate();
459                if (lastInventoryDate != null) {
460                    asset.setLastInventoryDate(new Timestamp(lastInventoryDate.getTime()));
461                }
462            }
463    
464            return asset;
465        }
466    
467        /**
468         * Off campus location appropriately set for this asset.
469         * 
470         * @param assetGlobalDetail containing data for the location
471         * @param asset object that location is set in
472         */
473        protected void setupAssetLocationOffCampus(AssetGlobalDetail assetGlobalDetail, Asset asset) {
474            // We are not checking if it already exists since on a new asset it can't
475            AssetLocation offCampusAssetLocation = new AssetLocation();
476            offCampusAssetLocation.setCapitalAssetNumber(asset.getCapitalAssetNumber());
477            offCampusAssetLocation.setAssetLocationTypeCode(CamsConstants.AssetLocationTypeCode.OFF_CAMPUS);
478            asset.getAssetLocations().add(offCampusAssetLocation);
479    
480            // Set the location fields either way
481            offCampusAssetLocation.setAssetLocationContactName(assetGlobalDetail.getOffCampusName());
482            offCampusAssetLocation.setAssetLocationContactIdentifier(assetGlobalDetail.getRepresentativeUniversalIdentifier());
483            offCampusAssetLocation.setAssetLocationInstitutionName(assetGlobalDetail.getAssetRepresentative().getPrimaryDepartmentCode());
484            offCampusAssetLocation.setAssetLocationStreetAddress(assetGlobalDetail.getOffCampusAddress());
485            offCampusAssetLocation.setAssetLocationCityName(assetGlobalDetail.getOffCampusCityName());
486            offCampusAssetLocation.setAssetLocationStateCode(assetGlobalDetail.getOffCampusStateCode());
487            offCampusAssetLocation.setAssetLocationCountryCode(assetGlobalDetail.getOffCampusCountryCode());
488            offCampusAssetLocation.setAssetLocationZipCode(assetGlobalDetail.getOffCampusZipCode());
489    
490            // There is no phone number field on Asset Global... odd...
491            offCampusAssetLocation.setAssetLocationPhoneNumber(null);
492        }
493    
494        /**
495         * Creates a payment for an asset in create new mode.
496         * 
497         * @param capitalAssetNumber to use for the payment
498         * @param acquisitionTypeCode for logic in determining how dates are to be set
499         * @param assetGlobalDetailsSize for logic in determining depreciation amounts (if asset is depreciable)
500         * @param assetGlobalDetailsIndex for logic in determining depreciation amounts (if asset is depreciable)
501         * @param assetPaymentDetail containing data for the payment
502         * @return payment for an asset in create new
503         */
504        protected AssetPayment setupCreateNewAssetPayment(Long capitalAssetNumber, String acquisitionTypeCode, int assetGlobalDetailsSize, int assetGlobalDetailsIndex, AssetPaymentDetail assetPaymentDetail) {
505            AssetPayment assetPayment = new AssetPayment(assetPaymentDetail, acquisitionTypeCode);
506            assetPayment.setCapitalAssetNumber(capitalAssetNumber);
507            assetPayment.setPaymentSequenceNumber(assetPaymentDetail.getSequenceNumber());
508            assetPayment.setTransferPaymentCode(CamsConstants.AssetPayment.TRANSFER_PAYMENT_CODE_N);
509            // Running this every time of the loop is inefficient, could be put into HashMap
510            KualiDecimalUtils kualiDecimalService = new KualiDecimalUtils(assetPaymentDetail.getAmount(), CamsConstants.CURRENCY_USD);
511            KualiDecimal[] amountBuckets = kualiDecimalService.allocateByQuantity(assetGlobalDetailsSize);
512    
513            assetPayment.setAccountChargeAmount(amountBuckets[assetGlobalDetailsIndex]);
514            ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class);
515            ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(assetPayment.getChartOfAccountsCode(), assetPayment.getFinancialObjectCode());
516    
517            boolean isDepreciablePayment = ObjectUtils.isNotNull(assetPaymentDetail.getObjectCode()) && !Arrays.asList(parameterService.getParameterValue(CAPITAL_ASSETS_BATCH.class, CamsConstants.Parameters.NON_DEPRECIABLE_FEDERALLY_OWNED_OBJECT_SUB_TYPES).split(";")).contains(objectCode.getFinancialObjectSubTypeCode());
518            if (isDepreciablePayment) {
519                assetPayment.setPrimaryDepreciationBaseAmount(amountBuckets[assetGlobalDetailsIndex]);
520            }
521            else {
522                assetPayment.setPrimaryDepreciationBaseAmount(KualiDecimal.ZERO);
523            }
524    
525            return assetPayment;
526        }
527    
528    
529        /**
530         * Gets the paymentSummaryService attribute.
531         * 
532         * @return Returns the paymentSummaryService.
533         */
534        public PaymentSummaryService getPaymentSummaryService() {
535            return paymentSummaryService;
536        }
537    
538        /**
539         * Sets the paymentSummaryService attribute value.
540         * 
541         * @param paymentSummaryService The paymentSummaryService to set.
542         */
543        public void setPaymentSummaryService(PaymentSummaryService paymentSummaryService) {
544            this.paymentSummaryService = paymentSummaryService;
545        }
546        
547        /**
548         * @return the parameter value for the new acquisition type code
549         */
550        public String getNewAcquisitionTypeCode() {
551            return getParameterService().getParameterValue(AssetGlobal.class, 
552                    CamsConstants.AssetGlobal.NEW_ACQUISITION_CODE_PARAM); 
553        }
554        /**
555         * @return the parameter value for the capital object acquisition code group
556         */
557        public String getCapitalObjectAcquisitionCodeGroup() {
558            return getParameterService().getParameterValue(AssetGlobal.class, 
559                    CamsConstants.AssetGlobal.CAPITAL_OBJECT_ACQUISITION_CODE_PARAM);  
560        }
561        /**
562         * @return the parameter value for the not new acquisition code group 
563         */
564        public String getNonNewAcquisitionCodeGroup() {
565            return getParameterService().getParameterValue(AssetGlobal.class, 
566                    CamsConstants.AssetGlobal.NON_NEW_ACQUISITION_GROUP_PARAM);         
567        }
568    
569    
570    }