/* * 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.ec.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.kuali.kfs.module.ec.EffortConstants; import org.kuali.kfs.module.ec.EffortPropertyConstants; import org.kuali.kfs.module.ec.businessobject.EffortCertificationDetail; import org.kuali.kfs.sys.DynamicCollectionComparator; import org.kuali.kfs.sys.DynamicCollectionComparator.SortOrder; import org.kuali.kfs.sys.ObjectUtil; import org.kuali.rice.core.api.util.type.KualiDecimal; /** * grouping a set of detail lines. The class is implemented to manage: summary line and delegating line. */ public class DetailLineGroup { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DetailLineGroup.class); EffortCertificationDetail summaryDetailLine; EffortCertificationDetail delegateDetailLine; List<EffortCertificationDetail> detailLines; /** * Constructs a DetailLineGroup.java. */ public DetailLineGroup() { this(null); } /** * Constructs a DetailLineGroup.java. * * @param detailLine the given detail line */ public DetailLineGroup(EffortCertificationDetail newDetailLine) { detailLines = new ArrayList<EffortCertificationDetail>(); summaryDetailLine = new EffortCertificationDetail(); if (newDetailLine != null) { String groupId = getKeysAsString(newDetailLine); ObjectUtil.buildObject(summaryDetailLine, newDetailLine); summaryDetailLine.setGroupId(groupId); this.addNewLineIntoGroup(newDetailLine, groupId); } summaryDetailLine.setFinancialObjectCode(null); summaryDetailLine.setPositionNumber(null); } /** * update the effort percent of the delegate detail line if the effort on the summary line has been changed */ public void updateDelegateDetailLineEffort() { Integer difference = this.getEffortPercentChanged(); if (difference != 0) { Integer effortPercent = delegateDetailLine.getEffortCertificationUpdatedOverallPercent() + difference; delegateDetailLine.setEffortCertificationUpdatedOverallPercent(effortPercent); } } /** * update the effort percents of the detail lines if the effort on the summary line has been changed */ public void updateDetailLineEffortPercent() { int totalDifference = this.getEffortPercentChanged(); List<EffortCertificationDetail> detailLines = this.getDetailLines(); DynamicCollectionComparator.sort(detailLines, SortOrder.DESC, EffortPropertyConstants.PERSISED_PAYROLL_AMOUNT); // restore the intial effort percents before update the detail lines for (EffortCertificationDetail detailLine : detailLines) { detailLine.setEffortCertificationUpdatedOverallPercent(detailLine.getPersistedEffortPercent()); } for (EffortCertificationDetail detailLine : detailLines) { if (totalDifference == 0) { break; } int currentPercent = detailLine.getPersistedEffortPercent(); int currentDifference = currentPercent + totalDifference; boolean needUpdateMultipleLines = (currentDifference < 0); int effortPercent = needUpdateMultipleLines ? 0 : currentDifference; detailLine.setEffortCertificationUpdatedOverallPercent(effortPercent); totalDifference = needUpdateMultipleLines ? currentDifference : 0; } } /** * update the payroll amounts of the detail lines if the payroll amount on the summary line has been changed */ public void updateDetailLinePayrollAmount() { KualiDecimal totalDifference = this.getPayrollAmountChanged(); if (totalDifference.isZero()) { return; } List<EffortCertificationDetail> detailLines = this.getDetailLines(); DynamicCollectionComparator.sort(detailLines, SortOrder.DESC, EffortPropertyConstants.PERSISED_PAYROLL_AMOUNT); // restore the intial payroll amounts before update the detail lines for (EffortCertificationDetail detailLine : detailLines) { detailLine.setEffortCertificationPayrollAmount(detailLine.getPersistedPayrollAmount()); } for (EffortCertificationDetail detailLine : detailLines) { if (totalDifference.isZero()) { break; } KualiDecimal currentAmount = detailLine.getPersistedPayrollAmount(); KualiDecimal currentDifference = currentAmount.add(totalDifference); boolean needUpdateMultipleLines = currentDifference.isNegative(); KualiDecimal payrollAmount = needUpdateMultipleLines ? KualiDecimal.ZERO : currentDifference; detailLine.setEffortCertificationPayrollAmount(payrollAmount); totalDifference = needUpdateMultipleLines ? currentDifference : KualiDecimal.ZERO; } } /** * group the given detail lines by the key fields * * @param detailLines the given detail lines * @param keyFields the given key fields * @return the groups of detail lines */ public static Map<String, DetailLineGroup> groupDetailLines(List<EffortCertificationDetail> detailLines) { Map<String, DetailLineGroup> detailLineGroupMap = new HashMap<String, DetailLineGroup>(); for (EffortCertificationDetail line : detailLines) { String groupId = getKeysAsString(line); if (detailLineGroupMap.containsKey(groupId)) { DetailLineGroup group = detailLineGroupMap.get(groupId); group.addNewLineIntoGroup(line, groupId); } else { DetailLineGroup group = new DetailLineGroup(line); detailLineGroupMap.put(groupId, group); } } return detailLineGroupMap; } /** * concat the keys of the given detail line as a single string * * @param line the given detail line * @return a single string built from the keys of the given detail line */ public static String getKeysAsString(EffortCertificationDetail line) { return ObjectUtil.concatPropertyAsString(line, EffortConstants.DETAIL_LINES_GROUPING_FILEDS); } /** * get the difference between the updated effort amount and the current effort amount * * @return the difference between the updated effort amount and the current effort amount */ private Integer getEffortPercentChanged() { Integer currentEffortPercent = EffortCertificationDetail.getTotalPersistedEffortPercent(detailLines); Integer updatedEffortPercent = summaryDetailLine.getEffortCertificationUpdatedOverallPercent(); return updatedEffortPercent - currentEffortPercent; } /** * get the difference between the updated payroll amount and the current payroll amount * * @return the difference between the updated payroll amount and the current payroll amount */ private KualiDecimal getPayrollAmountChanged() { KualiDecimal currentAmount = EffortCertificationDetail.getTotalPersistedPayrollAmount(detailLines); KualiDecimal updatedAmount = summaryDetailLine.getEffortCertificationPayrollAmount(); return updatedAmount.subtract(currentAmount); } /** * update the group when a new detail line is added * * @param line the new detail line */ private void addNewLineIntoGroup(EffortCertificationDetail newDetailLine, String groupId) { if (detailLines.contains(newDetailLine)) { return; } newDetailLine.setGroupId(groupId); detailLines.add(newDetailLine); delegateDetailLine = this.getDetailLineWithMaxPayrollAmount(detailLines); this.updateSummaryDetailLineAmount(); } /** * update the payroll amounts and effort percents based on current detail lines */ private void updateSummaryDetailLineAmount() { Integer originalEffortPercent = EffortCertificationDetail.getTotalOriginalEffortPercent(detailLines); summaryDetailLine.setEffortCertificationCalculatedOverallPercent(originalEffortPercent); Integer effortPercent = EffortCertificationDetail.getTotalEffortPercent(detailLines); summaryDetailLine.setEffortCertificationUpdatedOverallPercent(effortPercent); Integer persistedEffortPercent = EffortCertificationDetail.getTotalPersistedEffortPercent(detailLines); summaryDetailLine.setPersistedEffortPercent(persistedEffortPercent); KualiDecimal originalPayrollAmount = EffortCertificationDetail.getTotalOriginalPayrollAmount(detailLines); summaryDetailLine.setEffortCertificationOriginalPayrollAmount(originalPayrollAmount); KualiDecimal payrollAmount = EffortCertificationDetail.getTotalPayrollAmount(detailLines); summaryDetailLine.setEffortCertificationPayrollAmount(payrollAmount); KualiDecimal persistedPayrollAmount = EffortCertificationDetail.getTotalPersistedPayrollAmount(detailLines); summaryDetailLine.setPersistedPayrollAmount(persistedPayrollAmount); } /** * find the detail lines that have max payroll amount * * @return the detail lines that have max payroll amount */ private EffortCertificationDetail getDetailLineWithMaxPayrollAmount(List<EffortCertificationDetail> detailLines) { KualiDecimal maxAmount = null; EffortCertificationDetail detailLineWithMaxPayrollAmount = null; for (EffortCertificationDetail line : detailLines) { KualiDecimal currentAmount = line.getEffortCertificationOriginalPayrollAmount(); if (detailLineWithMaxPayrollAmount == null) { maxAmount = currentAmount; detailLineWithMaxPayrollAmount = line; continue; } if (maxAmount.isLessThan(currentAmount)) { maxAmount = currentAmount; detailLineWithMaxPayrollAmount = line; } } return detailLineWithMaxPayrollAmount; } /** * Gets the summaryDetailLine attribute. * * @return Returns the summaryDetailLine. */ public EffortCertificationDetail getSummaryDetailLine() { return summaryDetailLine; } /** * Sets the summaryDetailLine attribute value. * * @param summaryDetailLine The summaryDetailLine to set. */ public void setSummaryDetailLine(EffortCertificationDetail summaryDetailLine) { this.summaryDetailLine = summaryDetailLine; } /** * Gets the detailLines attribute. * * @return Returns the detailLines. */ public List<EffortCertificationDetail> getDetailLines() { return detailLines; } /** * Sets the detailLines attribute value. * * @param detailLines The detailLines to set. */ public void setDetailLines(List<EffortCertificationDetail> detailLines) { this.detailLines = detailLines; } /** * Gets the delegateDetailLine attribute. * * @return Returns the delegateDetailLine. */ public EffortCertificationDetail getDelegateDetailLine() { return delegateDetailLine; } /** * Sets the delegateDetailLine attribute value. * * @param delegateDetailLine The delegateDetailLine to set. */ public void setDelegateDetailLine(EffortCertificationDetail delegateDetailLine) { this.delegateDetailLine = delegateDetailLine; } }