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.HashMap;
021    import java.util.List;
022    import java.util.Map;
023    
024    import org.apache.commons.lang.StringUtils;
025    import org.kuali.kfs.coa.businessobject.Account;
026    import org.kuali.kfs.coa.businessobject.ObjectCode;
027    import org.kuali.kfs.coa.service.ObjectCodeService;
028    import org.kuali.kfs.module.cam.CamsConstants;
029    import org.kuali.kfs.module.cam.CamsPropertyConstants;
030    import org.kuali.kfs.module.cam.businessobject.Asset;
031    import org.kuali.kfs.module.cam.businessobject.AssetGlpeSourceDetail;
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.AssetPaymentDetail;
035    import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal;
036    import org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobalDetail;
037    import org.kuali.kfs.module.cam.document.gl.CamsGeneralLedgerPendingEntrySourceBase;
038    import org.kuali.kfs.module.cam.document.service.AssetObjectCodeService;
039    import org.kuali.kfs.module.cam.document.service.AssetPaymentService;
040    import org.kuali.kfs.module.cam.document.service.AssetRetirementService;
041    import org.kuali.kfs.module.cam.document.service.AssetService;
042    import org.kuali.kfs.module.cam.util.ObjectValueUtils;
043    import org.kuali.kfs.sys.KFSConstants;
044    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
045    import org.kuali.kfs.sys.context.SpringContext;
046    import org.kuali.kfs.sys.document.authorization.FinancialSystemMaintenanceDocumentAuthorizerBase;
047    import org.kuali.kfs.sys.service.UniversityDateService;
048    import org.kuali.rice.kns.bo.PersistableBusinessObject;
049    import org.kuali.rice.kns.document.MaintenanceDocument;
050    import org.kuali.rice.kns.service.BusinessObjectService;
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.KualiDecimal;
055    import org.kuali.rice.kns.util.ObjectUtils;
056    import org.kuali.rice.kns.util.TypedArrayList;
057    
058    public class AssetRetirementServiceImpl implements AssetRetirementService {
059    
060        protected enum AmountCategory {
061            
062            CAPITALIZATION {
063                void setParams(AssetGlpeSourceDetail postable, AssetPayment assetPayment, AssetObjectCode assetObjectCode) {
064                    postable.setCapitalization(true);
065                    ParameterService parameterService = SpringContext.getBean(ParameterService.class);
066                    String lineDescription = parameterService.getParameterValue(AssetRetirementGlobal.class, CamsConstants.AssetRetirementGlobal.CAPITALIZATION_LINE_DESCRIPTION);
067                    postable.setFinancialDocumentLineDescription(lineDescription);
068                    postable.setAmount(assetPayment.getAccountChargeAmount());
069                    postable.setFinancialObjectCode(assetObjectCode.getCapitalizationFinancialObjectCode());
070                    postable.setObjectCode(assetObjectCode.getCapitalizationFinancialObject());
071                };
072            },
073            ACCUMMULATE_DEPRECIATION {
074                void setParams(AssetGlpeSourceDetail postable, AssetPayment assetPayment, AssetObjectCode assetObjectCode) {
075                    postable.setAccumulatedDepreciation(true);
076                    ParameterService parameterService = SpringContext.getBean(ParameterService.class);
077                    String lineDescription = parameterService.getParameterValue(AssetRetirementGlobal.class, CamsConstants.AssetRetirementGlobal.ACCUMULATED_DEPRECIATION_LINE_DESCRIPTION);
078                    postable.setFinancialDocumentLineDescription(lineDescription);
079                    postable.setAmount(assetPayment.getAccumulatedPrimaryDepreciationAmount());
080                    postable.setFinancialObjectCode(assetObjectCode.getAccumulatedDepreciationFinancialObjectCode());
081                    postable.setObjectCode(assetObjectCode.getAccumulatedDepreciationFinancialObject());
082                };
083            },
084            OFFSET_AMOUNT {
085                void setParams(AssetGlpeSourceDetail postable, AssetPayment assetPayment, AssetObjectCode assetObjectCode) {
086                    postable.setCapitalizationOffset(true);
087                    ParameterService parameterService = SpringContext.getBean(ParameterService.class);
088                    String lineDescription = parameterService.getParameterValue(AssetRetirementGlobal.class, CamsConstants.AssetRetirementGlobal.OFFSET_AMOUNT_LINE_DESCRIPTION);
089                    postable.setFinancialDocumentLineDescription(lineDescription);
090    
091                    KualiDecimal accumlatedDepreciationAmount = (assetPayment.getAccumulatedPrimaryDepreciationAmount() == null ? new KualiDecimal(0) : assetPayment.getAccumulatedPrimaryDepreciationAmount());
092    
093                    postable.setAmount(assetPayment.getAccountChargeAmount().subtract(accumlatedDepreciationAmount));
094                    postable.setFinancialObjectCode(SpringContext.getBean(ParameterService.class).getParameterValue(AssetRetirementGlobal.class, CamsConstants.Parameters.DEFAULT_GAIN_LOSS_DISPOSITION_OBJECT_CODE).trim());
095    
096                    Map pkMap = new HashMap();
097                    UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class);
098                    String gainDispositionObjectCode = parameterService.getParameterValue(AssetRetirementGlobal.class, CamsConstants.Parameters.DEFAULT_GAIN_LOSS_DISPOSITION_OBJECT_CODE);
099    
100                    pkMap.put(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, universityDateService.getCurrentFiscalYear());
101                    pkMap.put(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, assetPayment.getAsset().getOrganizationOwnerChartOfAccountsCode());
102                    pkMap.put(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, gainDispositionObjectCode);
103    
104                    ObjectCode offsetFinancialObject = (ObjectCode) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(ObjectCode.class, pkMap);
105    
106                    postable.setObjectCode(offsetFinancialObject);
107                };
108            };
109    
110            abstract void setParams(AssetGlpeSourceDetail postable, AssetPayment assetPayment, AssetObjectCode assetObjectCode);
111        }
112    
113        private UniversityDateService universityDateService;
114        private AssetObjectCodeService assetObjectCodeService;
115        private BusinessObjectService businessObjectService;
116        private AssetPaymentService assetPaymentService;
117        private ParameterService parameterService;
118        private AssetService assetService;
119    
120        public ParameterService getParameterService() {
121            return parameterService;
122        }
123    
124        public void setParameterService(ParameterService parameterService) {
125            this.parameterService = parameterService;
126        }
127    
128        public AssetService getAssetService() {
129            return assetService;
130        }
131    
132        public void setAssetService(AssetService assetService) {
133            this.assetService = assetService;
134        }
135    
136        public UniversityDateService getUniversityDateService() {
137            return universityDateService;
138        }
139    
140        public void setUniversityDateService(UniversityDateService universityDateService) {
141            this.universityDateService = universityDateService;
142        }
143    
144        public AssetObjectCodeService getAssetObjectCodeService() {
145            return assetObjectCodeService;
146        }
147    
148        public void setAssetObjectCodeService(AssetObjectCodeService assetObjectCodeService) {
149            this.assetObjectCodeService = assetObjectCodeService;
150        }
151    
152    
153        public BusinessObjectService getBusinessObjectService() {
154            return businessObjectService;
155        }
156    
157        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
158            this.businessObjectService = businessObjectService;
159        }
160    
161        public AssetPaymentService getAssetPaymentService() {
162            return assetPaymentService;
163        }
164    
165        public void setAssetPaymentService(AssetPaymentService assetPaymentService) {
166            this.assetPaymentService = assetPaymentService;
167        }
168    
169        /**
170         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isAssetRetiredBySoldOrAuction(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal)
171         */
172        public boolean isAssetRetiredByAuction(AssetRetirementGlobal assetRetirementGlobal) {
173            return CamsConstants.AssetRetirementReasonCode.AUCTION.equalsIgnoreCase(assetRetirementGlobal.getRetirementReasonCode());
174        }
175    
176        /**
177         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isAssetRetiredBySold(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal)
178         */
179        public boolean isAssetRetiredBySold(AssetRetirementGlobal assetRetirementGlobal) {
180            return CamsConstants.AssetRetirementReasonCode.SOLD.equalsIgnoreCase(assetRetirementGlobal.getRetirementReasonCode());
181        }
182    
183        /**
184         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isAssetRetiredByExternalTransferOrGift(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal)
185         */
186        public boolean isAssetRetiredByExternalTransferOrGift(AssetRetirementGlobal assetRetirementGlobal) {
187            return CamsConstants.AssetRetirementReasonCode.EXTERNAL_TRANSFER.equalsIgnoreCase(assetRetirementGlobal.getRetirementReasonCode()) || CamsConstants.AssetRetirementReasonCode.GIFT.equalsIgnoreCase(assetRetirementGlobal.getRetirementReasonCode());
188        }
189    
190        /**
191         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isAssetRetiredByMerged(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal)
192         */
193        public boolean isAssetRetiredByMerged(AssetRetirementGlobal assetRetirementGlobal) {
194            return CamsConstants.AssetRetirementReasonCode.MERGED.equalsIgnoreCase(assetRetirementGlobal.getRetirementReasonCode());
195        }
196    
197        /**
198         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isAssetRetiredByTheft(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal)
199         */
200        public boolean isAssetRetiredByTheft(AssetRetirementGlobal assetRetirementGlobal) {
201            return CamsConstants.AssetRetirementReasonCode.THEFT.equalsIgnoreCase(assetRetirementGlobal.getRetirementReasonCode());
202        }
203    
204        /**
205         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#getAssetRetirementReasonName(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal)
206         */
207        public String getAssetRetirementReasonName(AssetRetirementGlobal assetRetirementGlobal) {
208            return assetRetirementGlobal.getRetirementReason() == null ? new String() : assetRetirementGlobal.getRetirementReason().getRetirementReasonName();
209        }
210    
211        /**
212         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#generateOffsetPaymentsForEachSource(org.kuali.kfs.module.cam.businessobject.Asset,
213         *      java.util.List, java.lang.String)
214         */
215        public void generateOffsetPaymentsForEachSource(Asset sourceAsset, List<PersistableBusinessObject> persistables, String currentDocumentNumber) {
216            List<AssetPayment> offsetPayments = new TypedArrayList(AssetPayment.class);
217            Integer maxSequenceNo = assetPaymentService.getMaxSequenceNumber(sourceAsset.getCapitalAssetNumber());
218    
219            try {
220                for (AssetPayment sourcePayment : sourceAsset.getAssetPayments()) {
221                    AssetPayment offsetPayment = new AssetPayment();
222                    ObjectValueUtils.copySimpleProperties(sourcePayment, offsetPayment);
223                    offsetPayment.setFinancialDocumentTypeCode(CamsConstants.PaymentDocumentTypeCodes.ASSET_RETIREMENT_MERGE);
224                    offsetPayment.setDocumentNumber(currentDocumentNumber);
225                    offsetPayment.setPaymentSequenceNumber(++maxSequenceNo);
226                    assetPaymentService.adjustPaymentAmounts(offsetPayment, true, false);
227                    offsetPayments.add(offsetPayment);
228                }
229            }
230            catch (Exception e) {
231                throw new RuntimeException("Error occured while creating offset payment in retirement", e);
232            }
233            persistables.addAll(offsetPayments);
234        }
235    
236        /**
237         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#generateNewPaymentForTarget(org.kuali.kfs.module.cam.businessobject.Asset,
238         *      org.kuali.kfs.module.cam.businessobject.Asset, java.util.List, java.lang.Integer, java.lang.String)
239         */
240        public Integer generateNewPaymentForTarget(Asset targetAsset, Asset sourceAsset, List<PersistableBusinessObject> persistables, Integer maxSequenceNo, String currentDocumentNumber) {
241            List<AssetPayment> newPayments = new TypedArrayList(AssetPayment.class);
242            try {
243                for (AssetPayment sourcePayment : sourceAsset.getAssetPayments()) {
244                    AssetPayment newPayment = new AssetPayment();
245                    ObjectValueUtils.copySimpleProperties(sourcePayment, newPayment);
246                    newPayment.setCapitalAssetNumber(targetAsset.getCapitalAssetNumber());
247                    newPayment.setFinancialDocumentTypeCode(CamsConstants.PaymentDocumentTypeCodes.ASSET_RETIREMENT_MERGE);
248                    newPayment.setPaymentSequenceNumber(++maxSequenceNo);
249                    newPayment.setDocumentNumber(currentDocumentNumber);
250                    assetPaymentService.adjustPaymentAmounts(newPayment, false, false);
251                    newPayments.add(newPayment);
252                }
253            }
254            catch (Exception e) {
255                throw new RuntimeException("Error occured while creating new payment in retirement", e);
256            }
257            persistables.addAll(newPayments);
258            return maxSequenceNo;
259        }
260    
261    
262        /**
263         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isRetirementReasonCodeInGroup(java.lang.String,
264         *      java.lang.String)
265         */
266        public boolean isRetirementReasonCodeInGroup(String reasonCodeGroup, String reasonCode) {
267            if (StringUtils.isBlank(reasonCodeGroup) || StringUtils.isBlank(reasonCode)) {
268                return false;
269            }
270            return Arrays.asList(reasonCodeGroup.split(";")).contains(reasonCode);
271        }
272    
273        /**
274         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#isAllowedRetireMultipleAssets(java.lang.String)
275         */
276        public boolean isAllowedRetireMultipleAssets(MaintenanceDocument maintenanceDocument) {
277            FinancialSystemMaintenanceDocumentAuthorizerBase documentAuthorizer = (FinancialSystemMaintenanceDocumentAuthorizerBase) SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(maintenanceDocument);
278            boolean isAuthorized = documentAuthorizer.isAuthorized(maintenanceDocument, CamsConstants.CAM_MODULE_CODE, 
279                    CamsConstants.PermissionNames.RETIRE_MULTIPLE, GlobalVariables.getUserSession().getPerson().getPrincipalId());
280            
281            return isAuthorized;
282        }
283    
284        /**
285         * @see org.kuali.kfs.module.cam.document.service.AssetRetirementService#createGLPostables(org.kuali.kfs.module.cam.businessobject.AssetRetirementGlobal,
286         *      org.kuali.module.cams.gl.CamsGlPosterBase)
287         */
288        public void createGLPostables(AssetRetirementGlobal assetRetirementGlobal, CamsGeneralLedgerPendingEntrySourceBase assetRetirementGlPoster) {
289    
290            List<AssetRetirementGlobalDetail> assetRetirementGlobalDetails = assetRetirementGlobal.getAssetRetirementGlobalDetails();
291    
292            for (AssetRetirementGlobalDetail assetRetirementGlobalDetail : assetRetirementGlobalDetails) {
293                Asset asset = assetRetirementGlobalDetail.getAsset();
294    
295                for (AssetPayment assetPayment : asset.getAssetPayments()) {
296                    if (!getAssetPaymentService().isPaymentFederalOwned(assetPayment) && !("Y".equals(assetPayment.getTransferPaymentCode()))) {
297                        List<GeneralLedgerPendingEntrySourceDetail> postables = generateGlPostablesForOnePayment(assetRetirementGlobal.getDocumentNumber(), assetRetirementGlPoster, asset, assetPayment);
298                        assetRetirementGlPoster.getPostables().addAll(postables);
299                    }
300                }
301            }
302    
303        }
304    
305        /**
306         * Generate a collection of Postables for each payment.
307         * 
308         * @param documentNumber
309         * @param assetRetirementGlPoster
310         * @param asset
311         * @param assetPayment
312         * @return
313         */
314        protected List<GeneralLedgerPendingEntrySourceDetail> generateGlPostablesForOnePayment(String documentNumber, CamsGeneralLedgerPendingEntrySourceBase assetRetirementGlPoster, Asset asset, AssetPayment assetPayment) {
315            List<GeneralLedgerPendingEntrySourceDetail> postables = new ArrayList<GeneralLedgerPendingEntrySourceDetail>();
316            Account plantAccount = getPlantFundAccount(asset, assetPayment);
317    
318            if (ObjectUtils.isNotNull(plantAccount)) {
319                if (assetPaymentService.isPaymentEligibleForCapitalizationGLPosting(assetPayment)) {
320                    createNewPostable(AmountCategory.CAPITALIZATION, asset, assetPayment, documentNumber, plantAccount, postables);
321                }
322    
323                if (assetPaymentService.isPaymentEligibleForAccumDeprGLPosting(assetPayment)) {
324                    createNewPostable(AmountCategory.ACCUMMULATE_DEPRECIATION, asset, assetPayment, documentNumber, plantAccount, postables);
325                }
326    
327                if (assetPaymentService.isPaymentEligibleForOffsetGLPosting(assetPayment)) {
328                    createNewPostable(AmountCategory.OFFSET_AMOUNT, asset, assetPayment, documentNumber, plantAccount, postables);
329                }
330            }
331            return postables;
332        }
333    
334        /**
335         * This method creates one postable and sets the values.
336         * 
337         * @param category
338         * @param asset
339         * @param assetPayment
340         * @param documentNumber
341         * @param plantAccount
342         * @return
343         */
344        protected void createNewPostable(AmountCategory category, Asset asset, AssetPayment assetPayment, String documentNumber, Account plantAccount, List<GeneralLedgerPendingEntrySourceDetail> postables) {
345            boolean success = true;
346            AssetGlpeSourceDetail postable = new AssetGlpeSourceDetail();
347    
348            AssetObjectCode assetObjectCode = getAssetObjectCode(asset, assetPayment);
349            category.setParams(postable, assetPayment, assetObjectCode);
350    
351            // Set Postable attributes which are common among Capitalized, Accumulated Depreciation and gain/loss disposition .
352            postable.setDocumentNumber(documentNumber);
353            postable.setAccount(plantAccount);
354            postable.setAccountNumber(plantAccount.getAccountNumber());
355            postable.setBalanceTypeCode(CamsConstants.Postable.GL_BALANCE_TYPE_CODE_AC);
356            postable.setChartOfAccountsCode(asset.getOrganizationOwnerChartOfAccountsCode());
357    
358            postable.setPostingYear(universityDateService.getCurrentFiscalYear());
359            // Fields copied from payment
360            postable.setFinancialSubObjectCode(assetPayment.getFinancialSubObjectCode());
361            postable.setProjectCode(assetPayment.getProjectCode());
362            postable.setSubAccountNumber(assetPayment.getSubAccountNumber());
363            postable.setOrganizationReferenceId(assetPayment.getOrganizationReferenceId());
364            postables.add(postable);
365        }
366    
367        protected AssetObjectCode getAssetObjectCode(Asset asset, AssetPayment assetPayment) {
368            ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class);
369            ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(assetPayment.getChartOfAccountsCode(), assetPayment.getFinancialObjectCode());
370    
371            AssetObjectCode assetObjectCode = assetObjectCodeService.findAssetObjectCode(asset.getOrganizationOwnerChartOfAccountsCode(), objectCode.getFinancialObjectSubTypeCode());
372            return assetObjectCode;
373        }
374    
375    
376        /**
377         * Get the offset Object Code.
378         * 
379         * @param asset
380         * @return
381         */
382        public ObjectCode getOffsetFinancialObject(String chartOfAccountsCode) {
383            Map pkMap = new HashMap();
384            UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class);
385            ParameterService parameterService = SpringContext.getBean(ParameterService.class);
386            String gainDispositionObjectCode = parameterService.getParameterValue(AssetRetirementGlobal.class, CamsConstants.Parameters.DEFAULT_GAIN_LOSS_DISPOSITION_OBJECT_CODE);
387    
388            pkMap.put(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, universityDateService.getCurrentFiscalYear());
389            pkMap.put(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, chartOfAccountsCode);
390            pkMap.put(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, gainDispositionObjectCode);
391    
392            return (ObjectCode) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(ObjectCode.class, pkMap);
393        }
394    
395    
396        /**
397         * Get the corresponding Plant Fund Account object based on the payment's financialObjectSubTypeCode.
398         * 
399         * @param asset
400         * @param payment
401         * @return
402         */
403        protected Account getPlantFundAccount(Asset asset, AssetPayment payment) {
404            Account plantFundAccount = null;
405    
406            payment.refreshReferenceObject(CamsPropertyConstants.AssetPayment.FINANCIAL_OBJECT);
407            asset.refreshReferenceObject(CamsPropertyConstants.Asset.ORGANIZATION_OWNER_ACCOUNT);
408    
409            if (ObjectUtils.isNotNull(payment.getFinancialObject()) && ObjectUtils.isNotNull(asset.getOrganizationOwnerAccount())) {
410                ObjectCodeService objectCodeService = (ObjectCodeService) SpringContext.getBean(ObjectCodeService.class);
411                ObjectCode objectCode = objectCodeService.getByPrimaryIdForCurrentYear(payment.getChartOfAccountsCode(), payment.getFinancialObjectCode());
412    
413                String financialObjectSubTypeCode = objectCode.getFinancialObjectSubTypeCode();
414    
415                if (assetService.isAssetMovableCheckByPayment(financialObjectSubTypeCode)) {
416                    plantFundAccount = asset.getOrganizationOwnerAccount().getOrganization().getOrganizationPlantAccount();
417                }
418                else {
419                    plantFundAccount = asset.getOrganizationOwnerAccount().getOrganization().getCampusPlantAccount();
420                }
421            }
422    
423            return plantFundAccount;
424        }
425        
426        /**
427         * This method generates the calculatedTotal amount based on salePrice + handlingFeeAmount + preventiveMaintenanceAmount.
428         * 
429         * @param salePrice
430         * @param handlingFeeAmount
431         * @param preventiveMaintenanceAmount
432         * @return
433         */
434        public String generateCalculatedTotal(String salePrice, String handlingFeeAmount, String preventiveMaintenanceAmount) {
435            KualiDecimal calculatedTotal = KualiDecimal.ZERO;
436    
437            if (!salePrice.isEmpty()) {
438                KualiDecimal testAmount = toKualiDecimal(salePrice);
439                if(testAmount.isZero()){
440                  return "Please enter Sale Price in 1,234,567.00 Format";
441                }
442                calculatedTotal = calculatedTotal.add(testAmount);
443            }
444            if (!handlingFeeAmount.isEmpty()) {
445                KualiDecimal testAmount = toKualiDecimal(handlingFeeAmount);
446                if(testAmount.isZero()){
447                   return "Please enter Handling Fee Amount in 1,234,567.00 Format";
448                }
449                calculatedTotal = calculatedTotal.add(testAmount);
450            }
451            if (!preventiveMaintenanceAmount.isEmpty()) {
452                KualiDecimal testAmount = toKualiDecimal(preventiveMaintenanceAmount);
453                if(testAmount.isZero()){
454                  return "Please enter Preventive Maintenance Amount in 1,234,567.00 Format";
455                }
456                calculatedTotal = calculatedTotal.add(testAmount);
457            }
458    
459            return calculatedTotal.toString();
460        }
461    
462        /**
463         * This method converts a String to a KualiDecimal via Double. Or else returns a Zero to invoke proper error message and to avoid breaking DWR call
464         * 
465         * @param amount
466         * @return
467         */
468        protected KualiDecimal toKualiDecimal(String amount) {
469            KualiDecimal newAmount;
470            try{
471                newAmount = new KualiDecimal(java.lang.Double.parseDouble(amount));
472            }catch(NumberFormatException e){
473                return KualiDecimal.ZERO;
474            }
475            return newAmount;
476        }
477    
478    }