Java tutorial
/* * Kuali Coeus, a comprehensive research administration system for higher education. * * Copyright 2005-2015 Kuali, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kra.award.budget; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.kuali.coeus.common.budget.framework.income.BudgetProjectIncome; import org.kuali.coeus.common.budget.framework.nonpersonnel.BudgetLineItemCalculatedAmount; import org.kuali.coeus.common.budget.framework.personnel.BudgetPersonnelCalculatedAmount; import org.kuali.coeus.common.framework.version.history.VersionHistory; import org.kuali.coeus.common.framework.version.history.VersionHistoryService; import org.kuali.coeus.propdev.impl.budget.modular.BudgetModular; import org.kuali.coeus.propdev.impl.budget.subaward.BudgetSubAwardPeriodDetail; import org.kuali.coeus.sys.api.model.ScaleTwoDecimal; import org.kuali.coeus.sys.framework.util.CollectionUtils; import org.kuali.kra.award.budget.calculator.AwardBudgetCalculationService; import org.kuali.kra.award.budget.document.AwardBudgetDocument; import org.kuali.kra.award.commitments.AwardFandaRate; import org.kuali.kra.award.document.AwardDocument; import org.kuali.kra.award.home.Award; import org.kuali.kra.award.home.AwardService; import org.kuali.kra.award.home.fundingproposal.AwardFundingProposal; import org.kuali.coeus.common.budget.framework.query.QueryList; import org.kuali.coeus.common.budget.api.rate.RateClassType; import org.kuali.coeus.common.budget.framework.query.operator.And; import org.kuali.coeus.common.budget.framework.query.operator.Equals; import org.kuali.coeus.common.budget.framework.core.Budget; import org.kuali.coeus.common.budget.framework.core.BudgetConstants; import org.kuali.coeus.common.budget.framework.core.BudgetParent; import org.kuali.coeus.common.budget.framework.core.BudgetParentDocument; import org.kuali.coeus.common.budget.framework.nonpersonnel.BudgetLineItem; import org.kuali.coeus.common.budget.framework.period.BudgetPeriod; import org.kuali.coeus.common.budget.framework.personnel.BudgetPerson; import org.kuali.coeus.common.budget.framework.personnel.BudgetPersonnelDetails; import org.kuali.coeus.common.budget.framework.rate.BudgetRate; import org.kuali.coeus.common.budget.framework.rate.RateType; import org.kuali.coeus.common.budget.framework.summary.BudgetSummaryService; import org.kuali.coeus.common.budget.framework.version.AddBudgetVersionEvent; import org.kuali.coeus.common.budget.framework.version.BudgetVersionRule; import org.kuali.coeus.common.budget.impl.core.AbstractBudgetService; import org.kuali.kra.infrastructure.Constants; import org.kuali.kra.infrastructure.KeyConstants; import org.kuali.kra.institutionalproposal.home.InstitutionalProposal; import org.kuali.kra.institutionalproposal.proposaladmindetails.ProposalAdminDetails; import org.kuali.coeus.propdev.impl.core.DevelopmentProposal; import org.kuali.coeus.propdev.impl.budget.ProposalDevelopmentBudgetExt; import org.kuali.rice.kew.api.WorkflowDocument; import org.kuali.rice.kew.api.exception.WorkflowException; import org.kuali.rice.krad.bo.BusinessObject; import org.kuali.rice.krad.bo.DocumentHeader; import org.kuali.rice.krad.bo.PersistableBusinessObject; import org.kuali.rice.krad.data.DataObjectService; import org.kuali.rice.krad.document.Document; import org.kuali.rice.krad.document.DocumentBase; import org.kuali.rice.krad.service.DocumentService; import org.kuali.rice.krad.service.LegacyDataAdapter; import org.kuali.rice.krad.util.GlobalVariables; import org.springframework.beans.BeanUtils; import java.lang.reflect.Method; import java.util.*; /** * This class is to process all basic services required for AwardBudget */ public class AwardBudgetServiceImpl extends AbstractBudgetService<Award> implements AwardBudgetService { private static final Log LOG = LogFactory.getLog(AwardBudgetServiceImpl.class); private final static String BUDGET_VERSION_ERROR_PREFIX = "document.parentDocument.budgetDocumentVersion"; private static final String INST_PROPOSAL_ID = "instProposalId"; public static final String AWARD_BUDGET_STATUS_CODE = "awardBudgetStatusCode"; public static final String BUDGET_VERSION_NUMBER = "budgetVersionNumber"; public static final String BUDGET_ID = "budgetId"; public static final String BUDGET_LINE_ITEM_ID = "budgetLineItemId"; public static final String BUDGET_PERIOD_ID = "budgetPeriodId"; public static final String SUBMIT_COST_SHARING_FLAG = "submitCostSharingFlag"; public static final String BUDGET_LINE_ITEM_CALCULATED_AMOUNTS = "budgetLineItemCalculatedAmounts"; public static final String BUDGET_PERSONNEL_DETAILS_LIST = "budgetPersonnelDetailsList"; public static final String BUDGET_RATE_AND_BASE_LIST = "budgetRateAndBaseList"; public static final String BUDGET_SUB_AWARD = "budgetSubAward"; public static final String BUDGET_PERSONNEL_LINE_ITEM_ID = "budgetPersonnelLineItemId"; public static final String BUDGET_PERSONNEL_CALCULATED_AMOUNTS = "budgetPersonnelCalculatedAmounts"; public static final String BUDGET_PERSONNEL_RATE_AND_BASE_LIST = "budgetPersonnelRateAndBaseList"; public static final String VALID_TO_APPLY_IN_RATE = "validToApplyInRate"; public static final String PERSON_SEQUENCE_NUMBER = "personSequenceNumber"; public static final String AWARD_NUMBER = "awardNumber"; public static final String AWARD_ID = "awardId"; public static final String PROPOSAL_NUMBER = "proposalNumber"; public static final String UNNAMED = "UNNAMED"; public static final String PERSONNEL_FRINGE_TOTALS = "personnelFringeTotals"; public static final String CALCULATED_COST = "calculatedCost"; public static final String RATE_CLASS_TYPE = "rateClassType"; public static final String AWARD_FANDA_RATE = "awardFandaRate"; public static final String RATE_CLASS_CODE = "rateClassCode"; public static final String RATE_TYPE_CODE = "rateTypeCode"; public static final String ON_OFF_CAMPUS_FLAG = "onOffCampusFlag"; public static final String COST_ELEMENT_BO = "costElementBO"; public static final String BUDGET_CATEGORY = "budgetCategory"; private DocumentService documentService; private BudgetSummaryService budgetSummaryService; private AwardBudgetCalculationService awardBudgetCalculationService; private VersionHistoryService versionHistoryService; private AwardService awardService; private BudgetVersionRule addBudgetVersionRule; private DataObjectService dataObjectService; private LegacyDataAdapter legacyDataAdapter; @Override public void post(AwardBudgetDocument awardBudgetDocument) { processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_POSTED); saveDocument(awardBudgetDocument); } public AwardBudgetDocument copyBudgetVersion(AwardBudgetDocument budgetDocument, boolean onlyOnePeriod) throws WorkflowException { AwardDocument awardDocument = (AwardDocument) budgetDocument.getBudget().getBudgetParent().getDocument(); String parentDocumentNumber = awardDocument.getDocumentNumber(); budgetDocument.toCopy(); awardDocument.getDocumentHeader().setDocumentNumber(parentDocumentNumber); awardDocument.setDocumentNumber(parentDocumentNumber); if (budgetDocument.getBudget() == null) { throw new RuntimeException("Not able to find any Budget Version associated with this document"); } Budget budget = budgetDocument.getBudget(); AwardBudgetExt copiedBudget = (AwardBudgetExt) copyBudgetVersion(budget, onlyOnePeriod); budgetDocument.getBudgets().add(copiedBudget); budgetDocument = (AwardBudgetDocument) documentService.saveDocument(budgetDocument); Map<String, Object> objectMap = new HashMap<>(); fixProperty(budget, "setBudgetId", Long.class, budgetDocument.getBudget().getBudgetId(), objectMap); objectMap.clear(); budgetDocument = saveBudgetDocument(budgetDocument, false); AwardDocument savedAwardDocument = (AwardDocument) budgetDocument.getBudget().getBudgetParent() .getDocument(); savedAwardDocument.refreshBudgetDocumentVersions(); return budgetDocument; } public Budget copyBudgetVersionSuper(Budget budget, boolean onlyOnePeriod) { if (onlyOnePeriod) { //Copy full first version, then include empty periods for remainder List<BudgetPeriod> oldBudgetPeriods = budget.getBudgetPeriods(); for (int i = 1; i < oldBudgetPeriods.size(); i++) { BudgetPeriod period = oldBudgetPeriods.get(i); period.getBudgetLineItems().clear(); period.setCostSharingAmount(new ScaleTwoDecimal(0.0)); period.setExpenseTotal(new ScaleTwoDecimal(0.0)); period.setTotalCost(new ScaleTwoDecimal(0.0)); period.setTotalCostLimit(new ScaleTwoDecimal(0.0)); period.setTotalDirectCost(new ScaleTwoDecimal(0.0)); period.setTotalIndirectCost(new ScaleTwoDecimal(0.0)); period.setUnderrecoveryAmount(new ScaleTwoDecimal(0.0)); } /** * KRACOEUS-6312 * Zero out any applicable BudgetSubAwardPeriodDetail lines. */ if (budget.getBudgetSubAwards() != null && budget.getBudgetSubAwards().size() > 0) { List<BudgetSubAwardPeriodDetail> budetSubawardPeriodDetail = budget.getBudgetSubAwards().get(0) .getBudgetSubAwardPeriodDetails(); for (int i = 1; i < budetSubawardPeriodDetail.size(); i++) { BudgetSubAwardPeriodDetail period = budetSubawardPeriodDetail.get(i); period.setAmountsModified(true); period.setCostShare(new ScaleTwoDecimal(0.0)); period.setDirectCost(new ScaleTwoDecimal(0.0)); period.setIndirectCost(new ScaleTwoDecimal(0.0)); period.setTotalCost(new ScaleTwoDecimal(0.0)); } } } budget.setBudgetVersionNumber(budget.getBudgetParent().getNextBudgetVersionNumber()); try { Map<String, Object> objectMap = new HashMap<>(); fixProperty(budget, "setBudgetId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetPeriodId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetLineItemId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetLineItemCalculatedAmountId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetPersonnelLineItemId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetPersonnelCalculatedAmountId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetPersonnelRateAndBaseId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setBudgetRateAndBaseId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setVersionNumber", Integer.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setAwardBudgetPeriodSummaryCalculatedAmountId", Long.class, null, objectMap); objectMap.clear(); fixProperty(budget, "setFinalVersionFlag", Boolean.class, Boolean.FALSE, objectMap); objectMap.clear(); } catch (Exception e) { throw new RuntimeException(e); } //Work around for 1-to-1 Relationship between BudgetPeriod & BudgetModular Map<String, BudgetModular> tmpBudgetModulars = new HashMap<>(); for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { BudgetModular tmpObject = null; if (budgetPeriod.getBudgetModular() != null) { tmpObject = (BudgetModular) org.kuali.rice.krad.util.ObjectUtils .deepCopy(budgetPeriod.getBudgetModular()); } tmpBudgetModulars.put("" + budgetPeriod.getBudget().getVersionNumber() + budgetPeriod.getBudgetPeriod(), tmpObject); budgetPeriod.setBudgetModular(null); } copyLineItemToPersonnelDetails(budget); budget.setVersionNumber(null); // setting this to null so copied budget can be posted. budget.setBudgetAdjustmentDocumentNumber(null); List<BudgetProjectIncome> projectIncomes = budget.getBudgetProjectIncomes(); budget.setBudgetProjectIncomes(new ArrayList<>()); if (projectIncomes != null && !projectIncomes.isEmpty()) { updateProjectIncomes(budget, projectIncomes); } for (BudgetPeriod tmpBudgetPeriod : budget.getBudgetPeriods()) { BudgetModular tmpBudgetModular = tmpBudgetModulars .get("" + tmpBudgetPeriod.getBudget().getVersionNumber() + tmpBudgetPeriod.getBudgetPeriod()); if (tmpBudgetModular != null) { tmpBudgetModular.setBudgetPeriodObj(tmpBudgetPeriod); tmpBudgetPeriod.setBudgetModular(tmpBudgetModular); } } return budget; } /** * Recurse through all of the BOs and if a BO has a ProposalNumber property, * set its value to the new proposal number. * @param object the object */ private void fixProperty(Object object, String methodName, Class clazz, Object propertyValue, Map<String, Object> objectMap) { if (org.kuali.rice.krad.util.ObjectUtils.isNotNull(object)) { if (object instanceof PersistableBusinessObject) { PersistableBusinessObject objectWId = (PersistableBusinessObject) object; if (objectMap.get(objectWId.getObjectId()) != null) return; objectMap.put(((PersistableBusinessObject) object).getObjectId(), object); Method[] methods = object.getClass().getMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { if (!(object instanceof DocumentBase)) { try { if (clazz.equals(Long.class)) method.invoke(object, (Long) propertyValue); else method.invoke(object, (Integer) propertyValue); } catch (Throwable e) { } } } else if (isPropertyGetterMethod(method, methods)) { Object value = null; try { value = method.invoke(object); } catch (Throwable e) { //We don't need to propagate this exception } if (value != null) { if (value instanceof Collection) { Collection<?> c = (Collection<?>) value; for (Object entry : c) { fixProperty(entry, methodName, clazz, propertyValue, objectMap); } } else { fixProperty(value, methodName, clazz, propertyValue, objectMap); } } } } } } } /** * Is the given method a getter method for a property? Must conform to * the following: * <ol> * <li>Must start with the <b>get</b></li> * <li>Must have a corresponding setter method</li> * <li>Must have zero arguments.</li> * </ol> * @param method the method to check * @param methods the other methods in the object * @return true if it is property getter method; otherwise false */ private boolean isPropertyGetterMethod(Method method, Method methods[]) { if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { String setterName = method.getName().replaceFirst("get", "set"); for (Method m : methods) { if (m.getName().equals(setterName)) { return true; } } } return false; } /** * * This method is to handle budgetprojectincomes independently. * budgetprojectincomes is a collection of 'budget', but it also reference to budgetperiod. * During copy budgetperiodid is set to null. If save with budgetdocument, then budgetperiodid will not be set. * So, has to use this to set manually. */ private void updateProjectIncomes(Budget budget, List<BudgetProjectIncome> projectIncomes) { for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { for (BudgetProjectIncome projectIncome : projectIncomes) { if (budgetPeriod.getBudgetPeriod().equals(projectIncome.getBudgetPeriodNumber())) { projectIncome.setBudgetId(budget.getBudgetId()); projectIncome.setBudgetPeriodId(budgetPeriod.getBudgetPeriodId()); } } } } @Override public Budget copyBudgetVersion(Budget budget, boolean onlyOnePeriod) { AwardBudgetExt copy = (AwardBudgetExt) copyBudgetVersionSuper(budget, onlyOnePeriod); for (BudgetPeriod period : copy.getBudgetPeriods()) { AwardBudgetPeriodExt awardPeriod = (AwardBudgetPeriodExt) period; awardPeriod.getAwardBudgetPeriodFnAAmounts().clear(); awardPeriod.getAwardBudgetPeriodFringeAmounts().clear(); } return copy; } @Override public void toggleStatus(AwardBudgetDocument awardBudgetDocument) { String currentStatusCode = awardBudgetDocument.getAwardBudget().getAwardBudgetStatusCode(); if (currentStatusCode.equals(getParameterValue(KeyConstants.AWARD_BUDGET_STATUS_TO_BE_POSTED))) { processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_DO_NOT_POST); } else if (currentStatusCode.equals(getParameterValue(KeyConstants.AWARD_BUDGET_STATUS_DO_NOT_POST))) { processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_TO_BE_POSTED); } saveDocument(awardBudgetDocument); } protected void saveDocument(AwardBudgetDocument awardBudgetDocument) { try { getDocumentService().saveDocument(awardBudgetDocument); } catch (WorkflowException e) { throw new RuntimeException(e); } } @Override public void processApproval(AwardBudgetDocument awardBudgetDocument) { WorkflowDocument workFlowDocument = getWorkflowDocument(awardBudgetDocument); if (workFlowDocument.isFinal()) { processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_TO_BE_POSTED); saveDocument(awardBudgetDocument); } } @Override public void processDisapproval(AwardBudgetDocument awardBudgetDocument) { processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_REJECTED); } @Override public void processSubmision(AwardBudgetDocument awardBudgetDocument) { processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_SUBMITTED); } protected void processStatusChange(AwardBudgetDocument awardBudgetDocument, String routingStatus) { WorkflowDocument workflowDocument = getWorkflowDocument(awardBudgetDocument); String submittedStatusCode = getParameterValue(routingStatus); String submittedStatus = findStatusDescription(submittedStatusCode); awardBudgetDocument.getAwardBudget().setAwardBudgetStatusCode(submittedStatusCode); workflowDocument.setApplicationDocumentStatus(submittedStatus); } protected String getParameterValue(String awardBudgetParameter) { return getParameterService().getParameterValueAsString(AwardBudgetDocument.class, awardBudgetParameter); } protected String findStatusDescription(String statusCode) { AwardBudgetStatus budgetStatus = getBusinessObjectService().findBySinglePrimaryKey(AwardBudgetStatus.class, statusCode); return budgetStatus.getDescription(); } @Override public AwardBudgetDocument rebudget(AwardDocument awardDocument, String documentDescription) throws WorkflowException { return createNewBudgetDocument(documentDescription, awardDocument.getAward(), true); } /** * Get the corresponding workflow document. * @param doc the document * @return the workflow document or null if there is none */ protected WorkflowDocument getWorkflowDocument(Document doc) { WorkflowDocument workflowDocument = null; if (doc != null) { DocumentHeader header = doc.getDocumentHeader(); if (header != null) { try { workflowDocument = header.getWorkflowDocument(); } catch (RuntimeException ex) { // do nothing; there is no workflow document } } } return workflowDocument; } @Override public Budget getNewBudgetVersion(BudgetParentDocument<Award> parentBudgetDocument, String documentDescription, Map<String, Object> options) { AwardDocument awardDocument = (AwardDocument) parentBudgetDocument; AwardBudgetDocument budgetDocument; try { budgetDocument = getNewBudgetVersionDocument(parentBudgetDocument, documentDescription, options); } catch (WorkflowException e) { throw new RuntimeException(e); } if (budgetDocument != null) { AwardBudgetExt budget = budgetDocument.getBudget(); if (budget.getBudgetPeriods().isEmpty() && budget.getStartDate() != null) { budget.setBudgetPeriods(getBudgetSummaryService().generateBudgetPeriods(budget)); } awardDocument.getAward().getCurrentVersionBudgets().add(budget); awardDocument.getAward().getBudgets().add(budget); try { budgetDocument = (AwardBudgetDocument) documentService.saveDocument(budgetDocument); } catch (WorkflowException e) { throw new RuntimeException(e); } return budgetDocument.getBudget(); } else { return null; } } @Override public AwardBudgetDocument getNewBudgetVersionDocument(BudgetParentDocument<Award> parentBudgetDocument, String documentDescription, Map<String, Object> options) throws WorkflowException { AwardDocument parentDocument = (AwardDocument) parentBudgetDocument; if (checkForOutstandingBudgets(parentDocument.getAward())) { return null; } return createNewBudgetDocument(documentDescription, parentDocument.getAward(), false); } protected AwardBudgetDocument createNewBudgetDocument(String documentDescription, Award award, boolean rebudget) throws WorkflowException { boolean success = new AwardBudgetVersionRule().processAddBudgetVersion( new AddBudgetVersionEvent(BUDGET_VERSION_ERROR_PREFIX, award, documentDescription)); if (!success) { return null; } Integer budgetVersionNumber = award.getNextBudgetVersionNumber(); AwardBudgetDocument awardBudgetDocument; if (isPostedBudgetExist(award)) { ScaleTwoDecimal obligatedChangeAmount = getTotalCostLimit(award); AwardBudgetExt previousPostedBudget = getLatestPostedBudget(award); AwardBudgetDocument postedBudgetDocument = previousPostedBudget.getBudgetDocument(); awardBudgetDocument = copyBudgetVersion(postedBudgetDocument); copyObligatedAmountToLineItems(awardBudgetDocument, obligatedChangeAmount); } else { awardBudgetDocument = (AwardBudgetDocument) documentService.getNewDocument(AwardBudgetDocument.class); } awardBudgetDocument.getDocumentHeader().setDocumentDescription(documentDescription); AwardBudgetExt awardBudget = awardBudgetDocument.getAwardBudget(); awardBudget.setBudgetVersionNumber(budgetVersionNumber); awardBudget.setBudgetDocument(awardBudgetDocument); awardBudget.setAward(award); awardBudget.setAwardId(award.getAwardId()); awardBudget.setName(documentDescription); awardBudget.setDocumentNumber(awardBudgetDocument.getDocumentNumber()); AwardBudgetExt lastBudgetVersion = getLastBudgetVersion(award); awardBudget.setOnOffCampusFlag(lastBudgetVersion == null ? BudgetConstants.DEFAULT_CAMPUS_FLAG : lastBudgetVersion.getOnOffCampusFlag()); if (awardBudgetDocument.getDocumentHeader() != null && awardBudgetDocument.getDocumentHeader().hasWorkflowDocument()) { awardBudget.setBudgetInitiator( awardBudgetDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId()); } awardBudget.setStartDate(award.getRequestedStartDateInitial()); awardBudget.setEndDate(award.getRequestedEndDateInitial()); if (awardBudget.getOhRatesNonEditable()) { awardBudget .setOhRateClassCode(getAwardParameterValue(Constants.AWARD_BUDGET_DEFAULT_FNA_RATE_CLASS_CODE)); awardBudget.setUrRateClassCode( getAwardParameterValue(Constants.AWARD_BUDGET_DEFAULT_UNDERRECOVERY_RATE_CLASS_CODE)); } else { awardBudget.setOhRateClassCode(getBudgetParameterValue(Constants.BUDGET_DEFAULT_OVERHEAD_RATE_CODE)); awardBudget .setUrRateClassCode(getBudgetParameterValue(Constants.BUDGET_DEFAULT_UNDERRECOVERY_RATE_CODE)); } awardBudget.setOhRateTypeCode(getBudgetParameterValue(Constants.BUDGET_DEFAULT_OVERHEAD_RATE_TYPE_CODE)); awardBudget.setModularBudgetFlag(getParameterService().getParameterValueAsBoolean(Budget.class, Constants.BUDGET_DEFAULT_MODULAR_FLAG)); awardBudget.setAwardBudgetStatusCode(getAwardParameterValue(KeyConstants.AWARD_BUDGET_STATUS_IN_PROGRESS)); // do not want the Budget adjustment doc number to be copied over to the new budget. // this should be null so the budget can be posted again to the financial system. awardBudget.setBudgetAdjustmentDocumentNumber(""); awardBudget.setRateClassTypesReloaded(true); setBudgetLimits(awardBudgetDocument, award); if (isPostedBudgetExist(award)) { if (awardBudget.getTotalCostLimit().equals(ScaleTwoDecimal.ZERO)) { rebudget = true; } } recalculateBudget(awardBudgetDocument.getBudget()); saveBudgetDocument(awardBudgetDocument, rebudget); awardBudgetDocument = (AwardBudgetDocument) documentService .getByDocumentHeaderId(awardBudgetDocument.getDocumentNumber()); return awardBudgetDocument; } private String getBudgetParameterValue(String parameter) { return getParameterService().getParameterValueAsString(Budget.class, parameter); } private String getAwardParameterValue(String parameter) { return getParameterService().getParameterValueAsString(AwardBudgetDocument.class, parameter); } public void setBudgetLimits(AwardBudgetDocument awardBudgetDocument, Award award) { AwardBudgetExt awardBudget = awardBudgetDocument.getAwardBudget(); awardBudget.setTotalCostLimit(getTotalCostLimit(award)); awardBudget.setObligatedTotal(new ScaleTwoDecimal(award.getBudgetTotalCostLimit().bigDecimalValue())); awardBudget.getAwardBudgetLimits().clear(); for (AwardBudgetLimit limit : award.getAwardBudgetLimits()) { awardBudget.getAwardBudgetLimits().add(new AwardBudgetLimit(limit)); } } protected void copyObligatedAmountToLineItems(AwardBudgetDocument awardBudgetDocument, ScaleTwoDecimal obligatedChangeAmount) { AwardBudgetExt newAwardBudgetFromPosted = awardBudgetDocument.getAwardBudget(); List<BudgetPeriod> awardBudgetPeriods = newAwardBudgetFromPosted.getBudgetPeriods(); for (BudgetPeriod budgetPeriod : awardBudgetPeriods) { AwardBudgetPeriodExt awardBudgetPeriod = (AwardBudgetPeriodExt) budgetPeriod; List<BudgetLineItem> lineItems = awardBudgetPeriod.getBudgetLineItems(); for (BudgetLineItem budgetLineItem : lineItems) { AwardBudgetLineItemExt awardBudgetLineItem = (AwardBudgetLineItemExt) budgetLineItem; List<BudgetPersonnelDetails> personnelDetailsList = awardBudgetLineItem .getBudgetPersonnelDetailsList(); for (BudgetPersonnelDetails budgetPersonnelDetails : personnelDetailsList) { AwardBudgetPersonnelDetailsExt awardBudgetPersonnelDetails = (AwardBudgetPersonnelDetailsExt) budgetPersonnelDetails; List<BudgetPersonnelCalculatedAmount> personnelCalcAmounts = awardBudgetPersonnelDetails .getBudgetCalculatedAmounts(); for (BudgetPersonnelCalculatedAmount budgetPersonnelCalculatedAmountExt : personnelCalcAmounts) { AwardBudgetPersonnelCalculatedAmountExt awardBudgetPersonnelCalculatedAmountExt = (AwardBudgetPersonnelCalculatedAmountExt) budgetPersonnelCalculatedAmountExt; awardBudgetPersonnelCalculatedAmountExt .setObligatedAmount(awardBudgetPersonnelCalculatedAmountExt.getObligatedAmount() .add(awardBudgetPersonnelCalculatedAmountExt.getCalculatedCost() .add(awardBudgetPersonnelCalculatedAmountExt .getCalculatedCostSharing()))); awardBudgetPersonnelCalculatedAmountExt.setCalculatedCost(ScaleTwoDecimal.ZERO); awardBudgetPersonnelCalculatedAmountExt.setCalculatedCostSharing(ScaleTwoDecimal.ZERO); } awardBudgetPersonnelDetails.setObligatedAmount( awardBudgetPersonnelDetails.getObligatedAmount().add(awardBudgetPersonnelDetails .getSalaryRequested().add(awardBudgetPersonnelDetails.getCostSharingAmount()))); awardBudgetPersonnelDetails.setPercentCharged(ScaleTwoDecimal.ZERO); awardBudgetPersonnelDetails.setPercentEffort(ScaleTwoDecimal.ZERO); awardBudgetPersonnelDetails.setSalaryRequested(ScaleTwoDecimal.ZERO); awardBudgetPersonnelDetails.setCostSharingAmount(ScaleTwoDecimal.ZERO); } List<BudgetLineItemCalculatedAmount> calcAmounts = awardBudgetLineItem.getBudgetCalculatedAmounts(); for (BudgetLineItemCalculatedAmount budgetLineItemCalculatedAmount : calcAmounts) { AwardBudgetLineItemCalculatedAmountExt awardBudgetLineItemCalculatedAmount = (AwardBudgetLineItemCalculatedAmountExt) budgetLineItemCalculatedAmount; awardBudgetLineItemCalculatedAmount.setObligatedAmount(awardBudgetLineItemCalculatedAmount .getObligatedAmount().add(awardBudgetLineItemCalculatedAmount.getCalculatedCost() .add(awardBudgetLineItemCalculatedAmount.getCalculatedCostSharing()))); awardBudgetLineItemCalculatedAmount.setCalculatedCost(ScaleTwoDecimal.ZERO); awardBudgetLineItemCalculatedAmount.setCalculatedCostSharing(ScaleTwoDecimal.ZERO); } awardBudgetLineItem.setObligatedAmount(awardBudgetLineItem.getObligatedAmount().add( awardBudgetLineItem.getLineItemCost().add(awardBudgetLineItem.getCostSharingAmount()))); awardBudgetLineItem.setLineItemCost(ScaleTwoDecimal.ZERO); awardBudgetLineItem.setCostSharingAmount(ScaleTwoDecimal.ZERO); } awardBudgetPeriod.setObligatedAmount( awardBudgetPeriod.getObligatedAmount().add(awardBudgetPeriod.getTotalCost())); awardBudgetPeriod.setTotalCost(ScaleTwoDecimal.ZERO); awardBudgetPeriod.setTotalDirectCost(ScaleTwoDecimal.ZERO); awardBudgetPeriod.setTotalIndirectCost(ScaleTwoDecimal.ZERO); awardBudgetPeriod.setTotalCostLimit(obligatedChangeAmount); } } protected AwardBudgetExt getLatestPostedBudget(Award award) { QueryList<AwardBudgetExt> budgets = new QueryList<>(); for (AwardBudgetExt budget : award.getBudgets()) { budgets.add(budget); } Equals eqPostedStatus = new Equals(AWARD_BUDGET_STATUS_CODE, getAwardPostedStatusCode()); QueryList<AwardBudgetExt> postedVersions = budgets.filter(eqPostedStatus); if (!postedVersions.isEmpty()) { postedVersions.sort(BUDGET_VERSION_NUMBER, false); return postedVersions.get(0); } return null; } @Override public ScaleTwoDecimal getTotalCostLimit(Award award) { ScaleTwoDecimal obligatedTotal = award.getObligatedDistributableTotal(); ScaleTwoDecimal costLimit = award.getTotalCostBudgetLimit(); ScaleTwoDecimal postedTotalAmount = getPostedTotalAmount(award); if (costLimit == null || costLimit.isGreaterEqual(obligatedTotal)) { return new ScaleTwoDecimal(obligatedTotal.bigDecimalValue()).subtract(postedTotalAmount); } else { return new ScaleTwoDecimal(costLimit.bigDecimalValue()).subtract(postedTotalAmount); } } /** * Gets the total posted amount from previously posted budgets */ protected ScaleTwoDecimal getPostedTotalAmount(Award award) { String postedStatusCode = getAwardPostedStatusCode(); ScaleTwoDecimal postedTotalAmount = ScaleTwoDecimal.ZERO; for (AwardBudgetExt budget : award.getBudgets()) { if (budget.getAwardBudgetStatusCode().equals(postedStatusCode)) { postedTotalAmount = postedTotalAmount.add(budget.getTotalCost()); } } return postedTotalAmount; } /* * A utility method to check whther a budget has been posted for this award, then it can be * used as one of the condition to set rebudget type. */ protected boolean isPostedBudgetExist(Award award) { boolean exist = false; String postedStatusCode = getAwardPostedStatusCode(); for (AwardBudgetExt budget : award.getBudgets()) { if (budget.getAwardBudgetStatusCode().equals(postedStatusCode)) { exist = true; break; } } return exist; } protected String getAwardPostedStatusCode() { return getParameterService().getParameterValueAsString(AwardBudgetDocument.class, KeyConstants.AWARD_BUDGET_STATUS_POSTED); } protected AwardBudgetExt getLastBudgetVersion(Award award) { List<AwardBudgetExt> awardBudgetDocumentVersions = award.getBudgets(); AwardBudgetExt latestBudget = null; int versionSize = awardBudgetDocumentVersions.size(); if (versionSize > 0) { latestBudget = awardBudgetDocumentVersions.get(versionSize - 1); } return latestBudget; } protected AwardBudgetDocument saveBudgetDocument(AwardBudgetDocument awardBudgetDocument, boolean rebudget) throws WorkflowException { AwardBudgetExt budgetExt = awardBudgetDocument.getAwardBudget(); String awardBudgetTypeID = getParameterValue( rebudget ? KeyConstants.AWARD_BUDGET_TYPE_REBUDGET : KeyConstants.AWARD_BUDGET_TYPE_NEW); AwardBudgetType awardBudgetType = getBusinessObjectService().findBySinglePrimaryKey(AwardBudgetType.class, awardBudgetTypeID); budgetExt.setAwardBudgetTypeCode(awardBudgetType.getAwardBudgetTypeCode()); budgetExt.setDescription(awardBudgetType.getDescription()); budgetExt.setAwardBudgetType(awardBudgetType); processStatusChange(awardBudgetDocument, KeyConstants.AWARD_BUDGET_STATUS_IN_PROGRESS); saveDocument(awardBudgetDocument); return awardBudgetDocument; } protected void copyProposalBudgetLineItemsToAwardBudget(BudgetPeriod awardBudgetPeriod, BudgetPeriod proposalBudgetPeriod) { List<BudgetLineItem> awardBudgetLineItems = awardBudgetPeriod.getBudgetLineItems(); List<BudgetLineItem> lineItems = proposalBudgetPeriod.getBudgetLineItems(); for (BudgetLineItem budgetLineItem : lineItems) { String[] ignoreProperties = { BUDGET_ID, BUDGET_LINE_ITEM_ID, BUDGET_PERIOD_ID, SUBMIT_COST_SHARING_FLAG, BUDGET_LINE_ITEM_CALCULATED_AMOUNTS, BUDGET_PERSONNEL_DETAILS_LIST, BUDGET_RATE_AND_BASE_LIST, BUDGET_SUB_AWARD }; AwardBudgetLineItemExt awardBudgetLineItem = new AwardBudgetLineItemExt(); BeanUtils.copyProperties(budgetLineItem, awardBudgetLineItem, ignoreProperties); awardBudgetLineItem.setLineItemNumber( awardBudgetPeriod.getBudget().getNextValue(Constants.BUDGET_LINEITEM_NUMBER)); awardBudgetLineItem.setBudgetId(awardBudgetPeriod.getBudgetId()); awardBudgetLineItem.setStartDate(awardBudgetPeriod.getStartDate()); awardBudgetLineItem.setEndDate(awardBudgetPeriod.getEndDate()); List<BudgetPersonnelDetails> awardBudgetPersonnelLineItems = awardBudgetLineItem .getBudgetPersonnelDetailsList(); List<BudgetPersonnelDetails> budgetPersonnelLineItems = budgetLineItem.getBudgetPersonnelDetailsList(); for (BudgetPersonnelDetails budgetPersonnelDetails : budgetPersonnelLineItems) { budgetPersonnelDetails.setBudgetLineItemId(budgetLineItem.getBudgetLineItemId()); budgetPersonnelDetails.setBudgetLineItem(budgetLineItem); AwardBudgetPersonnelDetailsExt awardBudgetPerDetails = new AwardBudgetPersonnelDetailsExt(); BeanUtils.copyProperties(budgetPersonnelDetails, awardBudgetPerDetails, BUDGET_PERSONNEL_LINE_ITEM_ID, BUDGET_LINE_ITEM_ID, BUDGET_ID, SUBMIT_COST_SHARING_FLAG, BUDGET_PERSONNEL_CALCULATED_AMOUNTS, BUDGET_PERSONNEL_RATE_AND_BASE_LIST, VALID_TO_APPLY_IN_RATE); awardBudgetPerDetails.setPersonNumber( awardBudgetPeriod.getBudget().getNextValue(Constants.BUDGET_PERSON_LINE_NUMBER)); BudgetPerson oldBudgetPerson = budgetPersonnelDetails.getBudgetPerson(); BudgetPerson currentBudgetPerson = findMatchingPersonInBudget(awardBudgetPeriod.getBudget(), oldBudgetPerson, budgetPersonnelDetails.getJobCode()); if (currentBudgetPerson == null) { currentBudgetPerson = new BudgetPerson(); BeanUtils.copyProperties(oldBudgetPerson, currentBudgetPerson, BUDGET_ID, PERSON_SEQUENCE_NUMBER); currentBudgetPerson.setBudgetId(awardBudgetPeriod.getBudgetId()); currentBudgetPerson.setPersonSequenceNumber( awardBudgetPeriod.getBudget().getNextValue(Constants.PERSON_SEQUENCE_NUMBER)); awardBudgetPeriod.getBudget().getBudgetPersons().add(currentBudgetPerson); } awardBudgetPerDetails.setBudgetPerson(currentBudgetPerson); awardBudgetPerDetails.setPersonSequenceNumber(currentBudgetPerson.getPersonSequenceNumber()); awardBudgetPerDetails.setBudget(awardBudgetPeriod.getBudget()); awardBudgetPerDetails.setBudgetId(awardBudgetPeriod.getBudgetId()); awardBudgetPerDetails.setCostElement(awardBudgetLineItem.getCostElement()); awardBudgetPerDetails.setStartDate(awardBudgetLineItem.getStartDate()); awardBudgetPerDetails.setEndDate(awardBudgetLineItem.getEndDate()); awardBudgetPersonnelLineItems.add(awardBudgetPerDetails); } awardBudgetLineItems.add(awardBudgetLineItem); getAwardBudgetCalculationService().populateCalculatedAmount(awardBudgetPeriod.getBudget(), awardBudgetLineItem); } } protected BudgetPerson findMatchingPersonInBudget(Budget budget, BudgetPerson oldBudgetPerson, String jobCode) { for (BudgetPerson budgetPerson : budget.getBudgetPersons()) { if (budgetPerson.isSamePerson(oldBudgetPerson) && StringUtils.equals(budgetPerson.getJobCode(), jobCode)) { return budgetPerson; } } return null; } /** * Copies budget version from previous one */ public AwardBudgetDocument copyBudgetVersion(AwardBudgetDocument budgetDocument) throws WorkflowException { return copyBudgetVersion(budgetDocument, false); } @Override public Budget copyBudgetVersion(Budget budget) { return copyBudgetVersion(budget, false); } public void copyLineItemsFromProposalPeriods(Collection<BudgetPeriod> rawValues, BudgetPeriod awardBudgetPeriod) throws WorkflowException { //calling awardBudgetPeriod.getBudget() will load Budget.class instead of AwardBudgetExt.class //this will cause classcastexceptions later as the budget with that id is technically an AwardBudgetExt //this is all due to an ojb bug. So here we make sure OJB caches the budget as an AwardBudgetExt correctly. AwardBudgetExt budget = getBusinessObjectService().findBySinglePrimaryKey(AwardBudgetExt.class, awardBudgetPeriod.getBudgetId()); awardBudgetPeriod.getBudgetLineItems().clear(); for (BudgetPeriod proposalPeriod : rawValues) { copyProposalBudgetLineItemsToAwardBudget(awardBudgetPeriod, proposalPeriod); } getDocumentService().saveDocument(((AwardBudgetExt) awardBudgetPeriod.getBudget()).getBudgetDocument()); getBudgetSummaryService().calculateBudget(awardBudgetPeriod.getBudget()); } protected <T extends BusinessObject> List<T> findMatching(Class<T> clazz, String key, Object value) { Map<String, Object> fieldValues = new HashMap<>(); fieldValues.put(key, value); return (List<T>) getBusinessObjectService().findMatching(clazz, fieldValues); } @Override public List<BudgetPeriod> findBudgetPeriodsFromLinkedProposal(String awardNumber) { return findBudgetPeriodsFromLinkedProposal(awardService.getActiveOrNewestAward(awardNumber)); } public List<BudgetPeriod> findBudgetPeriodsFromLinkedProposal(Award award) { Set<Long> budgetIdsAdded = new HashSet<>(); List<BudgetPeriod> budgetPeriods = new ArrayList<>(); for (AwardFundingProposal fundingProposal : award.getAllFundingProposals()) { if (fundingProposal.isActive()) { List<InstitutionalProposal> instProposals = findMatching(InstitutionalProposal.class, PROPOSAL_NUMBER, fundingProposal.getProposal().getProposalNumber()); for (InstitutionalProposal instProp : instProposals) { List<ProposalAdminDetails> proposalAdminDetails = findMatching(ProposalAdminDetails.class, INST_PROPOSAL_ID, instProp.getProposalId()); for (ProposalAdminDetails proposalAdminDetail : proposalAdminDetails) { String developmentProposalNumber = proposalAdminDetail.getDevProposalNumber(); DevelopmentProposal proposalDevelopment = getDataObjectService() .find(DevelopmentProposal.class, developmentProposalNumber); ProposalDevelopmentBudgetExt budget = proposalDevelopment.getFinalBudget(); if (!budgetIdsAdded.contains(budget.getBudgetId())) { budgetIdsAdded.add(budget.getBudgetId()); //if this result set is being used by @see org.kuali.kra.lookup.BudgetPeriodLookupableHelperServiceImpl //we need to populate these additional fields so always populate them. for (BudgetPeriod budgetPeriod : budget.getBudgetPeriods()) { budgetPeriod.setInstitutionalProposalNumber(instProp.getProposalNumber()); budgetPeriod.setInstitutionalProposalVersion(instProp.getSequenceNumber()); budgetPeriods.add(budgetPeriod); } } } } } } return budgetPeriods; } public boolean checkForOutstandingBudgets(Award award) { boolean result = false; for (AwardBudgetExt awardBudget : award.getBudgets()) { if (!(StringUtils.equals(awardBudget.getAwardBudgetStatusCode(), getPostedBudgetStatus()) || StringUtils.equals(awardBudget.getAwardBudgetStatusCode(), getRejectedBudgetStatus()) || StringUtils.equals(awardBudget.getAwardBudgetStatusCode(), getCancelledBudgetStatus()))) { result = true; GlobalVariables.getMessageMap().putError(BUDGET_VERSION_ERROR_PREFIX, KeyConstants.ERROR_AWARD_UNFINALIZED_BUDGET_EXISTS, (StringUtils.isBlank(awardBudget.getName()) ? UNNAMED : awardBudget.getName())); } } return result; } @Override public List<String> getInactiveBudgetStatus() { List<String> result = new ArrayList<>(); result.add(getRejectedBudgetStatus()); result.add(getCancelledBudgetStatus()); result.add(getDoNotPostBudgetStatus()); result.add(getDisapprovedBudgetStatus()); return result; } @Override public void populateBudgetLimitSummary(BudgetLimitSummaryHelper summary, Award award) { AwardBudgetExt currentBudget = getCurrentBudget(award); if (summary.getCurrentBudget() == null || !ObjectUtils.equals(summary.getCurrentBudget(), currentBudget)) { getAwardBudgetCalculationService().calculateBudgetSummaryTotals(currentBudget, false); summary.setCurrentBudget(currentBudget); } AwardBudgetExt prevBudget = getPreviousBudget(award); if (summary.getPreviousBudget() == null || !ObjectUtils.equals(summary.getPreviousBudget(), prevBudget)) { getAwardBudgetCalculationService().calculateBudgetSummaryTotals(prevBudget, true); summary.setPreviousBudget(prevBudget); } } /** * Returns the current budget for the award. Must be inprogress, submitted or to be posted * to be the current budget. */ protected AwardBudgetExt getCurrentBudget(Award award) { return getNewestBudgetByStatus(award, Arrays.asList(Constants.BUDGET_STATUS_CODE_IN_PROGRESS, Constants.BUDGET_STATUS_CODE_SUBMITTED, Constants.BUDGET_STATUS_CODE_TO_BE_POSTED)); } /** * Returns the previous budget for this award document which will be the newest posted budget */ protected AwardBudgetExt getPreviousBudget(Award award) { return getNewestBudgetByStatus(award, Arrays.asList(getPostedBudgetStatus())); } protected AwardBudgetExt getNewestBudgetByStatus(Award award, List<String> statuses) { AwardBudgetExt result = null; for (AwardBudgetExt version : award.getBudgets()) { if (statuses.contains(version.getAwardBudgetStatusCode())) { if (result == null || version.getBudgetVersionNumber() > result.getBudgetVersionNumber()) { result = version; } } } if (result == null) { result = new AwardBudgetExt(); } return result; } public List<AwardBudgetExt> getAllBudgetsForAward(Award award) { HashSet<AwardBudgetExt> result = new HashSet<>(); List<VersionHistory> versions = getVersionHistoryService().loadVersionHistory(Award.class, award.getAwardNumber()); for (VersionHistory version : versions) { if (version.getSequenceOwnerSequenceNumber() <= award.getSequenceNumber() && !(version.getSequenceOwner() == null) && !(((Award) version.getSequenceOwner()).getAwardDocument() == null)) { result.addAll(((Award) version.getSequenceOwner()).getCurrentVersionBudgets()); } } List<AwardBudgetExt> listResult = new ArrayList<>(result); Collections.sort(listResult); return listResult; } public Award getActiveOrNewestAward(String awardNumber) { return awardService.getActiveOrNewestAward(awardNumber); } protected String getPostedBudgetStatus() { return getParameterValue(KeyConstants.AWARD_BUDGET_STATUS_POSTED); } protected String getRejectedBudgetStatus() { return getParameterValue(KeyConstants.AWARD_BUDGET_STATUS_REJECTED); } protected String getCancelledBudgetStatus() { return Constants.BUDGET_STATUS_CODE_CANCELLED; } protected String getDisapprovedBudgetStatus() { return Constants.BUDGET_STATUS_CODE_DISAPPROVED; } protected String getDoNotPostBudgetStatus() { return getParameterValue(KeyConstants.AWARD_BUDGET_STATUS_DO_NOT_POST); } public boolean isRateOverridden(BudgetPeriod budgetPeriod) { return ((AwardBudgetPeriodExt) budgetPeriod).getRateOverrideFlag(); } private ScaleTwoDecimal getPeriodFringeTotal(BudgetPeriod budgetPeriod, Budget budget) { if (budget == null || budget.getBudgetSummaryTotals() == null || budget.getBudgetSummaryTotals().get(PERSONNEL_FRINGE_TOTALS) == null || budgetPeriod == null || !CollectionUtils.validIndexForList(budgetPeriod.getBudgetPeriod() - 1, budget.getBudgetSummaryTotals().get(PERSONNEL_FRINGE_TOTALS))) { return ScaleTwoDecimal.ZERO; } return budget.getBudgetSummaryTotals().get(PERSONNEL_FRINGE_TOTALS).get(budgetPeriod.getBudgetPeriod() - 1); } public void recalculateBudget(Budget budget) { List<BudgetPeriod> awardBudgetPeriods = budget.getBudgetPeriods(); for (BudgetPeriod budgetPeriod : awardBudgetPeriods) { removeBudgetSummaryPeriodCalcAmounts(budgetPeriod); } awardBudgetCalculationService.calculateBudget(budget); awardBudgetCalculationService.calculateBudgetSummaryTotals(budget); } public void recalculateBudgetPeriod(Budget budget, BudgetPeriod budgetPeriod) { removeBudgetSummaryPeriodCalcAmounts(budgetPeriod); awardBudgetCalculationService.calculateBudgetPeriod(budget, budgetPeriod); } public void calculateBudgetOnSave(Budget budget) { awardBudgetCalculationService.calculateBudget(budget); awardBudgetCalculationService.calculateBudgetSummaryTotals(budget); List<BudgetPeriod> awardBudgetPeriods = budget.getBudgetPeriods(); for (BudgetPeriod awardBudgetPeriod : awardBudgetPeriods) { AwardBudgetPeriodExt budgetPeriod = (AwardBudgetPeriodExt) awardBudgetPeriod; ScaleTwoDecimal periodFringeTotal = getPeriodFringeTotal(budgetPeriod, budget); ScaleTwoDecimal totalFringeAmount = budgetPeriod.getTotalFringeAmount(); ScaleTwoDecimal fringeAmountDiff = totalFringeAmount.subtract(periodFringeTotal); ScaleTwoDecimal totalDirect = budgetPeriod.getTotalDirectCost().add(fringeAmountDiff); if (!totalDirect.equals(budgetPeriod.getTotalDirectCost())) { budgetPeriod.setTotalDirectCost(totalDirect); } budgetPeriod.setTotalCost(budgetPeriod.getTotalDirectCost().add(budgetPeriod.getTotalIndirectCost())); } setBudgetCostsFromPeriods(budget); } public void populateSummaryCalcAmounts(Budget budget, BudgetPeriod budgetPeriod) { AwardBudgetPeriodExt awardBudgetPeriod = (AwardBudgetPeriodExt) budgetPeriod; List<AwardBudgetPeriodSummaryCalculatedAmount> awardBudgetPeriodFringeAmounts = awardBudgetPeriod .getAwardBudgetPeriodFringeAmounts(); awardBudgetPeriodFringeAmounts.clear(); if (awardBudgetPeriodFringeAmounts.isEmpty()) { Map<String, List<ScaleTwoDecimal>> objectCodePersonnelFringe = budget .getObjectCodePersonnelFringeTotals(); if (objectCodePersonnelFringe != null) { for (String costElement : objectCodePersonnelFringe.keySet()) { String[] costElementAndPersonId = costElement.split(","); List<ScaleTwoDecimal> fringeTotals = objectCodePersonnelFringe.get(costElement); AwardBudgetPeriodSummaryCalculatedAmount oldAwardBudgetPeriodSummaryCalculatedAmount = getSummaryCalculatedAmountFromList( awardBudgetPeriodFringeAmounts, costElementAndPersonId[0]); if (oldAwardBudgetPeriodSummaryCalculatedAmount == null) { AwardBudgetPeriodSummaryCalculatedAmount awardBudgetPeriodSummaryCalculatedAmount = createNewAwardBudgetPeriodSummaryCalculatedAmount( awardBudgetPeriod, costElementAndPersonId[0], RateClassType.EMPLOYEE_BENEFITS.getRateClassType(), fringeTotals.get(budgetPeriod.getBudgetPeriod() - 1)); awardBudgetPeriodFringeAmounts.add(awardBudgetPeriodSummaryCalculatedAmount); } else { oldAwardBudgetPeriodSummaryCalculatedAmount .setCalculatedCost(oldAwardBudgetPeriodSummaryCalculatedAmount.getCalculatedCost() .add(fringeTotals.get(budgetPeriod.getBudgetPeriod() - 1))); } } } QueryList<AwardBudgetPeriodSummaryCalculatedAmount> ebCalculatedAmounts = filterEBRates( awardBudgetPeriod); awardBudgetPeriod.setTotalFringeAmount(ebCalculatedAmounts.sumObjects(CALCULATED_COST)); } } private AwardBudgetPeriodSummaryCalculatedAmount getSummaryCalculatedAmountFromList( List<AwardBudgetPeriodSummaryCalculatedAmount> awardBudgetPeriodFringeAmounts, String costElement) { for (AwardBudgetPeriodSummaryCalculatedAmount awardBudgetPeriodSummaryCalculatedAmount : awardBudgetPeriodFringeAmounts) { if (awardBudgetPeriodSummaryCalculatedAmount.getCostElement().equals(costElement)) { return awardBudgetPeriodSummaryCalculatedAmount; } } return null; } /** * This method returns the query list after filtering all eb rates. */ private QueryList<AwardBudgetPeriodSummaryCalculatedAmount> filterEBRates(AwardBudgetPeriodExt budgetPeriod) { QueryList<AwardBudgetPeriodSummaryCalculatedAmount> qlAwardBudgetPeriodSummaryCalculatedAmounts = new QueryList<>( budgetPeriod.getAwardBudgetPeriodFringeAmounts()); Equals ebClassType = new Equals(RATE_CLASS_TYPE, RateClassType.EMPLOYEE_BENEFITS.getRateClassType()); return qlAwardBudgetPeriodSummaryCalculatedAmounts.filter(ebClassType); } private AwardBudgetPeriodSummaryCalculatedAmount createNewAwardBudgetPeriodSummaryCalculatedAmount( AwardBudgetPeriodExt budgetPeriodExt, String costElement, String rateClassType, ScaleTwoDecimal calculatedCost) { AwardBudgetPeriodSummaryCalculatedAmount awardBudgetPeriodSummaryCalculatedAmount = new AwardBudgetPeriodSummaryCalculatedAmount(); awardBudgetPeriodSummaryCalculatedAmount.setBudgetPeriodId(budgetPeriodExt.getBudgetPeriodId()); awardBudgetPeriodSummaryCalculatedAmount.setCalculatedCost(calculatedCost); awardBudgetPeriodSummaryCalculatedAmount.setCostElement(costElement); awardBudgetPeriodSummaryCalculatedAmount.setRateClassType(rateClassType); return awardBudgetPeriodSummaryCalculatedAmount; } /** * * 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()); } public void removeBudgetSummaryPeriodCalcAmounts(BudgetPeriod budgetPeriod) { AwardBudgetPeriodExt awardBudgetPeriod = (AwardBudgetPeriodExt) budgetPeriod; awardBudgetPeriod.setTotalFringeAmount(null); awardBudgetPeriod.getAwardBudgetPeriodFringeAmounts().clear(); awardBudgetPeriod.getAwardBudgetPeriodFnAAmounts().clear(); awardBudgetPeriod.setRateOverrideFlag(false); } @Override public boolean validateAddingNewBudget(BudgetParentDocument<Award> parentDocument) { AwardDocument awardDocument = (AwardDocument) parentDocument; return !checkForOutstandingBudgets(awardDocument.getAward()); } @Override public boolean checkRateChange(Collection<BudgetRate> savedBudgetRates, Award award) { award.refreshReferenceObject(AWARD_FANDA_RATE); List<AwardFandaRate> awardFandaRates = award.getAwardFandaRate(); boolean changeFlag = false; for (AwardFandaRate budgetFnARate : awardFandaRates) { RateType fnaRateType = budgetFnARate.getFandaRateType(); Equals eqRateClasCode = new Equals(RATE_CLASS_CODE, fnaRateType.getRateClassCode()); Equals eqRateTypeCode = new Equals(RATE_TYPE_CODE, fnaRateType.getRateTypeCode()); Equals eqCampusFlag = new Equals(ON_OFF_CAMPUS_FLAG, budgetFnARate.getOnOffCampusFlag()); And rateClassAndRateType = new And(eqRateClasCode, eqRateTypeCode); And rateClassAndRateTypeAndCampusFlag = new And(rateClassAndRateType, eqCampusFlag); QueryList<BudgetRate> matchAwardFnARate = new QueryList<>(savedBudgetRates) .filter(rateClassAndRateTypeAndCampusFlag); if (matchAwardFnARate.isEmpty() || matchAwardFnARate.size() > 1 || !matchAwardFnARate.get(0) .getApplicableRate().equals(budgetFnARate.getApplicableFandaRate())) { changeFlag = true; } } Equals eqRateClasCode = new Equals(RATE_CLASS_CODE, getBudgetParameterValue(Constants.AWARD_BUDGET_EB_RATE_CLASS_CODE)); Equals eqRateTypeCode = new Equals(RATE_TYPE_CODE, getBudgetParameterValue(Constants.AWARD_BUDGET_EB_RATE_TYPE_CODE)); And rateClassAndRateType = new And(eqRateClasCode, eqRateTypeCode); QueryList<BudgetRate> matchAwardEBCampusRates = new QueryList<>(savedBudgetRates) .filter(rateClassAndRateType); for (BudgetRate budgetEBRate : matchAwardEBCampusRates) { if (budgetEBRate.getOnOffCampusFlag()) { if (award.getSpecialEbRateOnCampus() != null && !award.getSpecialEbRateOnCampus().equals(budgetEBRate.getApplicableRate())) { changeFlag = true; } } else { if (award.getSpecialEbRateOffCampus() != null && !award.getSpecialEbRateOffCampus().equals(budgetEBRate.getApplicableRate())) { changeFlag = true; } } } if ((award.getSpecialEbRateOnCampus() != null || award.getSpecialEbRateOffCampus() != null) && matchAwardEBCampusRates.isEmpty()) { changeFlag = true; } return changeFlag; } @Override public boolean isBudgetVersionNameValid(BudgetParent parent, String name) { try { return getAddBudgetVersionRule() .processAddBudgetVersion(new AddBudgetVersionEvent(BUDGET_VERSION_ERROR_PREFIX, parent, name)); } catch (WorkflowException e) { LOG.error(e); return false; } } public BudgetVersionRule getAddBudgetVersionRule() { if (addBudgetVersionRule == null) { addBudgetVersionRule = new AwardBudgetVersionRule(); } return addBudgetVersionRule; } public void setAddBudgetVersionRule(BudgetVersionRule addBudgetVersionRule) { this.addBudgetVersionRule = addBudgetVersionRule; } @Override public void populateNewBudgetLineItem(BudgetLineItem newBudgetLineItem, BudgetPeriod budgetPeriod) { Budget budget = budgetPeriod.getBudget(); newBudgetLineItem.setBudgetPeriod(budgetPeriod.getBudgetPeriod()); newBudgetLineItem.setBudgetPeriodBO(budgetPeriod); newBudgetLineItem.setBudgetPeriodId(budgetPeriod.getBudgetPeriodId()); newBudgetLineItem.setStartDate(budgetPeriod.getStartDate()); newBudgetLineItem.setEndDate(budgetPeriod.getEndDate()); newBudgetLineItem.setBudgetId(budget.getBudgetId()); newBudgetLineItem.setLineItemNumber(budget.getNextValue(Constants.BUDGET_LINEITEM_NUMBER)); newBudgetLineItem.setApplyInRateFlag(true); newBudgetLineItem.setSubmitCostSharingFlag(budget.getSubmitCostSharingFlag()); refreshBudgetLineCostElement(newBudgetLineItem); // on/off campus flag enhancement String onOffCampusFlag = budget.getOnOffCampusFlag(); if (onOffCampusFlag.equalsIgnoreCase(BudgetConstants.DEFAULT_CAMPUS_FLAG)) { newBudgetLineItem.setOnOffCampusFlag(newBudgetLineItem.getCostElementBO().getOnOffCampusFlag()); } else { newBudgetLineItem.setOnOffCampusFlag(onOffCampusFlag.equalsIgnoreCase(Constants.ON_CAMUS_FLAG)); } newBudgetLineItem.setBudgetCategoryCode(newBudgetLineItem.getCostElementBO().getBudgetCategoryCode()); newBudgetLineItem.setLineItemSequence(newBudgetLineItem.getLineItemNumber()); refreshBudgetLineBudgetCategory(newBudgetLineItem); if (isBudgetFormulatedCostEnabled()) { List<String> formulatedCostElements = getFormulatedCostElements(); if (formulatedCostElements.contains(newBudgetLineItem.getCostElement())) { newBudgetLineItem.setFormulatedCostElementFlag(true); } } } protected void refreshBudgetLineCostElement(BudgetLineItem newBudgetLineItem) { if (StringUtils.isNotEmpty(newBudgetLineItem.getCostElement())) { getLegacyDataAdapter().refreshReferenceObject(newBudgetLineItem, COST_ELEMENT_BO); } } protected void refreshBudgetLineBudgetCategory(BudgetLineItem newBudgetLineItem) { if (StringUtils.isNotEmpty(newBudgetLineItem.getBudgetCategoryCode())) { getLegacyDataAdapter().refreshReferenceObject(newBudgetLineItem, BUDGET_CATEGORY); } } protected VersionHistoryService getVersionHistoryService() { return versionHistoryService; } public void setVersionHistoryService(VersionHistoryService versionHistoryService) { this.versionHistoryService = versionHistoryService; } protected AwardBudgetCalculationService getAwardBudgetCalculationService() { return awardBudgetCalculationService; } public void setAwardBudgetCalculationService(AwardBudgetCalculationService awardBudgetCalculationService) { this.awardBudgetCalculationService = awardBudgetCalculationService; } protected AwardService getAwardService() { return awardService; } public void setAwardService(AwardService awardService) { this.awardService = awardService; } public DocumentService getDocumentService() { return documentService; } public void setDocumentService(DocumentService documentService) { this.documentService = documentService; } public BudgetSummaryService getBudgetSummaryService() { return budgetSummaryService; } public void setBudgetSummaryService(BudgetSummaryService budgetSummaryService) { this.budgetSummaryService = budgetSummaryService; } public DataObjectService getDataObjectService() { return dataObjectService; } public void setDataObjectService(DataObjectService dataObjectService) { this.dataObjectService = dataObjectService; } public LegacyDataAdapter getLegacyDataAdapter() { return legacyDataAdapter; } public void setLegacyDataAdapter(LegacyDataAdapter legacyDataAdapter) { this.legacyDataAdapter = legacyDataAdapter; } }