0001: /*
0002: * Copyright 2006-2007 The Kuali Foundation.
0003: *
0004: * Licensed under the Educational Community License, Version 1.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.opensource.org/licenses/ecl1.php
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.kuali.module.kra.budget.service.impl;
0017:
0018: import java.math.BigDecimal;
0019: import java.util.ArrayList;
0020: import java.util.Calendar;
0021: import java.util.Collections;
0022: import java.util.Date;
0023: import java.util.HashMap;
0024: import java.util.Iterator;
0025: import java.util.List;
0026:
0027: import org.apache.commons.lang.StringUtils;
0028: import org.kuali.core.service.BusinessObjectService;
0029: import org.kuali.core.service.DateTimeService;
0030: import org.kuali.core.util.KualiDecimal;
0031: import org.kuali.core.util.KualiInteger;
0032: import org.kuali.core.util.ObjectUtils;
0033: import org.kuali.kfs.context.SpringContext;
0034: import org.kuali.kfs.service.ParameterService;
0035: import org.kuali.module.financial.service.UniversityDateService;
0036: import org.kuali.module.kra.KraConstants;
0037: import org.kuali.module.kra.budget.bo.AppointmentType;
0038: import org.kuali.module.kra.budget.bo.AppointmentTypeEffectiveDate;
0039: import org.kuali.module.kra.budget.bo.Budget;
0040: import org.kuali.module.kra.budget.bo.BudgetFringeRate;
0041: import org.kuali.module.kra.budget.bo.BudgetPeriod;
0042: import org.kuali.module.kra.budget.bo.BudgetTask;
0043: import org.kuali.module.kra.budget.bo.BudgetUser;
0044: import org.kuali.module.kra.budget.bo.UserAppointmentTask;
0045: import org.kuali.module.kra.budget.bo.UserAppointmentTaskPeriod;
0046: import org.kuali.module.kra.budget.document.BudgetDocument;
0047: import org.kuali.module.kra.budget.service.BudgetFringeRateService;
0048: import org.kuali.module.kra.budget.service.BudgetPersonnelService;
0049: import org.springframework.transaction.annotation.Transactional;
0050:
0051: @Transactional
0052: public class BudgetPersonnelServiceImpl implements
0053: BudgetPersonnelService {
0054:
0055: private static HashMap appointmentTypeMappings;
0056:
0057: private BusinessObjectService businessObjectService;
0058: private BudgetFringeRateService budgetFringeRateService;
0059: private ParameterService parameterService;
0060:
0061: /**
0062: * This method will create all the necessary task/period combinations for a given BudgetUser
0063: *
0064: * @parm budgetUser - The user that we are creating entries for
0065: * @parm budgetDocument - Stores information used to create the appropriate number of tasks/period
0066: */
0067: public void createPersonnelDetail(BudgetUser budgetUser,
0068: BudgetDocument budgetDocument) {
0069: BudgetFringeRate budgetFringeRate = budgetFringeRateService
0070: .getBudgetFringeRateForPerson(budgetUser);
0071: budgetUser.setAppointmentTypeCode(budgetFringeRate
0072: .getInstitutionAppointmentTypeCode());
0073: budgetUser.setAppointmentTypeDescription(budgetFringeRate
0074: .getAppointmentType().getAppointmentTypeDescription());
0075:
0076: BudgetFringeRate secondaryBudgetFringeRate = null;
0077: if (budgetFringeRate.getAppointmentType()
0078: .getRelatedAppointmentTypeCode() != null) {
0079: secondaryBudgetFringeRate = budgetFringeRateService
0080: .getBudgetFringeRate(budgetDocument
0081: .getDocumentNumber(), budgetFringeRate
0082: .getAppointmentType()
0083: .getRelatedAppointmentTypeCode());
0084: budgetUser
0085: .setSecondaryAppointmentTypeCode(secondaryBudgetFringeRate
0086: .getInstitutionAppointmentTypeCode());
0087: }
0088:
0089: for (BudgetTask task : budgetDocument.getBudget().getTasks()) {
0090: budgetUser.getUserAppointmentTasks().add(
0091: createUserAppointmentTask(budgetUser,
0092: budgetDocument, budgetFringeRate, task,
0093: budgetDocument.getBudget().getPeriods(),
0094: false));
0095: if (secondaryBudgetFringeRate != null) {
0096: budgetUser.getUserAppointmentTasks()
0097: .add(
0098: createUserAppointmentTask(budgetUser,
0099: budgetDocument,
0100: secondaryBudgetFringeRate,
0101: task, budgetDocument
0102: .getBudget()
0103: .getPeriods(), true));
0104: }
0105: }
0106:
0107: Collections.sort(budgetUser.getUserAppointmentTasks());
0108: }
0109:
0110: private UserAppointmentTask createUserAppointmentTask(
0111: BudgetUser budgetUser, BudgetDocument budgetDocument,
0112: BudgetFringeRate budgetFringeRate, BudgetTask task,
0113: List<BudgetPeriod> periods, boolean isSecondaryAppointment) {
0114: Integer budgetTaskSequenceNumber = task
0115: .getBudgetTaskSequenceNumber();
0116:
0117: UserAppointmentTask userAppointmentTask = new UserAppointmentTask();
0118: userAppointmentTask
0119: .setBudgetTaskSequenceNumber(budgetTaskSequenceNumber);
0120: userAppointmentTask.setBudgetUserSequenceNumber(budgetUser
0121: .getBudgetUserSequenceNumber());
0122: userAppointmentTask.setDocumentNumber(budgetUser
0123: .getDocumentNumber());
0124: userAppointmentTask
0125: .setInstitutionAppointmentTypeCode(budgetFringeRate
0126: .getInstitutionAppointmentTypeCode());
0127: userAppointmentTask.setBudgetFringeRate(budgetFringeRate);
0128: userAppointmentTask
0129: .setSecondaryAppointment(isSecondaryAppointment);
0130:
0131: userAppointmentTask.setTask(task);
0132:
0133: for (BudgetPeriod period : periods) {
0134:
0135: userAppointmentTask.getUserAppointmentTaskPeriods().add(
0136: createUserAppointmentTaskPeriod(budgetUser,
0137: budgetDocument, budgetFringeRate, task,
0138: period));
0139: }
0140:
0141: return userAppointmentTask;
0142: }
0143:
0144: private UserAppointmentTaskPeriod createUserAppointmentTaskPeriod(
0145: BudgetUser budgetUser, BudgetDocument budgetDocument,
0146: BudgetFringeRate budgetFringeRate, BudgetTask task,
0147: BudgetPeriod period) {
0148: Integer budgetPeriodSequenceNumber = period
0149: .getBudgetPeriodSequenceNumber();
0150:
0151: UserAppointmentTaskPeriod userAppointmentTaskPeriod;
0152:
0153: userAppointmentTaskPeriod = new UserAppointmentTaskPeriod();
0154: userAppointmentTaskPeriod.setDocumentNumber(budgetUser
0155: .getDocumentNumber());
0156: userAppointmentTaskPeriod
0157: .setBudgetUserSequenceNumber(budgetUser
0158: .getBudgetUserSequenceNumber());
0159: userAppointmentTaskPeriod.setBudgetTaskSequenceNumber(task
0160: .getBudgetTaskSequenceNumber());
0161: userAppointmentTaskPeriod
0162: .setBudgetPeriodSequenceNumber(budgetPeriodSequenceNumber);
0163: userAppointmentTaskPeriod
0164: .setInstitutionAppointmentTypeCode(budgetFringeRate
0165: .getInstitutionAppointmentTypeCode());
0166: userAppointmentTaskPeriod.setBudgetFringeRate(budgetFringeRate);
0167:
0168: if (StringUtils.contains(getAppointmentTypeMappings().get(
0169: KraConstants.ACADEMIC_YEAR_SUMMER).toString(),
0170: budgetFringeRate.getInstitutionAppointmentTypeCode())
0171: || StringUtils.contains(getAppointmentTypeMappings()
0172: .get(KraConstants.FULL_YEAR).toString(),
0173: budgetFringeRate
0174: .getInstitutionAppointmentTypeCode())) {
0175:
0176: PeriodSalary periodSalary = calculatePeriodSalaryAndDays(
0177: budgetUser, budgetFringeRate, period,
0178: budgetDocument.getBudget()
0179: .getBudgetPersonnelInflationRate());
0180:
0181: userAppointmentTaskPeriod.setPeriodSalary(periodSalary);
0182:
0183: userAppointmentTaskPeriod
0184: .setUserBudgetPeriodSalaryAmount(periodSalary
0185: .getPeriodSalary());
0186: }
0187:
0188: userAppointmentTaskPeriod.setTask(task);
0189: userAppointmentTaskPeriod.setPeriod(period);
0190:
0191: return userAppointmentTaskPeriod;
0192: }
0193:
0194: /**
0195: * This method will calculate the salary amount for a person for an individual period. The algorithm that this uses takes into
0196: * account what the current Fiscal Year is, the FY for the period that we are trying to calculate, the number of FYs that the
0197: * period spans, the number of days in each FY and the inflated salary for the FY
0198: *
0199: * @parm budgetUser - The user for whom we are calculating the period salary
0200: * @parm period - The period that we are calculation salary for
0201: * @inflationRate - The inflation rate to use when calculating the person's salary
0202: */
0203:
0204: public KualiInteger calculatePeriodSalary(BudgetUser budgetUser,
0205: BudgetFringeRate budgetFringeRate, BudgetPeriod period,
0206: KualiDecimal inflationRate) {
0207: return calculatePeriodSalaryAndDays(budgetUser,
0208: budgetFringeRate, period, inflationRate).periodSalary;
0209: }
0210:
0211: private PeriodSalary calculatePeriodSalaryAndDays(
0212: BudgetUser budgetUser, BudgetFringeRate budgetFringeRate,
0213: BudgetPeriod period, KualiDecimal inflationRate) {
0214:
0215: boolean calculateCalendarYear = StringUtils.equals(
0216: budgetFringeRate.getInstitutionAppointmentTypeCode(),
0217: getAppointmentTypeMappings().get(
0218: KraConstants.ACADEMIC_SUMMER).toString());
0219:
0220: Integer periodStartDateEvaluationYear = SpringContext.getBean(
0221: UniversityDateService.class).getFiscalYear(
0222: period.getBudgetPeriodBeginDate());
0223: Integer periodEndDateEvaluationYear = SpringContext.getBean(
0224: UniversityDateService.class).getFiscalYear(
0225: period.getBudgetPeriodEndDate());
0226:
0227: if (calculateCalendarYear) { // currently only used for Academic Summer appointments
0228: Calendar startDateCalendar = Calendar.getInstance();
0229: startDateCalendar
0230: .setTime(period.getBudgetPeriodBeginDate());
0231: periodStartDateEvaluationYear = new Integer(
0232: startDateCalendar.get(Calendar.YEAR));
0233:
0234: Calendar endDateCalendar = Calendar.getInstance();
0235: endDateCalendar.setTime(period.getBudgetPeriodEndDate());
0236: periodEndDateEvaluationYear = new Integer(endDateCalendar
0237: .get(Calendar.YEAR));
0238: }
0239:
0240: if (periodStartDateEvaluationYear
0241: .compareTo(periodEndDateEvaluationYear) != 0) {
0242: // Start date and end date are in different FYs
0243: // we know that the start date is before the end date b/c of validations, so if they are not equal the end date must be
0244: // in the next fiscal year
0245:
0246: budgetFringeRate.refreshReferenceObject("appointmentType");
0247:
0248: Date subPeriodOneEndDate = getAppointmentTypeEffectiveEndDate(
0249: budgetFringeRate.getAppointmentType(),
0250: periodStartDateEvaluationYear);
0251: Date subPeriodTwoStartDate = getAppointmentTypeEffectiveStartDate(
0252: budgetFringeRate.getAppointmentType(),
0253: periodEndDateEvaluationYear);
0254:
0255: BudgetPeriod subPeriodOne = new BudgetPeriod();
0256: subPeriodOne.setBudgetPeriodBeginDate(period
0257: .getBudgetPeriodBeginDate());
0258: subPeriodOne.setBudgetPeriodEndDate(new java.sql.Date(
0259: subPeriodOneEndDate.getTime()));
0260: PeriodSalary subPeriodOneSalary = calculatePeriodSalaryAndDays(
0261: budgetUser, budgetFringeRate, subPeriodOne,
0262: inflationRate);
0263:
0264: BudgetPeriod subPeriodTwo = new BudgetPeriod();
0265: subPeriodTwo.setBudgetPeriodBeginDate(new java.sql.Date(
0266: subPeriodTwoStartDate.getTime()));
0267: subPeriodTwo.setBudgetPeriodEndDate(period
0268: .getBudgetPeriodEndDate());
0269: PeriodSalary subPeriodTwoSalary = calculatePeriodSalaryAndDays(
0270: budgetUser, budgetFringeRate, subPeriodTwo,
0271: inflationRate);
0272:
0273: return subPeriodOneSalary.add(subPeriodTwoSalary);
0274: } else {
0275: // Start date and end date are in the same FY
0276: Integer currentFiscalYear = periodStartDateEvaluationYear;
0277:
0278: double inflationFactor = inflationRate.doubleValue() / 100 + 1;
0279:
0280: int compareToYear = SpringContext.getBean(
0281: UniversityDateService.class).getCurrentFiscalYear()
0282: .intValue();
0283:
0284: if (budgetUser.getBudgetSalaryFiscalYear() != null) {
0285: compareToYear = budgetUser.getBudgetSalaryFiscalYear()
0286: .intValue();
0287: } else {
0288: budgetUser.setBudgetSalaryFiscalYear(new Integer(
0289: compareToYear));
0290: }
0291:
0292: BigDecimal inflatedSalary = new BigDecimal((budgetUser
0293: .getBaseSalary() != null ? budgetUser
0294: .getBaseSalary().doubleValue() : 0)
0295: * Math.pow(inflationFactor,
0296: periodEndDateEvaluationYear.intValue()
0297: - compareToYear));
0298: // Step 1 - divide the annual salary by the number of days in the fiscal year (taking into account leap year) to
0299: // determine the daily salary
0300: KualiInteger fullSalaryForAppointmentTypeDuration = new KualiInteger(
0301: inflatedSalary);
0302:
0303: Date evalStartDate = getAppointmentTypeEffectiveStartDate(
0304: budgetFringeRate.getAppointmentType(),
0305: currentFiscalYear);
0306: Date evalEndDate = getAppointmentTypeEffectiveEndDate(
0307: budgetFringeRate.getAppointmentType(),
0308: currentFiscalYear);
0309:
0310: Date dailySalaryStartDate = evalStartDate;
0311: Date dailySalaryEndDate = evalEndDate;
0312:
0313: if (calculateCalendarYear) {
0314: AppointmentType surrogateAppointmentType = new AppointmentType();
0315: surrogateAppointmentType
0316: .setAppointmentTypeCode(getAppointmentTypeMappings()
0317: .get(KraConstants.ACADEMIC_YEAR)
0318: .toString());
0319: dailySalaryStartDate = getAppointmentTypeEffectiveStartDate(
0320: surrogateAppointmentType, currentFiscalYear);
0321: dailySalaryEndDate = getAppointmentTypeEffectiveEndDate(
0322: surrogateAppointmentType, currentFiscalYear);
0323: }
0324:
0325: BigDecimal dailySalaryForAppointmentTypeDuration = fullSalaryForAppointmentTypeDuration
0326: .divide(new BigDecimal(SpringContext.getBean(
0327: DateTimeService.class).dateDiff(
0328: dailySalaryStartDate, dailySalaryEndDate,
0329: true)));
0330:
0331: // Step 2 - find out the number of days in the period
0332: Date workStartDate = (period.getBudgetPeriodBeginDate()
0333: .before(evalStartDate) ? evalStartDate : period
0334: .getBudgetPeriodBeginDate());
0335: Date workEndDate = (period.getBudgetPeriodEndDate().after(
0336: evalEndDate) ? evalEndDate : period
0337: .getBudgetPeriodEndDate());
0338:
0339: // method can return a negative - this may occur in cases when we are modifying the dates to calcualte based on. For
0340: // example, summer appointments in periods that
0341: int dateDiff = SpringContext.getBean(DateTimeService.class)
0342: .dateDiff(workStartDate, workEndDate, true);
0343: int daysInPeriod = dateDiff > 0 ? dateDiff : 0;
0344:
0345: // Step 3 - multiply the number of days in the period (Step 2) by the daily salary (Step 1)
0346: KualiInteger periodSalary = new KualiInteger(daysInPeriod)
0347: .multiply(dailySalaryForAppointmentTypeDuration);
0348:
0349: return new PeriodSalary(periodSalary, daysInPeriod);
0350: }
0351: }
0352:
0353: /**
0354: * This method will calculate the period salary for an individual for each task and period that exists on the budget.
0355: *
0356: * @parm budgetUser - The budgetUser for whom we care calculating salary amounts
0357: * @parm budgetDocument - The budgetDocument stores values used to make calculations, like periods, period length, and inflation
0358: * rates.
0359: */
0360: public void calculatePersonSalary(BudgetUser budgetUser,
0361: BudgetDocument budgetDocument) {
0362:
0363: for (UserAppointmentTask userAppointmentTask : budgetUser
0364: .getUserAppointmentTasks()) {
0365:
0366: for (UserAppointmentTaskPeriod userAppointmentTaskPeriod : userAppointmentTask
0367: .getUserAppointmentTaskPeriods()) {
0368: BudgetPeriod budgetPeriod = new BudgetPeriod();
0369: budgetPeriod
0370: .setDocumentNumber(userAppointmentTaskPeriod
0371: .getDocumentNumber());
0372: budgetPeriod
0373: .setBudgetPeriodSequenceNumber(userAppointmentTaskPeriod
0374: .getBudgetPeriodSequenceNumber());
0375:
0376: BudgetPeriod period = (BudgetPeriod) (ObjectUtils
0377: .retrieveObjectWithIdentitcalKey(budgetDocument
0378: .getBudget().getPeriods(), budgetPeriod));
0379: userAppointmentTaskPeriod.setPeriod(period);
0380:
0381: if ((StringUtils.contains(getAppointmentTypeMappings()
0382: .get(KraConstants.ACADEMIC_YEAR_SUMMER)
0383: .toString(), userAppointmentTask
0384: .getInstitutionAppointmentTypeCode()) || StringUtils
0385: .contains(
0386: getAppointmentTypeMappings().get(
0387: KraConstants.FULL_YEAR)
0388: .toString(),
0389: userAppointmentTask
0390: .getInstitutionAppointmentTypeCode()))) {
0391:
0392: // the following should ensure that we have up to date fringe rates in the case of modification from Parameters
0393: BudgetFringeRate budgetFringeRate = new BudgetFringeRate();
0394: budgetFringeRate
0395: .setDocumentNumber(userAppointmentTaskPeriod
0396: .getDocumentNumber());
0397: budgetFringeRate
0398: .setInstitutionAppointmentTypeCode(userAppointmentTaskPeriod
0399: .getInstitutionAppointmentTypeCode());
0400:
0401: budgetFringeRate = (BudgetFringeRate) (ObjectUtils
0402: .retrieveObjectWithIdentitcalKey(
0403: budgetDocument.getBudget()
0404: .getFringeRates(),
0405: budgetFringeRate));
0406: if (budgetFringeRate != null) {
0407: userAppointmentTaskPeriod
0408: .setBudgetFringeRate(budgetFringeRate);
0409:
0410: PeriodSalary periodSalary = calculatePeriodSalaryAndDays(
0411: budgetUser,
0412: userAppointmentTaskPeriod
0413: .getBudgetFringeRate(),
0414: userAppointmentTaskPeriod.getPeriod(),
0415: budgetDocument
0416: .getBudget()
0417: .getBudgetPersonnelInflationRate());
0418:
0419: userAppointmentTaskPeriod
0420: .setPeriodSalary(periodSalary);
0421:
0422: userAppointmentTaskPeriod
0423: .setUserBudgetPeriodSalaryAmount(periodSalary
0424: .getPeriodSalary());
0425: }
0426: }
0427: }
0428: }
0429: }
0430:
0431: /**
0432: * This method will recalculate the agency and institution/institution cost share amounts based on the period salary/hourly
0433: * rate/number of hours/ fringe rates/etc... for every personnel entry
0434: *
0435: * @parm BudgetUser The user for whom request amounts are being calculated. Note that changing the appointment type class (for
0436: * example, changing from a full year appointment to an hourly appointment) does not clear out the existing values. This
0437: * is so we can switch back and forth and keep the appropriate values.
0438: */
0439: public void calculatePersonRequestAmounts(BudgetUser budgetUser,
0440: List budgetFringeRates) {
0441: BudgetFringeRate budgetFringeRate;
0442:
0443: for (UserAppointmentTask userAppointmentTask : budgetUser
0444: .getUserAppointmentTasks()) {
0445: userAppointmentTask
0446: .refreshReferenceObject("budgetFringeRate");
0447:
0448: BudgetFringeRate budgetFringeRateFromList = (BudgetFringeRate) (ObjectUtils
0449: .retrieveObjectWithIdentitcalKey(budgetFringeRates,
0450: userAppointmentTask.getBudgetFringeRate()));
0451: if (budgetFringeRateFromList != null) {
0452: budgetFringeRate = budgetFringeRateFromList;
0453: } else {
0454: budgetFringeRate = budgetFringeRateService
0455: .getBudgetFringeRate(
0456: userAppointmentTask.getDocumentNumber(),
0457: userAppointmentTask
0458: .getInstitutionAppointmentTypeCode());
0459: }
0460:
0461: // Zero out the totals
0462: userAppointmentTask
0463: .setAgencyRequestTotalAmountTask(new KualiInteger(0));
0464: userAppointmentTask
0465: .setAgencyFringeBenefitTotalAmountTask(new KualiInteger(
0466: 0));
0467: userAppointmentTask
0468: .setInstitutionCostShareRequestTotalAmountTask(new KualiInteger(
0469: 0));
0470: userAppointmentTask
0471: .setInstitutionCostShareFringeBenefitTotalAmountTask(new KualiInteger(
0472: 0));
0473: userAppointmentTask
0474: .setGradAsstAgencyHealthInsuranceTotal(new KualiInteger(
0475: 0));
0476: userAppointmentTask
0477: .setGradAsstAgencySalaryTotal(new KualiInteger(0));
0478: userAppointmentTask
0479: .setGradAsstInstHealthInsuranceTotal(new KualiInteger(
0480: 0));
0481: userAppointmentTask
0482: .setGradAsstInstSalaryTotal(new KualiInteger(0));
0483:
0484: for (UserAppointmentTaskPeriod userAppointmentTaskPeriod : userAppointmentTask
0485: .getUserAppointmentTaskPeriods()) {
0486: userAppointmentTaskPeriod
0487: .setBudgetFringeRate(userAppointmentTask
0488: .getBudgetFringeRate());
0489:
0490: userAppointmentTaskPeriod
0491: .setTotalFeeRemissionsAmount(new KualiInteger(0));
0492: userAppointmentTaskPeriod
0493: .setTotalFteAmount(new KualiInteger(0));
0494: userAppointmentTaskPeriod
0495: .setTotalHealthInsuranceAmount(new KualiInteger(
0496: 0));
0497: userAppointmentTaskPeriod
0498: .setTotalGradAsstSalaryAmount(new KualiInteger(
0499: 0));
0500: userAppointmentTaskPeriod
0501: .setTotalPercentEffort(new KualiInteger(0));
0502: userAppointmentTaskPeriod
0503: .setTotalSalaryAmount(new KualiInteger(0));
0504: userAppointmentTaskPeriod
0505: .setTotalFringeAmount(new KualiInteger(0));
0506:
0507: BigDecimal costShareFringeRateDecimalMultiplier = budgetFringeRate
0508: .getInstitutionCostShareFringeRateAmount()
0509: .bigDecimalValue().divide(
0510: BigDecimal.valueOf(100), 8,
0511: KualiDecimal.ROUND_BEHAVIOR);
0512: BigDecimal agnecyFringeRateDecimalMultiplier = budgetFringeRate
0513: .getContractsAndGrantsFringeRateAmount()
0514: .bigDecimalValue().divide(
0515: BigDecimal.valueOf(100), 8,
0516: KualiDecimal.ROUND_BEHAVIOR);
0517:
0518: if (StringUtils.equals(getAppointmentTypeMappings()
0519: .get(KraConstants.ACADEMIC_SUMMER).toString(),
0520: userAppointmentTask
0521: .getInstitutionAppointmentTypeCode())) {
0522: PeriodSalary periodSalary = userAppointmentTaskPeriod
0523: .getPeriodSalary() != null ? userAppointmentTaskPeriod
0524: .getPeriodSalary()
0525: : new PeriodSalary(new KualiInteger(0), 0);
0526: float weeks = periodSalary.getWorkDaysInPeriod() / 7;
0527:
0528: float workWeeks = userAppointmentTaskPeriod
0529: .getPersonWeeksAmount() != null ? userAppointmentTaskPeriod
0530: .getPersonWeeksAmount().intValue()
0531: : 0;
0532:
0533: if (workWeeks > weeks)
0534: workWeeks = weeks;
0535:
0536: BigDecimal workWeeksPercent = weeks > 0
0537: && workWeeks > 0 ? new BigDecimal(workWeeks
0538: / weeks) : new BigDecimal(0);
0539:
0540: BigDecimal userBudgetPeriodSalaryAmount = userAppointmentTaskPeriod
0541: .getUserBudgetPeriodSalaryAmount()
0542: .bigDecimalValue().multiply(
0543: workWeeksPercent).setScale(0,
0544: KualiDecimal.ROUND_BEHAVIOR);
0545:
0546: userAppointmentTaskPeriod
0547: .setUserBudgetPeriodSalaryAmount(new KualiInteger(
0548: userBudgetPeriodSalaryAmount));
0549:
0550: userAppointmentTaskPeriod
0551: .setTotalPercentEffort(userAppointmentTaskPeriod
0552: .getAgencyPercentEffortAmount()
0553: .add(
0554: userAppointmentTaskPeriod
0555: .getInstitutionCostSharePercentEffortAmount()));
0556: userAppointmentTaskPeriod
0557: .setTotalSalaryAmount(userAppointmentTaskPeriod
0558: .getAgencyRequestTotalAmount()
0559: .add(
0560: userAppointmentTaskPeriod
0561: .getInstitutionCostShareRequestTotalAmount()));
0562: userAppointmentTaskPeriod
0563: .setTotalFringeAmount(userAppointmentTaskPeriod
0564: .getAgencyFringeBenefitTotalAmount()
0565: .add(
0566: userAppointmentTaskPeriod
0567: .getInstitutionCostShareFringeBenefitTotalAmount()));
0568: }
0569:
0570: if (StringUtils.contains(getAppointmentTypeMappings()
0571: .get(KraConstants.FULL_YEAR).toString(),
0572: userAppointmentTask
0573: .getInstitutionAppointmentTypeCode())
0574: || StringUtils
0575: .contains(
0576: getAppointmentTypeMappings()
0577: .get(
0578: KraConstants.ACADEMIC_YEAR_SUMMER)
0579: .toString(),
0580: userAppointmentTask
0581: .getInstitutionAppointmentTypeCode())) {
0582:
0583: KualiInteger agencyRequestSalary = userAppointmentTaskPeriod
0584: .getUserBudgetPeriodSalaryAmount()
0585: .multiply(
0586: userAppointmentTaskPeriod
0587: .getAgencyPercentEffortAmount()
0588: .bigDecimalValue()
0589: .divide(
0590: BigDecimal
0591: .valueOf(100),
0592: 8,
0593: KualiDecimal.ROUND_BEHAVIOR));
0594: KualiInteger agencyRequestFringe = agencyRequestSalary
0595: .multiply(agnecyFringeRateDecimalMultiplier);
0596:
0597: KualiInteger institutionCostShareRequestSalary = userAppointmentTaskPeriod
0598: .getUserBudgetPeriodSalaryAmount()
0599: .multiply(
0600: userAppointmentTaskPeriod
0601: .getInstitutionCostSharePercentEffortAmount()
0602: .bigDecimalValue()
0603: .divide(
0604: BigDecimal
0605: .valueOf(100),
0606: 8,
0607: KualiDecimal.ROUND_BEHAVIOR));
0608: KualiInteger institutionCostShareRequestFringe = institutionCostShareRequestSalary
0609: .multiply(costShareFringeRateDecimalMultiplier);
0610:
0611: userAppointmentTaskPeriod
0612: .setAgencyRequestTotalAmount(agencyRequestSalary);
0613: userAppointmentTaskPeriod
0614: .setAgencyFringeBenefitTotalAmount(agencyRequestFringe);
0615:
0616: userAppointmentTask
0617: .setAgencyRequestTotalAmountTask(userAppointmentTask
0618: .getAgencyRequestTotalAmountTask()
0619: .add(agencyRequestSalary));
0620: userAppointmentTask
0621: .setAgencyFringeBenefitTotalAmountTask(userAppointmentTask
0622: .getAgencyFringeBenefitTotalAmountTask()
0623: .add(agencyRequestFringe));
0624:
0625: userAppointmentTaskPeriod
0626: .setInstitutionCostShareRequestTotalAmount(institutionCostShareRequestSalary);
0627: userAppointmentTaskPeriod
0628: .setInstitutionCostShareFringeBenefitTotalAmount(institutionCostShareRequestFringe);
0629:
0630: userAppointmentTask
0631: .setInstitutionCostShareRequestTotalAmountTask(userAppointmentTask
0632: .getInstitutionCostShareRequestTotalAmountTask()
0633: .add(
0634: institutionCostShareRequestSalary));
0635: userAppointmentTask
0636: .setInstitutionCostShareFringeBenefitTotalAmountTask(userAppointmentTask
0637: .getInstitutionCostShareFringeBenefitTotalAmountTask()
0638: .add(
0639: institutionCostShareRequestFringe));
0640:
0641: userAppointmentTaskPeriod
0642: .setTotalPercentEffort(userAppointmentTaskPeriod
0643: .getAgencyPercentEffortAmount()
0644: .add(
0645: userAppointmentTaskPeriod
0646: .getInstitutionCostSharePercentEffortAmount()));
0647: userAppointmentTaskPeriod
0648: .setTotalSalaryAmount(userAppointmentTaskPeriod
0649: .getAgencyRequestTotalAmount()
0650: .add(
0651: userAppointmentTaskPeriod
0652: .getInstitutionCostShareRequestTotalAmount()));
0653: userAppointmentTaskPeriod
0654: .setTotalFringeAmount(userAppointmentTaskPeriod
0655: .getAgencyFringeBenefitTotalAmount()
0656: .add(
0657: userAppointmentTaskPeriod
0658: .getInstitutionCostShareFringeBenefitTotalAmount()));
0659: } else if (StringUtils.contains(
0660: getAppointmentTypeMappings().get(
0661: KraConstants.HOURLY).toString(),
0662: userAppointmentTask
0663: .getInstitutionAppointmentTypeCode())) {
0664:
0665: KualiInteger hourlyAgencyRequest = userAppointmentTaskPeriod
0666: .getUserAgencyHours().multiply(
0667: userAppointmentTaskPeriod
0668: .getUserHourlyRate()
0669: .bigDecimalValue());
0670: KualiInteger hourlyInstitutionRequest = userAppointmentTaskPeriod
0671: .getUserInstitutionHours().multiply(
0672: userAppointmentTaskPeriod
0673: .getUserHourlyRate());
0674:
0675: userAppointmentTaskPeriod
0676: .setAgencyRequestTotalAmount(hourlyAgencyRequest);
0677: userAppointmentTaskPeriod
0678: .setAgencyFringeBenefitTotalAmount(hourlyAgencyRequest
0679: .multiply(agnecyFringeRateDecimalMultiplier));
0680:
0681: userAppointmentTask
0682: .setAgencyRequestTotalAmountTask(userAppointmentTask
0683: .getAgencyRequestTotalAmountTask()
0684: .add(hourlyAgencyRequest));
0685: userAppointmentTask
0686: .setAgencyFringeBenefitTotalAmountTask(userAppointmentTask
0687: .getAgencyFringeBenefitTotalAmountTask()
0688: .add(
0689: hourlyAgencyRequest
0690: .multiply(agnecyFringeRateDecimalMultiplier)));
0691:
0692: userAppointmentTaskPeriod
0693: .setInstitutionCostShareRequestTotalAmount(hourlyInstitutionRequest);
0694: userAppointmentTaskPeriod
0695: .setInstitutionCostShareFringeBenefitTotalAmount(hourlyInstitutionRequest
0696: .multiply(costShareFringeRateDecimalMultiplier));
0697:
0698: userAppointmentTask
0699: .setInstitutionCostShareRequestTotalAmountTask(userAppointmentTask
0700: .getInstitutionCostShareRequestTotalAmountTask()
0701: .add(hourlyInstitutionRequest));
0702: userAppointmentTask
0703: .setInstitutionCostShareFringeBenefitTotalAmountTask(userAppointmentTask
0704: .getInstitutionCostShareFringeBenefitTotalAmountTask()
0705: .add(
0706: hourlyInstitutionRequest
0707: .multiply(costShareFringeRateDecimalMultiplier)));
0708:
0709: userAppointmentTaskPeriod
0710: .setTotalPercentEffort(userAppointmentTaskPeriod
0711: .getAgencyPercentEffortAmount()
0712: .add(
0713: userAppointmentTaskPeriod
0714: .getInstitutionCostSharePercentEffortAmount()));
0715: userAppointmentTaskPeriod
0716: .setTotalSalaryAmount(userAppointmentTaskPeriod
0717: .getAgencyRequestTotalAmount()
0718: .add(
0719: userAppointmentTaskPeriod
0720: .getInstitutionCostShareRequestTotalAmount()));
0721: userAppointmentTaskPeriod
0722: .setTotalFringeAmount(userAppointmentTaskPeriod
0723: .getAgencyFringeBenefitTotalAmount()
0724: .add(
0725: userAppointmentTaskPeriod
0726: .getInstitutionCostShareFringeBenefitTotalAmount()));
0727: userAppointmentTaskPeriod
0728: .setTotalPercentEffort(userAppointmentTaskPeriod
0729: .getUserAgencyHours()
0730: .add(
0731: userAppointmentTaskPeriod
0732: .getUserInstitutionHours()));
0733: } else if (StringUtils.contains(
0734: getAppointmentTypeMappings().get(
0735: KraConstants.GRADUATE_ASSISTANT)
0736: .toString(), userAppointmentTask
0737: .getInstitutionAppointmentTypeCode())) {
0738:
0739: userAppointmentTask
0740: .setGradAsstAgencyHealthInsuranceTotal(userAppointmentTask
0741: .getGradAsstAgencyHealthInsuranceTotal()
0742: .add(
0743: userAppointmentTaskPeriod
0744: .getAgencyHealthInsuranceAmount()));
0745: userAppointmentTask
0746: .setGradAsstAgencySalaryTotal(userAppointmentTask
0747: .getGradAsstAgencySalaryTotal()
0748: .add(
0749: userAppointmentTaskPeriod
0750: .getAgencySalaryAmount()));
0751: userAppointmentTask
0752: .setGradAsstInstHealthInsuranceTotal(userAppointmentTask
0753: .getGradAsstInstHealthInsuranceTotal()
0754: .add(
0755: userAppointmentTaskPeriod
0756: .getInstitutionHealthInsuranceAmount()));
0757: userAppointmentTask
0758: .setGradAsstInstSalaryTotal(userAppointmentTask
0759: .getGradAsstInstSalaryTotal()
0760: .add(
0761: userAppointmentTaskPeriod
0762: .getInstitutionSalaryAmount()));
0763:
0764: userAppointmentTaskPeriod
0765: .setTotalFteAmount(userAppointmentTaskPeriod
0766: .getAgencyFullTimeEquivalentPercent()
0767: .add(
0768: userAppointmentTaskPeriod
0769: .getInstitutionFullTimeEquivalentPercent()));
0770: userAppointmentTaskPeriod
0771: .setTotalGradAsstSalaryAmount(userAppointmentTaskPeriod
0772: .getAgencySalaryAmount()
0773: .add(
0774: userAppointmentTaskPeriod
0775: .getInstitutionSalaryAmount()));
0776: userAppointmentTaskPeriod
0777: .setTotalHealthInsuranceAmount(userAppointmentTaskPeriod
0778: .getAgencyHealthInsuranceAmount()
0779: .add(
0780: userAppointmentTaskPeriod
0781: .getInstitutionHealthInsuranceAmount()));
0782: userAppointmentTaskPeriod
0783: .setTotalFeeRemissionsAmount(userAppointmentTaskPeriod
0784: .getUserCreditHoursNumber()
0785: .multiply(
0786: userAppointmentTaskPeriod
0787: .getUserCreditHourAmount())
0788: .add(
0789: userAppointmentTaskPeriod
0790: .getUserMiscellaneousFeeAmount()));
0791: }
0792: }
0793: }
0794: }
0795:
0796: /**
0797: * This method calculates the salary/period salary one person listed on a budget.
0798: *
0799: * @parm budgetUser - The user whose compensation is being calculated
0800: * @parm budgetDocument - The budgetDocument with information about how to calculate the period salary: period lengths and
0801: * inflation rates
0802: */
0803: public void calculatePersonCompensation(BudgetUser budgetUser,
0804: BudgetDocument budgetDocument) {
0805: calculatePersonSalary(budgetUser, budgetDocument);
0806: calculatePersonRequestAmounts(budgetUser, budgetDocument
0807: .getBudget().getFringeRates());
0808: }
0809:
0810: /**
0811: * This method calculates the salary/period salary for all people listed on a budget.
0812: *
0813: * @parm budgetUser - The user whose compensation is being calculated
0814: * @parm budgetDocument - The budgetDocument with information about how to calculate the period salary: period lengths and
0815: * inflation rates
0816: */
0817: public void calculateAllPersonnelCompensation(
0818: BudgetDocument budgetDocument) {
0819: budgetDocument.getBudget()
0820: .refreshReferenceObject("fringeRates");
0821: BudgetTask firstBudgetTask = (BudgetTask) budgetDocument
0822: .getBudget().getTasks().get(0);
0823: for (BudgetUser budgetUser : budgetDocument.getBudget()
0824: .getPersonnel()) {
0825: if (budgetUser.getCurrentTaskNumber() == null)
0826: budgetUser.setCurrentTaskNumber(firstBudgetTask
0827: .getBudgetTaskSequenceNumber());
0828: verifyAndPropogateAppointmentType(budgetUser,
0829: budgetDocument);
0830: calculatePersonCompensation(budgetUser, budgetDocument);
0831: }
0832: }
0833:
0834: private void verifyAndPropogateAppointmentType(
0835: BudgetUser budgetUser, BudgetDocument budgetDocument) {
0836: List newUserAppointmentTasks = new ArrayList();
0837:
0838: // check to see if the budgetUser.getAppointmentTypeCode has a value - if it doesn't, we're coming into the page from
0839: // another page or are reloading data. appointment type code is not stored
0840: // in the database. If it does exist, check to make sure that the type code hasn't changed since the last su
0841: if (budgetUser.getAppointmentTypeCode() != null
0842: && !budgetUser.getAppointmentTypeCode().equals(
0843: budgetUser.getPreviousAppointmentTypeCode())) {
0844: // appointment type has changed
0845:
0846: AppointmentType previousAppointmentType = (AppointmentType) businessObjectService
0847: .retrieve(new AppointmentType(budgetUser
0848: .getPreviousAppointmentTypeCode()));
0849:
0850: // Update the Fringes for this person to ensure that we're getting the most recent amounts
0851: BudgetFringeRate budgetFringeRate = budgetFringeRateService
0852: .getBudgetFringeRateForPerson(budgetUser);
0853: budgetUser.setAppointmentTypeCode(budgetFringeRate
0854: .getInstitutionAppointmentTypeCode());
0855: budgetUser.setAppointmentTypeDescription(budgetFringeRate
0856: .getAppointmentType()
0857: .getAppointmentTypeDescription());
0858:
0859: BudgetFringeRate secondaryBudgetFringeRate = null;
0860: if (budgetFringeRate.getAppointmentType()
0861: .getRelatedAppointmentTypeCode() != null) {
0862: secondaryBudgetFringeRate = budgetFringeRateService
0863: .getBudgetFringeRate(budgetDocument
0864: .getDocumentNumber(), budgetFringeRate
0865: .getAppointmentType()
0866: .getRelatedAppointmentTypeCode());
0867: budgetUser
0868: .setSecondaryAppointmentTypeCode(secondaryBudgetFringeRate
0869: .getInstitutionAppointmentTypeCode());
0870: } else {
0871: if (budgetUser.getSecondaryAppointmentTypeCode() != null
0872: && budgetUser
0873: .getSecondaryAppointmentTypeCode()
0874: .equals(
0875: budgetUser
0876: .getAppointmentTypeCode())) {
0877: // previous secondary appointment type is the same as the current appointment type - convert previous secondary
0878: // to new primary
0879: for (Iterator i = budgetUser
0880: .getUserAppointmentTasks().iterator(); i
0881: .hasNext();) {
0882: // using iterator instead of enhanced for-loop so I can use iter.remove()
0883: UserAppointmentTask userAppointmentTask = (UserAppointmentTask) i
0884: .next();
0885: if (userAppointmentTask
0886: .getInstitutionAppointmentTypeCode()
0887: .equals(
0888: budgetUser
0889: .getAppointmentTypeCode())) {
0890: i.remove();
0891: }
0892: }
0893: }
0894: budgetUser.setSecondaryAppointmentTypeCode(null);
0895: }
0896:
0897: for (UserAppointmentTask userAppointmentTask : budgetUser
0898: .getUserAppointmentTasks()) {
0899:
0900: // check to see if this userAppointmentTask is associated with the primary or secondary (related) appointment type.
0901: if (!userAppointmentTask.isSecondaryAppointment()) {
0902: userAppointmentTask
0903: .setBudgetFringeRate(budgetFringeRate);
0904: userAppointmentTask
0905: .setInstitutionAppointmentTypeCode(budgetFringeRate
0906: .getInstitutionAppointmentTypeCode());
0907:
0908: // trickle-down the new appointmentType into the userAppointmentTaskPeriod objects
0909: for (UserAppointmentTaskPeriod userAppointmentTaskPeriod : userAppointmentTask
0910: .getUserAppointmentTaskPeriods()) {
0911: userAppointmentTaskPeriod
0912: .setBudgetFringeRate(budgetFringeRate);
0913: userAppointmentTaskPeriod
0914: .setInstitutionAppointmentTypeCode(budgetFringeRate
0915: .getInstitutionAppointmentTypeCode());
0916: }
0917: } else if (secondaryBudgetFringeRate != null) {
0918: // this is a secondary appointment type record, update the record and the associated userAppointmentTaskPeriod
0919: // records
0920: userAppointmentTask
0921: .setBudgetFringeRate(secondaryBudgetFringeRate);
0922: userAppointmentTask
0923: .setInstitutionAppointmentTypeCode(secondaryBudgetFringeRate
0924: .getInstitutionAppointmentTypeCode());
0925:
0926: for (UserAppointmentTaskPeriod userAppointmentTaskPeriod : userAppointmentTask
0927: .getUserAppointmentTaskPeriods()) {
0928: userAppointmentTaskPeriod
0929: .setBudgetFringeRate(secondaryBudgetFringeRate);
0930: userAppointmentTaskPeriod
0931: .setInstitutionAppointmentTypeCode(secondaryBudgetFringeRate
0932: .getInstitutionAppointmentTypeCode());
0933: }
0934: }
0935: }
0936: if (secondaryBudgetFringeRate != null
0937: && budgetUser.getUserAppointmentTasks().size()
0938: / budgetDocument.getBudget().getTasks()
0939: .size() < (secondaryBudgetFringeRate != null ? 2
0940: : 1)) {
0941: // There is a secondary appointment type, but there are no records created for it yet. Create them.
0942: BudgetUser missingBudgetUser = new BudgetUser(
0943: budgetUser);
0944: missingBudgetUser
0945: .setAppointmentTypeCode(secondaryBudgetFringeRate
0946: .getInstitutionAppointmentTypeCode());
0947: for (BudgetTask task : budgetDocument.getBudget()
0948: .getTasks()) {
0949: budgetUser.getUserAppointmentTasks().add(
0950: createUserAppointmentTask(
0951: missingBudgetUser, budgetDocument,
0952: secondaryBudgetFringeRate, task,
0953: budgetDocument.getBudget()
0954: .getPeriods(), true));
0955: }
0956: }
0957: } else if (budgetUser.getAppointmentTypeCode() == null) {
0958: // Coming into the page with no appointment type code set in BudgetUser - need to set it.
0959: List<AppointmentType> appointmentTypes = new ArrayList();
0960: for (UserAppointmentTask userAppointmentTask : budgetUser
0961: .getUserAppointmentTasks()) {
0962: if (!appointmentTypes.contains(userAppointmentTask
0963: .getInstitutionAppointmentTypeCode())) {
0964: appointmentTypes
0965: .add((AppointmentType) businessObjectService
0966: .retrieve(new AppointmentType(
0967: userAppointmentTask
0968: .getInstitutionAppointmentTypeCode())));
0969: }
0970: }
0971: if (appointmentTypes.size() == 1) {
0972: BudgetFringeRate budgetFringeRate = budgetFringeRateService
0973: .getBudgetFringeRateForPerson(budgetUser);
0974: budgetUser.setAppointmentTypeCode(budgetFringeRate
0975: .getInstitutionAppointmentTypeCode());
0976: } else {
0977: for (AppointmentType appointmentType : appointmentTypes) {
0978: if (appointmentType.getRelatedAppointmentTypeCode() != null) {
0979: budgetUser
0980: .setAppointmentTypeCode(appointmentType
0981: .getAppointmentTypeCode());
0982: } else {
0983: budgetUser
0984: .setSecondaryAppointmentTypeCode(appointmentType
0985: .getAppointmentTypeCode());
0986: }
0987: }
0988: for (UserAppointmentTask userAppointmentTask : budgetUser
0989: .getUserAppointmentTasks()) {
0990: userAppointmentTask
0991: .setSecondaryAppointment(userAppointmentTask
0992: .getInstitutionAppointmentTypeCode()
0993: .equals(
0994: budgetUser
0995: .getSecondaryAppointmentTypeCode()));
0996: }
0997: }
0998: }
0999: }
1000:
1001: public void reconcileAndCalculatePersonnel(
1002: BudgetDocument budgetDocument) {
1003: BudgetTask firstBudgetTask = (BudgetTask) budgetDocument
1004: .getBudget().getTasks().get(0);
1005: for (BudgetUser budgetUser : budgetDocument.getBudget()
1006: .getPersonnel()) {
1007: if (budgetUser.getCurrentTaskNumber() == null)
1008: budgetUser.setCurrentTaskNumber(firstBudgetTask
1009: .getBudgetTaskSequenceNumber());
1010: reconcilePersonTaskPeriod(budgetUser, budgetDocument);
1011: calculatePersonCompensation(budgetUser, budgetDocument);
1012: }
1013: }
1014:
1015: /**
1016: * This method calculates whether tasks/period have been added to the budget that need to be included with all personnel
1017: *
1018: * @parm budgetDocument - The budgetDocument with information about how to calculate the period salary: period lengths and
1019: * inflation rates
1020: */
1021: public void reconcileAllPersonnelTaskPeriod(
1022: BudgetDocument budgetDocument) {
1023: for (BudgetUser budgetUser : budgetDocument.getBudget()
1024: .getPersonnel()) {
1025: reconcilePersonTaskPeriod(budgetUser, budgetDocument);
1026: }
1027: }
1028:
1029: /**
1030: * This method calculates whether tasks/period have been added to the budget that need to be included for one person
1031: *
1032: * @parm budgetDocument - The budgetDocument with information about how to calculate the period salary: period lengths and
1033: * inflation rates
1034: * @parm budgetUser - The individual for whom we are reconciling tasks/period
1035: */
1036: public void reconcilePersonTaskPeriod(BudgetUser budgetUser,
1037: BudgetDocument budgetDocument) {
1038: BudgetFringeRate budgetFringeRate = budgetFringeRateService
1039: .getBudgetFringeRateForPerson(budgetUser);
1040: budgetUser.setAppointmentTypeCode(budgetFringeRate
1041: .getInstitutionAppointmentTypeCode());
1042: budgetUser.setAppointmentTypeDescription(budgetFringeRate
1043: .getAppointmentType().getAppointmentTypeDescription());
1044: if (budgetFringeRate.getAppointmentType()
1045: .getRelatedAppointmentTypeCode() != null) {
1046: budgetUser.setSecondaryAppointmentTypeCode(budgetFringeRate
1047: .getAppointmentType()
1048: .getRelatedAppointmentTypeCode());
1049: }
1050:
1051: List<BudgetTask> tasks = new ArrayList(budgetDocument
1052: .getBudget().getTasks());
1053:
1054: List<BudgetFringeRate> budgetFringeRates = new ArrayList();
1055: budgetFringeRates.add(budgetFringeRate);
1056:
1057: // Iterate over the list of UserAppointmentTask objects, remove the task from each object from the Tasks List.
1058: for (UserAppointmentTask userAppointmentTask : budgetUser
1059: .getUserAppointmentTasks()) {
1060: userAppointmentTask
1061: .refreshReferenceObject(KraConstants.TASK);
1062: ObjectUtils.removeObjectWithIdentitcalKey(tasks,
1063: userAppointmentTask.getTask());
1064:
1065: if (!ObjectUtils.collectionContainsObjectWithIdentitcalKey(
1066: budgetFringeRates, userAppointmentTask
1067: .getBudgetFringeRate())) {
1068: budgetFringeRate = userAppointmentTask
1069: .getBudgetFringeRate();
1070: budgetFringeRates.add(budgetFringeRate);
1071: }
1072:
1073: List<BudgetPeriod> periods = new ArrayList(budgetDocument
1074: .getBudget().getPeriods());
1075:
1076: // Iterate over the list of UserAppointmentTaskPeriod objectes, remove the period associated with each object from the
1077: // uatpPeriods list
1078: for (UserAppointmentTaskPeriod userAppointmentTaskPeriod : userAppointmentTask
1079: .getUserAppointmentTaskPeriods()) {
1080: userAppointmentTaskPeriod
1081: .refreshReferenceObject(KraConstants.PERIOD);
1082: ObjectUtils.removeObjectWithIdentitcalKey(periods,
1083: userAppointmentTaskPeriod.getPeriod());
1084: }
1085:
1086: // Any periods still in the list do not have UserAppointmentTaskPeriod objects associated with them. Need to create one.
1087: for (BudgetPeriod period : periods) {
1088: userAppointmentTask.getUserAppointmentTaskPeriods()
1089: .add(
1090: createUserAppointmentTaskPeriod(
1091: budgetUser, budgetDocument,
1092: budgetFringeRate,
1093: userAppointmentTask.getTask(),
1094: period));
1095: }
1096:
1097: userAppointmentTask
1098: .setSecondaryAppointment(userAppointmentTask
1099: .getInstitutionAppointmentTypeCode()
1100: .equals(
1101: budgetUser
1102: .getSecondaryAppointmentTypeCode()));
1103:
1104: Collections.sort(userAppointmentTask
1105: .getUserAppointmentTaskPeriods());
1106: }
1107:
1108: // Any tasks left over did not have UserAppointmentTask objects associated with them. Create them.
1109: for (BudgetTask task : tasks) {
1110: for (Iterator budgetFringeRateIterator = budgetFringeRates
1111: .iterator(); budgetFringeRateIterator.hasNext();) {
1112: budgetFringeRate = (BudgetFringeRate) budgetFringeRateIterator
1113: .next();
1114: budgetUser
1115: .getUserAppointmentTasks()
1116: .add(
1117: createUserAppointmentTask(
1118: budgetUser,
1119: budgetDocument,
1120: budgetFringeRate,
1121: task,
1122: budgetDocument.getBudget()
1123: .getPeriods(),
1124: budgetFringeRate
1125: .getInstitutionAppointmentTypeCode()
1126: .equals(
1127: budgetUser
1128: .getSecondaryAppointmentTypeCode())));
1129: }
1130: }
1131:
1132: Collections.sort(budgetUser.getUserAppointmentTasks());
1133: }
1134:
1135: /**
1136: * This method will remove Personnel entries that relate to tasks/periods that no longer exist. See cleanseNonpersonnel
1137: *
1138: * @param budgetDocument
1139: */
1140: public void cleansePersonnel(BudgetDocument budgetDocument) {
1141: List budgetPersonnel = budgetDocument.getBudget()
1142: .getPersonnel();
1143: List budgetTasks = budgetDocument.getBudget().getTasks();
1144: List budgetPeriods = budgetDocument.getBudget().getPeriods();
1145:
1146: // Not using JDK 1.5 style for-loop so Iterator.remove() can be called
1147: for (Iterator budgetUserIter = budgetPersonnel.iterator(); budgetUserIter
1148: .hasNext();) {
1149: BudgetUser budgetUser = (BudgetUser) budgetUserIter.next();
1150: List userAppointments = new ArrayList();
1151: for (Iterator userAppointmentTaskIter = budgetUser
1152: .getUserAppointmentTasks().iterator(); userAppointmentTaskIter
1153: .hasNext();) {
1154: // loop through usreAppointmentTasks and check that the associated exists in the Task list
1155: UserAppointmentTask userAppointmentTask = (UserAppointmentTask) userAppointmentTaskIter
1156: .next();
1157: userAppointments.add(userAppointmentTask
1158: .getInstitutionAppointmentTypeCode());
1159: BudgetTask budgetTask = (BudgetTask) businessObjectService
1160: .retrieve(new BudgetTask(userAppointmentTask
1161: .getDocumentNumber(),
1162: userAppointmentTask
1163: .getBudgetTaskSequenceNumber()));
1164: if (!ObjectUtils
1165: .collectionContainsObjectWithIdentitcalKey(
1166: budgetTasks, budgetTask)) {
1167: userAppointmentTaskIter.remove();
1168: } else {
1169: // loop through userAppointmentTaskPeriods and check each period.
1170: for (Iterator userAppointmentTaskPeriodIter = userAppointmentTask
1171: .getUserAppointmentTaskPeriods().iterator(); userAppointmentTaskPeriodIter
1172: .hasNext();) {
1173: UserAppointmentTaskPeriod userAppointmentTaskPeriod = (UserAppointmentTaskPeriod) userAppointmentTaskPeriodIter
1174: .next();
1175: BudgetPeriod budgetPeriod = (BudgetPeriod) businessObjectService
1176: .retrieve(new BudgetPeriod(
1177: userAppointmentTaskPeriod
1178: .getDocumentNumber(),
1179: userAppointmentTaskPeriod
1180: .getBudgetPeriodSequenceNumber()));
1181: if (!ObjectUtils
1182: .collectionContainsObjectWithIdentitcalKey(
1183: budgetPeriods, budgetPeriod)) {
1184: userAppointmentTaskPeriodIter.remove();
1185: } else {
1186: if (!(StringUtils
1187: .contains(
1188: getAppointmentTypeMappings()
1189: .get(
1190: KraConstants.FULL_YEAR)
1191: .toString(),
1192: userAppointmentTask
1193: .getInstitutionAppointmentTypeCode()) || StringUtils
1194: .contains(
1195: getAppointmentTypeMappings()
1196: .get(
1197: KraConstants.ACADEMIC_YEAR_SUMMER)
1198: .toString(),
1199: userAppointmentTask
1200: .getInstitutionAppointmentTypeCode()))) {
1201: // Not a salaried appointment type
1202: userAppointmentTaskPeriod
1203: .setAgencyPercentEffortAmount(new KualiInteger(
1204: 0));
1205: userAppointmentTaskPeriod
1206: .setInstitutionCostSharePercentEffortAmount(new KualiInteger(
1207: 0));
1208:
1209: }
1210:
1211: if (!StringUtils
1212: .contains(
1213: getAppointmentTypeMappings()
1214: .get(
1215: KraConstants.HOURLY)
1216: .toString(),
1217: userAppointmentTask
1218: .getInstitutionAppointmentTypeCode())) {
1219: // Not an hourly appointment type; remove hourly data
1220: userAppointmentTaskPeriod
1221: .setUserAgencyHours(new KualiInteger(
1222: 0));
1223: userAppointmentTaskPeriod
1224: .setUserInstitutionHours(new KualiInteger(
1225: 0));
1226: }
1227:
1228: if (!StringUtils
1229: .contains(
1230: getAppointmentTypeMappings()
1231: .get(
1232: KraConstants.GRADUATE_ASSISTANT)
1233: .toString(),
1234: userAppointmentTask
1235: .getInstitutionAppointmentTypeCode())) {
1236: userAppointmentTaskPeriod
1237: .setAgencyFullTimeEquivalentPercent(new KualiInteger(
1238: 0));
1239: userAppointmentTaskPeriod
1240: .setAgencyHealthInsuranceAmount(new KualiInteger(
1241: 0));
1242: userAppointmentTaskPeriod
1243: .setAgencyRequestedFeesAmount(new KualiInteger(
1244: 0));
1245: userAppointmentTaskPeriod
1246: .setAgencySalaryAmount(new KualiInteger(
1247: 0));
1248: userAppointmentTaskPeriod
1249: .setInstitutionFullTimeEquivalentPercent(new KualiInteger(
1250: 0));
1251: userAppointmentTaskPeriod
1252: .setInstitutionHealthInsuranceAmount(new KualiInteger(
1253: 0));
1254: userAppointmentTaskPeriod
1255: .setInstitutionRequestedFeesAmount(new KualiInteger(
1256: 0));
1257: userAppointmentTaskPeriod
1258: .setUserMiscellaneousFeeAmount(new KualiInteger(
1259: 0));
1260: userAppointmentTaskPeriod
1261: .setUserCreditHourAmount(new KualiDecimal(
1262: 0));
1263: userAppointmentTaskPeriod
1264: .setUserCreditHoursNumber(new KualiInteger(
1265: 0));
1266: userAppointmentTaskPeriod
1267: .setInstitutionSalaryAmount(new KualiInteger(
1268: 0));
1269: }
1270: }
1271: }
1272:
1273: if (userAppointmentTask
1274: .getUserAppointmentTaskPeriods().isEmpty()
1275: || userAppointments.size() > 1
1276: && !userAppointments
1277: .contains(getAppointmentTypeMappings()
1278: .get(
1279: KraConstants.ACADEMIC_YEAR))
1280: && userAppointments
1281: .contains(getAppointmentTypeMappings()
1282: .get(
1283: KraConstants.ACADEMIC_SUMMER))) {
1284: // All of the associated userAppointmentTaskPeriods have been removed from this userAppointmentTask, and it
1285: // should therefore be removed as well
1286: userAppointmentTaskIter.remove();
1287: }
1288: }
1289: }
1290:
1291: // done evaluating userAppointmentTasks for this budgetUser, check to see if there are any remaining
1292: if (budgetUser.getUserAppointmentTasks().isEmpty()
1293: && !budgetUser.isPersonProjectDirectorIndicator()) {
1294: // none remaining remove this budgetUser from the list
1295: budgetUserIter.remove();
1296: }
1297: }
1298: }
1299:
1300: public void reconcileProjectDirector(BudgetDocument budgetDocument) {
1301: Budget budget = budgetDocument.getBudget();
1302:
1303: BudgetUser projectDirector = null;
1304:
1305: for (Iterator i = budget.getPersonnel().iterator(); i.hasNext();) {
1306: BudgetUser budgetUser = (BudgetUser) i.next();
1307: if (budgetUser.isPersonProjectDirectorIndicator()) {
1308: projectDirector = budgetUser;
1309: break;
1310: }
1311: }
1312:
1313: if (projectDirector == null) {
1314: // PD does not exist in Personnel List already
1315: projectDirector = new BudgetUser();
1316: if (!budget.isProjectDirectorToBeNamedIndicator()) {
1317: // PD is a real person (not TBN)
1318: projectDirector.setPersonUniversalIdentifier(budget
1319: .getBudgetProjectDirectorUniversalIdentifier());
1320: projectDirector.refresh();
1321: }
1322: budgetDocument.addPersonnel(projectDirector);
1323: } else {
1324: // PD does exist in Personnel List already
1325: String paramsPdUid = budget
1326: .getBudgetProjectDirectorUniversalIdentifier() != null ? budget
1327: .getBudgetProjectDirectorUniversalIdentifier()
1328: : "";
1329: String personnelSysId = projectDirector
1330: .getPersonUniversalIdentifier() != null ? projectDirector
1331: .getPersonUniversalIdentifier()
1332: : "";
1333: if (!(budget.isProjectDirectorToBeNamedIndicator() && StringUtils
1334: .isEmpty(personnelSysId))
1335: && !paramsPdUid.equals(personnelSysId)) {
1336: // PD from params is not the same as the PD from the Personnel List
1337:
1338: boolean projectDirectorFound = false;
1339:
1340: projectDirector
1341: .setPersonProjectDirectorIndicator(false);
1342: projectDirector = null;
1343:
1344: if (!budget.isProjectDirectorToBeNamedIndicator()) {
1345: // PD from Params is not TBN
1346: for (Iterator i = budget.getPersonnel().iterator(); i
1347: .hasNext()
1348: && !projectDirectorFound;) {
1349: BudgetUser budgetUser = (BudgetUser) i.next();
1350: if (budgetUser.getPersonUniversalIdentifier() != null
1351: && budgetUser
1352: .getPersonUniversalIdentifier()
1353: .equals(paramsPdUid)) {
1354: projectDirector = budgetUser;
1355: projectDirectorFound = true;
1356: }
1357: }
1358:
1359: if (!projectDirectorFound) {
1360: // PD from params was not found in the existing Personnel list; need to create a new personnel entry
1361: projectDirector = new BudgetUser();
1362: projectDirector
1363: .setPersonUniversalIdentifier(paramsPdUid);
1364: projectDirector.refresh();
1365: budgetDocument.addPersonnel(projectDirector);
1366: }
1367: } else {
1368: // PD from Params is TBN
1369: projectDirector = new BudgetUser();
1370: budgetDocument.addPersonnel(projectDirector);
1371: }
1372: }
1373: }
1374: projectDirector.setPersonProjectDirectorIndicator(true);
1375: projectDirector.setPersonSeniorKeyIndicator(true);
1376: projectDirector.setRole(KraConstants.PROJECT_DIRECTOR);
1377: }
1378:
1379: public synchronized HashMap getAppointmentTypeMappings() {
1380: // if (appointmentTypeMappings == null) {
1381: appointmentTypeMappings = new HashMap();
1382:
1383: // using Arrays.asList(String[]).toString() so I can easily check from elsewhere whether or not a particular appointment
1384: // type is in the list
1385: appointmentTypeMappings
1386: .put(
1387: KraConstants.FULL_YEAR,
1388: parameterService
1389: .getParameterValues(
1390: BudgetDocument.class,
1391: KraConstants.KRA_BUDGET_PERSONNEL_FULL_YEAR_APPOINTMENT_TYPES)
1392: .toString());
1393: List<String> academicYearSummerList = parameterService
1394: .getParameterValues(
1395: BudgetDocument.class,
1396: KraConstants.KRA_BUDGET_PERSONNEL_SUMMER_GRID_APPOINTMENT_TYPES);
1397: appointmentTypeMappings.put(KraConstants.ACADEMIC_YEAR_SUMMER,
1398: academicYearSummerList.toString());
1399: appointmentTypeMappings.put(
1400: KraConstants.ACADEMIC_YEAR_SUMMER_ARRAY,
1401: academicYearSummerList.toArray(new String[] {}));
1402: appointmentTypeMappings
1403: .put(
1404: KraConstants.HOURLY,
1405: parameterService
1406: .getParameterValues(
1407: BudgetDocument.class,
1408: KraConstants.KRA_BUDGET_PERSONNEL_HOURLY_APPOINTMENT_TYPES)
1409: .toString());
1410: appointmentTypeMappings
1411: .put(
1412: KraConstants.GRADUATE_ASSISTANT,
1413: parameterService
1414: .getParameterValues(
1415: BudgetDocument.class,
1416: KraConstants.KRA_BUDGET_PERSONNEL_GRADUATE_RESEARCH_ASSISTANT_APPOINTMENT_TYPES)
1417: .toString());
1418: appointmentTypeMappings
1419: .put(
1420: KraConstants.ACADEMIC_SUMMER,
1421: parameterService
1422: .getParameterValue(
1423: BudgetDocument.class,
1424: KraConstants.KRA_BUDGET_PERSONNEL_SUMMER_GRID_APPOINTMENT_TYPE));
1425: appointmentTypeMappings
1426: .put(
1427: KraConstants.ACADEMIC_YEAR,
1428: parameterService
1429: .getParameterValue(
1430: BudgetDocument.class,
1431: KraConstants.KRA_BUDGET_PERSONNEL_ACADEMIC_YEAR_APPOINTMENT_TYPE));
1432: // }
1433: return appointmentTypeMappings;
1434: }
1435:
1436: public Date getAppointmentTypeEffectiveStartDate(
1437: AppointmentType appointmentType, Integer fiscalYear) {
1438:
1439: AppointmentTypeEffectiveDate appointmentTypeEffectiveDate = (AppointmentTypeEffectiveDate) businessObjectService
1440: .retrieve(new AppointmentTypeEffectiveDate(
1441: appointmentType.getAppointmentTypeCode(),
1442: fiscalYear));
1443:
1444: if (appointmentTypeEffectiveDate != null) {
1445: return appointmentTypeEffectiveDate
1446: .getAppointmentTypeBeginDate();
1447: } else {
1448: return SpringContext.getBean(UniversityDateService.class)
1449: .getFirstDateOfFiscalYear(fiscalYear);
1450: }
1451: }
1452:
1453: public Date getAppointmentTypeEffectiveEndDate(
1454: AppointmentType appointmentType, Integer fiscalYear) {
1455:
1456: AppointmentTypeEffectiveDate appointmentTypeEffectiveDate = (AppointmentTypeEffectiveDate) businessObjectService
1457: .retrieve(new AppointmentTypeEffectiveDate(
1458: appointmentType.getAppointmentTypeCode(),
1459: fiscalYear));
1460:
1461: if (appointmentTypeEffectiveDate != null) {
1462: return appointmentTypeEffectiveDate
1463: .getAppointmentTypeEndDate();
1464: } else {
1465: return SpringContext.getBean(UniversityDateService.class)
1466: .getLastDateOfFiscalYear(fiscalYear);
1467: }
1468: }
1469:
1470: public void setBusinessObjectService(
1471: BusinessObjectService businessObjectService) {
1472: this .businessObjectService = businessObjectService;
1473: }
1474:
1475: public void setBudgetFringeRateService(
1476: BudgetFringeRateService budgetFringeRateService) {
1477: this .budgetFringeRateService = budgetFringeRateService;
1478: }
1479:
1480: public class PeriodSalary {
1481: private int workDaysInPeriod;
1482: private KualiInteger periodSalary;
1483:
1484: public PeriodSalary(KualiInteger periodSalary,
1485: int workDaysInPeriod) {
1486: this .periodSalary = periodSalary;
1487: this .workDaysInPeriod = workDaysInPeriod;
1488: }
1489:
1490: public PeriodSalary add(PeriodSalary periodSalary) {
1491: this .periodSalary = this .periodSalary
1492: .add(periodSalary.periodSalary);
1493: this .workDaysInPeriod += periodSalary.workDaysInPeriod;
1494: return this ;
1495: }
1496:
1497: public KualiInteger getPeriodSalary() {
1498: return periodSalary;
1499: }
1500:
1501: public void setPeriodSalary(KualiInteger periodSalary) {
1502: this .periodSalary = periodSalary;
1503: }
1504:
1505: public int getWorkDaysInPeriod() {
1506: return workDaysInPeriod;
1507: }
1508:
1509: public void setWorkDaysInPeriod(int workDaysInPeriod) {
1510: this .workDaysInPeriod = workDaysInPeriod;
1511: }
1512: }
1513:
1514: public void setParameterService(ParameterService parameterService) {
1515: this.parameterService = parameterService;
1516: }
1517: }
|