View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.lm.leavepayout.validation;
17  
18  import java.math.BigDecimal;
19  import java.sql.Date;
20  import java.util.List;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.hr.lm.LMConstants;
24  import org.kuali.hr.lm.accrual.AccrualCategory;
25  import org.kuali.hr.lm.accrual.AccrualCategoryRule;
26  import org.kuali.hr.lm.leavepayout.LeavePayout;
27  import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
28  import org.kuali.hr.time.principal.PrincipalHRAttributes;
29  import org.kuali.hr.time.service.base.TkServiceLocator;
30  import org.kuali.hr.time.util.TKUtils;
31  import org.kuali.hr.time.util.TkConstants;
32  import org.kuali.rice.krad.util.GlobalVariables;
33  import org.kuali.rice.krad.util.ObjectUtils;
34  
35  public class LeavePayoutValidationUtils {
36  
37  	public static boolean validatePayout(LeavePayout leavePayout) {
38  		boolean isValid = true;
39  		String principalId = leavePayout.getPrincipalId();
40  		Date effectiveDate = leavePayout.getEffectiveDate();
41  		String fromAccrualCategory = leavePayout.getFromAccrualCategory();
42  		String payoutEarnCode = leavePayout.getEarnCode();
43  		AccrualCategory fromCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(fromAccrualCategory, effectiveDate);
44  		AccrualCategory toCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(payoutEarnCode, effectiveDate);
45  		PrincipalHRAttributes pha = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId,effectiveDate);
46  		
47  		if(ObjectUtils.isNotNull(pha)) {
48  			if(ObjectUtils.isNotNull(pha.getLeavePlan())) {
49  				AccrualCategoryRule acr = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(fromCat, effectiveDate, pha.getServiceDate());
50  				if(ObjectUtils.isNotNull(acr)) {
51  					if(ObjectUtils.isNotNull(acr.getMaxBalFlag())
52  							&& StringUtils.isNotBlank(acr.getMaxBalFlag())
53  							&& StringUtils.isNotEmpty(acr.getMaxBalFlag())
54  							&& StringUtils.equals(acr.getMaxBalFlag(), "Y")) {
55  						if(ObjectUtils.isNotNull(acr.getMaxPayoutEarnCode()) || StringUtils.equals(LMConstants.ACTION_AT_MAX_BAL.LOSE, acr.getActionAtMaxBalance())) {
56  /*							isValid &= validatePrincipal(pha,principalId);
57  							isValid &= validateEffectiveDate(effectiveDate);
58  							isValid &= validateAgainstLeavePlan(pha,fromCat,toCat,effectiveDate);
59  							isValid &= validateTransferFromAccrualCategory(fromCat,principalId,effectiveDate,acr);
60  							isValid &= validateTransferToAccrualCategory(toCat,principalId,effectiveDate,acr);
61  */
62  							isValid &= validatePayoutAmount(leavePayout.getPayoutAmount(),fromCat,toCat, principalId, effectiveDate, acr);
63  						}
64  						else {
65  							//should never be the case if accrual category rules are validated correctly.
66  							GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
67  									"leavePayout.fromAccrualCategory.rules.payoutToEarnCode",
68  									fromAccrualCategory);
69  							isValid &= false;
70  						}
71  					}
72  					else {
73  						//max bal flag null, blank, empty, or "N"
74  						GlobalVariables.getMessageMap().putError("document.newMaintinableObject.fromAccrualCategory",
75  								"leavePayout.fromAccrualCategory.rules.maxBalFlag", fromAccrualCategory);
76  						isValid &= false;
77  					}
78  				}
79  				else {
80  					//department admins must validate amount to transfer does not exceed current balance.
81  					GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
82  							"leavePayout.fromAccrualCategory.rules.exist",fromCat.getAccrualCategory());
83  					isValid &= false;
84  				}
85  			}
86  			else {
87  				//if the principal doesn't have a leave plan, there aren't any accrual categories that can be debited/credited.
88  				GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","leavePayout.principal.noLeavePlan");
89  				isValid &=false;
90  			}
91  		}
92  		else  {
93  			//if the principal has no principal hr attributes, they're not a principal.
94  			GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","leavePayout.principal.noAttributes");
95  			isValid &= false;
96  		}
97  /*		}*/
98  		return isValid;
99  
100 	}
101 
102 	private static boolean validatePayoutAmount(BigDecimal payoutAmount,
103 			AccrualCategory fromCat, AccrualCategory toCat, String principalId,
104 			Date effectiveDate, AccrualCategoryRule accrualRule) {
105 
106 		BigDecimal balance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, fromCat, effectiveDate);
107 		//transfer amount must be less than the max transfer amount defined in the accrual category rule.
108 		//it cannot be negative.
109 		boolean isValid = true;
110 		
111 		BigDecimal maxPayoutAmount = null;
112 		BigDecimal adjustedMaxPayoutAmount = null;
113 		if(ObjectUtils.isNotNull(accrualRule.getMaxPayoutAmount())) {
114 			maxPayoutAmount = new BigDecimal(accrualRule.getMaxPayoutAmount());
115 			BigDecimal fullTimeEngagement = TkServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);
116 			adjustedMaxPayoutAmount = maxPayoutAmount.multiply(fullTimeEngagement);
117 		}
118 		
119 		//use override if one exists.
120 		EmployeeOverride maxPayoutAmountOverride = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverride(principalId, fromCat.getLeavePlan(), fromCat.getAccrualCategory(), "MPA", effectiveDate);
121 		if(ObjectUtils.isNotNull(maxPayoutAmountOverride))
122 			adjustedMaxPayoutAmount = new BigDecimal(maxPayoutAmountOverride.getOverrideValue());
123 				
124 				
125 		if(ObjectUtils.isNotNull(adjustedMaxPayoutAmount)) {
126 			if(payoutAmount.compareTo(adjustedMaxPayoutAmount) > 0) {
127 				isValid &= false;
128 				String fromUnitOfTime = TkConstants.UNIT_OF_TIME.get(fromCat.getUnitOfTime());
129 				GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount","leavePayout.payoutAmount.maxPayoutAmount",adjustedMaxPayoutAmount.toString(),fromUnitOfTime);
130 			}
131 		}
132 		// check for a positive amount.
133 		if(payoutAmount.compareTo(BigDecimal.ZERO) < 0 ) {
134 			isValid &= false;
135 			GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount","leavePayout.payoutAmount.negative");
136 		}
137 		
138 		if(balance.subtract(payoutAmount).compareTo(BigDecimal.ZERO) < 0 ) {
139 			if(StringUtils.equals(fromCat.getEarnCodeObj().getAllowNegativeAccrualBalance(),"Y"))
140 				isValid &= true;
141 			else {
142 				isValid &= false;
143 				GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount", "maxBalance.amount.exceedsBalance");
144 			}
145 		}	
146 		return isValid;
147 	}
148 
149 	private boolean validateMaxBalance() {
150 		//This validation could assert that the payout amount, together with forfeiture
151 		//brings the balance for the given accrual category back to, or under, the balance limit
152 		//without exceeding the total accrued balance.
153 		return true;
154 	}
155 	
156 	private boolean validateMaxCarryOver() {
157 		//This validation could assert that the payout amount, together with forfeiture
158 		//brings the balance for the given accrual category back to, or under, the max carry over limit
159 		//without exceeding the total accrued balance.
160 		return true;
161 	}
162 	
163 }