/**
  * This method will return the budget data periods for calculated amounts.It checks rate type code
  * ,rate class code against list of Budget LineItem Calculated Amounts for each budget line item
  * of each budget period of budget ,if it is equals then add calculated cost of budget LineItem
  * Calculated Amount to period cost.
  *
  * @param rateClassCode
  * @param rateTypeCode
  * @return list of BudgetDataPeriod VO's
  */
 protected List<BudgetDataPeriodVO> getBudgetDataPeriodsForCalculatedAmounts(
     String rateClassCode, String rateTypeCode, boolean includeNonPersonnel) {
   List<BudgetDataPeriodVO> budgetPeriodDataList = new ArrayList<BudgetDataPeriodVO>();
   int budgetPeriodDataId = 0;
   for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) {
     BudgetDataPeriodVO budgetPeriodVO = new BudgetDataPeriodVO();
     budgetPeriodVO.setBudgetPeriodId(++budgetPeriodDataId);
     ScaleTwoDecimal periodCost = ScaleTwoDecimal.ZERO;
     for (BudgetLineItem budgetLineItem : budgetPeriod.getBudgetLineItems()) {
       String budgetCategoryType = getBudgetCategoryTypeCode(budgetLineItem);
       if (includeNonPersonnel || isPersonnel(budgetCategoryType)) {
         for (BudgetLineItemCalculatedAmount budgetLineItemCalcAmount :
             budgetLineItem.getBudgetLineItemCalculatedAmounts()) {
           if (budgetLineItemCalcAmount.getRateClassCode() != null
               && budgetLineItemCalcAmount.getRateClassCode().equals(rateClassCode)
               && budgetLineItemCalcAmount.getRateTypeCode() != null
               && budgetLineItemCalcAmount.getRateTypeCode().equals(rateTypeCode)) {
             periodCost = periodCost.add(budgetLineItemCalcAmount.getCalculatedCost());
           }
         }
       }
     }
     budgetPeriodVO.setPeriodCost(periodCost);
     budgetPeriodDataList.add(budgetPeriodVO);
   }
   return budgetPeriodDataList;
 }
 /**
  * This method will set the values to salaryType VO for budget line calculated amount
  *
  * @param salaryTypeVoList is a list contains set of salary types based on budget line calculated
  *     amount
  */
 protected void setSalaryTypesForLineItemCalcuAmount(
     List<SalaryTypeVO> salaryTypeVoList, boolean includeNonPersonnel) {
   List<String> calculatedAmountDescList = new ArrayList<String>();
   SalaryTypeVO salaryTypeVO = new SalaryTypeVO();
   salaryTypeVO.setCostElement(CALCULATED_AMOUNT_COST_ELEMENT_DESC);
   salaryTypeVoList.add(salaryTypeVO);
   for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) {
     for (BudgetLineItem budgetLineItem : new ArrayList<>(budgetPeriod.getBudgetLineItems())) {
       List<BudgetLineItemCalculatedAmount> budgetLineItemCalculatedAmounts =
           budgetLineItem.getBudgetLineItemCalculatedAmounts();
       for (BudgetLineItemCalculatedAmount budgetLineItemCalcAmount :
           budgetLineItemCalculatedAmounts) {
         String rateClassCode = budgetLineItemCalcAmount.getRateClassCode();
         String rateTypeCode = budgetLineItemCalcAmount.getRateTypeCode();
         RateClass rateClass = getRateClassBo(rateClassCode);
         String costElementDesc =
             getCostElementDescriptionForLineItem(budgetLineItemCalcAmount, rateClass);
         if (costElementDesc != null && !calculatedAmountDescList.contains(costElementDesc)) {
           calculatedAmountDescList.add(costElementDesc);
           SalaryTypeVO salaryTypeVOForCalculatedAmount = new SalaryTypeVO();
           salaryTypeVOForCalculatedAmount.setName(costElementDesc);
           List<BudgetDataPeriodVO> budgetPeriodDataList =
               getBudgetDataPeriodsForCalculatedAmounts(
                   rateClassCode, rateTypeCode, includeNonPersonnel);
           salaryTypeVOForCalculatedAmount.setBudgetPeriodVOs(budgetPeriodDataList);
           salaryTypeVoList.add(salaryTypeVOForCalculatedAmount);
         }
       }
     }
   }
 }
  /**
   * This method returns the fringe totals.
   *
   * @param currentPersonnelObjectCodes
   * @param budget
   * @return
   */
  protected Map<RateClassRateType, ScaleTwoDecimal> getFringeTotals(
      List<CostElement> currentPersonnelObjectCodes, Budget budget) {
    /*
     * Things like Animal care and Travel also have a rateClassType of E so need to filter that
     * out to only get Personnel
     */
    Map<RateClassRateType, ScaleTwoDecimal> fringeTotals =
        new HashMap<RateClassRateType, ScaleTwoDecimal>();

    if (CollectionUtils.isNotEmpty(currentPersonnelObjectCodes)) {
      for (CostElement personnelCostElement : currentPersonnelObjectCodes) {
        for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) {
          List<BudgetLineItem> filteredLineItems =
              getPersonnelLineItems(budgetPeriod, personnelCostElement);
          for (BudgetLineItem lineItem : filteredLineItems) {
            for (BudgetLineItemCalculatedAmount lineItemCalculatedAmount :
                lineItem.getBudgetLineItemCalculatedAmounts()) {
              lineItemCalculatedAmount.refreshReferenceObject("rateClass");
              // Check for Employee Benefits RateClassType
              if (lineItemCalculatedAmount
                  .getRateClass()
                  .getRateClassTypeCode()
                  .equalsIgnoreCase("E")) {
                RateClassRateType currentKey =
                    new RateClassRateType(
                        lineItemCalculatedAmount.getRateClassCode(),
                        lineItemCalculatedAmount.getRateTypeCode());
                if (fringeTotals.containsKey(currentKey)) {
                  fringeTotals.put(
                      currentKey,
                      fringeTotals
                          .get(currentKey)
                          .add(lineItemCalculatedAmount.getCalculatedCost()));
                } else {
                  fringeTotals.put(currentKey, lineItemCalculatedAmount.getCalculatedCost());
                }
              }
            }
          }
        }
      }
    }
    return fringeTotals;
  }
 /*
  * This method will get the unique list of cost element description.Iterate
  * over budget periods and budget line items check's with map whether that
  * cost element is available in map , if not found add cost element
  * description to map.
  */
 private Map<String, String> getListOfCostElementDescription(
     List<List<BudgetLineItemCalculatedAmount>> budgetLineItemCalcAmountsList) {
   Map<String, String> lineItems = new HashMap<String, String>();
   for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) {
     List<BudgetLineItemCalculatedAmount> budgetLineItemCalcAmounts =
         new ArrayList<BudgetLineItemCalculatedAmount>();
     for (BudgetLineItem budgetLineItem : budgetPeriod.getBudgetLineItems()) {
       budgetLineItemCalcAmounts = budgetLineItem.getBudgetLineItemCalculatedAmounts();
       budgetLineItemCalcAmountsList.add(budgetLineItemCalcAmounts);
       if (budgetLineItem.getCostElementBO() != null) {
         String costElementDesc = budgetLineItem.getCostElementBO().getDescription();
         if (costElementDesc != null
             && !lineItems.containsKey(costElementDesc)
             && budgetLineItem.getCostElementBO().getCostElement() != null) {
           lineItems.put(costElementDesc, budgetLineItem.getCostElementBO().getCostElement());
         }
       }
     }
   }
   return lineItems;
 }
  /**
   * This method returns the indirect cost for the accounting line.
   *
   * @return
   */
  public Map<RateClassRateType, ScaleTwoDecimal> getIndirectCost(
      Budget currentBudget, AwardBudgetExt previousBudget) {
    int period = currentBudget.getBudgetPeriods().size() - 1;
    List<BudgetLineItem> currentLineItems =
        currentBudget.getBudgetPeriods().get(period).getBudgetLineItems();
    Map<RateClassRateType, ScaleTwoDecimal> currentIndirectTotals =
        new HashMap<RateClassRateType, ScaleTwoDecimal>();

    for (BudgetLineItem lineItem : currentLineItems) {
      for (BudgetLineItemCalculatedAmount lineItemCalculatedAmount :
          lineItem.getBudgetLineItemCalculatedAmounts()) {
        lineItemCalculatedAmount.refreshReferenceObject("rateClass");
        if (lineItemCalculatedAmount.getRateClass().getRateClassTypeCode().equalsIgnoreCase("O")) {
          RateClassRateType currentKey =
              new RateClassRateType(
                  lineItemCalculatedAmount.getRateClassCode(),
                  lineItemCalculatedAmount.getRateTypeCode());
          if (currentIndirectTotals.containsKey(currentKey)) {
            currentIndirectTotals.put(
                currentKey,
                currentIndirectTotals
                    .get(currentKey)
                    .add(lineItemCalculatedAmount.getCalculatedCost()));
          } else {
            currentIndirectTotals.put(currentKey, lineItemCalculatedAmount.getCalculatedCost());
          }
        }
      }
    }

    Map<RateClassRateType, ScaleTwoDecimal> netIndirectTotals =
        new HashMap<RateClassRateType, ScaleTwoDecimal>();
    for (RateClassRateType rate : currentIndirectTotals.keySet()) {
      netIndirectTotals.put(rate, currentIndirectTotals.get(rate));
    }

    return netIndirectTotals;
  }