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.lang.reflect.Method;
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    
023    import org.apache.commons.lang.ArrayUtils;
024    import org.kuali.kfs.module.cam.CamsConstants;
025    import org.kuali.kfs.module.cam.CamsPropertyConstants;
026    import org.kuali.kfs.module.cam.businessobject.Asset;
027    import org.kuali.kfs.module.cam.businessobject.AssetPayment;
028    import org.kuali.kfs.module.cam.document.service.PaymentSummaryService;
029    import org.kuali.kfs.sys.service.UniversityDateService;
030    import org.kuali.rice.kns.service.ParameterService;
031    import org.kuali.rice.kns.util.KualiDecimal;
032    import org.kuali.rice.kns.util.ObjectUtils;
033    
034    /**
035     * This class implements PaymentSummaryService
036     */
037    public class PaymentSummaryServiceImpl implements PaymentSummaryService {
038    
039    
040        private static Map<Integer, Method> DEPR_AMT_FIELDS = new HashMap<Integer, Method>();
041        /**
042         * Map will store getter method mapped to each primary depreciation period column. Based on the current fiscal month, current
043         * month depreciation column can be identified easily from this map
044         */
045        static {
046            try {
047                Class<?>[] emptyParams = new Class[] {};
048                DEPR_AMT_FIELDS.put(1, AssetPayment.class.getMethod("getPeriod1Depreciation1Amount", emptyParams));
049                DEPR_AMT_FIELDS.put(2, AssetPayment.class.getMethod("getPeriod2Depreciation1Amount", emptyParams));
050                DEPR_AMT_FIELDS.put(3, AssetPayment.class.getMethod("getPeriod3Depreciation1Amount", emptyParams));
051                DEPR_AMT_FIELDS.put(4, AssetPayment.class.getMethod("getPeriod4Depreciation1Amount", emptyParams));
052                DEPR_AMT_FIELDS.put(5, AssetPayment.class.getMethod("getPeriod5Depreciation1Amount", emptyParams));
053                DEPR_AMT_FIELDS.put(6, AssetPayment.class.getMethod("getPeriod6Depreciation1Amount", emptyParams));
054                DEPR_AMT_FIELDS.put(7, AssetPayment.class.getMethod("getPeriod7Depreciation1Amount", emptyParams));
055                DEPR_AMT_FIELDS.put(8, AssetPayment.class.getMethod("getPeriod8Depreciation1Amount", emptyParams));
056                DEPR_AMT_FIELDS.put(9, AssetPayment.class.getMethod("getPeriod9Depreciation1Amount", emptyParams));
057                DEPR_AMT_FIELDS.put(10, AssetPayment.class.getMethod("getPeriod10Depreciation1Amount", emptyParams));
058                DEPR_AMT_FIELDS.put(11, AssetPayment.class.getMethod("getPeriod11Depreciation1Amount", emptyParams));
059                DEPR_AMT_FIELDS.put(12, AssetPayment.class.getMethod("getPeriod12Depreciation1Amount", emptyParams));
060            }
061            catch (Exception e) {
062                throw new RuntimeException(e);
063            }
064        }
065    
066        private UniversityDateService universityDateService;
067        private ParameterService parameterService;
068    
069        protected KualiDecimal addAmount(KualiDecimal amount, KualiDecimal addend) {
070            if (addend != null) {
071                return amount.add(addend);
072            }
073            return amount;
074        }
075    
076        /**
077         * @see org.kuali.kfs.module.cam.document.service.PaymentSummaryService#calculateAndSetPaymentSummary(org.kuali.kfs.module.cam.businessobject.Asset)
078         */
079    
080        public void calculateAndSetPaymentSummary(Asset asset) {
081            asset.setFederalContribution(calculateFederalContribution(asset));
082            setPaymentYearToDate(asset);
083            asset.setPaymentTotalCost(calculatePaymentTotalCost(asset));
084            asset.setAccumulatedDepreciation(calculatePrimaryAccumulatedDepreciation(asset));
085            asset.setBaseAmount(calculatePrimaryBaseAmount(asset));
086            asset.setBookValue(calculatePrimaryBookValue(asset));
087            asset.setPrevYearDepreciation(calculatePrimaryPrevYearDepreciation(asset));
088            asset.setYearToDateDepreciation(calculatePrimaryYTDDepreciation(asset));
089            asset.setCurrentMonthDepreciation(calculatePrimaryCurrentMonthDepreciation(asset));
090        }
091    
092    
093        /**
094         * @see org.kuali.kfs.module.cam.document.service.PaymentSummaryService#calculateFederalContribution(org.kuali.kfs.module.cam.businessobject.Asset)
095         */
096        public KualiDecimal calculateFederalContribution(Asset asset) {
097            KualiDecimal amount = new KualiDecimal(0);
098            List<AssetPayment> assetPayments = asset.getAssetPayments();
099    
100            for (AssetPayment payment : assetPayments) {
101                // Refresh the financial object
102                if (ObjectUtils.isNull(payment.getFinancialObject())) {
103                    payment.refreshReferenceObject(CamsPropertyConstants.AssetPayment.FINANCIAL_OBJECT);
104                }
105                Object[] fedContrTypes = parameterService.getParameterValues(Asset.class, CamsConstants.Parameters.FEDERAL_CONTRIBUTIONS_OBJECT_SUB_TYPES).toArray();
106                if (ArrayUtils.contains(fedContrTypes, payment.getFinancialObject().getFinancialObjectSubTypeCode())) {
107                    amount = addAmount(amount, payment.getAccountChargeAmount());
108                }
109            }
110            return amount;
111        }
112    
113        /**
114         * Sums up total payment cost for an asset
115         * 
116         * @param asset Asset
117         * @return Total Payment Amount
118         */
119        public KualiDecimal calculatePaymentTotalCost(Asset asset) {
120            List<AssetPayment> payments = asset.getAssetPayments();
121            KualiDecimal totalCost = new KualiDecimal(0);
122            for (AssetPayment payment : payments) {
123                totalCost = addAmount(totalCost, payment.getAccountChargeAmount());
124            }
125            return totalCost;
126        }
127    
128        /**
129         * Sums up primary accumulated depreciation amount
130         * 
131         * @param asset Asset
132         * @return Accumulated Primary Depreciation Amount
133         */
134        public KualiDecimal calculatePrimaryAccumulatedDepreciation(Asset asset) {
135            List<AssetPayment> assetPayments = asset.getAssetPayments();
136            KualiDecimal amount = new KualiDecimal(0);
137            if (assetPayments != null) {
138                for (AssetPayment assetPayment : assetPayments) {
139                    amount = addAmount(amount, assetPayment.getAccumulatedPrimaryDepreciationAmount());
140                }
141            }
142            return amount;
143        }
144    
145    
146        /**
147         * Sums up primary base amount for an asset
148         * 
149         * @param asset Asset
150         * @return Base Amount
151         */
152        protected KualiDecimal calculatePrimaryBaseAmount(Asset asset) {
153            List<AssetPayment> assetPayments = asset.getAssetPayments();
154            KualiDecimal amount = new KualiDecimal(0);
155            if (assetPayments != null) {
156                for (AssetPayment assetPayment : assetPayments) {
157                    amount = addAmount(amount, assetPayment.getPrimaryDepreciationBaseAmount());
158                }
159            }
160            return amount;
161        }
162    
163        /**
164         * Sums up primary book value for an asset
165         * 
166         * @param asset Asset
167         * @return Book Value Amount
168         */
169        public KualiDecimal calculatePrimaryBookValue(Asset asset) {
170            KualiDecimal baseAmount = calculatePrimaryBaseAmount(asset);
171            KualiDecimal accumDeprAmount = calculatePrimaryAccumulatedDepreciation(asset);
172            KualiDecimal salvageAmount = asset.getSalvageAmount();
173            // If depreciation method is "SV", then minus it from base amount
174            if (CamsConstants.Asset.DEPRECIATION_METHOD_SALVAGE_VALUE_CODE.equals(asset.getPrimaryDepreciationMethodCode()) && salvageAmount != null) {
175                return baseAmount.subtract(accumDeprAmount).subtract(salvageAmount);
176            }
177            return baseAmount.subtract(accumDeprAmount);
178        }
179    
180    
181        /**
182         * Sums current month depreciation amount for an asset
183         * 
184         * @param asset Asset
185         * @return Current month depreciation amount
186         */
187        protected KualiDecimal calculatePrimaryCurrentMonthDepreciation(Asset asset) {
188            List<AssetPayment> assetPayments = asset.getAssetPayments();
189            KualiDecimal amount = new KualiDecimal(0);
190            if (assetPayments != null) {
191                for (AssetPayment assetPayment : assetPayments) {
192                    amount = addAmount(amount, getCurrentMonthDepreciationAmount(assetPayment));
193    
194                }
195            }
196            return amount;
197        }
198    
199    
200        /**
201         * Sums up previous year depreciation amount for an asset
202         * 
203         * @param asset Asset
204         * @return Previoud Year Depreciation Amount
205         */
206        protected KualiDecimal calculatePrimaryPrevYearDepreciation(Asset asset) {
207            List<AssetPayment> assetPayments = asset.getAssetPayments();
208            KualiDecimal amount = new KualiDecimal(0);
209            if (assetPayments != null) {
210                for (AssetPayment assetPayment : assetPayments) {
211                    amount = addAmount(amount, assetPayment.getPreviousYearPrimaryDepreciationAmount());
212                }
213            }
214            return amount;
215        }
216    
217    
218        /**
219         * Sums up year to date depreciation amount for an asset
220         * 
221         * @param asset Asset
222         * @return Year To Date Depreciation Amount
223         */
224        protected KualiDecimal calculatePrimaryYTDDepreciation(Asset asset) {
225            List<AssetPayment> assetPayments = asset.getAssetPayments();
226            KualiDecimal amount = new KualiDecimal(0);
227            if (assetPayments != null) {
228                for (AssetPayment assetPayment : assetPayments) {
229                    amount = addAmount(amount, assetPayment.getPeriod1Depreciation1Amount());
230                    amount = addAmount(amount, assetPayment.getPeriod2Depreciation1Amount());
231                    amount = addAmount(amount, assetPayment.getPeriod3Depreciation1Amount());
232                    amount = addAmount(amount, assetPayment.getPeriod4Depreciation1Amount());
233                    amount = addAmount(amount, assetPayment.getPeriod5Depreciation1Amount());
234                    amount = addAmount(amount, assetPayment.getPeriod6Depreciation1Amount());
235                    amount = addAmount(amount, assetPayment.getPeriod7Depreciation1Amount());
236                    amount = addAmount(amount, assetPayment.getPeriod8Depreciation1Amount());
237                    amount = addAmount(amount, assetPayment.getPeriod9Depreciation1Amount());
238                    amount = addAmount(amount, assetPayment.getPeriod10Depreciation1Amount());
239                    amount = addAmount(amount, assetPayment.getPeriod11Depreciation1Amount());
240                    amount = addAmount(amount, assetPayment.getPeriod12Depreciation1Amount());
241                }
242            }
243            return amount;
244        }
245    
246        /**
247         * Helper methods uses university date service to identify the right depreciation month column for the current month
248         * 
249         * @param assetPayment Asset Payment Record
250         * @return Depreciation Amount for current month
251         */
252        protected KualiDecimal getCurrentMonthDepreciationAmount(AssetPayment assetPayment) {
253            Object[] emptyParams = new Object[] {};
254            Integer currPeriod = Integer.valueOf(universityDateService.getCurrentUniversityDate().getUniversityFiscalAccountingPeriod());
255            KualiDecimal amount = null;
256            try {
257                amount = (KualiDecimal) (DEPR_AMT_FIELDS.get(currPeriod).invoke(assetPayment, emptyParams));
258            }
259            catch (Exception e) {
260                throw new RuntimeException(e);
261            }
262            return amount;
263        }
264    
265        public UniversityDateService getUniversityDateService() {
266            return universityDateService;
267        }
268    
269        /**
270         * Sets sum of depreciation for each asset payment record
271         * 
272         * @param asset Asset
273         */
274        protected void setPaymentYearToDate(Asset asset) {
275            List<AssetPayment> assetPayments = asset.getAssetPayments();
276            if (assetPayments != null) {
277                for (AssetPayment assetPayment : assetPayments) {
278                    KualiDecimal yearToDate = new KualiDecimal(0);
279                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod1Depreciation1Amount());
280                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod2Depreciation1Amount());
281                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod3Depreciation1Amount());
282                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod4Depreciation1Amount());
283                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod5Depreciation1Amount());
284                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod6Depreciation1Amount());
285                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod7Depreciation1Amount());
286                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod8Depreciation1Amount());
287                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod9Depreciation1Amount());
288                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod10Depreciation1Amount());
289                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod11Depreciation1Amount());
290                    yearToDate = addAmount(yearToDate, assetPayment.getPeriod12Depreciation1Amount());
291                    assetPayment.setYearToDate(yearToDate);
292                }
293            }
294    
295        }
296    
297        public void setUniversityDateService(UniversityDateService universityDateService) {
298            this.universityDateService = universityDateService;
299        }
300    
301        public ParameterService getParameterService() {
302            return parameterService;
303        }
304    
305        public void setParameterService(ParameterService parameterService) {
306            this.parameterService = parameterService;
307        }
308    }