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 }