Java tutorial
/* * Copyright 2005-2010 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.kra.budget.calculator; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.kuali.kra.award.budget.AwardBudgetExt; import org.kuali.kra.award.budget.AwardBudgetLineItemCalculatedAmountExt; import org.kuali.kra.award.budget.AwardBudgetLineItemExt; import org.kuali.kra.budget.BudgetDecimal; import org.kuali.kra.budget.calculator.query.And; import org.kuali.kra.budget.calculator.query.Equals; import org.kuali.kra.budget.core.Budget; import org.kuali.kra.budget.core.BudgetCategoryType; import org.kuali.kra.budget.core.BudgetCommonService; import org.kuali.kra.budget.core.BudgetCommonServiceFactory; import org.kuali.kra.budget.core.BudgetParent; import org.kuali.kra.budget.core.CostElement; import org.kuali.kra.budget.distributionincome.BudgetDistributionAndIncomeService; import org.kuali.kra.budget.document.BudgetDocument; import org.kuali.kra.budget.nonpersonnel.BudgetLineItem; import org.kuali.kra.budget.nonpersonnel.BudgetLineItemCalculatedAmount; import org.kuali.kra.budget.nonpersonnel.BudgetRateAndBase; import org.kuali.kra.budget.parameters.BudgetPeriod; import org.kuali.kra.budget.personnel.BudgetPersonnelCalculatedAmount; import org.kuali.kra.budget.personnel.BudgetPersonnelDetails; import org.kuali.kra.budget.personnel.BudgetPersonnelRateAndBase; import org.kuali.kra.budget.rates.RateClass; import org.kuali.kra.budget.rates.RateType; import org.kuali.kra.budget.web.struts.form.BudgetForm; import org.kuali.kra.infrastructure.KraServiceLocator; import org.kuali.kra.proposaldevelopment.hierarchy.HierarchyStatusConstants; import org.kuali.rice.kns.service.BusinessObjectService; import org.kuali.rice.kns.service.ParameterService; import org.kuali.rice.kns.util.ErrorMap; import org.kuali.rice.kns.util.GlobalVariables; import org.kuali.rice.kns.web.struts.form.KualiForm; /** * This class implements all methods declared in BudgetCalculationService */ public class BudgetCalculationServiceImpl implements BudgetCalculationService { private static final String EQUIPMENT = "E"; private static final String TRAVEL = "T"; private static final String PARTICIPANT_SUPPORT = "S"; private static final String OTHER_DIRECT = "O"; private static final String CALCULATED_COST = "CalculatedCost"; private static final String INDIRECT_COST = "IndirectCost"; private static final String SALARY = "Salary"; private static final String FRINGE = "Fringe"; private BusinessObjectService businessObjectService; private BudgetDistributionAndIncomeService budgetDistributionAndIncomeService; /** * @see org.kuali.kra.budget.calculator.BudgetCalculationService#calculateBudget(java.lang.String, java.lang.Integer) */ public void calculateBudget(Budget budget) { List<BudgetPeriod> budgetPeriods = budget.getBudgetPeriods(); String ohRateClassCodePrevValue = null; BudgetForm form = getBudgetFormFromGlobalVariables(); for (BudgetPeriod budgetPeriod : budgetPeriods) { if (isCalculationRequired(budget, budgetPeriod)) { String workOhCode = null; if (budget.getOhRateClassCode() != null && form != null && budget.getBudgetPeriods().size() > budgetPeriod.getBudgetPeriod()) { workOhCode = form.getOhRateClassCodePrevValue(); } calculateBudgetPeriod(budget, budgetPeriod); if (budget.getOhRateClassCode() != null && form != null && budget.getBudgetPeriods().size() > budgetPeriod.getBudgetPeriod()) { // this should be set at the last period, otherwise, only the first period will be updated properly because lots of places check prevohrateclass ohRateClassCodePrevValue = form.getOhRateClassCodePrevValue(); form.setOhRateClassCodePrevValue(workOhCode); } } } if (form != null && form.getOhRateClassCodePrevValue() == null && ohRateClassCodePrevValue != null) { // if not all periods are calculated, then this code has potential to be null, and this will force // to create calamts again form.setOhRateClassCodePrevValue(ohRateClassCodePrevValue); } if (budgetPeriods != null && !budgetPeriods.isEmpty()) { syncCostsToBudget(budget); } } /** * Checks if a calculation is required where Budget periods must be synced in line items. * * @param budgetLineItemDeleted whether of not a budget line item has been deleted. * @param budgetPeriod the current budget period. * * @return true if calculation is required false if not */ protected boolean isCalculationRequired(Budget budget, final BudgetPeriod budgetPeriod) { assert budgetPeriod != null : "The budget period is null"; boolean budgetLineItemDeleted = budget.isBudgetLineItemDeleted(); if (getBudgetCommonService(budget).isRateOverridden(budgetPeriod)) { return false; } if (StringUtils.equals(budgetPeriod.getBudget().getBudgetParent().getHierarchyStatus(), HierarchyStatusConstants.Parent.code())) { return true; } final boolean isLineItemsEmpty = budgetPeriod.getBudgetLineItems().isEmpty(); if (isLineItemsEmpty && !budgetLineItemDeleted) { final Map<Object, Object> fieldValues = new HashMap<Object, Object>(); fieldValues.put("budgetId", budgetPeriod.getBudgetId()); fieldValues.put("budgetPeriod", budgetPeriod.getBudgetPeriod()); @SuppressWarnings("unchecked") final Collection<BudgetLineItem> deletedLineItems = this.businessObjectService .findMatching(BudgetLineItem.class, fieldValues); return !deletedLineItems.isEmpty(); } return true; } protected void copyLineItemToPersonnelDetails(BudgetLineItem budgetLineItem, BudgetPersonnelDetails budgetPersonnelDetails) { budgetPersonnelDetails.setBudgetId(budgetLineItem.getBudgetId()); budgetPersonnelDetails.setBudgetPeriod(budgetLineItem.getBudgetPeriod()); budgetPersonnelDetails.setLineItemNumber(budgetLineItem.getLineItemNumber()); budgetPersonnelDetails.setCostElement(budgetLineItem.getCostElement()); budgetPersonnelDetails.setCostElementBO(budgetLineItem.getCostElementBO()); budgetPersonnelDetails.setApplyInRateFlag(budgetLineItem.getApplyInRateFlag()); budgetPersonnelDetails.setOnOffCampusFlag(budgetLineItem.getOnOffCampusFlag()); } public void calculateBudgetLineItem(Budget budget, BudgetPersonnelDetails budgetLineItem) { new PersonnelLineItemCalculator(budget, budgetLineItem).calculate(); } /** * @see org.kuali.kra.budget.calculator.BudgetCalculationService#calculateBudgetLineItem(org.kuali.kra.budget.nonpersonnel.BudgetLineItem) */ public void calculateBudgetLineItem(Budget budget, BudgetLineItem budgetLineItem) { BudgetLineItem budgetLineItemToCalc = budgetLineItem; List<BudgetPersonnelDetails> budgetPersonnelDetList = budgetLineItemToCalc.getBudgetPersonnelDetailsList(); if (budgetLineItemToCalc.isBudgetPersonnelLineItemDeleted() || (budgetPersonnelDetList != null && !budgetPersonnelDetList.isEmpty())) { updatePersonnelBudgetRate(budgetLineItemToCalc); BudgetDecimal personnelLineItemTotal = BudgetDecimal.ZERO; BudgetDecimal personnelTotalCostSharing = BudgetDecimal.ZERO; Map<String, BudgetDecimal> totalCalculatedCost = new HashMap<String, BudgetDecimal>(); Map<String, BudgetDecimal> totalCalculatedCostSharing = new HashMap<String, BudgetDecimal>(); BudgetDecimal newTotalUrAmount = BudgetDecimal.ZERO; budgetLineItem.getBudgetRateAndBaseList().clear(); int rateNumber = 0; boolean resetTotalUnderRecovery = false; BudgetDecimal calcDirectCost = BudgetDecimal.ZERO; BudgetDecimal calcIndirectCost = BudgetDecimal.ZERO; BudgetDecimal calcTotalCostSharing = BudgetDecimal.ZERO; for (BudgetPersonnelDetails budgetPersonnelDetails : budgetPersonnelDetList) { copyLineItemToPersonnelDetails(budgetLineItemToCalc, budgetPersonnelDetails); new PersonnelLineItemCalculator(budget, budgetPersonnelDetails).calculate(); personnelLineItemTotal = personnelLineItemTotal.add(budgetPersonnelDetails.getLineItemCost()); personnelTotalCostSharing = personnelTotalCostSharing .add(budgetPersonnelDetails.getCostSharingAmount()); newTotalUrAmount = newTotalUrAmount.add(budgetPersonnelDetails.getUnderrecoveryAmount()); resetTotalUnderRecovery = true; List<BudgetPersonnelCalculatedAmount> calAmts = budgetPersonnelDetails.getBudgetCalculatedAmounts(); if (CollectionUtils.isNotEmpty(calAmts)) { String rateKey; for (BudgetPersonnelCalculatedAmount personnelCalAmt : calAmts) { rateKey = personnelCalAmt.getRateClassCode() + ":" + personnelCalAmt.getRateTypeCode(); if (!totalCalculatedCost.containsKey(rateKey)) { totalCalculatedCost.put(rateKey, personnelCalAmt.getCalculatedCost()); totalCalculatedCostSharing.put(rateKey, personnelCalAmt.getCalculatedCostSharing()); } else { BudgetDecimal value = totalCalculatedCost.get(rateKey); value = value.add(personnelCalAmt.getCalculatedCost()); totalCalculatedCost.put(rateKey, value); value = totalCalculatedCostSharing.get(rateKey); value = value.add(personnelCalAmt.getCalculatedCostSharing()); totalCalculatedCostSharing.put(rateKey, value); } if (personnelCalAmt.getRateClass() == null) { personnelCalAmt.refreshReferenceObject("rateClass"); } if (!personnelCalAmt.getRateClass().getRateClassType().equals("O")) { calcDirectCost = calcDirectCost.add(personnelCalAmt.getCalculatedCost()); } else { calcIndirectCost = calcIndirectCost.add(personnelCalAmt.getCalculatedCost()); } calcTotalCostSharing = calcTotalCostSharing.add(personnelCalAmt.getCalculatedCostSharing()); } } populateRateAndBase(budgetLineItem, budgetPersonnelDetails, rateNumber); } if (resetTotalUnderRecovery) { budgetLineItem.setUnderrecoveryAmount(newTotalUrAmount); } budgetLineItem.setLineItemCost(personnelLineItemTotal); budgetLineItem.setCostSharingAmount(personnelTotalCostSharing); budgetLineItem.setDirectCost(calcDirectCost.add(personnelLineItemTotal)); budgetLineItem.setTotalCostSharingAmount(calcTotalCostSharing.add(personnelTotalCostSharing)); budgetLineItem.setIndirectCost(calcIndirectCost); boolean lineItemCalcAmntsOutOfDate = false; if (budgetLineItem.getBudgetCalculatedAmounts().size() == totalCalculatedCost.size()) { for (BudgetLineItemCalculatedAmount lineItemCalAmt : budgetLineItem .getBudgetLineItemCalculatedAmounts()) { String rateKey = lineItemCalAmt.getRateClassCode() + ":" + lineItemCalAmt.getRateTypeCode(); if (!totalCalculatedCost.containsKey(rateKey)) { lineItemCalcAmntsOutOfDate = true; break; } } } else { lineItemCalcAmntsOutOfDate = true; } if (lineItemCalcAmntsOutOfDate) { rePopulateCalculatedAmount(budget, budgetLineItemToCalc); } List<BudgetLineItemCalculatedAmount> budgetLineItemCalculatedAmounts = budgetLineItem .getBudgetLineItemCalculatedAmounts(); if (CollectionUtils.isNotEmpty(budgetLineItemCalculatedAmounts)) { String rateKey; for (BudgetLineItemCalculatedAmount lineItemCalAmt : budgetLineItemCalculatedAmounts) { rateKey = lineItemCalAmt.getRateClassCode() + ":" + lineItemCalAmt.getRateTypeCode(); if (totalCalculatedCost.containsKey(rateKey)) { lineItemCalAmt.setCalculatedCost(totalCalculatedCost.get(rateKey)); lineItemCalAmt.setCalculatedCostSharing(totalCalculatedCostSharing.get(rateKey)); } } } } else { new LineItemCalculator(budget, budgetLineItem).calculate(); } } protected void populateRateAndBase(BudgetLineItem bli, BudgetPersonnelDetails budgetPersonnelDetails, int rateNumber) { List<BudgetRateAndBase> budgetRateAndBaseList = bli.getBudgetRateAndBaseList(); List<BudgetPersonnelRateAndBase> budgetPersonnelRateBaseList = budgetPersonnelDetails .getBudgetPersonnelRateAndBaseList(); for (BudgetPersonnelRateAndBase budgetPersonnelRateAndBase : budgetPersonnelRateBaseList) { BudgetRateAndBase budgetRateBase = new BudgetRateAndBase(); BudgetDecimal appliedRate = budgetPersonnelRateAndBase.getAppliedRate(); budgetRateBase.setAppliedRate(BudgetDecimal.returnZeroIfNull(appliedRate)); BudgetDecimal calculatedCost = budgetPersonnelRateAndBase.getCalculatedCost(); BudgetDecimal calculatedCostSharing = budgetPersonnelRateAndBase.getCalculatedCostSharing(); budgetRateBase.setBaseCostSharing(budgetPersonnelRateAndBase.getBaseCostSharing()); budgetRateBase.setBaseCost(budgetPersonnelRateAndBase.getSalaryRequested()); budgetRateBase.setBudgetPeriodId(budgetPersonnelRateAndBase.getBudgetPeriodId()); budgetRateBase.setBudgetPeriod(budgetPersonnelRateAndBase.getBudgetPeriod()); budgetRateBase.setCalculatedCost(calculatedCost); budgetRateBase.setCalculatedCostSharing(calculatedCostSharing); budgetRateBase.setEndDate(budgetPersonnelRateAndBase.getEndDate()); budgetRateBase.setLineItemNumber(budgetPersonnelRateAndBase.getLineItemNumber()); budgetRateBase.setOnOffCampusFlag(budgetPersonnelRateAndBase.getOnOffCampusFlag()); budgetRateBase.setBudgetId(budgetPersonnelRateAndBase.getBudgetId()); budgetRateBase.setRateClassCode(budgetPersonnelRateAndBase.getRateClassCode()); budgetRateBase.setRateNumber(++rateNumber); budgetRateBase.setRateTypeCode(budgetPersonnelRateAndBase.getRateTypeCode()); budgetRateBase.setStartDate(budgetPersonnelRateAndBase.getStartDate()); budgetRateAndBaseList.add(budgetRateBase); } } public void calculateAndSyncBudgetLineItem(Budget budget, BudgetLineItem budgetLineItem) { new LineItemCalculator(budget, budgetLineItem).calculate(); syncCostsToBudget(budget); } /** * @see org.kuali.kra.budget.calculator.BudgetCalculationService#calculateCalculatedAmount(org.kuali.kra.budget.nonpersonnel.BudgetLineItem) */ public void populateCalculatedAmount(Budget budget, BudgetLineItem budgetLineItem) { new LineItemCalculator(budget, budgetLineItem).populateCalculatedAmountLineItems(); } /** * @see org.kuali.kra.budget.calculator.BudgetCalculationService#calculateCalculatedAmount(org.kuali.kra.budget.nonpersonnel.BudgetLineItem) */ public void populateCalculatedAmount(Budget budget, BudgetPersonnelDetails budgetPersonnelDetails) { new PersonnelLineItemCalculator(budget, budgetPersonnelDetails).populateCalculatedAmountLineItems(); } /** * @see org.kuali.kra.budget.calculator.BudgetCalculationService#calculateSalary(org.kuali.kra.budget.personnel.BudgetPersonnelDetails) */ public void calculateSalary(Budget budget, BudgetPersonnelDetails budgetPersonnelLineItem) { new SalaryCalculator(budget, budgetPersonnelLineItem).calculate(); } public void calculateBudgetPeriod(Budget budget, BudgetPeriod budgetPeriod) { if (isCalculationRequired(budget, budgetPeriod)) { // if(deleteSummaryCalcAmtsFlag){ // getBudgetCommonService(budget).removeBudgetSummaryPeriodCalcAmounts(budgetPeriod); // } new BudgetPeriodCalculator().calculate(budget, budgetPeriod); } } public void calculateAndSyncBudgetPeriod(Budget budget, BudgetPeriod budgetPeriod) { calculateBudgetPeriod(budget, budgetPeriod); syncCostsToBudget(budget); } /** * Syncs the calculated costs in the budget document with the calculated costs in the budget * periods. If the certain costs are not positive then lists on items related to those costs * are also cleared and reset (i.e. UnrecoveredFandAs). * This method modifies the passed in Budget. * * @param budget the budget document */ protected void syncCostsToBudget(final Budget budget) { assert budget != null : "The budget was null"; this.initCostDependentItems(budget); this.ensureBudgetPeriodHasSyncedCosts(budget); this.setBudgetCostsFromPeriods(budget); } /** * Initializes items that are dependent on a cost value. (i.e. UnrecoveredFandAs) * This method modifies the passed in Budget. * * @param budget the budget document */ protected void initCostDependentItems(final Budget budget) { assert budget != null : "The budget was null"; if (!this.isPositiveTotalUnderreoveryAmount(budget)) { this.initUnrecoveredFandAs(budget); } if (!this.isPositiveTotalCostSharingAmount(budget)) { this.initCostSharing(budget); } } /** * Clears and initializes the UnrecoveredFandAs in a budget document. * This method modifies the passed in Budget. * * @param document the budget document. */ protected void initUnrecoveredFandAs(final Budget document) { assert document != null : "the document was null"; document.getBudgetUnrecoveredFandAs().clear(); this.getBudgetDistributionAndIncomeService().initializeUnrecoveredFandACollectionDefaults(document); } /** * Clears and initializes the CostSharing in a budget document. * This method modifies the passed in Budget. * * @param document the budget document. */ protected void initCostSharing(final Budget document) { assert document != null : "the document was null"; document.getBudgetCostShares().clear(); this.getBudgetDistributionAndIncomeService().initializeCostSharingCollectionDefaults(document); } /** * Ensures that a budget period has synced costs with other budget objects (i.e. line items) * * @param budgetLineItemDeleted whether or not a budget line item has been deleted * @param currentPeriod the current period. */ protected void ensureBudgetPeriodHasSyncedCosts(final Budget budget) { assert budget != null : "the document was null"; for (final BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { if (this.isCalculationRequired(budget, budgetPeriod)) { this.setBudgetPeriodCostsFromLineItems(budgetPeriod); } } } /** * * This method sets the budget document's costs from the budget periods' costs. * This method modifies the passed in budget document. * * @param budget the budget document to set the costs on. */ protected void setBudgetCostsFromPeriods(final Budget budget) { assert budget != null : "The document is null"; budget.setTotalDirectCost(budget.getSumDirectCostAmountFromPeriods()); budget.setTotalIndirectCost(budget.getSumIndirectCostAmountFromPeriods()); budget.setTotalCost(budget.getSumTotalCostAmountFromPeriods()); budget.setUnderrecoveryAmount(budget.getSumUnderreoveryAmountFromPeriods()); budget.setCostSharingAmount(budget.getSumCostSharingAmountFromPeriods()); } /** * * This method sets the budget period costs from the line item costs. * This method modifies the passed in budget period. * * @param budgetPeriod the budget periods to set the costs on. */ protected void setBudgetPeriodCostsFromLineItems(final BudgetPeriod budgetPeriod) { assert budgetPeriod != null : "The period is null"; budgetPeriod.setTotalDirectCost(budgetPeriod.getSumDirectCostAmountFromLineItems()); budgetPeriod.setTotalIndirectCost(budgetPeriod.getSumIndirectCostAmountFromLineItems()); budgetPeriod.setTotalCost(budgetPeriod.getSumTotalCostAmountFromLineItems()); budgetPeriod.setUnderrecoveryAmount(budgetPeriod.getSumUnderreoveryAmountFromLineItems()); budgetPeriod.setCostSharingAmount(budgetPeriod.getSumTotalCostSharingAmountFromLineItems()); } /** * Checks if a positive Total Underrecoverary Amount exists in a line item or in a budget period. * @param document The budget Document * @return true if positive. */ protected final boolean isPositiveTotalUnderreoveryAmount(final Budget document) { assert document != null : "The periods is null"; BudgetDecimal lineItemsAmount = BudgetDecimal.ZERO; for (final BudgetPeriod budgetPeriod : document.getBudgetPeriods()) { lineItemsAmount = lineItemsAmount.add(budgetPeriod.getSumUnderreoveryAmountFromLineItems()); } return lineItemsAmount.isPositive() || document.getSumUnderreoveryAmountFromPeriods().isPositive(); } /** * Checks if a positive Total CostSharing Amount exists in a line item or in a budget period. * @param document The budget Document * @return true if positive. */ protected final boolean isPositiveTotalCostSharingAmount(final Budget document) { assert document != null : "The document is null"; BudgetDecimal lineItemsAmount = BudgetDecimal.ZERO; for (final BudgetPeriod budgetPeriod : document.getBudgetPeriods()) { lineItemsAmount = lineItemsAmount.add(budgetPeriod.getSumTotalCostSharingAmountFromLineItems()); } return lineItemsAmount.isPositive() || document.getSumCostSharingAmountFromPeriods().isPositive(); } protected SortedMap<BudgetCategoryType, List<CostElement>> categorizeObjectCodesByCategory(Budget budget) { SortedMap<CostElement, List<BudgetDecimal>> objectCodeTotals = budget.getObjectCodeTotals(); SortedMap<BudgetCategoryType, List<CostElement>> objectCodeListByBudgetCategoryType = new TreeMap<BudgetCategoryType, List<CostElement>>(); for (CostElement objectCode : objectCodeTotals.keySet()) { objectCode.refreshReferenceObject("budgetCategory"); if (objectCode.getBudgetCategory() != null) { objectCode.getBudgetCategory().refreshReferenceObject("budgetCategoryType"); objectCode.setBudgetCategoryTypeCode(objectCode.getBudgetCategory().getBudgetCategoryTypeCode()); } if (!objectCodeListByBudgetCategoryType .containsKey(objectCode.getBudgetCategory().getBudgetCategoryType())) { List<CostElement> filteredObjectCodes = filterObjectCodesByBudgetCategoryType( objectCodeTotals.keySet(), objectCode.getBudgetCategoryTypeCode()); objectCodeListByBudgetCategoryType.put(objectCode.getBudgetCategory().getBudgetCategoryType(), filteredObjectCodes); } } return objectCodeListByBudgetCategoryType; } protected BudgetCategoryType getPersonnelCategoryType() { final Map<String, String> primaryKeys = new HashMap<String, String>(); primaryKeys.put("budgetCategoryTypeCode", "P"); return (BudgetCategoryType) this.getBusinessObjectService().findByPrimaryKey(BudgetCategoryType.class, primaryKeys); } public void calculateBudgetSummaryTotals(Budget budget) { calculateBudgetTotals(budget); //Categorize all Object Codes per their Category Type SortedMap<BudgetCategoryType, List<CostElement>> objectCodeListByBudgetCategoryType = categorizeObjectCodesByCategory( budget); SortedMap<CostElement, List<BudgetPersonnelDetails>> objectCodeUniquePersonnelList = new TreeMap<CostElement, List<BudgetPersonnelDetails>>(); SortedMap<String, List<BudgetDecimal>> objectCodePersonnelSalaryTotals = new TreeMap<String, List<BudgetDecimal>>(); SortedMap<String, List<BudgetDecimal>> objectCodePersonnelFringeTotals = new TreeMap<String, List<BudgetDecimal>>(); //Temp collections for maintaining Sub Section Totals SortedSet<String> objectCodePersonnelSalaryTotalsByPeriod = new TreeSet<String>(); SortedSet<String> objectCodePersonnelFringeTotalsByPeriod = new TreeSet<String>(); SortedMap<RateType, List<BudgetDecimal>> personnelCalculatedExpenseTotals = new TreeMap<RateType, List<BudgetDecimal>>(); SortedMap<RateType, List<BudgetDecimal>> nonPersonnelCalculatedExpenseTotals = new TreeMap<RateType, List<BudgetDecimal>>(); List<BudgetDecimal> periodSummarySalaryTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodSummarySalaryTotals.add(i, BudgetDecimal.ZERO); } List<BudgetDecimal> periodSummaryFringeTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodSummaryFringeTotals.add(i, BudgetDecimal.ZERO); } SortedMap<String, List<BudgetDecimal>> subTotalsBySubSection = new TreeMap<String, List<BudgetDecimal>>(); subTotalsBySubSection.put("personnelSalaryTotals", periodSummarySalaryTotals); subTotalsBySubSection.put("personnelFringeTotals", periodSummaryFringeTotals); //Loop thru the Personnel Object Codes - to calculate Salary, Fringe Totals etc.. per person BudgetCategoryType personnelCategory = getPersonnelCategoryType(); List<CostElement> personnelObjectCodes = objectCodeListByBudgetCategoryType.get(personnelCategory); if (CollectionUtils.isNotEmpty(personnelObjectCodes)) { for (CostElement personnelCostElement : personnelObjectCodes) { if (!objectCodeUniquePersonnelList.containsKey(personnelCostElement)) { objectCodeUniquePersonnelList.put(personnelCostElement, new ArrayList<BudgetPersonnelDetails>()); } for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { budgetPeriod.setBudget(budget); QueryList lineItemQueryList = new QueryList(); lineItemQueryList.addAll(budgetPeriod.getBudgetLineItems()); Equals objectCodeEquals = new Equals("costElement", personnelCostElement.getCostElement()); QueryList<BudgetLineItem> filteredLineItems = lineItemQueryList.filter(objectCodeEquals); QueryList personnelQueryList = new QueryList(); //Loop thru the matching Line Items to gather personnel info for (BudgetLineItem matchingLineItem : filteredLineItems) { personnelQueryList.addAll(matchingLineItem.getBudgetPersonnelDetailsList()); } int matchingLineItemIndex = 0; for (BudgetLineItem matchingLineItem : filteredLineItems) { for (BudgetPersonnelDetails budgetPersonnelDetails : matchingLineItem .getBudgetPersonnelDetailsList()) { budgetPersonnelDetails.refreshReferenceObject("budgetPerson"); Equals personIdEquals = new Equals("personId", budgetPersonnelDetails.getPersonId()); QueryList personOccurrencesForSameObjectCode = personnelQueryList .filter(personIdEquals); //Calculate the Salary Totals for each Person BudgetDecimal personSalaryTotalsForCurrentPeriod = personOccurrencesForSameObjectCode .sumObjects("salaryRequested"); if (!objectCodePersonnelSalaryTotals.containsKey(matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId())) { objectCodeUniquePersonnelList.get(matchingLineItem.getCostElementBO()) .add(budgetPersonnelDetails); // set up for all periods and put into map List<BudgetDecimal> periodTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodTotals.add(i, BudgetDecimal.ZERO); } objectCodePersonnelSalaryTotals.put(matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId(), periodTotals); } //Setting the total lines here - so that they'll be set just once for a unique person within an Object Code objectCodePersonnelSalaryTotals .get(matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId()) .set(budgetPeriod.getBudgetPeriod() - 1, personSalaryTotalsForCurrentPeriod); //subTotalsBySubSection.get("personnelSalaryTotals").set(budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (subTotalsBySubSection.get("personnelSalaryTotals").get(budgetPeriod.getBudgetPeriod() - 1))).add(personSalaryTotalsForCurrentPeriod)); if (objectCodePersonnelSalaryTotalsByPeriod .add(budgetPeriod.getBudgetPeriod().toString() + "," + matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId())) { subTotalsBySubSection.get("personnelSalaryTotals").set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (subTotalsBySubSection.get("personnelSalaryTotals") .get(budgetPeriod.getBudgetPeriod() - 1))) .add(personSalaryTotalsForCurrentPeriod)); } //Calculate the Fringe Totals for each Person if (!objectCodePersonnelFringeTotals.containsKey(matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId())) { // set up for all periods and put into map List<BudgetDecimal> periodFringeTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodFringeTotals.add(i, BudgetDecimal.ZERO); } objectCodePersonnelFringeTotals.put(matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId(), periodFringeTotals); } BudgetDecimal personFringeTotalsForCurrentPeriod = BudgetDecimal.ZERO; // if(!isSummaryCalcAmountChanged(budget,budgetPeriod)){ //Calculate the Fringe Totals for that Person (cumulative fringe for all occurrences of the person) for (Object person : personOccurrencesForSameObjectCode) { BudgetPersonnelDetails personOccurrence = (BudgetPersonnelDetails) person; for (BudgetPersonnelCalculatedAmount calcExpenseAmount : personOccurrence .getBudgetPersonnelCalculatedAmounts()) { calcExpenseAmount.refreshReferenceObject("rateClass"); //Check for Employee Benefits RateClassType if (calcExpenseAmount.getRateClass().getRateClassType().equalsIgnoreCase("E")) { personFringeTotalsForCurrentPeriod = personFringeTotalsForCurrentPeriod .add(calcExpenseAmount.getCalculatedCost()); } } } objectCodePersonnelFringeTotals .get(matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId()) .set(budgetPeriod.getBudgetPeriod() - 1, personFringeTotalsForCurrentPeriod); //subTotalsBySubSection.get("personnelFringeTotals").set(budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (subTotalsBySubSection.get("personnelFringeTotals").get(budgetPeriod.getBudgetPeriod() - 1))).add(personFringeTotalsForCurrentPeriod)); // } if (objectCodePersonnelFringeTotalsByPeriod .add(budgetPeriod.getBudgetPeriod().toString() + "," + matchingLineItem.getCostElement() + "," + budgetPersonnelDetails.getPersonId())) { subTotalsBySubSection.get("personnelFringeTotals").set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (subTotalsBySubSection.get("personnelFringeTotals") .get(budgetPeriod.getBudgetPeriod() - 1))) .add(personFringeTotalsForCurrentPeriod)); } } //Need to handle the Summary Items - if any if (CollectionUtils.isEmpty(matchingLineItem.getBudgetPersonnelDetailsList())) { //Include Summary Item Salary (Line Item Cost) if (!objectCodePersonnelSalaryTotals.containsKey(matchingLineItem.getCostElement())) { // set up for all periods and put into map List<BudgetDecimal> periodTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodTotals.add(i, BudgetDecimal.ZERO); } objectCodePersonnelSalaryTotals.put(matchingLineItem.getCostElement(), periodTotals); } objectCodePersonnelSalaryTotals.get(matchingLineItem.getCostElement()).set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) objectCodePersonnelSalaryTotals .get(matchingLineItem.getCostElement()) .get(budgetPeriod.getBudgetPeriod() - 1)) .add(matchingLineItem.getLineItemCost())); //Include Summary Item Fringe Amt BudgetDecimal summaryFringeTotalsForCurrentPeriod = BudgetDecimal.ZERO; if (!objectCodePersonnelFringeTotals.containsKey(matchingLineItem.getCostElement())) { // set up for all periods and put into map List<BudgetDecimal> periodFringeTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodFringeTotals.add(i, BudgetDecimal.ZERO); } objectCodePersonnelFringeTotals.put(matchingLineItem.getCostElement(), periodFringeTotals); } for (BudgetLineItemCalculatedAmount lineItemCalculatedAmount : matchingLineItem .getBudgetLineItemCalculatedAmounts()) { lineItemCalculatedAmount.refreshReferenceObject("rateClass"); //Check for Employee Benefits RateClassType if (lineItemCalculatedAmount.getRateClass().getRateClassType() .equalsIgnoreCase("E")) { summaryFringeTotalsForCurrentPeriod = summaryFringeTotalsForCurrentPeriod .add(lineItemCalculatedAmount.getCalculatedCost()); } } objectCodePersonnelFringeTotals.get(matchingLineItem.getCostElement()).set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) objectCodePersonnelFringeTotals .get(matchingLineItem.getCostElement()) .get(budgetPeriod.getBudgetPeriod() - 1)) .add(summaryFringeTotalsForCurrentPeriod)); //if(matchingLineItemIndex == filteredLineItems.size()-1) { subTotalsBySubSection.get("personnelSalaryTotals").set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (subTotalsBySubSection.get("personnelSalaryTotals") .get(budgetPeriod.getBudgetPeriod() - 1))) .add((BudgetDecimal) (objectCodePersonnelSalaryTotals .get(matchingLineItem.getCostElement()) .get(budgetPeriod.getBudgetPeriod() - 1)))); subTotalsBySubSection.get("personnelFringeTotals").set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (subTotalsBySubSection.get("personnelFringeTotals") .get(budgetPeriod.getBudgetPeriod() - 1))) .add((BudgetDecimal) (objectCodePersonnelFringeTotals .get(matchingLineItem.getCostElement()) .get(budgetPeriod.getBudgetPeriod() - 1)))); //} } matchingLineItemIndex++; } } //Budget Period Looping Ends here } //Personnel Object Code Looping Ends here } budget.setBudgetSummaryTotals(subTotalsBySubSection); personnelCalculatedExpenseTotals = calculateExpenseTotals(budget, true); nonPersonnelCalculatedExpenseTotals = calculateExpenseTotals(budget, false); budget.setObjectCodeListByBudgetCategoryType(objectCodeListByBudgetCategoryType); //budget.setObjectCodePersonnelList(objectCodePersonnelList); budget.setObjectCodePersonnelList(objectCodeUniquePersonnelList); budget.setObjectCodePersonnelSalaryTotals(objectCodePersonnelSalaryTotals); budget.setObjectCodePersonnelFringeTotals(objectCodePersonnelFringeTotals); budget.setPersonnelCalculatedExpenseTotals(personnelCalculatedExpenseTotals); budget.setNonPersonnelCalculatedExpenseTotals(nonPersonnelCalculatedExpenseTotals); calculateNonPersonnelSummaryTotals(budget); populateBudgetPeriodSummaryCalcAmounts(budget); } @SuppressWarnings("unchecked") protected BudgetCommonService<BudgetParent> getBudgetCommonService(Budget budget) { return BudgetCommonServiceFactory.createInstance(budget.getBudgetDocument().getParentDocument()); } private boolean isRateOveridden(Budget budget, BudgetPeriod budgetPeriod) { BudgetCommonService<BudgetParent> budgetService = getBudgetCommonService(budget); return budgetService.isRateOverridden(budgetPeriod); } private void populateBudgetPeriodSummaryCalcAmounts(Budget budget) { List<BudgetPeriod> budgetPeriods = budget.getBudgetPeriods(); for (BudgetPeriod budgetPeriod : budgetPeriods) { if (!isRateOveridden(budget, budgetPeriod)) { getBudgetCommonService(budget).populateSummaryCalcAmounts(budget, budgetPeriod); } } } protected void calculateNonPersonnelSummaryTotals(Budget budget) { for (BudgetCategoryType budgetCategoryType : budget.getObjectCodeListByBudgetCategoryType().keySet()) { if (!StringUtils.equals(budgetCategoryType.getBudgetCategoryTypeCode(), "P")) { List<BudgetDecimal> nonPersonnelTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { nonPersonnelTotals.add(i, BudgetDecimal.ZERO); } budget.getBudgetSummaryTotals().put(budgetCategoryType.getBudgetCategoryTypeCode(), nonPersonnelTotals); List<CostElement> objectCodes = budget.getObjectCodeListByBudgetCategoryType() .get(budgetCategoryType); for (CostElement objectCode : objectCodes) { if (!StringUtils.equalsIgnoreCase(objectCode.getCostElement(), KraServiceLocator.getService(ParameterService.class).getParameterValue( BudgetDocument.class, "proposalHierarchySubProjectIndirectCostElement"))) { List<BudgetDecimal> objectCodePeriodTotals = budget.getObjectCodeTotals().get(objectCode); for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { budget.getBudgetSummaryTotals().get(budgetCategoryType.getBudgetCategoryTypeCode()).set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (budget.getBudgetSummaryTotals() .get(budgetCategoryType.getBudgetCategoryTypeCode()) .get(budgetPeriod.getBudgetPeriod() - 1))) .add(objectCodePeriodTotals .get(budgetPeriod.getBudgetPeriod() - 1))); } } } } } } protected List<CostElement> filterObjectCodesByBudgetCategoryType(Set<CostElement> objectCodes, String budgetCategoryType) { List<CostElement> filteredObjectCodes = new ArrayList<CostElement>(); for (CostElement costElement : objectCodes) { if (costElement.getBudgetCategory().getBudgetCategoryTypeCode().equalsIgnoreCase(budgetCategoryType)) { filteredObjectCodes.add(costElement); } } return filteredObjectCodes; } protected SortedMap<RateType, List<BudgetDecimal>> calculateExpenseTotals(Budget budget, boolean personnelFlag) { SortedMap<RateType, List<BudgetDecimal>> calculatedExpenseTotals = new TreeMap<RateType, List<BudgetDecimal>>(); List<BudgetDecimal> calculatedDirectCostSummaryTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { calculatedDirectCostSummaryTotals.add(i, BudgetDecimal.ZERO); } String totalsMapKey = null; if (personnelFlag) { totalsMapKey = "personnelCalculatedExpenseSummaryTotals"; } else { totalsMapKey = "nonPersonnelCalculatedExpenseSummaryTotals"; } budget.getBudgetSummaryTotals().put(totalsMapKey, calculatedDirectCostSummaryTotals); for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { for (BudgetLineItem budgetLineItem : budgetPeriod.getBudgetLineItems()) { if ((personnelFlag && StringUtils.equals( budgetLineItem.getCostElementBO().getBudgetCategory().getBudgetCategoryTypeCode(), "P")) || (!personnelFlag && !StringUtils.equals( budgetLineItem.getCostElementBO().getBudgetCategory().getBudgetCategoryTypeCode(), "P"))) { // get calculated expenses QueryList lineItemCalcAmtQueryList = new QueryList(); lineItemCalcAmtQueryList.addAll(budgetLineItem.getBudgetLineItemCalculatedAmounts()); List<RateType> rateTypes = new ArrayList<RateType>(); for (Object item : budgetLineItem.getBudgetLineItemCalculatedAmounts()) { BudgetLineItemCalculatedAmount budgetLineItemCalculatedAmount = (BudgetLineItemCalculatedAmount) item; // if (budgetLineItemCalculatedAmount.getRateType() == null) { // budgetLineItemCalculatedAmount.refreshReferenceObject("rateType"); // } // if (budgetLineItemCalculatedAmount.getRateType() != null && budgetLineItemCalculatedAmount.getRateType().getRateClass() == null) { // budgetLineItemCalculatedAmount.getRateType().refreshReferenceObject("rateClass"); // } RateType rateType = createRateType(budgetLineItemCalculatedAmount); RateClass rateClass = null; if (rateType != null) { rateType.refreshReferenceObject("rateClass"); rateClass = rateType.getRateClass(); } if (((personnelFlag && rateClass != null && !StringUtils.equals(rateClass.getRateClassType(), "E")) || !personnelFlag) && !rateTypes.contains(rateType)) { rateTypes.add(rateType); Equals equalsRC = new Equals("rateClassCode", budgetLineItemCalculatedAmount.getRateClassCode()); Equals equalsRT = new Equals("rateTypeCode", budgetLineItemCalculatedAmount.getRateTypeCode()); And RCandRT = new And(equalsRC, equalsRT); BudgetDecimal rateTypeTotalInThisPeriod = lineItemCalcAmtQueryList .sumObjects("calculatedCost", RCandRT); if (!calculatedExpenseTotals.containsKey(rateType)) { List<BudgetDecimal> rateTypePeriodTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { rateTypePeriodTotals.add(i, BudgetDecimal.ZERO); } calculatedExpenseTotals.put(rateType, rateTypePeriodTotals); } calculatedExpenseTotals.get(rateType).set(budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) calculatedExpenseTotals.get(rateType) .get(budgetPeriod.getBudgetPeriod() - 1)) .add(rateTypeTotalInThisPeriod)); if (!StringUtils.equals(rateClass.getRateClassType(), "O")) { budget.getBudgetSummaryTotals().get(totalsMapKey).set( budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) (budget.getBudgetSummaryTotals().get(totalsMapKey) .get(budgetPeriod.getBudgetPeriod() - 1))) .add(rateTypeTotalInThisPeriod)); } budgetPeriod .setExpenseTotal(budgetPeriod.getExpenseTotal().add(rateTypeTotalInThisPeriod)); } } } } } return calculatedExpenseTotals; } protected RateType createRateType(BudgetLineItemCalculatedAmount budgetLineItemCalculatedAmount) { RateType rateType = new RateType(); rateType.setRateClassCode(budgetLineItemCalculatedAmount.getRateClassCode()); rateType.setRateTypeCode(budgetLineItemCalculatedAmount.getRateTypeCode()); rateType.setDescription(budgetLineItemCalculatedAmount.getRateTypeDescription()); rateType.setRateClass(budgetLineItemCalculatedAmount.getRateClass()); return rateType; } /** * * @see org.kuali.kra.budget.calculator.BudgetCalculationService#calculateBudgetTotals(org.kuali.kra.budget.core.Budget) */ @SuppressWarnings("unchecked") public void calculateBudgetTotals(Budget budget) { // do we need to cache the totals ? SortedMap<CostElement, List<BudgetDecimal>> objectCodeTotals = new TreeMap<CostElement, List<BudgetDecimal>>(); SortedMap<RateType, List<BudgetDecimal>> calculatedExpenseTotals = new TreeMap<RateType, List<BudgetDecimal>>(); for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { List<CostElement> objectCodes = new ArrayList<CostElement>(); QueryList lineItemQueryList = new QueryList(); lineItemQueryList.addAll(budgetPeriod.getBudgetLineItems()); budgetPeriod.setExpenseTotal(BudgetDecimal.ZERO); // probably need to add '0' to the period that has no such object code or ratetype ? for (BudgetLineItem budgetLineItem : budgetPeriod.getBudgetLineItems()) { if (budgetLineItem.getCostElementBO() == null) { budgetLineItem.refreshReferenceObject("costElementBO"); } CostElement costElement = budgetLineItem.getCostElementBO(); if (!objectCodes.contains(costElement)) { objectCodes.add(costElement); Equals equalsCostElement = new Equals("costElement", budgetLineItem.getCostElement()); BudgetDecimal objectCodeTotalInThisPeriod = lineItemQueryList.sumObjects("lineItemCost", equalsCostElement); if (!objectCodeTotals.containsKey(costElement)) { // set up for all periods and put into map List<BudgetDecimal> periodTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { periodTotals.add(i, BudgetDecimal.ZERO); } objectCodeTotals.put(costElement, periodTotals); } objectCodeTotals.get(costElement).set(budgetPeriod.getBudgetPeriod() - 1, objectCodeTotalInThisPeriod); budgetPeriod.setExpenseTotal(budgetPeriod.getExpenseTotal().add(objectCodeTotalInThisPeriod)); } // get calculated expenses QueryList lineItemCalcAmtQueryList = new QueryList(); lineItemCalcAmtQueryList.addAll(budgetLineItem.getBudgetLineItemCalculatedAmounts()); List<RateType> rateTypes = new ArrayList<RateType>(); for (Object item : budgetLineItem.getBudgetLineItemCalculatedAmounts()) { BudgetLineItemCalculatedAmount budgetLineItemCalculatedAmount = (BudgetLineItemCalculatedAmount) item; // if (budgetLineItemCalculatedAmount.getRateType() == null) { // budgetLineItemCalculatedAmount.refreshReferenceObject("rateType"); // } RateType rateType = createRateType(budgetLineItemCalculatedAmount); if (!rateTypes.contains(rateType)) { rateTypes.add(rateType); Equals equalsRC = new Equals("rateClassCode", budgetLineItemCalculatedAmount.getRateClassCode()); Equals equalsRT = new Equals("rateTypeCode", budgetLineItemCalculatedAmount.getRateTypeCode()); And RCandRT = new And(equalsRC, equalsRT); BudgetDecimal rateTypeTotalInThisPeriod = lineItemCalcAmtQueryList .sumObjects("calculatedCost", RCandRT); if (!calculatedExpenseTotals.containsKey(rateType)) { List<BudgetDecimal> rateTypePeriodTotals = new ArrayList<BudgetDecimal>(); for (int i = 0; i < budget.getBudgetPeriods().size(); i++) { rateTypePeriodTotals.add(i, BudgetDecimal.ZERO); } calculatedExpenseTotals.put(rateType, rateTypePeriodTotals); } calculatedExpenseTotals.get(rateType) .set(budgetPeriod.getBudgetPeriod() - 1, ((BudgetDecimal) calculatedExpenseTotals.get(rateType) .get(budgetPeriod.getBudgetPeriod() - 1)) .add(rateTypeTotalInThisPeriod)); budgetPeriod.setExpenseTotal(budgetPeriod.getExpenseTotal().add(rateTypeTotalInThisPeriod)); } } } } budget.setObjectCodeTotals(objectCodeTotals); budget.setCalculatedExpenseTotals(calculatedExpenseTotals); } public void syncToPeriodCostLimit(Budget budget, BudgetPeriod budgetPeriod, BudgetLineItem budgetLineItem) { BudgetPeriodCalculator periodCalculator = new BudgetPeriodCalculator(); periodCalculator.syncToPeriodCostLimit(budget, budgetPeriod, budgetLineItem); List<String> errors = periodCalculator.getErrorMessages(); ErrorMap errorMap = GlobalVariables.getErrorMap(); if (!errors.isEmpty()) { for (String error : errors) { errorMap.putError("document.budgetPeriod[" + (budgetPeriod.getBudgetPeriod() - 1) + "].budgetLineItem[" + (budgetLineItem.getLineItemNumber() - 1) + "].lineItemCost", error); } } } public void syncToPeriodDirectCostLimit(Budget budget, BudgetPeriod budgetPeriod, BudgetLineItem budgetLineItem) { BudgetPeriodCalculator periodCalculator = new BudgetPeriodCalculator(); periodCalculator.syncToPeriodDirectCostLimit(budget, budgetPeriod, budgetLineItem); List<String> errors = periodCalculator.getErrorMessages(); ErrorMap errorMap = GlobalVariables.getErrorMap(); if (!errors.isEmpty()) { for (String error : errors) { errorMap.putError("document.budgetPeriod[" + (budgetPeriod.getBudgetPeriod() - 1) + "].budgetLineItem[" + (budgetLineItem.getLineItemNumber() - 1) + "].lineItemCost", error); } } } public void applyToLaterPeriods(Budget budget, BudgetPeriod budgetPeriod, BudgetLineItem budgetLineItem) { BudgetPeriodCalculator periodCalculator = new BudgetPeriodCalculator(); periodCalculator.applyToLaterPeriods(budget, budgetPeriod, budgetLineItem); List<String> errors = periodCalculator.getErrorMessages(); if (!errors.isEmpty()) { ErrorMap errorMap = GlobalVariables.getErrorMap(); for (String error : errors) { errorMap.putError("document.budgetPeriod[" + (budgetPeriod.getBudgetPeriod() - 1) + "].budgetLineItem[" + (budgetLineItem.getLineItemNumber() - 1) + "].costElement", error); } } } public BusinessObjectService getBusinessObjectService() { return businessObjectService; } public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } /** * Gets the budgetDistributionAndIncomeService attribute. * @return Returns the budgetDistributionAndIncomeService. */ public BudgetDistributionAndIncomeService getBudgetDistributionAndIncomeService() { return this.budgetDistributionAndIncomeService; } /** * Sets the budgetDistributionAndIncomeService attribute value. * @param budgetDistributionAndIncomeService The budgetDistributionAndIncomeService to set. */ public void setBudgetDistributionAndIncomeService(BudgetDistributionAndIncomeService service) { this.budgetDistributionAndIncomeService = service; } public void rePopulateCalculatedAmount(Budget budget, BudgetLineItem budgetLineItem) { budgetLineItem.getBudgetCalculatedAmounts().clear(); new LineItemCalculator(budget, budgetLineItem).setCalculatedAmounts(budget, budgetLineItem); } public void rePopulateCalculatedAmount(Budget budget, BudgetPersonnelDetails newBudgetPersonnelDetails) { newBudgetPersonnelDetails.getBudgetCalculatedAmounts().clear(); new PersonnelLineItemCalculator(budget, newBudgetPersonnelDetails).setCalculatedAmounts(budget, newBudgetPersonnelDetails); } public void updatePersonnelBudgetRate(BudgetLineItem budgetLineItem) { int j = 0; for (BudgetPersonnelDetails budgetPersonnelDetails : budgetLineItem.getBudgetPersonnelDetailsList()) { if (budgetPersonnelDetails.getCostElement() == null) { budgetPersonnelDetails.setCostElement(budgetLineItem.getCostElement()); budgetPersonnelDetails.setCostElementBO(budgetLineItem.getCostElementBO()); } j = 0; for (BudgetPersonnelCalculatedAmount budgetPersonnelCalculatedAmount : budgetPersonnelDetails .getBudgetPersonnelCalculatedAmounts()) { Boolean updatedApplyRateFlag = null; for (BudgetLineItemCalculatedAmount budgetLineItemCalculatedAmout : budgetLineItem .getBudgetLineItemCalculatedAmounts()) { if (budgetLineItemCalculatedAmout.getRateClassCode() .equalsIgnoreCase(budgetPersonnelCalculatedAmount.getRateClassCode()) && budgetLineItemCalculatedAmout.getRateTypeCode() .equalsIgnoreCase(budgetPersonnelCalculatedAmount.getRateTypeCode())) { updatedApplyRateFlag = budgetLineItemCalculatedAmout.getApplyRateFlag(); } } budgetPersonnelCalculatedAmount.setApplyRateFlag(updatedApplyRateFlag); j++; } } } public BudgetForm getBudgetFormFromGlobalVariables() { BudgetForm budgetForm = null; KualiForm form = GlobalVariables.getKualiForm(); if (form != null && form instanceof BudgetForm) { budgetForm = (BudgetForm) form; } return budgetForm; } // Attempt for budget limit panel public List<Map<String, List<BudgetDecimal>>> getBudgetLimitsTotals(String budgetId) { final Map<Object, Object> fieldValues = new HashMap<Object, Object>(); List<Map<String, List<BudgetDecimal>>> retList = new ArrayList<Map<String, List<BudgetDecimal>>>(); fieldValues.put("budgetId", budgetId); Budget budget = (Budget) this.businessObjectService.findByPrimaryKey(AwardBudgetExt.class, fieldValues); calculateBudgetTotals(budget); Map<String, List<BudgetDecimal>> personnelBudgetLimits = getPersonnelMap(); Map<String, List<BudgetDecimal>> nonPersonnelBudgetLimits = getNonPersonnelMap(); for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { // budgetPeriod.refreshReferenceObject("budgetLineItems"); for (BudgetLineItem budgetLineItem : budgetPeriod.getBudgetLineItems()) { AwardBudgetLineItemExt awardBudgetLineItem = (AwardBudgetLineItemExt) budgetLineItem; if (!"P".equals( awardBudgetLineItem.getCostElementBO().getBudgetCategory().getBudgetCategoryTypeCode())) { addBudgetLimits(nonPersonnelBudgetLimits.get( awardBudgetLineItem.getCostElementBO().getBudgetCategory().getBudgetCategoryTypeCode()), awardBudgetLineItem, false); getNonPersonnelCalAmt(nonPersonnelBudgetLimits, awardBudgetLineItem, false); } else { addBudgetLimits(personnelBudgetLimits.get(SALARY), awardBudgetLineItem, false); getFringeAndCalculatedCost(personnelBudgetLimits, awardBudgetLineItem, false); } } } if (((AwardBudgetExt) budget).getPrevBudget().getBudgetId() != null) { getPreviousBudgetLimits(((AwardBudgetExt) budget).getPrevBudget().getBudgetId(), personnelBudgetLimits, nonPersonnelBudgetLimits); } Map<String, List<BudgetDecimal>> totallBudgetLimits = getTotalMap(); addTotals(personnelBudgetLimits, totallBudgetLimits); addTotals(nonPersonnelBudgetLimits, totallBudgetLimits); retList.add(personnelBudgetLimits); retList.add(nonPersonnelBudgetLimits); retList.add(totallBudgetLimits); return retList; } protected void getPreviousBudgetLimits(Long budgetId, Map<String, List<BudgetDecimal>> personnelBudgetLimits, Map<String, List<BudgetDecimal>> nonPersonnelBudgetLimits) { Map keyMap = new HashMap(); keyMap.put("budgetId", budgetId); AwardBudgetExt budget = (AwardBudgetExt) getBusinessObjectService().findByPrimaryKey(AwardBudgetExt.class, keyMap); if (budget != null) { for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { // budgetPeriod.refreshReferenceObject("budgetLineItems"); for (BudgetLineItem budgetLineItem : budgetPeriod.getBudgetLineItems()) { AwardBudgetLineItemExt awardBudgetLineItem = (AwardBudgetLineItemExt) budgetLineItem; if (!"P".equals(awardBudgetLineItem.getCostElementBO().getBudgetCategory() .getBudgetCategoryTypeCode())) { addBudgetLimits( nonPersonnelBudgetLimits.get(awardBudgetLineItem.getCostElementBO() .getBudgetCategory().getBudgetCategoryTypeCode()), awardBudgetLineItem, true); getNonPersonnelCalAmt(nonPersonnelBudgetLimits, awardBudgetLineItem, true); } else { addBudgetLimits(personnelBudgetLimits.get(SALARY), awardBudgetLineItem, true); getFringeAndCalculatedCost(personnelBudgetLimits, awardBudgetLineItem, true); } } } } } protected List<BudgetDecimal> initBudgetLimits() { List<BudgetDecimal> budgetLimits = new ArrayList<BudgetDecimal>(); budgetLimits.add(BudgetDecimal.ZERO); budgetLimits.add(BudgetDecimal.ZERO); budgetLimits.add(BudgetDecimal.ZERO); return budgetLimits; } protected void addTotals(Map<String, List<BudgetDecimal>> budgetLimitMap, Map<String, List<BudgetDecimal>> totalsMap) { List<BudgetDecimal> budgetLimits = initBudgetLimits(); for (Map.Entry entry : budgetLimitMap.entrySet()) { List<BudgetDecimal> limit = (List<BudgetDecimal>) entry.getValue(); if (!INDIRECT_COST.equalsIgnoreCase((String) entry.getKey())) { addToLimit(budgetLimits, limit); } else { addToLimit(totalsMap.get("FAndA"), limit); addToLimit(totalsMap.get("Totals"), limit); } } budgetLimitMap.put("Totals", budgetLimits); addToLimit(totalsMap.get("Direct"), budgetLimits); addToLimit(totalsMap.get("Totals"), budgetLimits); // addToLimit(totalsMap.get("Totals"), totalsMap.get("FAndA")); } protected void addToLimit(List<BudgetDecimal> budgetLimits, List<BudgetDecimal> limits) { budgetLimits.set(0, budgetLimits.get(0).add(limits.get(0))); budgetLimits.set(1, budgetLimits.get(1).add(limits.get(1))); budgetLimits.set(2, budgetLimits.get(2).add(limits.get(2))); } protected void addBudgetLimits(List<BudgetDecimal> budgetLimits, AwardBudgetLineItemExt awardBudgetLineItem, boolean isPrevBudget) { if (isPrevBudget) { budgetLimits.set(1, budgetLimits.get(1).add(awardBudgetLineItem.getLineItemCost())); } else { budgetLimits.set(0, budgetLimits.get(0).add(awardBudgetLineItem.getLineItemCost())); } budgetLimits.set(2, budgetLimits.get(2).add(awardBudgetLineItem.getLineItemCost())); } protected void addBudgetLimits(List<BudgetDecimal> budgetLimits, AwardBudgetLineItemCalculatedAmountExt awardCalcAmt, boolean isPrevBudget) { if (isPrevBudget) { budgetLimits.set(1, budgetLimits.get(1).add(awardCalcAmt.getCalculatedCost())); } else { budgetLimits.set(0, budgetLimits.get(0).add(awardCalcAmt.getCalculatedCost())); } budgetLimits.set(2, budgetLimits.get(2).add(awardCalcAmt.getCalculatedCost())); } protected Map<String, List<BudgetDecimal>> getNonPersonnelMap() { Map<String, List<BudgetDecimal>> nonPersonnelBudgetLimits = new HashMap<String, List<BudgetDecimal>>(); nonPersonnelBudgetLimits.put(EQUIPMENT, initBudgetLimits()); nonPersonnelBudgetLimits.put(TRAVEL, initBudgetLimits()); nonPersonnelBudgetLimits.put(PARTICIPANT_SUPPORT, initBudgetLimits()); nonPersonnelBudgetLimits.put(OTHER_DIRECT, initBudgetLimits()); nonPersonnelBudgetLimits.put(CALCULATED_COST, initBudgetLimits()); nonPersonnelBudgetLimits.put(INDIRECT_COST, initBudgetLimits()); return nonPersonnelBudgetLimits; } protected Map<String, List<BudgetDecimal>> getPersonnelMap() { Map<String, List<BudgetDecimal>> personnelBudgetLimits = new HashMap<String, List<BudgetDecimal>>(); personnelBudgetLimits.put(SALARY, initBudgetLimits()); personnelBudgetLimits.put(FRINGE, initBudgetLimits()); personnelBudgetLimits.put(CALCULATED_COST, initBudgetLimits()); personnelBudgetLimits.put(INDIRECT_COST, initBudgetLimits()); return personnelBudgetLimits; } protected Map<String, List<BudgetDecimal>> getTotalMap() { Map<String, List<BudgetDecimal>> personnelBudgetLimits = new HashMap<String, List<BudgetDecimal>>(); personnelBudgetLimits.put("Direct", initBudgetLimits()); personnelBudgetLimits.put("FAndA", initBudgetLimits()); personnelBudgetLimits.put("Totals", initBudgetLimits()); return personnelBudgetLimits; } protected void getFringeAndCalculatedCost(Map<String, List<BudgetDecimal>> personnelBudgetLimits, AwardBudgetLineItemExt awardBudgetLineItem, boolean isPrevBudget) { for (BudgetLineItemCalculatedAmount calcExpenseAmount : awardBudgetLineItem .getBudgetLineItemCalculatedAmounts()) { calcExpenseAmount.refreshReferenceObject("rateClass"); AwardBudgetLineItemCalculatedAmountExt awardCalcAmt = (AwardBudgetLineItemCalculatedAmountExt) calcExpenseAmount; // Check for Employee Benefits RateClassType if (calcExpenseAmount.getRateClass().getRateClassType().equalsIgnoreCase("E")) { addBudgetLimits(personnelBudgetLimits.get(FRINGE), awardCalcAmt, isPrevBudget); } else if (!calcExpenseAmount.getRateClass().getRateClassType().equalsIgnoreCase("O")) { addBudgetLimits(personnelBudgetLimits.get(CALCULATED_COST), awardCalcAmt, isPrevBudget); } else { addBudgetLimits(personnelBudgetLimits.get(INDIRECT_COST), awardCalcAmt, isPrevBudget); } } } protected void getNonPersonnelCalAmt(Map<String, List<BudgetDecimal>> personnelBudgetLimits, AwardBudgetLineItemExt awardBudgetLineItem, boolean isPrevBudget) { for (BudgetLineItemCalculatedAmount calcExpenseAmount : awardBudgetLineItem .getBudgetLineItemCalculatedAmounts()) { calcExpenseAmount.refreshReferenceObject("rateClass"); AwardBudgetLineItemCalculatedAmountExt awardCalcAmt = (AwardBudgetLineItemCalculatedAmountExt) calcExpenseAmount; // Check for Employee Benefits RateClassType if (!calcExpenseAmount.getRateClass().getRateClassType().equalsIgnoreCase("O")) { addBudgetLimits(personnelBudgetLimits.get(CALCULATED_COST), awardCalcAmt, isPrevBudget); } else { addBudgetLimits(personnelBudgetLimits.get(INDIRECT_COST), awardCalcAmt, isPrevBudget); } } } }