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.apache.commons.lang.StringUtils;
026 import org.apache.ojb.broker.PersistenceBrokerException;
027 import org.kuali.kfs.module.bc.BCConstants;
028 import org.kuali.kfs.module.bc.BCKeyConstants;
029 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAccountSalaryDetailReport;
030 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAccountSalaryDetailReportTotal;
031 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAdministrativePost;
032 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionCalculatedSalaryFoundationTracker;
033 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionIntendedIncumbent;
034 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition;
035 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding;
036 import org.kuali.kfs.module.bc.document.service.BudgetConstructionAccountSalaryDetailReportService;
037 import org.kuali.kfs.module.bc.document.service.BudgetConstructionReportsServiceHelper;
038 import org.kuali.kfs.module.bc.document.service.SalarySettingService;
039 import org.kuali.kfs.module.bc.report.BudgetConstructionReportHelper;
040 import org.kuali.kfs.sys.KFSPropertyConstants;
041 import org.kuali.rice.kns.service.KualiConfigurationService;
042 import org.kuali.rice.kns.util.KualiInteger;
043 import org.springframework.transaction.annotation.Transactional;
044
045 /**
046 * Service implementation of BudgetConstructionLevelSummaryReportService.
047 */
048 @Transactional
049 public class BudgetConstructionAccountSalaryDetailReportServiceImpl implements BudgetConstructionAccountSalaryDetailReportService {
050
051 private KualiConfigurationService kualiConfigurationService;
052 private BudgetConstructionReportsServiceHelper budgetConstructionReportsServiceHelper;
053 private SalarySettingService salarySettingService;
054
055 /**
056 * @see org.kuali.kfs.module.bc.document.service.BudgetConstructionLevelSummaryReportService#buildReports(java.lang.Integer,
057 * java.util.Collection)
058 */
059 public Collection<BudgetConstructionAccountSalaryDetailReport> buildReports(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String subAccountNumber) {
060 Collection<BudgetConstructionAccountSalaryDetailReport> reportSet = new ArrayList<BudgetConstructionAccountSalaryDetailReport>();
061
062 Map<String, Object> searchCriteria = buildSearchCriteria(universityFiscalYear, chartOfAccountsCode, accountNumber, subAccountNumber);
063 List<String> orderList = buildOrderByList();
064
065 Collection<PendingBudgetConstructionAppointmentFunding> pendingAppointmentFundingList = budgetConstructionReportsServiceHelper.getDataForBuildingReports(PendingBudgetConstructionAppointmentFunding.class, searchCriteria, orderList);
066 List<PendingBudgetConstructionAppointmentFunding> listForTotal = BudgetConstructionReportHelper.deleteDuplicated((List) pendingAppointmentFundingList, fieldsForTotal());
067
068 Collection<BudgetConstructionAccountSalaryDetailReportTotal> accountSalaryDetailTotal = calculateTotal(pendingAppointmentFundingList, listForTotal);
069 for (PendingBudgetConstructionAppointmentFunding pendingAppointmentFunding : pendingAppointmentFundingList) {
070 BudgetConstructionAccountSalaryDetailReport accountSalaryDetailReport = new BudgetConstructionAccountSalaryDetailReport();
071
072 buildReportsHeader(universityFiscalYear, pendingAppointmentFunding, accountSalaryDetailReport);
073 buildReportsBody(universityFiscalYear, pendingAppointmentFunding, accountSalaryDetailReport);
074 buildReportsTotal(pendingAppointmentFunding, accountSalaryDetailReport, accountSalaryDetailTotal);
075
076 reportSet.add(accountSalaryDetailReport);
077 }
078
079 return reportSet;
080 }
081
082 /**
083 * builds report Header
084 *
085 * @param BudgetConstructionObjectSummary bcas
086 */
087 protected void buildReportsHeader(Integer universityFiscalYear, PendingBudgetConstructionAppointmentFunding pendingAppointmentFunding, BudgetConstructionAccountSalaryDetailReport accountSalaryDetailReport) {
088
089 Integer prevFiscalyear = universityFiscalYear - 1;
090 accountSalaryDetailReport.setFiscalYear(prevFiscalyear.toString() + "-" + universityFiscalYear.toString().substring(2, 4));
091
092
093 accountSalaryDetailReport.setAccountNumber(pendingAppointmentFunding.getAccountNumber());
094 accountSalaryDetailReport.setSubAccountNumber(pendingAppointmentFunding.getSubAccountNumber());
095 accountSalaryDetailReport.setChartOfAccountsCode(pendingAppointmentFunding.getChartOfAccountsCode());
096 accountSalaryDetailReport.setOrganizationCode(pendingAppointmentFunding.getAccount().getOrganizationCode());
097
098 String chartOfAccountDescription = "";
099 if (pendingAppointmentFunding.getChartOfAccounts() != null) {
100 try {
101 chartOfAccountDescription = pendingAppointmentFunding.getChartOfAccounts().getFinChartOfAccountDescription();
102 }
103 catch (PersistenceBrokerException e) {
104 chartOfAccountDescription = kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_CHART_DESCRIPTION);
105 }
106 }
107 else {
108 chartOfAccountDescription = BCConstants.Report.CHART + BCConstants.Report.NOT_DEFINED;
109 }
110
111 accountSalaryDetailReport.setChartOfAccountDescription(chartOfAccountDescription);
112
113 String orgName = null;
114 try {
115 orgName = pendingAppointmentFunding.getAccount().getOrganization().getOrganizationName();
116 }
117 catch (PersistenceBrokerException e) {
118 }
119 String accountName = pendingAppointmentFunding.getAccount().getAccountName();
120 String fundGroupCode = pendingAppointmentFunding.getAccount().getSubFundGroup().getFundGroupCode();
121 String fundGroupName = pendingAppointmentFunding.getAccount().getSubFundGroup().getFundGroup().getName();
122
123 if (orgName == null) {
124 accountSalaryDetailReport.setOrganizationName(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_ORGANIZATION_NAME));
125 }
126 else {
127 accountSalaryDetailReport.setOrganizationName(orgName);
128 }
129
130 if (fundGroupCode == null) {
131 accountSalaryDetailReport.setFundGroupCode(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_FUNDGROUP_CODE));
132 }
133 else {
134 accountSalaryDetailReport.setFundGroupCode(fundGroupCode);
135 }
136
137 if (fundGroupName == null) {
138 accountSalaryDetailReport.setFundGroupName(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_FUNDGROUP_NAME));
139 }
140 else {
141 accountSalaryDetailReport.setFundGroupName(fundGroupName);
142 }
143
144 if (accountName == null) {
145 accountSalaryDetailReport.setAccountName(kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_ACCOUNT_DESCRIPTION));
146 }
147 else {
148 accountSalaryDetailReport.setAccountName(accountName);
149 }
150
151 String subAccountName = "";
152
153 if (!pendingAppointmentFunding.getSubAccountNumber().equals(BCConstants.Report.DASHES_SUB_ACCOUNT_CODE)) {
154 try {
155 subAccountName = pendingAppointmentFunding.getSubAccount().getSubAccountName();
156 }
157 catch (PersistenceBrokerException e) {
158 subAccountName = kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_SUB_ACCOUNT_DESCRIPTION);
159 }
160 }
161 accountSalaryDetailReport.setSubAccountName(subAccountName);
162
163
164 }
165
166 /**
167 * builds report body
168 *
169 * @param BudgetConstructionLevelSummary bcas
170 */
171 protected void buildReportsBody(Integer universityFiscalYear, PendingBudgetConstructionAppointmentFunding pendingAppointmentFunding, BudgetConstructionAccountSalaryDetailReport accountMonthlyDetailReport) {
172 Integer amountChange = new Integer(0);
173 BigDecimal percentChange = BigDecimal.ZERO;
174
175 BudgetConstructionIntendedIncumbent intendedIncumbent = budgetConstructionReportsServiceHelper.getBudgetConstructionIntendedIncumbent(pendingAppointmentFunding);
176 BudgetConstructionAdministrativePost administrativePost = budgetConstructionReportsServiceHelper.getBudgetConstructionAdministrativePost(pendingAppointmentFunding);
177 BudgetConstructionPosition position = budgetConstructionReportsServiceHelper.getBudgetConstructionPosition(universityFiscalYear, pendingAppointmentFunding);
178 BudgetConstructionCalculatedSalaryFoundationTracker csfTracker = pendingAppointmentFunding.getEffectiveCSFTracker();
179
180 // from PendingBudgetConstructionAppointmentFunding
181 accountMonthlyDetailReport.setFinancialSubObjectCode(pendingAppointmentFunding.getFinancialSubObjectCode());
182
183 // from BudgetConstructionIntendedIncumbent
184 if (intendedIncumbent != null) {
185 accountMonthlyDetailReport.setIuClassificationLevel(intendedIncumbent.getIuClassificationLevel());
186 }
187
188 // from BudgetConstructionAdministrativePost
189 if (administrativePost != null) {
190 accountMonthlyDetailReport.setAdministrativePost(administrativePost.getAdministrativePost());
191 }
192
193 // from BudgetConstructionPosition
194 if (position != null) {
195 accountMonthlyDetailReport.setPositionNumber(position.getPositionNumber());
196 accountMonthlyDetailReport.setPositionSalaryPlanDefault(position.getPositionSalaryPlanDefault());
197 accountMonthlyDetailReport.setPositionGradeDefault(position.getPositionGradeDefault());
198 accountMonthlyDetailReport.setNormalWorkMonthsAndiuPayMonths(position.getIuNormalWorkMonths() + "/" + position.getIuPayMonths());
199 }
200
201 // from BudgetConstructionCalculatedSalaryFoundationTracker
202 if (csfTracker != null) {
203 accountMonthlyDetailReport.setPositionCsfAmount(csfTracker.getCsfAmount().intValue());
204 accountMonthlyDetailReport.setCsfTimePercent(BudgetConstructionReportHelper.setDecimalDigit(csfTracker.getCsfTimePercent(), 2, false));
205 accountMonthlyDetailReport.setPositionCsfFullTimeEmploymentQuantity(BudgetConstructionReportHelper.setDecimalDigit(csfTracker.getCsfFullTimeEmploymentQuantity(), 5, false));
206 accountMonthlyDetailReport.setPositionCsfFundingStatusCode(csfTracker.getCsfFundingStatusCode());
207
208 BigDecimal csfFte = BudgetConstructionReportHelper.setDecimalDigit(csfTracker.getCsfFullTimeEmploymentQuantity(), 5, false);
209 BigDecimal reqFte = BudgetConstructionReportHelper.setDecimalDigit(pendingAppointmentFunding.getAppointmentRequestedFteQuantity(), 5, false);
210 if (reqFte.compareTo(csfFte) == 0) {
211 amountChange = pendingAppointmentFunding.getAppointmentRequestedAmount().subtract(csfTracker.getCsfAmount()).intValue();
212
213 if (!csfTracker.getCsfAmount().equals(KualiInteger.ZERO)) {
214 percentChange = BudgetConstructionReportHelper.calculatePercent(amountChange, csfTracker.getCsfAmount().intValue());
215 }
216 }
217 }
218
219 // from PendingBudgetConstructionAppointmentFunding
220 accountMonthlyDetailReport.setAppointmentFundingMonth(pendingAppointmentFunding.getAppointmentFundingMonth());
221 if (salarySettingService.isHourlyPaidObject(pendingAppointmentFunding.getUniversityFiscalYear(), pendingAppointmentFunding.getChartOfAccountsCode(), pendingAppointmentFunding.getFinancialObjectCode())){
222 accountMonthlyDetailReport.setAppointmentRequestedPayRate(pendingAppointmentFunding.getAppointmentRequestedPayRate());
223 }
224
225 accountMonthlyDetailReport.setAppointmentRequestedAmount(pendingAppointmentFunding.getAppointmentRequestedAmount().intValue());
226 accountMonthlyDetailReport.setAppointmentRequestedTimePercent(BudgetConstructionReportHelper.setDecimalDigit(pendingAppointmentFunding.getAppointmentRequestedTimePercent(), 2, false));
227 accountMonthlyDetailReport.setAppointmentRequestedFteQuantity(BudgetConstructionReportHelper.setDecimalDigit(pendingAppointmentFunding.getAppointmentRequestedFteQuantity(), 5, false));
228 accountMonthlyDetailReport.setAppointmentRequestedCsfAmount(pendingAppointmentFunding.getAppointmentRequestedCsfAmount().intValue());
229 accountMonthlyDetailReport.setAppointmentRequestedCsfTimePercent(BudgetConstructionReportHelper.setDecimalDigit(pendingAppointmentFunding.getAppointmentRequestedCsfTimePercent(), 2, false));
230 accountMonthlyDetailReport.setAppointmentRequestedCsfFteQuantity(BudgetConstructionReportHelper.setDecimalDigit(pendingAppointmentFunding.getAppointmentRequestedCsfFteQuantity(), 5, false));
231 accountMonthlyDetailReport.setAppointmentFundingDurationCode(pendingAppointmentFunding.getAppointmentFundingDurationCode());
232 accountMonthlyDetailReport.setAppointmentTotalIntendedAmount(pendingAppointmentFunding.getAppointmentTotalIntendedAmount().intValue());
233 accountMonthlyDetailReport.setAppointmentTotalIntendedFteQuantity(BudgetConstructionReportHelper.setDecimalDigit(pendingAppointmentFunding.getAppointmentTotalIntendedFteQuantity(), 5, false));
234
235 accountMonthlyDetailReport.setFinancialObjectCode(pendingAppointmentFunding.getFinancialObjectCode());
236 accountMonthlyDetailReport.setFinancialObjectCodeName(pendingAppointmentFunding.getFinancialObject().getFinancialObjectCodeName());
237
238 String deleteBox = pendingAppointmentFunding.isAppointmentFundingDeleteIndicator() ? BCConstants.Report.DELETE_MARK : BCConstants.Report.BLANK;
239 accountMonthlyDetailReport.setDeleteBox(deleteBox);
240
241 if (pendingAppointmentFunding.getEmplid().equals(BCConstants.Report.VACANT)){
242 accountMonthlyDetailReport.setName(BCConstants.Report.VACANT);
243 } else {
244 int nameLength = intendedIncumbent.getName().length();
245 accountMonthlyDetailReport.setName(intendedIncumbent.getName().substring(0, (nameLength > 35) ? 35 : nameLength));
246
247 }
248
249 accountMonthlyDetailReport.setAmountChange(amountChange);
250 accountMonthlyDetailReport.setPercentChange(percentChange);
251 }
252
253 protected void buildReportsTotal(PendingBudgetConstructionAppointmentFunding pendingAppointmentFunding, BudgetConstructionAccountSalaryDetailReport accountMonthlyDetailReport, Collection<BudgetConstructionAccountSalaryDetailReportTotal> accountSalaryDetailTotal) {
254
255 for (BudgetConstructionAccountSalaryDetailReportTotal totalEntry : accountSalaryDetailTotal) {
256 if (BudgetConstructionReportHelper.isSameEntry(totalEntry.getPendingBudgetConstructionAppointmentFunding(), pendingAppointmentFunding, fieldsForTotal())) {
257
258 String objectCodeName = StringUtils.EMPTY;
259 if (pendingAppointmentFunding.getFinancialObject() != null) {
260 try {
261 objectCodeName = pendingAppointmentFunding.getFinancialObject().getFinancialObjectCodeName();
262 }
263 catch (PersistenceBrokerException e) {
264 objectCodeName = kualiConfigurationService.getPropertyString(BCKeyConstants.ERROR_REPORT_GETTING_OBJECT_NAME);
265 }
266 }
267 else {
268 objectCodeName = BCConstants.Report.OBJECT + BCConstants.Report.NOT_DEFINED;
269 }
270 accountMonthlyDetailReport.setTotalDescription(objectCodeName);
271
272 accountMonthlyDetailReport.setTotalBaseAmount(totalEntry.getTotalBaseAmount());
273 accountMonthlyDetailReport.setTotalBaseFte(totalEntry.getTotalBaseFte());
274 accountMonthlyDetailReport.setTotalRequestAmount(totalEntry.getTotalRequestAmount());
275 accountMonthlyDetailReport.setTotalRequestFte(totalEntry.getTotalRequestFte());
276
277 accountMonthlyDetailReport.setTotalAmountChange(totalEntry.getTotalRequestAmount() - totalEntry.getTotalBaseAmount());
278 accountMonthlyDetailReport.setTotalPercentChange(BudgetConstructionReportHelper.calculatePercent(accountMonthlyDetailReport.getTotalAmountChange(), totalEntry.getTotalBaseAmount()));
279 }
280 }
281 }
282
283
284 protected Collection<BudgetConstructionAccountSalaryDetailReportTotal> calculateTotal(Collection<PendingBudgetConstructionAppointmentFunding> pendingAppointmentFundingList, List<PendingBudgetConstructionAppointmentFunding> listForTotal) {
285 Collection<BudgetConstructionAccountSalaryDetailReportTotal> reportTotals = new ArrayList<BudgetConstructionAccountSalaryDetailReportTotal>();
286
287 for (PendingBudgetConstructionAppointmentFunding totalEntry : listForTotal) {
288 KualiInteger totalBaseAmount = KualiInteger.ZERO;
289 BigDecimal totalBaseFte = BigDecimal.ZERO;
290 Integer totalRequestAmount = new Integer(0);
291 BigDecimal totalRequestFte = BigDecimal.ZERO;
292
293 BudgetConstructionAccountSalaryDetailReportTotal budgetConstructionAccountSalaryDetailReportTotal = new BudgetConstructionAccountSalaryDetailReportTotal();
294 for (PendingBudgetConstructionAppointmentFunding appointmentFundingEntry : pendingAppointmentFundingList) {
295 if (BudgetConstructionReportHelper.isSameEntry(totalEntry, appointmentFundingEntry, fieldsForTotal())) {
296 BudgetConstructionCalculatedSalaryFoundationTracker csfTracker = appointmentFundingEntry.getEffectiveCSFTracker();
297
298 if (csfTracker != null) {
299 totalBaseAmount = totalBaseAmount.add(csfTracker.getCsfAmount());
300 totalBaseFte = totalBaseFte.add(csfTracker.getCsfFullTimeEmploymentQuantity());
301 }
302
303 totalRequestAmount = totalRequestAmount + new Integer(appointmentFundingEntry.getAppointmentRequestedAmount().intValue());
304 totalRequestFte = totalRequestFte.add(appointmentFundingEntry.getAppointmentRequestedFteQuantity());
305 }
306 }
307
308 budgetConstructionAccountSalaryDetailReportTotal.setTotalBaseAmount(totalBaseAmount.intValue());
309 budgetConstructionAccountSalaryDetailReportTotal.setTotalBaseFte(totalBaseFte);
310 budgetConstructionAccountSalaryDetailReportTotal.setTotalRequestAmount(totalRequestAmount);
311 budgetConstructionAccountSalaryDetailReportTotal.setTotalRequestFte(totalRequestFte);
312 budgetConstructionAccountSalaryDetailReportTotal.setPendingBudgetConstructionAppointmentFunding(totalEntry);
313
314 reportTotals.add(budgetConstructionAccountSalaryDetailReportTotal);
315 }
316
317 return reportTotals;
318 }
319
320
321 protected List<String> fieldsForTotal() {
322 List<String> fieldList = new ArrayList<String>();
323 fieldList.add(KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
324
325 return fieldList;
326 }
327
328 /**
329 * builds orderByList for sort order.
330 *
331 * @return returnList
332 */
333 protected List<String> buildOrderByList() {
334 List<String> returnList = new ArrayList<String>();
335 returnList.add(KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
336 returnList.add(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE);
337 returnList.add(KFSPropertyConstants.POSITION_NUMBER);
338 returnList.add(KFSPropertyConstants.EMPLID);
339
340 return returnList;
341 }
342
343 protected Map<String, Object> buildSearchCriteria(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String subAccountNumber) {
344 Map<String, Object> searchCriteria = new HashMap<String, Object>();
345 searchCriteria.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, universityFiscalYear);
346 searchCriteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartOfAccountsCode);
347 searchCriteria.put(KFSPropertyConstants.ACCOUNT_NUMBER, accountNumber);
348 searchCriteria.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, subAccountNumber);
349
350 return searchCriteria;
351 }
352
353 /**
354 * Sets the kualiConfigurationService attribute value.
355 *
356 * @param kualiConfigurationService The kualiConfigurationService to set.
357 */
358 public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) {
359 this.kualiConfigurationService = kualiConfigurationService;
360 }
361
362 /**
363 * Sets the budgetConstructionReportsServiceHelper attribute value.
364 *
365 * @param budgetConstructionReportsServiceHelper The budgetConstructionReportsServiceHelper to set.
366 */
367 public void setBudgetConstructionReportsServiceHelper(BudgetConstructionReportsServiceHelper budgetConstructionReportsServiceHelper) {
368 this.budgetConstructionReportsServiceHelper = budgetConstructionReportsServiceHelper;
369 }
370
371 /**
372 * Sets the salarySettingService attribute value.
373 * @param salarySettingService The salarySettingService to set.
374 */
375 public void setSalarySettingService(SalarySettingService salarySettingService) {
376 this.salarySettingService = salarySettingService;
377 }
378 }