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.bc.document.service.impl;
017    
018    import java.math.BigDecimal;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.kuali.kfs.coa.businessobject.Chart;
026    import org.kuali.kfs.module.bc.BCConstants;
027    import org.kuali.kfs.module.bc.BCKeyConstants;
028    import org.kuali.kfs.module.bc.businessobject.BudgetConstructionOrgReasonStatisticsReport;
029    import org.kuali.kfs.module.bc.businessobject.BudgetConstructionReportThresholdSettings;
030    import org.kuali.kfs.module.bc.businessobject.BudgetConstructionSalaryTotal;
031    import org.kuali.kfs.module.bc.document.dataaccess.BudgetConstructionReasonStatisticsReportDao;
032    import org.kuali.kfs.module.bc.document.service.BudgetConstructionOrganizationReportsService;
033    import org.kuali.kfs.module.bc.document.service.BudgetConstructionReasonStatisticsReportService;
034    import org.kuali.kfs.module.bc.document.service.BudgetConstructionReportsServiceHelper;
035    import org.kuali.kfs.module.bc.report.BudgetConstructionReportHelper;
036    import org.kuali.kfs.sys.KFSPropertyConstants;
037    import org.kuali.rice.kns.service.BusinessObjectService;
038    import org.kuali.rice.kns.service.KualiConfigurationService;
039    import org.kuali.rice.kns.util.KualiDecimal;
040    import org.springframework.transaction.annotation.Transactional;
041    
042    /**
043     * Service implementation of BudgetConstructionAccountSummaryReportService.
044     */
045    @Transactional
046    public class BudgetConstructionReasonStatisticsReportServiceImpl implements BudgetConstructionReasonStatisticsReportService {
047    
048        BudgetConstructionReasonStatisticsReportDao budgetConstructionReasonStatisticsReportDao;
049        BudgetConstructionOrganizationReportsService budgetConstructionOrganizationReportsService;
050        private BudgetConstructionReportsServiceHelper budgetConstructionReportsServiceHelper;
051        KualiConfigurationService kualiConfigurationService;
052        BusinessObjectService businessObjectService;
053    
054        /**
055         * @see org.kuali.kfs.module.bc.document.service.BudgetConstructionReasonStatisticsReportService#updateReasonStatisticsReport(java.lang.String,
056         *      java.lang.Integer, org.kuali.kfs.module.bc.businessobject.BudgetConstructionReportThresholdSettings)
057         */
058        public void updateReasonStatisticsReport(String principalName, Integer universityFiscalYear, BudgetConstructionReportThresholdSettings budgetConstructionReportThresholdSettings) {
059            boolean applyAThreshold = budgetConstructionReportThresholdSettings.isUseThreshold();
060            boolean selectOnlyGreaterThanOrEqualToThreshold = budgetConstructionReportThresholdSettings.isUseGreaterThanOperator();
061            KualiDecimal thresholdPercent = budgetConstructionReportThresholdSettings.getThresholdPercent();
062            if (applyAThreshold) {
063                budgetConstructionReasonStatisticsReportDao.updateReasonStatisticsReportsWithAThreshold(principalName, universityFiscalYear - 1, selectOnlyGreaterThanOrEqualToThreshold, thresholdPercent);
064            }
065            else {
066                budgetConstructionReasonStatisticsReportDao.updateReasonStatisticsReportsWithoutAThreshold(principalName, universityFiscalYear - 1);
067            }
068    
069        }
070    
071        /**
072         * @see org.kuali.kfs.module.bc.document.service.BudgetConstructionReasonStatisticsReportService#buildReports(java.lang.Integer,
073         *      java.lang.String, org.kuali.kfs.module.bc.businessobject.BudgetConstructionReportThresholdSettings)
074         */
075        public Collection<BudgetConstructionOrgReasonStatisticsReport> buildReports(Integer universityFiscalYear, String principalId, BudgetConstructionReportThresholdSettings budgetConstructionReportThresholdSettings) {
076            Collection<BudgetConstructionOrgReasonStatisticsReport> reportSet = new ArrayList<BudgetConstructionOrgReasonStatisticsReport>();
077    
078            BudgetConstructionOrgReasonStatisticsReport orgReasonStatisticsReportEntry;
079            // build searchCriteria
080            Map<String, Object> searchCriteria = new HashMap<String, Object>();
081            searchCriteria.put(KFSPropertyConstants.KUALI_USER_PERSON_UNIVERSAL_IDENTIFIER, principalId);
082    
083            // build order list
084            List<String> orderList = buildOrderByList();
085            Collection<BudgetConstructionSalaryTotal> reasonStatisticsList = budgetConstructionOrganizationReportsService.getBySearchCriteriaOrderByList(BudgetConstructionSalaryTotal.class, searchCriteria, orderList);
086    
087            // get object codes
088            String objectCodes = budgetConstructionReportsServiceHelper.getSelectedObjectCodes(principalId);
089    
090            // get reason codes
091            String reasonCodes = budgetConstructionReportsServiceHelper.getSelectedReasonCodes(principalId);
092    
093            // build reports
094            for (BudgetConstructionSalaryTotal reasonStatisticsEntry : reasonStatisticsList) {
095                orgReasonStatisticsReportEntry = new BudgetConstructionOrgReasonStatisticsReport();
096                buildReportsHeader(universityFiscalYear, objectCodes, reasonCodes, orgReasonStatisticsReportEntry, reasonStatisticsEntry, budgetConstructionReportThresholdSettings);
097                buildReportsBody(orgReasonStatisticsReportEntry, reasonStatisticsEntry);
098                reportSet.add(orgReasonStatisticsReportEntry);
099            }
100    
101            return reportSet;
102        }
103    
104        /**
105         * builds report Header
106         * 
107         * @param BudgetConstructionObjectDump bcod
108         */
109        public void buildReportsHeader(Integer universityFiscalYear, String objectCodes, String reasonCodes, BudgetConstructionOrgReasonStatisticsReport orgReasonStatisticsReportEntry, BudgetConstructionSalaryTotal salaryTotalEntry, BudgetConstructionReportThresholdSettings budgetConstructionReportThresholdSettings) {
110    
111            // set fiscal year
112            Integer prevFiscalyear = universityFiscalYear - 1;
113            orgReasonStatisticsReportEntry.setFiscalYear(prevFiscalyear.toString() + "-" + universityFiscalYear.toString().substring(2, 4));
114    
115            // get Chart with orgChartCode
116            Map<String, Object> searchCriteria = new HashMap<String, Object>();
117            searchCriteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, salaryTotalEntry.getOrganizationChartOfAccountsCode());
118            Chart chart = (Chart) businessObjectService.findByPrimaryKey(Chart.class, searchCriteria);
119    
120            // set OrgCode and Desc
121            String orgName = salaryTotalEntry.getOrganization().getOrganizationName();
122            orgReasonStatisticsReportEntry.setOrganizationCode(salaryTotalEntry.getOrganizationCode());
123            if (orgName == null) {
124                orgReasonStatisticsReportEntry.setOrganizationName(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_ORGANIZATION_NAME));
125            }
126            else {
127                orgReasonStatisticsReportEntry.setOrganizationName(orgName);
128            }
129            // set ChartCode and Desc
130            if (chart == null) {
131                orgReasonStatisticsReportEntry.setChartOfAccountDescription(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_CHART_DESCRIPTION));
132                orgReasonStatisticsReportEntry.setChartOfAccountsCode(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_CHART_DESCRIPTION));
133            }
134            else {
135                orgReasonStatisticsReportEntry.setChartOfAccountsCode(chart.getChartOfAccountsCode());
136                orgReasonStatisticsReportEntry.setChartOfAccountDescription(chart.getFinChartOfAccountDescription());
137            }
138            Integer prevPrevFiscalyear = prevFiscalyear - 1;
139            orgReasonStatisticsReportEntry.setObjectCodes(objectCodes);
140    
141            if (budgetConstructionReportThresholdSettings.isUseThreshold()) {
142                if (budgetConstructionReportThresholdSettings.isUseGreaterThanOperator()) {
143                    orgReasonStatisticsReportEntry.setThresholdOrReason(BCConstants.Report.THRESHOLD + BCConstants.Report.THRESHOLD_GREATER + budgetConstructionReportThresholdSettings.getThresholdPercent().toString() + BCConstants.Report.PERCENT);
144                }
145                else {
146                    orgReasonStatisticsReportEntry.setThresholdOrReason(BCConstants.Report.THRESHOLD + BCConstants.Report.THRESHOLD_LESS + budgetConstructionReportThresholdSettings.getThresholdPercent().toString() + BCConstants.Report.PERCENT);
147                }
148            }
149            else {
150                orgReasonStatisticsReportEntry.setThresholdOrReason(BCConstants.Report.SELECTED_REASONS + reasonCodes);
151            }
152    
153        }
154    
155        public void buildReportsBody(BudgetConstructionOrgReasonStatisticsReport orgReasonStatisticsReportEntry, BudgetConstructionSalaryTotal salaryTotalEntry) {
156            orgReasonStatisticsReportEntry.setInitialRequestedFteQuantity(salaryTotalEntry.getInitialRequestedFteQuantity());
157            orgReasonStatisticsReportEntry.setTotalInitialRequestedAmount(BudgetConstructionReportHelper.convertKualiInteger(salaryTotalEntry.getInitialRequestedAmount()));
158    
159            BigDecimal averageAmount = BudgetConstructionReportHelper.calculateDivide(salaryTotalEntry.getInitialRequestedAmount().bigDecimalValue(), salaryTotalEntry.getInitialRequestedFteQuantity());
160            orgReasonStatisticsReportEntry.setTotalAverageAmount(BudgetConstructionReportHelper.setDecimalDigit(averageAmount, 0, false).intValue());
161    
162            BigDecimal requestedFteQuantity = salaryTotalEntry.getAppointmentRequestedFteQuantity().setScale(5, BigDecimal.ROUND_HALF_UP);
163            orgReasonStatisticsReportEntry.setAppointmentRequestedFteQuantity(requestedFteQuantity);
164            
165            orgReasonStatisticsReportEntry.setTotalCsfAmount(BudgetConstructionReportHelper.convertKualiInteger(salaryTotalEntry.getCsfAmount()));
166            orgReasonStatisticsReportEntry.setTotalAppointmentRequestedAmount(BudgetConstructionReportHelper.convertKualiInteger(salaryTotalEntry.getAppointmentRequestedAmount()));
167    
168            BigDecimal csfAmount = new BigDecimal(BudgetConstructionReportHelper.convertKualiInteger(salaryTotalEntry.getCsfAmount()));
169            BigDecimal averageCsfAmount = BudgetConstructionReportHelper.calculateDivide(csfAmount, salaryTotalEntry.getAppointmentRequestedFteQuantity());
170            orgReasonStatisticsReportEntry.setAverageCsfAmount(BudgetConstructionReportHelper.setDecimalDigit(averageCsfAmount, 0, false));
171    
172            BigDecimal appointmentRequestedAmount = new BigDecimal(BudgetConstructionReportHelper.convertKualiInteger(salaryTotalEntry.getAppointmentRequestedAmount()));
173            BigDecimal averageRequestedAmount = BudgetConstructionReportHelper.calculateDivide(appointmentRequestedAmount, requestedFteQuantity);
174            orgReasonStatisticsReportEntry.setAverageAppointmentRequestedAmount(BudgetConstructionReportHelper.setDecimalDigit(averageRequestedAmount, 0, false));
175    
176            orgReasonStatisticsReportEntry.setAverageChange(orgReasonStatisticsReportEntry.getAverageAppointmentRequestedAmount().subtract(orgReasonStatisticsReportEntry.getAverageCsfAmount()));
177    
178            orgReasonStatisticsReportEntry.setPercentChange(BudgetConstructionReportHelper.calculatePercent(orgReasonStatisticsReportEntry.getAverageChange(), orgReasonStatisticsReportEntry.getAverageCsfAmount()));
179        }
180    
181        /**
182         * builds orderByList for sort order.
183         * 
184         * @return returnList
185         */
186        public List<String> buildOrderByList() {
187            List<String> returnList = new ArrayList<String>();
188            returnList.add(KFSPropertyConstants.ORGANIZATION_CHART_OF_ACCOUNTS_CODE);
189            returnList.add(KFSPropertyConstants.ORGANIZATION_CODE);
190    
191            return returnList;
192        }
193    
194        /**
195         * Sets the budgetConstructionReasonStatisticsReportDao attribute value.
196         * 
197         * @param budgetConstructionReasonStatisticsReportDao The budgetConstructionReasonStatisticsReportDao to set.
198         */
199        public void setBudgetConstructionReasonStatisticsReportDao(BudgetConstructionReasonStatisticsReportDao budgetConstructionReasonStatisticsReportDao) {
200            this.budgetConstructionReasonStatisticsReportDao = budgetConstructionReasonStatisticsReportDao;
201        }
202    
203        /**
204         * Sets the budgetConstructionOrganizationReportsService attribute value.
205         * 
206         * @param budgetConstructionOrganizationReportsService The budgetConstructionOrganizationReportsService to set.
207         */
208        public void setBudgetConstructionOrganizationReportsService(BudgetConstructionOrganizationReportsService budgetConstructionOrganizationReportsService) {
209            this.budgetConstructionOrganizationReportsService = budgetConstructionOrganizationReportsService;
210        }
211    
212        /**
213         * Sets the kualiConfigurationService attribute value.
214         * 
215         * @param kualiConfigurationService The kualiConfigurationService to set.
216         */
217        public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) {
218            this.kualiConfigurationService = kualiConfigurationService;
219        }
220    
221        /**
222         * Sets the businessObjectService attribute value.
223         * 
224         * @param businessObjectService The businessObjectService to set.
225         */
226        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
227            this.businessObjectService = businessObjectService;
228        }
229    
230        /**
231         * Sets the budgetConstructionReportsServiceHelper attribute value.
232         * 
233         * @param budgetConstructionReportsServiceHelper The budgetConstructionReportsServiceHelper to set.
234         */
235        public void setBudgetConstructionReportsServiceHelper(BudgetConstructionReportsServiceHelper budgetConstructionReportsServiceHelper) {
236            this.budgetConstructionReportsServiceHelper = budgetConstructionReportsServiceHelper;
237        }
238    }