/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * 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.kfs.module.bc.document.service.impl; import static org.kuali.kfs.module.bc.BCConstants.AppointmentFundingDurationCodes.NONE; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.integration.ld.LaborLedgerObject; import org.kuali.kfs.integration.ld.LaborModuleService; import org.kuali.kfs.module.bc.BCConstants; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAppointmentFundingReason; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAppointmentFundingReasonCode; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionCalculatedSalaryFoundationTracker; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition; import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding; import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger; import org.kuali.kfs.module.bc.businessobject.SalarySettingExpansion; import org.kuali.kfs.module.bc.document.BudgetConstructionDocument; import org.kuali.kfs.module.bc.document.service.BenefitsCalculationService; import org.kuali.kfs.module.bc.document.service.BudgetConstructionProcessorService; import org.kuali.kfs.module.bc.document.service.BudgetDocumentService; import org.kuali.kfs.module.bc.document.service.LockService; import org.kuali.kfs.module.bc.document.service.SalarySettingService; import org.kuali.kfs.module.bc.util.BudgetParameterFinder; import org.kuali.kfs.module.bc.util.SalarySettingCalculator; import org.kuali.kfs.module.bc.util.SalarySettingFieldsHolder; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.ObjectUtil; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.service.OptionsService; import org.kuali.rice.core.api.config.property.ConfigurationService; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.core.api.util.type.KualiInteger; import org.kuali.rice.kew.api.exception.WorkflowException; import org.kuali.rice.kim.api.identity.Person; import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer; import org.kuali.rice.kns.service.DocumentHelperService; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.service.DocumentService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; import org.springframework.transaction.annotation.Transactional; /** * implements the service methods defined in the SalarySettingService * * @see org.kuali.kfs.module.bc.document.service.SalarySettingService */ @Transactional public class SalarySettingServiceImpl implements SalarySettingService { private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SalarySettingServiceImpl.class); protected ConfigurationService kualiConfigurationService; protected BusinessObjectService businessObjectService; protected LaborModuleService laborModuleService; protected BudgetDocumentService budgetDocumentService; protected BenefitsCalculationService benefitsCalculationService; protected OptionsService optionsService; protected LockService lockService; protected DocumentHelperService documentHelperService; protected DocumentService documentService; protected BudgetConstructionProcessorService budgetConstructionProcessorService; /** * for now just return false, implement application parameter if decision is made implement this functionality * * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#isSalarySettingDisabled() */ public boolean isSalarySettingDisabled() { return false; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#calculateHourlyPayRate(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public BigDecimal calculateHourlyPayRate(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("calculateHourlyPayRate() start"); KualiInteger requestedAmount = appointmentFunding.getAppointmentRequestedAmount(); BigDecimal fteQuantity = this.calculateFteQuantityFromAppointmentFunding(appointmentFunding); BigDecimal annualWorkingHours = BigDecimal.valueOf(BudgetParameterFinder.getAnnualWorkingHours()); BigDecimal totalPayHoursForYear = fteQuantity.multiply(annualWorkingHours); BigDecimal hourlyPayRate = BigDecimal.ZERO; if (totalPayHoursForYear.compareTo(BigDecimal.ZERO) != 0) { hourlyPayRate = requestedAmount.divide(totalPayHoursForYear).setScale(2, BigDecimal.ROUND_HALF_UP); } return hourlyPayRate; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#calculateAnnualPayAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public KualiInteger calculateAnnualPayAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("calculateAnnualPayAmount() start"); KualiInteger annualPayAmount = KualiInteger.ZERO; BigDecimal hourlyPayRate = appointmentFunding.getAppointmentRequestedPayRate(); BigDecimal fteQuantity = this.calculateFteQuantityFromAppointmentFunding(appointmentFunding); if (fteQuantity.compareTo(BigDecimal.ZERO) == 0){ // revert to entered amount for zero FTE to allow error message annualPayAmount = appointmentFunding.getAppointmentRequestedAmount(); } else { BigDecimal annualWorkingHours = BigDecimal.valueOf(BudgetParameterFinder.getAnnualWorkingHours()); BigDecimal totalPayHoursForYear = fteQuantity.multiply(annualWorkingHours); annualPayAmount = new KualiInteger(hourlyPayRate.multiply(totalPayHoursForYear)); } return annualPayAmount; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#normalizePayRateAndAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void normalizePayRateAndAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("normalizePayRateAndAmount() start"); BigDecimal currentHourlyPayRate = appointmentFunding.getAppointmentRequestedPayRate(); if (currentHourlyPayRate != null && !currentHourlyPayRate.equals(BigDecimal.ZERO)) { KualiInteger annualPayAmount = this.calculateAnnualPayAmount(appointmentFunding); appointmentFunding.setAppointmentRequestedAmount(annualPayAmount); } else { KualiInteger currentAnnualPayAmount = appointmentFunding.getAppointmentRequestedAmount(); if (currentAnnualPayAmount != null && currentAnnualPayAmount.isNonZero()) { BigDecimal hourlyPayRate = this.calculateHourlyPayRate(appointmentFunding); appointmentFunding.setAppointmentRequestedPayRate(hourlyPayRate); } currentHourlyPayRate = appointmentFunding.getAppointmentRequestedPayRate(); if (currentHourlyPayRate != null) { KualiInteger annualPayAmount = this.calculateAnnualPayAmount(appointmentFunding); appointmentFunding.setAppointmentRequestedAmount(annualPayAmount); } else { appointmentFunding.setAppointmentRequestedPayRate(BigDecimal.ZERO); } } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#calculateFteQuantityForAppointmentFunding(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public BigDecimal calculateFteQuantityFromAppointmentFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("calculateFteQuantity() start"); // appointmentFunding.refreshReferenceObject(BCPropertyConstants.BUDGET_CONSTRUCTION_POSITION); BudgetConstructionPosition position = appointmentFunding.getBudgetConstructionPosition(); if (ObjectUtils.isNull(position)) { return BigDecimal.ZERO; } Integer payMonth = position.getIuPayMonths(); Integer fundingMonth = appointmentFunding.getAppointmentFundingMonth(); BigDecimal requestedTimePercent = appointmentFunding.getAppointmentRequestedTimePercent(); return this.calculateFteQuantity(payMonth, fundingMonth, requestedTimePercent); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#calculateFteQuantity(java.lang.Integer, java.lang.Integer, * java.math.BigDecimal) */ public BigDecimal calculateFteQuantity(Integer payMonth, Integer fundingMonth, BigDecimal requestedTimePercent) { LOG.debug("calculateFteQuantity() start"); if (payMonth == null || fundingMonth == null || requestedTimePercent == null) { return BigDecimal.ZERO; } BigDecimal payMonthAsDecimal = BigDecimal.valueOf(payMonth); BigDecimal fundingMonthAsDecimal = BigDecimal.valueOf(fundingMonth); BigDecimal fundingMonthPercent = fundingMonthAsDecimal.divide(payMonthAsDecimal, 5, BigDecimal.ROUND_HALF_UP); BigDecimal fteQuantity = requestedTimePercent.multiply(fundingMonthPercent).divide(KFSConstants.ONE_HUNDRED.bigDecimalValue()); return fteQuantity.setScale(5, BigDecimal.ROUND_HALF_UP); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#calculateCSFFteQuantityFromAppointmentFunding(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public BigDecimal calculateCSFFteQuantityFromAppointmentFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("calculateCSFFteQuantity() start"); // appointmentFunding.refreshReferenceObject(BCPropertyConstants.BUDGET_CONSTRUCTION_POSITION); BudgetConstructionPosition position = appointmentFunding.getBudgetConstructionPosition(); if (position == null) { return BigDecimal.ZERO; } Integer payMonth = position.getIuPayMonths(); Integer normalWorkMonth = position.getIuNormalWorkMonths(); BigDecimal requestedCSFTimePercent = appointmentFunding.getAppointmentRequestedCsfTimePercent(); return this.calculateCSFFteQuantity(payMonth, normalWorkMonth, requestedCSFTimePercent); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#calculateCSFFteQuantity(java.lang.Integer, * java.lang.Integer, java.math.BigDecimal) */ public BigDecimal calculateCSFFteQuantity(Integer payMonth, Integer normalWorkMonth, BigDecimal requestedCSFTimePercent) { LOG.debug("calculateCSFFteQuantity() start"); if (payMonth == null || normalWorkMonth == null || requestedCSFTimePercent == null) { return BigDecimal.ZERO; } BigDecimal payMonthAsDecimal = BigDecimal.valueOf(payMonth); BigDecimal normalMonthAsDecimal = BigDecimal.valueOf(normalWorkMonth); BigDecimal fundingMonthPercent = normalMonthAsDecimal.divide(payMonthAsDecimal, 5, BigDecimal.ROUND_HALF_UP); BigDecimal fteQuantity = requestedCSFTimePercent.multiply(fundingMonthPercent).divide(KFSConstants.ONE_HUNDRED.bigDecimalValue()); return fteQuantity.setScale(5, BigDecimal.ROUND_HALF_UP); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#isHourlyPaid(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger) */ public boolean isHourlyPaid(PendingBudgetConstructionGeneralLedger pendingBudgetConstructionGeneralLedger) { LOG.debug("isHourlyPaid() start"); Integer fiscalYear = pendingBudgetConstructionGeneralLedger.getUniversityFiscalYear(); String chartOfAccountsCode = pendingBudgetConstructionGeneralLedger.getChartOfAccountsCode(); String objectCode = pendingBudgetConstructionGeneralLedger.getFinancialObjectCode(); return this.isHourlyPaidObject(fiscalYear, chartOfAccountsCode, objectCode); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#isHourlyPaid(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public boolean isHourlyPaid(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("isHourlyPaid() start"); Integer fiscalYear = appointmentFunding.getUniversityFiscalYear(); String chartOfAccountsCode = appointmentFunding.getChartOfAccountsCode(); String objectCode = appointmentFunding.getFinancialObjectCode(); return this.isHourlyPaidObject(fiscalYear, chartOfAccountsCode, objectCode); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#isHourlyPaid(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger) */ public boolean isHourlyPaidObject(Integer fiscalYear, String chartOfAccountsCode, String objectCode) { LOG.debug("isHourlyPaid() start"); LaborLedgerObject laborLedgerObject = laborModuleService.retrieveLaborLedgerObject(fiscalYear, chartOfAccountsCode, objectCode); if (laborLedgerObject == null) { return false; } return BudgetParameterFinder.getBiweeklyPayTypeCodes().contains(laborLedgerObject.getFinancialObjectPayTypeCode()); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#canBeVacant(java.util.List, * org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public boolean canBeVacant(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("canBeVacant(List, PendingBudgetConstructionAppointmentFunding) start"); if (!this.canBeVacant(appointmentFunding)) { return false; } return this.findVacantAppointmentFunding(appointmentFundings, appointmentFunding) == null; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#findVacantAppointmentFunding(java.util.List, * org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public PendingBudgetConstructionAppointmentFunding findVacantAppointmentFunding(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("findVacantAppointmentFunding() start"); PendingBudgetConstructionAppointmentFunding vacantAppointmentFunding = this.createVacantAppointmentFunding(appointmentFunding); return this.findAppointmentFunding(appointmentFundings, vacantAppointmentFunding); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#findAppointmentFunding(java.util.List, * org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public PendingBudgetConstructionAppointmentFunding findAppointmentFunding(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("findAppointmentFunding() start"); Map<String, Object> keyFieldValues = appointmentFunding.getValuesMap(); List<String> keyFields = new ArrayList<String>(); keyFields.addAll(keyFieldValues.keySet()); // determine whether there is vacant for the given appointment funding in its list for (PendingBudgetConstructionAppointmentFunding fundingLine : appointmentFundings) { if (ObjectUtil.equals(fundingLine, appointmentFunding, keyFields)) { return fundingLine; } } return null; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#canBeVacant(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public boolean canBeVacant(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("canBeVacant() start"); if (appointmentFunding.isNewLineIndicator()) { return false; } // the given funding line has not been deleted if (appointmentFunding.isAppointmentFundingDeleteIndicator()) { return false; } // the given funding line cannot be a vacant line String emplid = appointmentFunding.getEmplid(); if (BCConstants.VACANT_EMPLID.equals(emplid)) { return false; } // check if the associated position is valid and active BudgetConstructionPosition position = appointmentFunding.getBudgetConstructionPosition(); if (position == null || !position.isBudgetedPosition() || !position.isEffective()) { return false; } // check if there is an existing vacant appintment funcding for the given funding line boolean hasBeenVacated = this.hasBeenVacated(appointmentFunding); if (hasBeenVacated) { return false; } return true; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#vacateAppointmentFunding(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public PendingBudgetConstructionAppointmentFunding vacateAppointmentFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("vacateAppointmentFunding() start"); PendingBudgetConstructionAppointmentFunding vacantAppointmentFunding = this.createVacantAppointmentFunding(appointmentFunding); this.markAsDelete(appointmentFunding); return vacantAppointmentFunding; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#vacateAppointmentFunding(java.util.List, * org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public PendingBudgetConstructionAppointmentFunding vacateAppointmentFunding(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, PendingBudgetConstructionAppointmentFunding appointmentFunding) { PendingBudgetConstructionAppointmentFunding vacantAppointmentFunding = this.vacateAppointmentFunding(appointmentFunding); if (vacantAppointmentFunding != null) { appointmentFundings.add(vacantAppointmentFunding); } return vacantAppointmentFunding; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#purgeAppointmentFundings(java.util.List) */ public void purgeAppointmentFundings(List<PendingBudgetConstructionAppointmentFunding> purgedAppointmentFundings) { // remove the purged appointment funding lines and their referenced records for (PendingBudgetConstructionAppointmentFunding appointmentFunding : purgedAppointmentFundings) { if (!appointmentFunding.isNewLineIndicator()) { businessObjectService.delete(appointmentFunding); } } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#adjustRequestedSalaryByAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void adjustRequestedSalaryByAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("adjustRequestedSalaryByAmount() start"); int inputAdjustmentAmount = appointmentFunding.getAdjustmentAmount().intValue(); KualiInteger adjustmentAmount = new KualiInteger(inputAdjustmentAmount); KualiInteger csfAmount = this.getCsfAmount(appointmentFunding); KualiInteger appointmentRequestedAmount = csfAmount.add(adjustmentAmount); appointmentFunding.setAppointmentRequestedAmount(appointmentRequestedAmount); if (appointmentFunding.isHourlyPaid()) { appointmentFunding.setAppointmentRequestedPayRate(BigDecimal.ZERO); this.normalizePayRateAndAmount(appointmentFunding); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#adjustRequestedSalaryByPercent(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void adjustRequestedSalaryByPercent(PendingBudgetConstructionAppointmentFunding appointmentFunding) { LOG.debug("adjustRequestedSalaryByPercent() start"); KualiInteger csfAmount = this.getCsfAmount(appointmentFunding); if (csfAmount.isNonZero()) { KualiDecimal percent = appointmentFunding.getAdjustmentAmount(); BigDecimal adjustedAmount = csfAmount.multiply(percent).divide(KFSConstants.ONE_HUNDRED); KualiInteger appointmentRequestedAmount = new KualiInteger(adjustedAmount).add(csfAmount); appointmentFunding.setAppointmentRequestedAmount(appointmentRequestedAmount); } if (appointmentFunding.isHourlyPaid()) { appointmentFunding.setAppointmentRequestedPayRate(BigDecimal.ZERO); this.normalizePayRateAndAmount(appointmentFunding); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#saveSalarySetting(org.kuali.kfs.module.bc.businessobject.SalarySettingExpansion) */ public void saveSalarySetting(SalarySettingExpansion salarySettingExpansion) { LOG.debug("saveSalarySetting() start"); List<PendingBudgetConstructionAppointmentFunding> appointmentFundings = salarySettingExpansion.getPendingBudgetConstructionAppointmentFunding(); this.resetDeletedFundingLines(appointmentFundings); this.updateAppointmentFundingsBeforeSaving(appointmentFundings); KualiInteger requestedAmountTotal = SalarySettingCalculator.getAppointmentRequestedAmountTotal(appointmentFundings); KualiInteger changes = KualiInteger.ZERO; if (requestedAmountTotal != null) { KualiInteger annualBalanceAmount = salarySettingExpansion.getAccountLineAnnualBalanceAmount(); changes = (annualBalanceAmount != null) ? requestedAmountTotal.subtract(annualBalanceAmount) : requestedAmountTotal; } salarySettingExpansion.setAccountLineAnnualBalanceAmount(requestedAmountTotal); businessObjectService.save(salarySettingExpansion); // now create a pseudo funding line if the BCAF list is empty so we can pass it to create 2PLG below Boolean wasSalarySettingExpansionBCAFEmpty = salarySettingExpansion.getPendingBudgetConstructionAppointmentFunding().isEmpty(); if (wasSalarySettingExpansionBCAFEmpty) { appointmentFundings.add(this.createPseudoAppointmentFundingLine(salarySettingExpansion)); } // update or create plug line if the total amount has been changed if (changes.isNonZero()) { budgetDocumentService.updatePendingBudgetGeneralLedgerPlug(appointmentFundings.get(0), changes.negated()); } } public void savePBGLSalarySetting(SalarySettingExpansion salarySettingExpansion) { LOG.debug("savePBGLSalarySetting() start"); // gwp - added this method to handle detail salary setting PBGL updates // instead of using saveSalarySetting(SalarySettingExpansion salarySettingExpansion) List<PendingBudgetConstructionAppointmentFunding> appointmentFundings = salarySettingExpansion.getPendingBudgetConstructionAppointmentFunding(); // this is already done in saveSalarySetting by a call to saveAppointmentFundings // this.resetDeletedFundingLines(appointmentFundings); // this.updateAppointmentFundingsBeforeSaving(appointmentFundings); KualiInteger requestedAmountTotal = SalarySettingCalculator.getAppointmentRequestedAmountTotal(appointmentFundings); KualiInteger changes = KualiInteger.ZERO; if (requestedAmountTotal != null) { KualiInteger annualBalanceAmount = salarySettingExpansion.getAccountLineAnnualBalanceAmount(); changes = (annualBalanceAmount != null) ? requestedAmountTotal.subtract(annualBalanceAmount) : requestedAmountTotal; } // salarySettingExpansion.setAccountLineAnnualBalanceAmount(requestedAmountTotal); // businessObjectService.save(salarySettingExpansion); // now create a pseudo funding line if the BCAF list is empty so we can pass it to create 2PLG below Boolean wasSalarySettingExpansionBCAFEmpty = salarySettingExpansion.getPendingBudgetConstructionAppointmentFunding().isEmpty(); if (wasSalarySettingExpansionBCAFEmpty) { appointmentFundings.add(this.createPseudoAppointmentFundingLine(salarySettingExpansion)); } // For detail salary setting, we need to update existing or create new PBGL row for the BCAF set // We can't save salarySettingExpansion here since it will also save the associated BCAF rows // which in this case would be rows we might not have worked on. // Also, don't save PBGL if it is not in DB already and the BCAF set was empty (no doo doo). // that is, save if PBGL exists in DB or BCAF was not empty if (salarySettingExpansion.getVersionNumber() != null || !wasSalarySettingExpansionBCAFEmpty) { budgetDocumentService.updatePendingBudgetGeneralLedger(appointmentFundings.get(0), changes); } // update or create plug line if the total amount has been changed if (changes.isNonZero()) { budgetDocumentService.updatePendingBudgetGeneralLedgerPlug(appointmentFundings.get(0), changes.negated()); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#saveSalarySetting(java.util.List) */ public void saveSalarySetting(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, Boolean isSalarySettingByIncumbent) { // Do the save/delete of BCAF rows from the salary setting detail screen first this.saveAppointmentFundings(appointmentFundings); // From the DB get the current unique set of SalarySettingExpansions (PBGL) // associated with our Incumbent or Position BCAF rows. // Each PBGL row from the DB will, in turn, have all the BCAF rows associated, including the // ones we just stored as part of this save operation (see above) // No one else would be updating these since we have a transaction lock on the account Set<SalarySettingExpansion> salarySettingExpansionSet = new HashSet<SalarySettingExpansion>(); // these keep track of purged/unpurged used to unlock funding // when the last line for that account is purged Set<SalarySettingExpansion> purgedSseSet = new HashSet<SalarySettingExpansion>(); Set<SalarySettingExpansion> unpurgedSseSet = new HashSet<SalarySettingExpansion>(); // these keep track of purged/unpurged used to unlock positions // when the last line for that position is purged Set<BudgetConstructionPosition> purgedBPOSNSet = new HashSet<BudgetConstructionPosition>(); Set<BudgetConstructionPosition> unpurgedBPOSNSet = new HashSet<BudgetConstructionPosition>(); for (PendingBudgetConstructionAppointmentFunding fundingLine : appointmentFundings) { SalarySettingExpansion salarySettingExpansion = this.retriveSalarySalarySettingExpansion(fundingLine); if (salarySettingExpansion != null) { salarySettingExpansionSet.add(salarySettingExpansion); } else { // No PBGL row yet, create one to work with in memory only for now. // Don't set versionNumber, this will indicate this is in memory only, // so we can check for the case where there are no BCAF rows in the DB // and no PBGL row either. We don't want to create a new zero request PBGL row in this case. salarySettingExpansion = new SalarySettingExpansion(); salarySettingExpansion.setUniversityFiscalYear(fundingLine.getUniversityFiscalYear()); salarySettingExpansion.setChartOfAccountsCode(fundingLine.getChartOfAccountsCode()); salarySettingExpansion.setAccountNumber(fundingLine.getAccountNumber()); salarySettingExpansion.setSubAccountNumber(fundingLine.getSubAccountNumber()); salarySettingExpansion.setFinancialObjectCode(fundingLine.getFinancialObjectCode()); salarySettingExpansion.setFinancialSubObjectCode(fundingLine.getFinancialSubObjectCode()); salarySettingExpansion.setFinancialBalanceTypeCode(optionsService.getOptions(fundingLine.getUniversityFiscalYear()).getBaseBudgetFinancialBalanceTypeCd()); salarySettingExpansion.setFinancialObjectTypeCode(optionsService.getOptions(fundingLine.getUniversityFiscalYear()).getFinObjTypeExpenditureexpCd()); salarySettingExpansion.setAccountLineAnnualBalanceAmount(KualiInteger.ZERO); salarySettingExpansion.setFinancialBeginningBalanceLineAmount(KualiInteger.ZERO); // If this has been created in memory already, the list should already be attached // and be in the current salarySettingExpansionSet. // This handles the case where at least 2 new BCAF rows for the same non-existent PBGL row // were saved earlier as part of this save operation. if (!salarySettingExpansionSet.contains(salarySettingExpansion)) { // Get the BCAF rows from the DB that are associated with the // newly created salarySettingExpansion and attach so the // method savePBGLSalarySetting() called below can get the total. List<PendingBudgetConstructionAppointmentFunding> bcafRows = this.retrievePendingBudgetConstructionAppointmentFundings(salarySettingExpansion); salarySettingExpansion.getPendingBudgetConstructionAppointmentFunding().addAll(bcafRows); salarySettingExpansionSet.add(salarySettingExpansion); } } // collect the set of purge/notpurged SalarySettingExpansions here if (fundingLine.isPurged()) { purgedSseSet.add(salarySettingExpansion); } else { unpurgedSseSet.add(salarySettingExpansion); } // if SS by incumbent collect the set of purged/notpurged BudgetConstructionPositions here if (isSalarySettingByIncumbent) { BudgetConstructionPosition budgetConstructionPosition = fundingLine.getBudgetConstructionPosition(); if (fundingLine.isPurged()) { purgedBPOSNSet.add(budgetConstructionPosition); } else { unpurgedBPOSNSet.add(budgetConstructionPosition); } } } // remove from set of purged SSEs the set of notpurged SSEs // leftover are those SSEs to release funding locks for after successful save purgedSseSet.removeAll(unpurgedSseSet); // if SS by incumbent, remove from set of purged BPOSNs the set of nonpurged BPOSNs if (isSalarySettingByIncumbent) { purgedBPOSNSet.removeAll(unpurgedBPOSNSet); } // Use the salarySettingExpansionSet to drive the update of PBGL rows (including any 2PLGs) for (SalarySettingExpansion salarySettingExpansion : salarySettingExpansionSet) { this.savePBGLSalarySetting(salarySettingExpansion); } // iterate leftover purged SSEs and release funding lock for each for (SalarySettingExpansion salarySettingExpansion : purgedSseSet) { String chartOfAccountsCode = salarySettingExpansion.getChartOfAccountsCode(); String accountNumber = salarySettingExpansion.getAccountNumber(); String subAccountNumber = salarySettingExpansion.getSubAccountNumber(); Integer fiscalYear = salarySettingExpansion.getUniversityFiscalYear(); String principalId = GlobalVariables.getUserSession().getPerson().getPrincipalId(); // release the associated funding lock lockService.unlockFunding(chartOfAccountsCode, accountNumber, subAccountNumber, fiscalYear, principalId); } // if SS by incumbent iterate leftover purged BPOSNs and release position lock for each for (BudgetConstructionPosition budgetConstructionPosition : purgedBPOSNSet) { Person person = GlobalVariables.getUserSession().getPerson(); lockService.unlockPostion(budgetConstructionPosition, person); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#saveAppointmentFundings(java.util.List) */ public void saveAppointmentFundings(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings) { LOG.debug("saveAppointmentFundings() start"); // remove the appointment funding lines being purged List<PendingBudgetConstructionAppointmentFunding> purgedAppointmentFundings = new ArrayList<PendingBudgetConstructionAppointmentFunding>(); for (PendingBudgetConstructionAppointmentFunding appointmentFunding : appointmentFundings) { if (appointmentFunding.isPurged()) { purgedAppointmentFundings.add(appointmentFunding); } } this.purgeAppointmentFundings(purgedAppointmentFundings); // save the appointment funding lines that have been updated or newly created List<PendingBudgetConstructionAppointmentFunding> savableAppointmentFundings = new ArrayList<PendingBudgetConstructionAppointmentFunding>(appointmentFundings); savableAppointmentFundings.removeAll(purgedAppointmentFundings); // gwp - added this as part of double save optimistic exception fix // since savePBGLSalarySetting does not call this like saveSalarySetting does this.resetDeletedFundingLines(appointmentFundings); this.updateAppointmentFundingsBeforeSaving(savableAppointmentFundings); // save each line so deletion aware reasons get removed when needed for (PendingBudgetConstructionAppointmentFunding savableAppointmentFunding : savableAppointmentFundings){ businessObjectService.save(savableAppointmentFunding); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#retriveSalarySalarySettingExpansion(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public SalarySettingExpansion retriveSalarySalarySettingExpansion(PendingBudgetConstructionAppointmentFunding appointmentFunding) { BudgetConstructionHeader budgetDocument = budgetDocumentService.getBudgetConstructionHeader(appointmentFunding); Map<String, Object> fieldValues = ObjectUtil.buildPropertyMap(appointmentFunding, SalarySettingExpansion.getPrimaryKeyFields()); fieldValues.put(KFSPropertyConstants.DOCUMENT_NUMBER, budgetDocument.getDocumentNumber()); return businessObjectService.findByPrimaryKey(SalarySettingExpansion.class, fieldValues); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#retrievePendingBudgetConstructionAppointmentFundings(org.kuali.kfs.module.bc.businessobject.SalarySettingExpansion) */ public List<PendingBudgetConstructionAppointmentFunding> retrievePendingBudgetConstructionAppointmentFundings(SalarySettingExpansion salarySettingExpansion) { Map<String, Object> fieldValues = new HashMap<String, Object>(); fieldValues.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, salarySettingExpansion.getUniversityFiscalYear()); fieldValues.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, salarySettingExpansion.getChartOfAccountsCode()); fieldValues.put(KFSPropertyConstants.ACCOUNT_NUMBER, salarySettingExpansion.getAccountNumber()); fieldValues.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, salarySettingExpansion.getSubAccountNumber()); fieldValues.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, salarySettingExpansion.getFinancialObjectCode()); fieldValues.put(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, salarySettingExpansion.getFinancialSubObjectCode()); return (List<PendingBudgetConstructionAppointmentFunding>) businessObjectService.findMatching(PendingBudgetConstructionAppointmentFunding.class, fieldValues); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#resetAppointmentFunding(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void resetAppointmentFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding) { appointmentFunding.setAppointmentRequestedAmount(KualiInteger.ZERO); appointmentFunding.setAppointmentRequestedTimePercent(BigDecimal.ZERO); appointmentFunding.setAppointmentRequestedPayRate(BigDecimal.ZERO); appointmentFunding.setAppointmentRequestedFteQuantity(BigDecimal.ZERO); appointmentFunding.setAppointmentRequestedCsfAmount(KualiInteger.ZERO); appointmentFunding.setAppointmentRequestedCsfFteQuantity(BigDecimal.ZERO); appointmentFunding.setAppointmentRequestedCsfTimePercent(BigDecimal.ZERO); appointmentFunding.setAppointmentTotalIntendedAmount(KualiInteger.ZERO); appointmentFunding.setAppointmentTotalIntendedFteQuantity(BigDecimal.ZERO); appointmentFunding.setAppointmentFundingDurationCode(BCConstants.AppointmentFundingDurationCodes.NONE.durationCode); appointmentFunding.setPositionObjectChangeIndicator(false); appointmentFunding.setPositionSalaryChangeIndicator(false); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#markAsDelete(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void markAsDelete(PendingBudgetConstructionAppointmentFunding appointmentFunding) { this.resetAppointmentFunding(appointmentFunding); appointmentFunding.setAppointmentFundingDeleteIndicator(true); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#revert(java.util.List, * org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void revert(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, PendingBudgetConstructionAppointmentFunding appointmentFunding) { PendingBudgetConstructionAppointmentFunding vacantFunding = this.findVacantAppointmentFunding(appointmentFundings, appointmentFunding); if (vacantFunding != null) { appointmentFundings.remove(vacantFunding); } PendingBudgetConstructionAppointmentFunding newAppointmentFunding = (PendingBudgetConstructionAppointmentFunding) businessObjectService.retrieve(appointmentFunding); appointmentFundings.add(newAppointmentFunding); appointmentFundings.remove(appointmentFunding); } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#updateAccessOfAppointmentFunding(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding, * org.kuali.kfs.module.bc.util.SalarySettingFieldsHolder, boolean, java.util.Map, org.kuali.rice.kim.api.identity.Person) */ public boolean updateAccessOfAppointmentFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding, SalarySettingFieldsHolder salarySettingFieldsHolder, boolean budgetByObjectMode, boolean hasDocumentEditAccess, Person person) { String budgetChartOfAccountsCode = salarySettingFieldsHolder.getChartOfAccountsCode(); String budgetAccountNumber = salarySettingFieldsHolder.getAccountNumber(); String budgetSubAccountNumber = salarySettingFieldsHolder.getSubAccountNumber(); String budgetObjectCode = salarySettingFieldsHolder.getFinancialObjectCode(); String budgetSubObjectCode = salarySettingFieldsHolder.getFinancialSubObjectCode(); String chartOfAccountsCode = appointmentFunding.getChartOfAccountsCode(); String accountNumber = appointmentFunding.getAccountNumber(); String subAccountNumber = appointmentFunding.getSubAccountNumber(); String objectCode = appointmentFunding.getFinancialObjectCode(); String subObjectCode = appointmentFunding.getFinancialSubObjectCode(); // just allow edit if budget by object mode (general case of single account mode) if (budgetByObjectMode && StringUtils.equals(chartOfAccountsCode, budgetChartOfAccountsCode) && StringUtils.equals(accountNumber, budgetAccountNumber) && StringUtils.equals(subAccountNumber, budgetSubAccountNumber)) { // use the edit permission already calculated for the home account during document open appointmentFunding.setDisplayOnlyMode(!hasDocumentEditAccess); return true; } boolean isUpdatedByUserLevel = this.updateAccessOfAppointmentFundingByUserLevel(appointmentFunding, person); if (isUpdatedByUserLevel) { return true; } return false; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#updateAccessOfAppointmentFundingByUserLevel(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding, * org.kuali.rice.kim.api.identity.Person) */ public boolean updateAccessOfAppointmentFundingByUserLevel(PendingBudgetConstructionAppointmentFunding appointmentFunding, Person user) { BudgetConstructionHeader budgetConstructionHeader = budgetDocumentService.getBudgetConstructionHeader(appointmentFunding); if (budgetConstructionHeader == null) { return false; } BudgetConstructionDocument document; try { document = (BudgetConstructionDocument) documentService.getByDocumentHeaderId(budgetConstructionHeader.getDocumentNumber()); } catch (WorkflowException e) { throw new RuntimeException("Fail to retrieve budget document for doc id " + budgetConstructionHeader.getDocumentNumber()); } TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) getDocumentHelperService().getDocumentAuthorizer(document); boolean hasEditAccess = documentAuthorizer.isAuthorized(document, BCConstants.BUDGET_CONSTRUCTION_NAMESPACE, BCConstants.KimApiConstants.EDIT_BCAF_PERMISSION_NAME, user.getPrincipalId()); appointmentFunding.setDisplayOnlyMode(!hasEditAccess); boolean hasViewAmountsAccess = documentAuthorizer.isAuthorized(document, BCConstants.BUDGET_CONSTRUCTION_NAMESPACE, BCConstants.KimApiConstants.VIEW_BCAF_AMOUNTS_PERMISSION_NAME, user.getPrincipalId()); appointmentFunding.setExcludedFromTotal(!hasViewAmountsAccess); return true; } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#updateDerivedInformationForAppointmentFundings(java.util.List) */ public void updateAppointmentFundingsBeforeSaving(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings) { LOG.debug("updateDerivedInformationForAppointmentFundings() start"); for (PendingBudgetConstructionAppointmentFunding appointmentFunding : appointmentFundings) { this.recalculateDerivedInformation(appointmentFunding); appointmentFunding.setNewLineIndicator(false); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#updateDerivedInformationForAppointmentFunding(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding) */ public void recalculateDerivedInformation(PendingBudgetConstructionAppointmentFunding appointmentFunding) { this.preprocessFundingReason(appointmentFunding); this.preprocessLeaveRequest(appointmentFunding); boolean isHourlyPaid = this.isHourlyPaid(appointmentFunding); appointmentFunding.setHourlyPaid(isHourlyPaid); if (appointmentFunding.isHourlyPaid()) { this.normalizePayRateAndAmount(appointmentFunding); } else { appointmentFunding.setAppointmentRequestedPayRate(BigDecimal.ZERO); } BigDecimal requestedFteQuantity = this.calculateFteQuantityFromAppointmentFunding(appointmentFunding); appointmentFunding.setAppointmentRequestedFteQuantity(requestedFteQuantity); if (!appointmentFunding.getAppointmentFundingDurationCode().equals(NONE.durationCode)) { BigDecimal requestedCSFFteQuantity = this.calculateCSFFteQuantityFromAppointmentFunding(appointmentFunding); appointmentFunding.setAppointmentRequestedCsfFteQuantity(requestedCSFFteQuantity); } } /** * reset the amount values of each line in the given appointment fundings as zeros and remove the reason annotations if the line * is marked as deleted * * @param pendingBudgetConstructionAppointmentFunding the given appointment fundings */ protected void resetDeletedFundingLines(List<PendingBudgetConstructionAppointmentFunding> pendingBudgetConstructionAppointmentFunding) { for (PendingBudgetConstructionAppointmentFunding appointmentFunding : pendingBudgetConstructionAppointmentFunding) { if (!appointmentFunding.isAppointmentFundingDeleteIndicator() || appointmentFunding.isPersistedDeleteIndicator()) { continue; } this.markAsDelete(appointmentFunding); List<BudgetConstructionAppointmentFundingReason> reasons = appointmentFunding.getBudgetConstructionAppointmentFundingReason(); if (reasons != null) { reasons.clear(); } appointmentFunding.setPersistedDeleteIndicator(true); } } /** * get the csf tracker amount of the given appointment funding * * @param appointmentFunding the given appointment funding * @return the csf tracker amount of the given appointment funding if any; otherwise, return zero */ protected KualiInteger getCsfAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding) { if (appointmentFunding == null) { return KualiInteger.ZERO; } BudgetConstructionCalculatedSalaryFoundationTracker csfTracker = appointmentFunding.getEffectiveCSFTracker(); if (csfTracker == null) { return KualiInteger.ZERO; } return csfTracker.getCsfAmount(); } /** * determine whether there exists at lease one vacant funding line for the given appointment funding * * @param appointmentFunding the given appointment funding * @return true if there exists at lease one vacant funding line for the given appointment funding; otherwise, return false */ protected boolean hasBeenVacated(PendingBudgetConstructionAppointmentFunding appointmentFunding) { Map<String, Object> keyFieldValues = appointmentFunding.getValuesMap(); keyFieldValues.put(KFSPropertyConstants.EMPLID, BCConstants.VACANT_EMPLID); return businessObjectService.countMatching(PendingBudgetConstructionAppointmentFunding.class, keyFieldValues) > 0; } /** * create a vacant appointment funding based on the given budget funding * * @param appointmentFunding the given appointment funding * @return a vacant appointment funding */ protected PendingBudgetConstructionAppointmentFunding createVacantAppointmentFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding) { PendingBudgetConstructionAppointmentFunding vacantAppointmentFunding = new PendingBudgetConstructionAppointmentFunding(); ObjectUtil.buildObjectWithoutReferenceFields(vacantAppointmentFunding, appointmentFunding); vacantAppointmentFunding.setEmplid(BCConstants.VACANT_EMPLID); vacantAppointmentFunding.setAppointmentFundingDeleteIndicator(false); vacantAppointmentFunding.setPersistedDeleteIndicator(false); vacantAppointmentFunding.setVersionNumber(null); vacantAppointmentFunding.setNewLineIndicator(true); return vacantAppointmentFunding; } /** * create a pseudo appointment funding for the salary setting expansion this is used when there are no funding lines for the * salary setting expansion to get a funding line to be used to pass primary key info * * @param salarySettingExpansion * @return a pseudo appointment funding */ protected PendingBudgetConstructionAppointmentFunding createPseudoAppointmentFundingLine(SalarySettingExpansion salarySettingExpansion) { PendingBudgetConstructionAppointmentFunding pseudoAppointmentFunding = new PendingBudgetConstructionAppointmentFunding(); pseudoAppointmentFunding.setUniversityFiscalYear(salarySettingExpansion.getUniversityFiscalYear()); pseudoAppointmentFunding.setChartOfAccountsCode(salarySettingExpansion.getChartOfAccountsCode()); pseudoAppointmentFunding.setAccountNumber(salarySettingExpansion.getAccountNumber()); pseudoAppointmentFunding.setSubAccountNumber(salarySettingExpansion.getSubAccountNumber()); pseudoAppointmentFunding.setFinancialObjectCode(salarySettingExpansion.getFinancialObjectCode()); pseudoAppointmentFunding.setFinancialSubObjectCode(salarySettingExpansion.getFinancialSubObjectCode()); pseudoAppointmentFunding.setAppointmentFundingDeleteIndicator(false); pseudoAppointmentFunding.setAppointmentRequestedAmount(KualiInteger.ZERO); pseudoAppointmentFunding.refreshReferenceObject(KFSPropertyConstants.ACCOUNT); return pseudoAppointmentFunding; } /** * preprocess the funding reason of the given appointment funding before the funding is saved * * @param appointmentFunding the given appointment funding */ public void preprocessFundingReason(PendingBudgetConstructionAppointmentFunding appointmentFunding) { List<BudgetConstructionAppointmentFundingReason> fundingReasons = appointmentFunding.getBudgetConstructionAppointmentFundingReason(); // do special removal of any reason rows where the reason code is blank if (!fundingReasons.isEmpty() && StringUtils.isBlank(fundingReasons.get(0).getAppointmentFundingReasonCode())) { fundingReasons.clear(); } } /** * preprocess the leave request of the given appointment funding before the funding is saved * * @param appointmentFunding the given appointment funding */ public void preprocessLeaveRequest(PendingBudgetConstructionAppointmentFunding appointmentFunding) { String durationCode = appointmentFunding.getAppointmentFundingDurationCode(); if (StringUtils.isEmpty(durationCode) || StringUtils.equals(durationCode, BCConstants.AppointmentFundingDurationCodes.NONE.durationCode)) { appointmentFunding.setAppointmentRequestedCsfAmount(KualiInteger.ZERO); appointmentFunding.setAppointmentRequestedCsfFteQuantity(BigDecimal.ZERO); appointmentFunding.setAppointmentRequestedCsfTimePercent(BigDecimal.ZERO); } } /** * @see org.kuali.kfs.module.bc.document.service.SalarySettingService#hasExistingFundingReason(org.kuali.kfs.module.bc.businessobject.BudgetConstructionAppointmentFundingReasonCode) */ public boolean hasExistingFundingReason(BudgetConstructionAppointmentFundingReasonCode budgetConstructionAppointmentFundingReasonCode) { Map<String, Object> queryMap = new HashMap<String, Object>(); queryMap.put("appointmentFundingReasonCode", budgetConstructionAppointmentFundingReasonCode.getAppointmentFundingReasonCode()); return (businessObjectService.countMatching(BudgetConstructionAppointmentFundingReason.class, queryMap) > 0); } /** * Sets the kualiConfigurationService attribute value. * * @param kualiConfigurationService The kualiConfigurationService to set. */ public void setConfigurationService(ConfigurationService kualiConfigurationService) { this.kualiConfigurationService = kualiConfigurationService; } /** * Sets the businessObjectService attribute value. * * @param businessObjectService The businessObjectService to set. */ public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } /** * Sets the laborModuleService attribute value. * * @param laborModuleService The laborModuleService to set. */ public void setLaborModuleService(LaborModuleService laborModuleService) { this.laborModuleService = laborModuleService; } /** * Sets the budgetDocumentService attribute value. * * @param budgetDocumentService The budgetDocumentService to set. */ public void setBudgetDocumentService(BudgetDocumentService budgetDocumentService) { this.budgetDocumentService = budgetDocumentService; } /** * Sets the benefitsCalculationService attribute value. * * @param benefitsCalculationService The benefitsCalculationService to set. */ public void setBenefitsCalculationService(BenefitsCalculationService benefitsCalculationService) { this.benefitsCalculationService = benefitsCalculationService; } /** * Sets the optionsService attribute value. * * @param optionsService The optionsService to set. */ public void setOptionsService(OptionsService optionsService) { this.optionsService = optionsService; } /** * Sets the lockService attribute value. * * @param lockService The lockService to set. */ public void setLockService(LockService lockService) { this.lockService = lockService; } /** * Gets the documentHelperService attribute. * * @return Returns the documentHelperService. */ public DocumentHelperService getDocumentHelperService() { if (documentHelperService == null) { documentHelperService = SpringContext.getBean(DocumentHelperService.class); } return documentHelperService; } /** * Sets the documentHelperService attribute value. * * @param documentHelperService The documentHelperService to set. */ public void setDocumentHelperService(DocumentHelperService documentHelperService) { this.documentHelperService = documentHelperService; } /** * Sets the documentService attribute value. * * @param documentService The documentService to set. */ public void setDocumentService(DocumentService documentService) { this.documentService = documentService; } /** * Sets the budgetConstructionProcessorService attribute value. * * @param budgetConstructionProcessorService The budgetConstructionProcessorService to set. */ public void setBudgetConstructionProcessorService(BudgetConstructionProcessorService budgetConstructionProcessorService) { this.budgetConstructionProcessorService = budgetConstructionProcessorService; } }