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 }