001 /**
002 * Copyright 2004-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.hr.lm.balancetransfer.validation;
017
018 import java.math.BigDecimal;
019 import java.sql.Date;
020 import java.util.List;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.kuali.hr.lm.LMConstants;
024 import org.kuali.hr.lm.accrual.AccrualCategory;
025 import org.kuali.hr.lm.accrual.AccrualCategoryRule;
026 import org.kuali.hr.lm.balancetransfer.BalanceTransfer;
027 import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
028 import org.kuali.hr.lm.timeoff.SystemScheduledTimeOff;
029 import org.kuali.hr.time.principal.PrincipalHRAttributes;
030 import org.kuali.hr.time.service.base.TkServiceLocator;
031 import org.kuali.hr.time.util.TKUtils;
032 import org.kuali.hr.time.util.TkConstants;
033 import org.kuali.rice.krad.util.GlobalVariables;
034 import org.kuali.rice.krad.util.ObjectUtils;
035
036 public class BalanceTransferValidationUtils {
037
038 public static boolean validateTransfer(BalanceTransfer balanceTransfer) {
039 boolean isValid = true;
040 if(StringUtils.isNotEmpty(balanceTransfer.getSstoId())) {
041 return isValid && validateSstoTranser(balanceTransfer) ;
042 }
043 String principalId = balanceTransfer.getPrincipalId();
044 Date effectiveDate = balanceTransfer.getEffectiveDate();
045 String fromAccrualCategory = balanceTransfer.getFromAccrualCategory();
046 String toAccrualCategory = balanceTransfer.getToAccrualCategory();
047 AccrualCategory fromCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(fromAccrualCategory, effectiveDate);
048 AccrualCategory toCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(toAccrualCategory, effectiveDate);
049 PrincipalHRAttributes pha = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId,effectiveDate);
050
051 if(ObjectUtils.isNotNull(pha)) {
052 if(ObjectUtils.isNotNull(pha.getLeavePlan())) {
053 AccrualCategoryRule acr = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(fromCat,
054 effectiveDate, pha.getServiceDate());
055 if(ObjectUtils.isNotNull(acr)) {
056 if(ObjectUtils.isNotNull(acr.getMaxBalFlag())
057 && StringUtils.isNotBlank(acr.getMaxBalFlag())
058 && StringUtils.isNotEmpty(acr.getMaxBalFlag())
059 && StringUtils.equals(acr.getMaxBalFlag(), "Y")) {
060 if(ObjectUtils.isNotNull(acr.getMaxBalanceTransferToAccrualCategory()) || StringUtils.equals(LMConstants.ACTION_AT_MAX_BAL.LOSE, acr.getActionAtMaxBalance())) {
061 /* isValid &= validatePrincipal(pha,principalId);
062 isValid &= validateEffectiveDate(effectiveDate);
063 isValid &= validateAgainstLeavePlan(pha,fromCat,toCat,effectiveDate);
064 isValid &= validateTransferFromAccrualCategory(fromCat,principalId,effectiveDate,acr);
065 isValid &= validateTransferToAccrualCategory(toCat,principalId,effectiveDate,acr);*/
066 isValid &= validateMaxCarryOver(balanceTransfer.getAmountTransferred(),toCat,principalId,effectiveDate,acr, pha);
067 isValid &= validateTransferAmount(balanceTransfer.getTransferAmount(),fromCat,toCat, principalId, effectiveDate, acr);
068 }
069 else {
070 //should never be the case if accrual category rules are validated correctly.
071 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
072 "balanceTransfer.fromAccrualCategory.rules.transferToAccrualCategory",
073 fromAccrualCategory);
074 isValid &= false;
075 }
076 }
077 else {
078 //max bal flag null, blank, empty, or "N"
079 GlobalVariables.getMessageMap().putError("document.newMaintinableObject.fromAccrualCategory",
080 "balanceTransfer.fromAccrualCategory.rules.maxBalFlag", fromAccrualCategory);
081 isValid &= false;
082 }
083 }
084 else {
085 //department admins must validate amount to transfer does not exceed current balance.
086 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
087 "balanceTransfer.fromAccrualCategory.rules.exist",fromCat.getAccrualCategory());
088 isValid &= false;
089 }
090 }
091 else {
092 //if the principal doesn't have a leave plan, there aren't any accrual categories that can be debited/credited.
093 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","balanceTransfer.principal.noLeavePlan");
094 isValid &=false;
095 }
096 }
097 else {
098 //if the principal has no principal hr attributes, they're not a principal.
099 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","balanceTransfer.principal.noAttributes");
100 isValid &= false;
101 }
102 /* }*/
103 return isValid;
104
105 }
106
107 private static boolean validateMaxCarryOver(BigDecimal amountTransferred,
108 AccrualCategory toCat, String principalId, Date effectiveDate,
109 AccrualCategoryRule acr, PrincipalHRAttributes pha) {
110 /* List<AccrualCategoryRule> rules = toCat.getAccrualCategoryRules();
111 Date serviceDate = pha.getServiceDate();
112 Interval interval = new Interval(serviceDate.getTime(), effectiveDate.getTime());
113 for(AccrualCategoryRule rule : rules) {
114 String unitOfTime = rule.getServiceUnitOfTime();
115 if(StringUtils.equals(unitOfTime, LMConstants.SERVICE_TIME_MONTHS))
116 }*/
117 return true;
118 }
119
120 private static boolean validateTransferAmount(BigDecimal transferAmount,
121 AccrualCategory fromCat, AccrualCategory toCat, String principalId,
122 Date effectiveDate, AccrualCategoryRule accrualRule) {
123
124 //transfer amount must be less than the max transfer amount defined in the accrual category rule.
125 //it cannot be negative.
126 boolean isValid = true;
127 BigDecimal maxTransferAmount = null;
128 BigDecimal adjustedMaxTransferAmount = null;
129 if(ObjectUtils.isNotNull(accrualRule.getMaxTransferAmount())) {
130 maxTransferAmount = new BigDecimal(accrualRule.getMaxTransferAmount());
131 BigDecimal fullTimeEngagement = TkServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);
132 adjustedMaxTransferAmount = maxTransferAmount.multiply(fullTimeEngagement);
133 }
134
135 //use override if one exists.
136 List<EmployeeOverride> overrides = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverrides(principalId, effectiveDate);
137 for(EmployeeOverride override : overrides) {
138 if(override.getOverrideType().equals(TkConstants.EMPLOYEE_OVERRIDE_TYPE.get("MTA")))
139 adjustedMaxTransferAmount = new BigDecimal(override.getOverrideValue());
140 }
141
142 if(ObjectUtils.isNotNull(adjustedMaxTransferAmount)) {
143 if(transferAmount.compareTo(adjustedMaxTransferAmount) > 0) {
144 isValid &= false;
145 String fromUnitOfTime = TkConstants.UNIT_OF_TIME.get(fromCat.getUnitOfTime());
146 GlobalVariables.getMessageMap().putError("balanceTransfer.transferAmount","balanceTransfer.transferAmount.maxTransferAmount",adjustedMaxTransferAmount.toString(),fromUnitOfTime);
147 }
148 }
149 // check for a positive amount.
150 if(transferAmount.compareTo(BigDecimal.ZERO) < 0 ) {
151 isValid &= false;
152 GlobalVariables.getMessageMap().putError("balanceTransfer.transferAmount","balanceTransfer.transferAmount.negative");
153 }
154 return isValid;
155 }
156
157 public static boolean validateSstoTranser(BalanceTransfer bt) {
158 // make sure from accrual category is consistent with the ssto's
159 SystemScheduledTimeOff ssto = TkServiceLocator.getSysSchTimeOffService().getSystemScheduledTimeOff(bt.getSstoId());
160 if(ssto == null) {
161 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.transferSSTO.sstoDoesNotExis", bt.getSstoId());
162 return false;
163 }
164 if(!ssto.getAccrualCategory().equals(bt.getFromAccrualCategory())) {
165 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.transferSSTO.fromACWrong", bt.getFromAccrualCategory(), ssto.getAccrualCategory());
166 return false;
167 }
168
169 if(bt.getFromAccrualCategory().equals(bt.getToAccrualCategory())) {
170 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.transferSSTO.fromAndToACTheSame");
171 return false;
172 }
173
174 AccrualCategory fromAC = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(bt.getFromAccrualCategory(), bt.getEffectiveDate());
175 if(fromAC == null) {
176 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.transferSSTO.acDoesNotExist", bt.getFromAccrualCategory());
177 return false;
178 }
179 AccrualCategory toAC = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(bt.getToAccrualCategory(), bt.getEffectiveDate());
180 if(toAC == null) {
181 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.toAccrualCategory", "balanceTransfer.transferSSTO.acDoesNotExist", bt.getToAccrualCategory());
182 return false;
183 }
184 // make sure the leave plan of from/to accrual categories are consistent with the employee's leave plan
185 PrincipalHRAttributes pha = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(bt.getPrincipalId(),bt.getEffectiveDate());
186 if(StringUtils.isNotEmpty(fromAC.getLeavePlan())){
187 if(!fromAC.getLeavePlan().equals(pha.getLeavePlan())) {
188 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.transferSSTO.wrongACLeavePlan", fromAC.getLeavePlan(), pha.getLeavePlan());
189 return false;
190 }
191 }
192 if(StringUtils.isNotEmpty(toAC.getLeavePlan())){
193 if(!fromAC.getLeavePlan().equals(pha.getLeavePlan())) {
194 GlobalVariables.getMessageMap().putError("document.newMaintainableObject.toAccrualCategory", "balanceTransfer.transferSSTO.wrongACLeavePlan", toAC.getLeavePlan(), pha.getLeavePlan());
195 return false;
196 }
197 }
198
199 return true;
200 }
201
202
203 }