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.sql.Date; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.kuali.kra.award.commitments.FandaRateType; 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.calculator.query.GreaterThan; import org.kuali.kra.budget.calculator.query.LesserThan; import org.kuali.kra.budget.calculator.query.NotEquals; import org.kuali.kra.budget.calculator.query.Or; import org.kuali.kra.budget.calculator.query.QueryEngine; import org.kuali.kra.budget.core.Budget; import org.kuali.kra.budget.core.CostElement; import org.kuali.kra.budget.nonpersonnel.AbstractBudgetCalculatedAmount; import org.kuali.kra.budget.nonpersonnel.BudgetLineItemBase; import org.kuali.kra.budget.nonpersonnel.BudgetLineItem; import org.kuali.kra.budget.nonpersonnel.BudgetLineItemCalculatedAmount; import org.kuali.kra.budget.personnel.BudgetPersonnelCalculatedAmount; import org.kuali.kra.budget.personnel.BudgetPersonnelDetails; import org.kuali.kra.budget.rates.AbstractBudgetRate; import org.kuali.kra.budget.rates.BudgetLaRate; import org.kuali.kra.budget.rates.BudgetRate; import org.kuali.kra.budget.rates.BudgetRatesService; import org.kuali.kra.budget.rates.RateType; import org.kuali.kra.budget.rates.ValidCeRateType; import org.kuali.kra.budget.web.struts.form.BudgetForm; import org.kuali.kra.infrastructure.KraServiceLocator; import org.kuali.kra.proposaldevelopment.bo.DevelopmentProposal; import org.kuali.rice.kns.service.BusinessObjectService; import org.kuali.rice.kns.service.DateTimeService; import org.kuali.rice.kns.service.KNSServiceLocator; /** * * Base class for <code>LineItemCalculator<code> and <code>PersonnelLineItemCalculator</code>. */ public abstract class AbstractBudgetCalculator { private static final String UNDER_REECOVERY_RATE_TYPE_CODE = "1"; private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory .getLog(AbstractBudgetCalculator.class); private BusinessObjectService businessObjectService; private DateTimeService dateTimeService; protected Budget budget; protected BudgetLineItemBase budgetLineItem; private QueryList<BudgetLaRate> lineItemPropLaRates; private QueryList<BudgetRate> lineItemPropRates; private List<BreakUpInterval> breakupIntervals; private QueryList<ValidCeRateType> infltionValidCalcCeRates; private QueryList<BudgetRate> underrecoveryRates; private QueryList<BudgetRate> inflationRates; private BudgetCalculationService budgetCalcultionService; /** * * Constructs a CalculatorBase.java. * @param budget * @param budgetLineItem */ public AbstractBudgetCalculator(Budget budget, BudgetLineItemBase budgetLineItem) { this.budget = budget; this.budgetLineItem = budgetLineItem; businessObjectService = KraServiceLocator.getService(BusinessObjectService.class); dateTimeService = KNSServiceLocator.getDateTimeService(); budgetCalcultionService = KraServiceLocator.getService(BudgetCalculationService.class); breakupIntervals = new ArrayList<BreakUpInterval>(); } /** * * Abstract method to populate the applicable cost and applicable cost sharing in boundary. * For LineItemCalculator, applicableCost would be the line item cost and * for PersonnelLineItemCalculator applicable cost would be cumulative salary of all personnel line item * @param boundary */ public abstract void populateApplicableCosts(Boundary boundary); /** * This method is for filtering rates and lab allocation rates. * @param rates * @return */ public QueryList filterRates(List rates) { String activityTypeCode = budget.getBudgetDocument().getParentDocument().getBudgetParent() .getActivityTypeCode(); if (!rates.isEmpty() && rates.get(0) instanceof BudgetRate) { QueryList qList = filterRates(rates, budgetLineItem.getStartDate(), budgetLineItem.getEndDate(), activityTypeCode); if (qList.isEmpty() && !budget.getActivityTypeCode().equals(activityTypeCode)) { qList = filterRates(rates, budgetLineItem.getStartDate(), budgetLineItem.getEndDate(), budget.getActivityTypeCode()); } return qList; } else { return filterRates(rates, budgetLineItem.getStartDate(), budgetLineItem.getEndDate(), null); } } /** * * This method is for filtering rates between startdate and enddate. * <code>activityTypeCode</code> will be null if its a lab allocation rates * @param rates * @param startDate * @param endDate * @param activityTypeCode * @return list of filtered rates */ private QueryList filterRates(List rates, Date startDate, Date endDate, String activityTypeCode) { List<AbstractBudgetCalculatedAmount> lineItemCalcAmts = budgetLineItem.getBudgetCalculatedAmounts(); QueryList qlRates = new QueryList(rates); QueryList budgetProposalRates = new QueryList(); /* * Get all rates from Proposal Rates & Proposal LA Rates which matches with the rates in line item cal amts */ for (AbstractBudgetCalculatedAmount calAmtsBean : lineItemCalcAmts) { String rateClassCode = calAmtsBean.getRateClassCode(); String rateTypeCode = calAmtsBean.getRateTypeCode(); Equals equalsRC = new Equals("rateClassCode", rateClassCode); Equals equalsRT = new Equals("rateTypeCode", rateTypeCode); Equals equalsOnOff = new Equals("onOffCampusFlag", budgetLineItem.getOnOffCampusFlag()); And RCandRT = new And(equalsRC, equalsRT); And RCRTandOnOff = new And(RCandRT, equalsOnOff); QueryList filteredRates = qlRates.filter(RCRTandOnOff); if (filteredRates != null && !filteredRates.isEmpty()) { budgetProposalRates.addAll(qlRates.filter(RCRTandOnOff)); } } if (activityTypeCode != null) { // Add inflation rates separately because, calculated amount list will not have inflation rates listed if (infltionValidCalcCeRates != null && !infltionValidCalcCeRates.isEmpty()) { for (ValidCeRateType inflationValidceRate : infltionValidCalcCeRates) { Equals equalsRC = new Equals("rateClassCode", inflationValidceRate.getRateClassCode()); Equals equalsRT = new Equals("rateTypeCode", inflationValidceRate.getRateTypeCode()); Equals equalsOnOff = new Equals("onOffCampusFlag", budgetLineItem.getOnOffCampusFlag()); And RCandRT = new And(equalsRC, equalsRT); And RCRTandOnOff = new And(RCandRT, equalsOnOff); Equals eActType = new Equals("activityTypeCode", activityTypeCode); And RCRTandOnOffandActType = new And(RCRTandOnOff, eActType); QueryList<BudgetRate> filteredRates = qlRates.filter(RCRTandOnOffandActType); if (filteredRates != null && !filteredRates.isEmpty()) { setInflationRates(filteredRates); budgetProposalRates.addAll(filteredRates); } } } // Add underrecovery rates if (!isUndercoveryMatchesOverhead()) { Equals equalsRC = new Equals("rateClassCode", budget.getUrRateClassCode()); Equals equalsRT = new Equals("rateTypeCode", UNDER_REECOVERY_RATE_TYPE_CODE); Equals equalsOnOff = new Equals("onOffCampusFlag", budgetLineItem.getOnOffCampusFlag()); And RCandRT = new And(equalsRC, equalsRT); And RCRTandOnOff = new And(RCandRT, equalsOnOff); budgetProposalRates.addAll(qlRates.filter(RCRTandOnOff)); } Equals eActType = new Equals("activityTypeCode", activityTypeCode); budgetProposalRates = budgetProposalRates.filter(eActType); } if (budgetProposalRates != null && !budgetProposalRates.isEmpty()) { LesserThan lesserThan = new LesserThan("startDate", endDate); Equals equals = new Equals("startDate", endDate); Or or = new Or(lesserThan, equals); budgetProposalRates = budgetProposalRates.filter(or); } return budgetProposalRates; } private boolean isUndercoveryMatchesOverhead() { return budget.getOhRateClassCode().equals(budget.getUrRateClassCode()); } public void calculate() { if (budget.getBudgetParent() instanceof DevelopmentProposal && ((DevelopmentProposal) budget.getBudgetParent()).isParent()) { // if this budget belongs to a ProposalHierarchy parent skip rate-based recalculations and just sum budgetLineItem.setDirectCost(budgetLineItem.getLineItemCost()); budgetLineItem.setTotalCostSharingAmount(budgetLineItem.getCostSharingAmount()); budgetLineItem.setIndirectCost(BudgetDecimal.ZERO); if (budgetLineItem instanceof BudgetPersonnelDetails) { BudgetPersonnelDetails budgetPersonnelLineItem = (BudgetPersonnelDetails) budgetLineItem; SalaryCalculator salaryCalculator = new SalaryCalculator(budget, budgetPersonnelLineItem); salaryCalculator.calculate(); budgetPersonnelLineItem.setLineItemCost(budgetPersonnelLineItem.getSalaryRequested()); } QueryList<AbstractBudgetCalculatedAmount> calcAmts = new QueryList<AbstractBudgetCalculatedAmount>(); calcAmts.addAll(budgetLineItem.getBudgetCalculatedAmounts()); for (AbstractBudgetCalculatedAmount calcAmt : calcAmts) { calcAmt.refreshReferenceObject("rateClass"); calcAmt.setRateClassType(calcAmt.getRateClass().getRateClassType()); //calcAmt.refreshReferenceObject("rateClassType"); } NotEquals notEqualsOH = new NotEquals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); Equals equalsOH = new Equals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); budgetLineItem.setDirectCost( budgetLineItem.getDirectCost().add(calcAmts.sumObjects("calculatedCost", notEqualsOH))); budgetLineItem.setIndirectCost( budgetLineItem.getIndirectCost().add(calcAmts.sumObjects("calculatedCost", equalsOH))); budgetLineItem.setTotalCostSharingAmount( budgetLineItem.getTotalCostSharingAmount().add(calcAmts.sumObjects("calculatedCostSharing"))); return; } budgetLineItem.setDirectCost(budgetLineItem.getLineItemCost()); budgetLineItem.setTotalCostSharingAmount(budgetLineItem.getCostSharingAmount()); budgetLineItem.setIndirectCost(BudgetDecimal.ZERO); budgetLineItem.setUnderrecoveryAmount(BudgetDecimal.ZERO); createAndCalculateBreakupIntervals(); updateBudgetLineItemCalculatedAmounts(); populateBudgetRateBaseList(); // if (!uRMatchesOh && (!OHAvailable || cvLineItemCalcAmts == null || cvLineItemCalcAmts.size() == 0)) { // calculateURBase(); // } } protected abstract void populateBudgetRateBaseList(); protected void updateBudgetLineItemCalculatedAmounts() { List<AbstractBudgetCalculatedAmount> lineItemCalcAmts = budgetLineItem.getBudgetCalculatedAmounts(); List<BreakUpInterval> cvLIBreakupIntervals = getBreakupIntervals(); if (lineItemCalcAmts != null && lineItemCalcAmts.size() > 0 && cvLIBreakupIntervals != null && cvLIBreakupIntervals.size() > 0) { /* * Sum up all the calculated costs for each breakup interval and then update the line item cal amts. */ String rateClassCode = "0"; String rateTypeCode = "0"; BudgetDecimal totalCalculatedCost = BudgetDecimal.ZERO; BudgetDecimal totalCalculatedCostSharing = BudgetDecimal.ZERO; BudgetDecimal totalUnderRecovery = BudgetDecimal.ZERO; BudgetDecimal directCost = BudgetDecimal.ZERO; BudgetDecimal indirectCost = BudgetDecimal.ZERO; Equals equalsRC; Equals equalsRT; And RCandRT = null; QueryList<RateAndCost> cvCombinedAmtDetails = new QueryList<RateAndCost>(); // Loop and add all the amount details from all the breakup intervals for (BreakUpInterval brkUpInterval : cvLIBreakupIntervals) { cvCombinedAmtDetails.addAll(brkUpInterval.getRateAndCosts()); } // loop thru all cal amount rates, sum up the costs and set it for (AbstractBudgetCalculatedAmount calculatedAmount : lineItemCalcAmts) { rateClassCode = calculatedAmount.getRateClassCode(); rateTypeCode = calculatedAmount.getRateTypeCode(); equalsRC = new Equals("rateClassCode", rateClassCode); equalsRT = new Equals("rateTypeCode", rateTypeCode); RCandRT = new And(equalsRC, equalsRT); totalCalculatedCost = cvCombinedAmtDetails.sumObjects("calculatedCost", RCandRT); calculatedAmount.setCalculatedCost(totalCalculatedCost); totalCalculatedCostSharing = cvCombinedAmtDetails.sumObjects("calculatedCostSharing", RCandRT); calculatedAmount.setCalculatedCostSharing(totalCalculatedCostSharing); } /* * Sum up all the underRecovery costs for each breakup interval and then update the line item details. */ totalUnderRecovery = new QueryList<BreakUpInterval>(cvLIBreakupIntervals).sumObjects("underRecovery"); budgetLineItem.setUnderrecoveryAmount(totalUnderRecovery); /* * Sum up all direct costs ie, rates for RateClassType <> 'O', for each breakup interval plus the line item cost, and * then update the line item details. */ NotEquals notEqualsOH = new NotEquals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); boolean directCostRolledUp = false; boolean resetTotalUnderRecovery = false; BudgetDecimal newTotalUrAmount = BudgetDecimal.ZERO; BudgetDecimal newTotalCostSharing = BudgetDecimal.ZERO; if (budgetLineItem instanceof BudgetLineItem && CollectionUtils .isNotEmpty(((BudgetLineItem) budgetLineItem).getBudgetPersonnelDetailsList())) { for (BudgetPersonnelDetails budgetPersonnelDetail : ((BudgetLineItem) budgetLineItem) .getBudgetPersonnelDetailsList()) { List<BudgetPersonnelCalculatedAmount> personnelCalAmts = budgetPersonnelDetail .getBudgetCalculatedAmounts(); newTotalUrAmount = newTotalUrAmount.add(budgetPersonnelDetail.getUnderrecoveryAmount()); resetTotalUnderRecovery = true; if (CollectionUtils.isNotEmpty(personnelCalAmts)) { for (BudgetPersonnelCalculatedAmount personnelCalAmt : personnelCalAmts) { if (personnelCalAmt.getRateClass() == null) { personnelCalAmt.refreshReferenceObject("rateClass"); } if (!personnelCalAmt.getRateClass().getRateClassType().equals("O")) { directCost = directCost.add(personnelCalAmt.getCalculatedCost()); } else { indirectCost = indirectCost.add(personnelCalAmt.getCalculatedCost()); } newTotalCostSharing = newTotalCostSharing .add(personnelCalAmt.getCalculatedCostSharing()); directCostRolledUp = true; } } } } if (resetTotalUnderRecovery) { budgetLineItem.setUnderrecoveryAmount(newTotalUrAmount); } if (!directCostRolledUp) { directCost = cvCombinedAmtDetails.sumObjects("calculatedCost", notEqualsOH); } budgetLineItem.setDirectCost(directCost.add(budgetLineItem.getLineItemCost())); /* * Sum up all Indirect costs ie, rates for RateClassType = 'O', for each breakup interval and then update the line item * details. */ Equals equalsOH = new Equals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); if (!directCostRolledUp) { indirectCost = cvCombinedAmtDetails.sumObjects("calculatedCost", equalsOH); } budgetLineItem.setIndirectCost(indirectCost); /* * Sum up all Cost Sharing amounts ie, rates for RateClassType <> 'O' and set in the calculatedCostSharing field of line * item details */ if (!directCostRolledUp) { totalCalculatedCostSharing = cvCombinedAmtDetails.sumObjects("calculatedCostSharing"); } else { totalCalculatedCostSharing = newTotalCostSharing; } budgetLineItem.setTotalCostSharingAmount( budgetLineItem.getCostSharingAmount() == null ? totalCalculatedCostSharing : budgetLineItem.getCostSharingAmount().add(totalCalculatedCostSharing)); } else if (lineItemCalcAmts != null && lineItemCalcAmts.size() > 0 && (budgetLineItem.getLineItemCost().equals(BudgetDecimal.ZERO) || CollectionUtils.isEmpty(cvLIBreakupIntervals))) { // if total is 0 or no matching rate to calculate for (AbstractBudgetCalculatedAmount calculatedAmount : lineItemCalcAmts) { calculatedAmount.setCalculatedCost(BudgetDecimal.ZERO); calculatedAmount.setCalculatedCostSharing(BudgetDecimal.ZERO); } } } protected void createAndCalculateBreakupIntervals() { populateCalculatedAmountLineItems(); setQlLineItemPropLaRates(filterRates(budget.getBudgetLaRates())); setQlLineItemPropRates(filterRates(budget.getBudgetRates())); createBreakUpInterval(); calculateBreakUpInterval(); } /** * Combine the sorted Prop & LA rates, which should be in sorted order(asc). Now create the breakup boundaries and use it to * create breakup intervals and set all the values required for calculation. Then call calculateBreakupInterval method for each * AmountBean for setting the calculated cost & calculated cost sharing ie for each rate class & rate type. */ protected void createBreakUpInterval() { LOG.info("Line item details before going to create breakup interval " + budgetLineItem); // Initialize the Message that should be shown if rate not avalilable for any period String messageTemplate = ""; String multipleRatesMesgTemplate = ""; String message = ""; if (breakupIntervals == null) breakupIntervals = new ArrayList<BreakUpInterval>(); if (budgetLineItem.getOnOffCampusFlag()) { messageTemplate = "On-Campus rate information not available for Rate Class - \'"; multipleRatesMesgTemplate = "Multiple On-Campus rates found for the period "; } else { messageTemplate = "Off-Campus rate information not available for Rate Class - \'"; multipleRatesMesgTemplate = "Multiple Off-Campus rates found for the period "; } QueryList<BudgetLaRate> qlLineItemPropLaRates = getQlLineItemPropLaRates(); LOG.info("Budget proposal LA rates size is " + qlLineItemPropLaRates.size()); QueryList<BudgetRate> qlLineItemPropRates = getQlLineItemPropRates(); LOG.info("Budget proposal rates size is " + qlLineItemPropRates.size()); // combine the sorted Prop & LA Rates QueryList qlCombinedRates = new QueryList(); qlCombinedRates.addAll(qlLineItemPropRates); qlCombinedRates.addAll(qlLineItemPropLaRates); qlCombinedRates.sort("startDate", true); Date liStartDate = budgetLineItem.getStartDate(); Date liEndDate = budgetLineItem.getEndDate(); List<Boundary> boundaries = createBreakupBoundaries(qlCombinedRates, liStartDate, liEndDate); LOG.info("Breakup boundaries size is " + boundaries.size()); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM-dd-yyyy"); // create breakup intervals based on the breakup boundaries if (boundaries != null && boundaries.size() > 0) { for (Boundary boundary : boundaries) { BreakUpInterval breakUpInterval = new BreakUpInterval(); breakUpInterval.setBoundary(boundary); breakUpInterval.setBudgetId(budgetLineItem.getBudgetId()); breakUpInterval.setBudgetPeriod(budgetLineItem.getBudgetPeriod()); breakUpInterval.setLineItemNumber(budgetLineItem.getLineItemNumber()); QueryList<RateAndCost> qlRateAndCosts = new QueryList<RateAndCost>(); QueryList<BudgetRate> qlBreakupPropRates = new QueryList<BudgetRate>(); QueryList<BudgetLaRate> qlBreakupPropLARates = new QueryList<BudgetLaRate>(); QueryList qlTempRates = new QueryList(); QueryList qlMultipleRates = new QueryList(); String rateClassType; String rateClassCode; String rateTypeCode; Boolean applyRateFlag; populateApplicableCosts(boundary); breakUpInterval.setApplicableAmt(boundary.getApplicableCost()); breakUpInterval.setApplicableAmtCostSharing(boundary.getApplicableCostSharing()); List<AbstractBudgetCalculatedAmount> qlLineItemCalcAmts = budgetLineItem .getBudgetCalculatedAmounts(); List<String> warningMessages = new ArrayList<String>(); for (AbstractBudgetCalculatedAmount budgetLineItemCalculatedAmount : qlLineItemCalcAmts) { budgetLineItemCalculatedAmount.refreshNonUpdateableReferences(); applyRateFlag = budgetLineItemCalculatedAmount.getApplyRateFlag(); rateClassCode = budgetLineItemCalculatedAmount.getRateClassCode(); rateTypeCode = budgetLineItemCalculatedAmount.getRateTypeCode(); // form the rate not available message // These two statements have to move to the populate method of calculatedAmount later. budgetLineItemCalculatedAmount.refreshReferenceObject("rateClass"); rateClassType = budgetLineItemCalculatedAmount.getRateClass().getRateClassType(); // end block to be moved message = messageTemplate + budgetLineItemCalculatedAmount.getRateClass().getDescription() + "\' Rate Type - \'" + budgetLineItemCalculatedAmount.getRateTypeDescription() + "\' for Period - "; // if apply flag is false and rate class type is not Overhead then skip if ((applyRateFlag == null || !applyRateFlag) && !rateClassType.equals(RateClassType.OVERHEAD.getRateClassType())) { continue; } RateAndCost rateCost = new RateAndCost(); rateCost.setApplyRateFlag(applyRateFlag); rateCost.setRateClassType(rateClassType); rateCost.setRateClassCode(rateClassCode); rateCost.setRateTypeCode(rateTypeCode); rateCost.setCalculatedCost(BudgetDecimal.ZERO); rateCost.setCalculatedCostSharing(BudgetDecimal.ZERO); qlRateAndCosts.add(rateCost); // filter & store the rates applicable for this rate class / rate type Equals equalsRC = new Equals("rateClassCode", rateClassCode); Equals equalsRT = new Equals("rateTypeCode", rateTypeCode); LesserThan ltEndDate = new LesserThan("startDate", boundary.getEndDate()); Equals equalsEndDate = new Equals("startDate", boundary.getEndDate()); GreaterThan gtStartDate = new GreaterThan("startDate", boundary.getStartDate()); Equals equalsStartDate = new Equals("startDate", boundary.getStartDate()); Or gtStartDateOrEqStartDate = new Or(gtStartDate, equalsStartDate); Or ltEndDateOrEqEndDate = new Or(ltEndDate, equalsEndDate); And gtOrEqStartDateAndltOrEqEndDate = new And(gtStartDateOrEqStartDate, ltEndDateOrEqEndDate); And RCandRT = new And(equalsRC, equalsRT); And RCRTandLtStartDate = new And(RCandRT, ltEndDateOrEqEndDate); And RCRTandgtStartDateAndltEndDate = new And(RCandRT, gtOrEqStartDateAndltOrEqEndDate); if (rateClassType.equalsIgnoreCase(RateClassType.LAB_ALLOCATION.getRateClassType()) || rateClassType.equalsIgnoreCase(RateClassType.LA_SALARIES.getRateClassType())) { qlTempRates = qlLineItemPropLaRates.filter(RCRTandLtStartDate); if (qlTempRates != null && qlTempRates.size() > 0) { /* * Check if multiple rates are present got this period. If there, then show message and don't add any * rates. */ List cvMultipleRates = qlLineItemPropLaRates.filter(RCRTandgtStartDateAndltEndDate); if (qlMultipleRates != null && qlMultipleRates.size() > 1) { // Store the multiple rates available message in a message vector message = multipleRatesMesgTemplate + simpleDateFormat.format(boundary.getStartDate()) + " to " + simpleDateFormat.format(boundary.getEndDate()) + " for Rate Class - \'" + budgetLineItemCalculatedAmount.getRateClass().getDescription() + "\' Rate Type - \'" + budgetLineItemCalculatedAmount.getRateTypeDescription(); warningMessages.add(message); } else { /** * sort the rates in desc order and take the first rate which is the latest */ qlTempRates.sort("startDate", false); BudgetLaRate tempPropLaRate = (BudgetLaRate) qlTempRates.get(0); qlBreakupPropLARates.add(tempPropLaRate); } } else { // Store the rate not available message in a message vector message = message + simpleDateFormat.format(boundary.getStartDate()) + " to " + simpleDateFormat.format(boundary.getEndDate()); warningMessages.add(message); } } else { qlTempRates = qlLineItemPropRates.filter(RCRTandLtStartDate); if (qlTempRates != null && qlTempRates.size() > 0) { /** * Check if multiple rates are present for this boundary. If there, then show message and don't add any * rates. */ qlMultipleRates = qlLineItemPropRates.filter(RCRTandgtStartDateAndltEndDate); if (qlMultipleRates != null && qlMultipleRates.size() > 1) { // Store the multiple rates available message in a message vector message = multipleRatesMesgTemplate + simpleDateFormat.format(boundary.getStartDate()) + " to " + simpleDateFormat.format(boundary.getEndDate()) + " for Rate Class - \'" + budgetLineItemCalculatedAmount.getRateClass().getDescription() + "\' Rate Type - \'" + budgetLineItemCalculatedAmount.getRateTypeDescription(); warningMessages.add(message); } else { /** * sort the rates in desc order and take the first rate which is the latest */ qlTempRates.sort("startDate", false); qlBreakupPropRates.add((BudgetRate) qlTempRates.get(0)); } } else { // Store the rate not available message in a message vector message = message + simpleDateFormat.format(boundary.getStartDate()) + " to " + simpleDateFormat.format(boundary.getEndDate()); warningMessages.add(message); } } } // breakup interval data setting loop ends here // set the values for the breakup interval in the BreakupInterval bean if (qlRateAndCosts != null && qlRateAndCosts.size() > 0) { breakUpInterval.setRateAndCosts(qlRateAndCosts); breakUpInterval.setBudgetProposalRates(qlBreakupPropRates); breakUpInterval.setBudgetProposalLaRates(qlBreakupPropLARates); breakupIntervals.add(breakUpInterval); } // Set the URRates if required if (!isUndercoveryMatchesOverhead() && hasValidUnderRecoveryRate()) { Equals equalsRC = new Equals("rateClassCode", budget.getUrRateClassCode()); Equals equalsRT = new Equals("rateTypeCode", UNDER_REECOVERY_RATE_TYPE_CODE); Equals equalsOnOff = new Equals("onOffCampusFlag", budgetLineItem.getOnOffCampusFlag()); And RCandRT = new And(equalsRC, equalsRT); And RCRTandOnOff = new And(RCandRT, equalsOnOff); QueryList<BudgetRate> qlUnderRecoveryRates = qlLineItemPropRates.filter(RCRTandOnOff); if (qlUnderRecoveryRates != null && qlUnderRecoveryRates.size() > 0) { LesserThan ltEndDate = new LesserThan("startDate", boundary.getEndDate()); Equals equalsEndDate = new Equals("startDate", boundary.getEndDate()); Or ltEndDateOrEqEndDate = new Or(ltEndDate, equalsEndDate); qlTempRates = qlUnderRecoveryRates.filter(ltEndDateOrEqEndDate); if (qlTempRates != null && qlTempRates.size() > 0) { /* * sort the rates in desc order and take the first rate which is the latest */ qlTempRates.sort("startDate", false); breakUpInterval.setURRatesBean((BudgetRate) qlTempRates.get(0)); } } } } // breakup interval creation loop ends here } // if for vecBoundaries checking ends here } private boolean hasValidUnderRecoveryRate() { Equals equalsRC = new Equals("rateClassCode", budget.getUrRateClassCode()); Equals equalsRT = new Equals("rateTypeCode", UNDER_REECOVERY_RATE_TYPE_CODE); Equals equalsRCT = new Equals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); And RCandRT = new And(equalsRC, equalsRT); And RCRTandRCT = new And(RCandRT, equalsRCT); if (budgetLineItem.getCostElementBO() != null && budgetLineItem.getCostElementBO().getValidCeRateTypes().isEmpty()) { budgetLineItem.getCostElementBO().refreshReferenceObject("validCeRateTypes"); } QueryList<ValidCeRateType> validCeRateTypes = new QueryList<ValidCeRateType>( budgetLineItem.getCostElementBO().getValidCeRateTypes()); return !validCeRateTypes.filter(RCRTandRCT).isEmpty(); } /** * Use the combined & sorted Prop & LA rates to create Boundary objects. Each Boundary will contain start date & end date. Check * whether any rate changes, and break at this point to create a new boundary. * * @return List of boundary objects */ public List<Boundary> createBreakupBoundaries(QueryList<AbstractBudgetRate> qlCombinedRates, Date liStartDate, Date liEndDate) { List<Boundary> boundaries = new ArrayList<Boundary>(); if (qlCombinedRates != null && qlCombinedRates.size() > 0) { Date tempStartDate = liStartDate; Date tempEndDate = liEndDate; Date rateChangeDate; GreaterThan greaterThan = new GreaterThan("startDate", liStartDate); qlCombinedRates = qlCombinedRates.filter(greaterThan); qlCombinedRates.sort("startDate", true); for (AbstractBudgetRate laRate : qlCombinedRates) { rateChangeDate = laRate.getStartDate(); if (rateChangeDate.after(tempStartDate)) { Calendar temEndCal = dateTimeService.getCalendar(rateChangeDate); temEndCal.add(Calendar.DAY_OF_MONTH, -1); try { tempEndDate = dateTimeService.convertToSqlDate(temEndCal.get(Calendar.YEAR) + "-" + (temEndCal.get(Calendar.MONTH) + 1) + "-" + temEndCal.get(Calendar.DAY_OF_MONTH)); } catch (ParseException e) { tempEndDate = new Date(rateChangeDate.getTime() - 86400000); } Boundary boundary = new Boundary(tempStartDate, tempEndDate); boundaries.add(boundary); tempStartDate = rateChangeDate; } } /** * add one more boundary if no rate change on endDate and atleast one boundary is present */ if (boundaries.size() > 0) { Boundary boundary = new Boundary(tempStartDate, liEndDate); boundaries.add(boundary); } /** * if no rate changes during the period create one boundary with startDate & endDate same as that for line item */ if (boundaries.size() == 0) { Boundary boundary = new Boundary(liStartDate, liEndDate); boundaries.add(boundary); } } return boundaries; } // end createBreakupBoundaries protected void calculateBreakUpInterval() { int rateNumber = 0; List<BreakUpInterval> cvLIBreakupIntervals = getBreakupIntervals(); for (BreakUpInterval breakUpInterval : cvLIBreakupIntervals) { // QueryList cvRateBaseData = new QueryList(); breakUpInterval.setRateNumber(rateNumber); breakUpInterval.calculateBreakupInterval(); // if(breakUpInterval.getRateBase()!= null && breakUpInterval.getRateBase().size() >0){ // cvRateBaseData.addAll(breakUpInterval.getRateBase()); // rateNumber += breakUpInterval.getRateAndCosts().size(); // } } // cvRateBase = queryEngine.getDetails(key,BudgetRateBaseBean.class); // cvRateBase.addAll(cvRateBaseData); // queryEngine.addCollection(key,BudgetRateBaseBean.class,cvRateBase); } protected List<ValidCalcType> getValidCalcTypes() { return (List<ValidCalcType>) businessObjectService.findAll(ValidCalcType.class); } protected abstract void populateCalculatedAmountLineItems(); private CostElement getCostElementForLineItem(BudgetLineItemBase lineItem) { Map<String, String> costElementQMap = new HashMap<String, String>(); costElementQMap.put("costElement", lineItem.getCostElement()); return (CostElement) businessObjectService.findByPrimaryKey(CostElement.class, costElementQMap); } private <T> QueryList<T> createQueryList(List<T> immutableList) { if (immutableList == null) { return new QueryList(); } return new QueryList(immutableList); } private void setInflationRateOnLineItem(BudgetLineItemBase lineItem) { QueryList<ValidCeRateType> qValidCeRateTypes = createQueryList( budgetLineItem.getCostElementBO().getValidCeRateTypes()); // Check whether it contains Inflation Rate QueryList<ValidCeRateType> inflationValidCeRates = qValidCeRateTypes .filter(new Equals("rateClassType", RateClassType.INFLATION.getRateClassType())); if (!inflationValidCeRates.isEmpty()) { if (lineItem.getApplyInRateFlag()) { setInfltionValidCalcCeRates(inflationValidCeRates); } } else { lineItem.setApplyInRateFlag(false); } } private Equals equalsOverHeadRateClassType() { return new Equals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); } private NotEquals notEqualsInflationRateClassType() { return new NotEquals("rateClassType", RateClassType.INFLATION.getRateClassType()); } private Equals equalsOverHeadRateClassCode() { return new Equals("rateClassCode", "" + budget.getOhRateClassCode()); } private NotEquals notEqualsOverHeadRateClassType() { return new NotEquals("rateClassType", RateClassType.OVERHEAD.getRateClassType()); } private And notEqualsLabAllocationRateClassType() { return new NotEquals("rateClassType", RateClassType.LAB_ALLOCATION.getRateClassType()) .and(new NotEquals("rateClassType", RateClassType.LA_SALARIES.getRateClassType())); } private void setValidCeRateTypeCalculatedAmounts(BudgetLineItemBase lineItem) { QueryList<ValidCeRateType> qValidCeRateTypes = createQueryList( budgetLineItem.getCostElementBO().getValidCeRateTypes()); qValidCeRateTypes = qValidCeRateTypes .filter(equalsOverHeadRateClassType().and(equalsOverHeadRateClassCode()) .or(notEqualsOverHeadRateClassType()).and(notEqualsInflationRateClassType())); List<BudgetLaRate> budgetLaRates = budget.getBudgetLaRates(); if (budgetLaRates == null || budgetLaRates.size() == 0) { qValidCeRateTypes = qValidCeRateTypes.filter(notEqualsLabAllocationRateClassType()); } addBudgetLineItemCalculatedAmountsForRateTypes(qValidCeRateTypes); } private void addBudgetLineItemCalculatedAmountsForRateTypes(List<ValidCeRateType> rateTypes) { if (CollectionUtils.isEmpty(rateTypes)) { return; } for (ValidCeRateType validCeRateType : rateTypes) { validCeRateType.refreshNonUpdateableReferences(); String rateClassType = validCeRateType.getRateClass().getRateClassType(); if (rateClassType.equals(RateClassType.OVERHEAD.getRateClassType()) && !Boolean.valueOf(budget.getBudgetDocument().getProposalBudgetFlag())) { addOHBudgetLineItemCalculatedAmountForAward(validCeRateType.getRateClassCode(), validCeRateType.getRateType(), validCeRateType.getRateClass().getRateClassType()); } else { addBudgetLineItemCalculatedAmount(validCeRateType.getRateClassCode(), validCeRateType.getRateType(), validCeRateType.getRateClass().getRateClassType()); } } } private void addOHBudgetLineItemCalculatedAmountForAward(String rateClassCode, RateType rateType, String rateClassType) { QueryList<BudgetRate> budgetRates = new QueryList<BudgetRate>(budget.getBudgetRates()); Equals eqOhRateClassType = new Equals("rateClassType", rateClassType); Equals eqOhRateClassOnCampusFlag = new Equals("onOffCampusFlag", budgetLineItem.getOnOffCampusFlag()); And eqRateClassTypeAndOhCampusFlag = new And(eqOhRateClassType, eqOhRateClassOnCampusFlag); List<BudgetRate> filteredBudgetRates = budgetRates.filter(eqRateClassTypeAndOhCampusFlag); if (!filteredBudgetRates.isEmpty()) { BudgetRate awardBudgetRate = filteredBudgetRates.get(0); awardBudgetRate.setBudget(budget); if (awardBudgetRate.getNonEditableRateFlag()) { AbstractBudgetCalculatedAmount budgetCalculatedAmount = getNewCalculatedAmountInstance(); budgetCalculatedAmount.setBudgetId(budgetLineItem.getBudgetId()); budgetCalculatedAmount.setBudgetPeriod(budgetLineItem.getBudgetPeriod()); budgetCalculatedAmount.setBudgetPeriodId(budgetLineItem.getBudgetPeriodId()); budgetCalculatedAmount.setLineItemNumber(budgetLineItem.getLineItemNumber()); budgetCalculatedAmount.setRateClassType(rateClassType); budgetCalculatedAmount.setRateClassCode(awardBudgetRate.getRateClassCode()); budgetCalculatedAmount.setRateTypeCode(awardBudgetRate.getRateTypeCode()); budgetCalculatedAmount.setApplyRateFlag(true); budgetCalculatedAmount .setRateTypeDescription(getAwardRateTypeDescription(awardBudgetRate.getRateTypeCode())); budgetCalculatedAmount.setRateClass(awardBudgetRate.getRateClass()); addCalculatedAmount(budgetCalculatedAmount); } else { addBudgetLineItemCalculatedAmount(rateClassCode, rateType, rateClassType); } } } private String getAwardRateTypeDescription(String rateTypeCode) { return getBusinessObjectService().findBySinglePrimaryKey(FandaRateType.class, rateTypeCode) .getDescription(); } private Equals equalsEmployeeBenefitsRateClassType() { return new Equals("rateClassType", RateClassType.EMPLOYEE_BENEFITS.getRateClassType()); } private Equals equalsVacationRateClassType() { return new Equals("rateClassType", RateClassType.VACATION.getRateClassType()); } private Equals equalsLabAllocationSalariesRateClassType() { return new Equals("rateClassType", RateClassType.LA_SALARIES.getRateClassType()); } private void setLabAllocationSalariesCalculatedAmounts(BudgetLineItemBase lineItem) { QueryEngine queryEngine = new QueryEngine(); queryEngine.addDataCollection(ValidCalcType.class, getValidCalcTypes()); QueryList<ValidCeRateType> qValidCeRateTypes = createQueryList( budgetLineItem.getCostElementBO().getValidCeRateTypes()); QueryList<ValidCeRateType> qLabAllocSalRates = qValidCeRateTypes .filter(equalsLabAllocationSalariesRateClassType()); if (CollectionUtils.isNotEmpty(qLabAllocSalRates)) { List<ValidCalcType> validCalCTypes = queryEngine.executeQuery(ValidCalcType.class, equalsEmployeeBenefitsRateClassType()); if (CollectionUtils.isNotEmpty(validCalCTypes)) { ValidCalcType validCalcType = validCalCTypes.get(0); if (validCalcType.getDependentRateClassType() .equals(RateClassType.LA_SALARIES.getRateClassType())) { addBudgetLineItemCalculatedAmount(validCalcType.getRateClassCode(), validCalcType.getRateType(), validCalcType.getRateClassType()); } } validCalCTypes = queryEngine.executeQuery(ValidCalcType.class, equalsVacationRateClassType()); if (!validCalCTypes.isEmpty()) { ValidCalcType validCalcType = (ValidCalcType) validCalCTypes.get(0); if (validCalcType.getDependentRateClassType() .equals(RateClassType.LA_SALARIES.getRateClassType())) { addBudgetLineItemCalculatedAmount(validCalcType.getRateClassCode(), validCalcType.getRateType(), validCalcType.getRateClassType()); } } } } public final void setCalculatedAmounts(Budget budget, BudgetLineItemBase budgetLineItem) { QueryEngine queryEngine = new QueryEngine(); BudgetLineItemCalculatedAmount budgetLineItemCalculatedAmt = null; budgetLineItem.setCostElementBO(getCostElementForLineItem(budgetLineItem)); Map<String, String> validCeQMap = new HashMap<String, String>(); validCeQMap.put("costElement", budgetLineItem.getCostElement()); budgetLineItem.getCostElementBO().refreshReferenceObject("validCeRateTypes"); QueryList<ValidCeRateType> qValidCeRateTypes = createQueryList( budgetLineItem.getCostElementBO().getValidCeRateTypes()); setInflationRateOnLineItem(budgetLineItem); setValidCeRateTypeCalculatedAmounts(budgetLineItem); setLabAllocationSalariesCalculatedAmounts(budgetLineItem); } protected void setInfltionValidCalcCeRates(QueryList<ValidCeRateType> infltionValidCalcCeRates) { this.infltionValidCalcCeRates = infltionValidCalcCeRates; } private void addBudgetLineItemCalculatedAmount(String rateClassCode, RateType rateType, String rateClassType) { QueryList<BudgetRate> budgetRates = new QueryList<BudgetRate>(budget.getBudgetRates()); QueryList<BudgetLaRate> qlBudgetLaRates = new QueryList<BudgetLaRate>(budget.getBudgetLaRates()); Equals eqValidRateClassCode = new Equals("rateClassCode", rateClassCode); Equals eqValidRateTypeCode = new Equals("rateTypeCode", rateType.getRateTypeCode()); And eqRateClassCodeAndRateTypeCode = new And(eqValidRateClassCode, eqValidRateTypeCode); List<BudgetRate> filteredBudgetRates = budgetRates.filter(eqRateClassCodeAndRateTypeCode); List<BudgetLaRate> filteredBudgetLaRates = qlBudgetLaRates.filter(eqRateClassCodeAndRateTypeCode); if (filteredBudgetRates.isEmpty() && filteredBudgetLaRates.isEmpty()) return; AbstractBudgetCalculatedAmount budgetCalculatedAmount = getNewCalculatedAmountInstance(); budgetCalculatedAmount.setBudgetId(budgetLineItem.getBudgetId()); budgetCalculatedAmount.setBudgetPeriod(budgetLineItem.getBudgetPeriod()); budgetCalculatedAmount.setBudgetPeriodId(budgetLineItem.getBudgetPeriodId()); budgetCalculatedAmount.setLineItemNumber(budgetLineItem.getLineItemNumber()); budgetCalculatedAmount.setRateClassType(rateClassType); budgetCalculatedAmount.setRateClassCode(rateClassCode); budgetCalculatedAmount.setRateTypeCode(rateType.getRateTypeCode()); budgetCalculatedAmount.setApplyRateFlag(true); budgetCalculatedAmount.refreshReferenceObject("rateClass"); budgetCalculatedAmount.setRateTypeDescription(rateType.getDescription()); addCalculatedAmount(budgetCalculatedAmount); } protected abstract AbstractBudgetCalculatedAmount getNewCalculatedAmountInstance(); protected abstract void addCalculatedAmount(AbstractBudgetCalculatedAmount budgetCalculatedAmount); /** * Gets the businessObjectService attribute. * * @return Returns the businessObjectService. */ public BusinessObjectService getBusinessObjectService() { return businessObjectService; } /** * Sets the businessObjectService attribute value. * * @param businessObjectService The businessObjectService to set. */ public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } protected List<BreakUpInterval> getBreakupIntervals() { return breakupIntervals; } protected void setBreakupIntervals(List<BreakUpInterval> breakupIntervals) { this.breakupIntervals = breakupIntervals; } protected DateTimeService getDateTimeService() { return dateTimeService; } /** * Gets the underrecoveryRates attribute. * * @return Returns the underrecoveryRates. */ public QueryList<BudgetRate> getUnderrecoveryRates() { return underrecoveryRates; } /** * Sets the underrecoveryRates attribute value. * * @param underrecoveryRates The underrecoveryRates to set. */ public void setUnderrecoveryRates(QueryList<BudgetRate> underrecoveryRates) { this.underrecoveryRates = underrecoveryRates; } public QueryList<BudgetRate> getInflationRates() { return inflationRates; } public void setInflationRates(QueryList<BudgetRate> inflationRates) { this.inflationRates = inflationRates; } /** * Gets the qlLineItemPropLaRates attribute. * @return Returns the qlLineItemPropLaRates. */ public QueryList<BudgetLaRate> getQlLineItemPropLaRates() { return lineItemPropLaRates; } /** * Sets the qlLineItemPropLaRates attribute value. * @param qlLineItemPropLaRates The qlLineItemPropLaRates to set. */ public void setQlLineItemPropLaRates(QueryList<BudgetLaRate> qlLineItemPropLaRates) { this.lineItemPropLaRates = qlLineItemPropLaRates; } /** * Gets the qlLineItemPropRates attribute. * @return Returns the qlLineItemPropRates. */ public QueryList<BudgetRate> getQlLineItemPropRates() { return lineItemPropRates; } /** * Sets the qlLineItemPropRates attribute value. * @param qlLineItemPropRates The qlLineItemPropRates to set. */ public void setQlLineItemPropRates(QueryList<BudgetRate> qlLineItemPropRates) { this.lineItemPropRates = qlLineItemPropRates; } protected BudgetForm getBudgetFormFromGlobalVariables() { return budgetCalcultionService.getBudgetFormFromGlobalVariables(); } protected BudgetRatesService getBudgetRateService() { return KraServiceLocator.getService(BudgetRatesService.class); } }