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.kpme.tklm.leave.payout.validation;
17  
18  import java.math.BigDecimal;
19  
20  import org.apache.commons.lang.StringUtils;
21  import org.joda.time.LocalDate;
22  import org.kuali.kpme.core.accrualcategory.AccrualCategory;
23  import org.kuali.kpme.core.accrualcategory.rule.AccrualCategoryRule;
24  import org.kuali.kpme.core.earncode.EarnCode;
25  import org.kuali.kpme.core.principal.PrincipalHRAttributes;
26  import org.kuali.kpme.core.service.HrServiceLocator;
27  import org.kuali.kpme.core.util.HrConstants;
28  import org.kuali.kpme.core.util.ValidationUtils;
29  import org.kuali.kpme.tklm.leave.override.EmployeeOverride;
30  import org.kuali.kpme.tklm.leave.payout.LeavePayout;
31  import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
32  import org.kuali.kpme.tklm.leave.summary.LeaveSummary;
33  import org.kuali.kpme.tklm.leave.summary.LeaveSummaryRow;
34  import org.kuali.rice.krad.util.GlobalVariables;
35  import org.kuali.rice.krad.util.ObjectUtils;
36  
37  public class LeavePayoutValidationUtils {
38  
39  	public static boolean validatePayout(LeavePayout leavePayout) {
40  		boolean isValid = true;
41  		String principalId = leavePayout.getPrincipalId();
42  		LocalDate effectiveDate = leavePayout.getEffectiveLocalDate();
43  		String fromAccrualCategory = leavePayout.getFromAccrualCategory();
44  		String payoutEarnCode = leavePayout.getEarnCode();
45  		
46  		if(!ValidationUtils.validateAccrualCategory(fromAccrualCategory, effectiveDate)) {
47  			GlobalVariables.getMessageMap().putError("leavePayout.fromAccrualCategory", "leavePayout.fromAccrualCategory.exists");
48  			isValid &= false;
49  		}
50  		
51  		if(!ValidationUtils.validateEarnCode(payoutEarnCode, effectiveDate)) {
52  			GlobalVariables.getMessageMap().putError("leavePayout.earnCode", "leavePayout.earncode.exists");
53  			isValid &= false;
54  		}
55  		
56  		if(!ValidationUtils.validatePrincipalId(principalId)) {
57  			GlobalVariables.getMessageMap().putError("leavePayout.principalId", "leavePayout.principal.exists");
58  			isValid &= false;
59  		}
60  		
61  		if(effectiveDate.isAfter(LocalDate.now().plusYears(1))) {
62  			GlobalVariables.getMessageMap().putError("leavePayout.effectiveDate", "leavePayout.effectiveDate.overOneYear");
63  			isValid &= false;
64  		}
65  		
66  		
67  		
68  		if(isValid) {
69  			
70  			AccrualCategory fromCat = HrServiceLocator.getAccrualCategoryService().getAccrualCategory(fromAccrualCategory, effectiveDate);
71  			EarnCode earnCode = HrServiceLocator.getEarnCodeService().getEarnCode(payoutEarnCode, effectiveDate);
72  			PrincipalHRAttributes pha = HrServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId,effectiveDate);
73  			
74  			if(ObjectUtils.isNotNull(pha)) {
75  				if(ObjectUtils.isNotNull(pha.getLeavePlan())) {
76  					AccrualCategoryRule acr = HrServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(fromCat, effectiveDate, pha.getServiceLocalDate());
77  
78  					if(ObjectUtils.isNotNull(acr)) {
79  						if(ObjectUtils.isNotNull(acr.getMaxBalFlag())
80  								&& StringUtils.isNotBlank(acr.getMaxBalFlag())
81  								&& StringUtils.isNotEmpty(acr.getMaxBalFlag())
82  								&& StringUtils.equals(acr.getMaxBalFlag(), "Y")) {
83  							if(ObjectUtils.isNotNull(acr.getMaxPayoutEarnCode()) || StringUtils.equals(HrConstants.ACTION_AT_MAX_BALANCE.LOSE, acr.getActionAtMaxBalance())) {
84  	/*							isValid &= validatePrincipal(pha,principalId);
85  								isValid &= validateEffectiveDate(effectiveDate);
86  								isValid &= validateAgainstLeavePlan(pha,fromCat,toCat,effectiveDate);
87  								isValid &= validateTransferFromAccrualCategory(fromCat,principalId,effectiveDate,acr);
88  								isValid &= validateTransferToAccrualCategory(toCat,principalId,effectiveDate,acr);
89  	*/
90  								isValid &= validateForfeitedAmount(leavePayout.getForfeitedAmount());
91  								isValid &= validatePayoutAmount(leavePayout.getPayoutAmount(),fromCat, earnCode, principalId, effectiveDate, acr);
92  							}
93  							else {
94  								//should never be the case if accrual category rules are validated correctly.
95  								GlobalVariables.getMessageMap().putError("leavePayout.fromAccrualCategory",
96  										"leavePayout.fromAccrualCategory.rules.payoutToEarnCode",
97  										fromAccrualCategory);
98  								isValid &= false;
99  							}
100 						}
101 						else {
102 							//max bal flag null, blank, empty, or "N"
103 							GlobalVariables.getMessageMap().putError("leavePayout.fromAccrualCategory",
104 									"leavePayout.fromAccrualCategory.rules.maxBalFlag", fromAccrualCategory);
105 							isValid &= false;
106 						}
107 					}
108 					else {
109 						//department admins must validate amount to transfer does not exceed current balance.
110 						GlobalVariables.getMessageMap().putError("leavePayout.fromAccrualCategory",
111 								"leavePayout.fromAccrualCategory.rules.exist",fromCat.getAccrualCategory());
112 						isValid &= false;
113 					}
114 				}
115 				else {
116 					//if the principal doesn't have a leave plan, there aren't any accrual categories that can be debited/credited.
117 					GlobalVariables.getMessageMap().putError("leavePayout.principalId","leavePayout.principal.noLeavePlan");
118 					isValid &=false;
119 				}
120 			}
121 			else  {
122 				//if the principal has no principal hr attributes, they're not a principal.
123 				GlobalVariables.getMessageMap().putError("leavePayout.principalId","leavePayout.principal.noAttributes");
124 				isValid &= false;
125 			}
126 		}
127 		return isValid;
128 
129 	}
130 
131 	private static boolean validateForfeitedAmount(BigDecimal forfeitedAmount) {
132 		if(forfeitedAmount.compareTo(BigDecimal.ZERO) < 0) {
133 			GlobalVariables.getMessageMap().putError("leavePayout.forfeitedAmount", "balanceTransfer.transferAmount.negative");
134 			return false;
135 		}
136 		return true;
137 	}
138 
139 	private static boolean validatePayoutAmount(BigDecimal payoutAmount,
140 			AccrualCategory fromCat, EarnCode earnCode, String principalId,
141 			LocalDate effectiveDate, AccrualCategoryRule accrualRule) {
142 
143 		LeaveSummary leaveSummary = LmServiceLocator.getLeaveSummaryService().getLeaveSummaryAsOfDateForAccrualCategory(principalId, effectiveDate, fromCat.getAccrualCategory());
144 		LeaveSummaryRow row = leaveSummary.getLeaveSummaryRowForAccrualCtgy(fromCat.getAccrualCategory());
145 		BigDecimal balance = row.getAccruedBalance();
146 		//transfer amount must be less than the max transfer amount defined in the accrual category rule.
147 		//it cannot be negative.
148 		boolean isValid = true;
149 		
150 		BigDecimal maxPayoutAmount = null;
151 		BigDecimal adjustedMaxPayoutAmount = null;
152 		if(ObjectUtils.isNotNull(accrualRule.getMaxPayoutAmount())) {
153 			maxPayoutAmount = new BigDecimal(accrualRule.getMaxPayoutAmount());
154 			BigDecimal fullTimeEngagement = HrServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);
155 			adjustedMaxPayoutAmount = maxPayoutAmount.multiply(fullTimeEngagement);
156 		}
157 		
158 		//use override if one exists.
159 		EmployeeOverride maxPayoutAmountOverride = LmServiceLocator.getEmployeeOverrideService().getEmployeeOverride(principalId, fromCat.getLeavePlan(), fromCat.getAccrualCategory(), "MPA", effectiveDate);
160 		if(ObjectUtils.isNotNull(maxPayoutAmountOverride))
161 			adjustedMaxPayoutAmount = new BigDecimal(maxPayoutAmountOverride.getOverrideValue());
162 				
163 				
164 		if(ObjectUtils.isNotNull(adjustedMaxPayoutAmount)) {
165 			if(payoutAmount.compareTo(adjustedMaxPayoutAmount) > 0) {
166 				isValid &= false;
167 				String fromUnitOfTime = HrConstants.UNIT_OF_TIME.get(fromCat.getUnitOfTime());
168 				GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount","leavePayout.payoutAmount.maxPayoutAmount",adjustedMaxPayoutAmount.toString(),fromUnitOfTime);
169 			}
170 		}
171 		// check for a positive amount.
172 		if(payoutAmount.compareTo(BigDecimal.ZERO) < 0 ) {
173 			isValid &= false;
174 			GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount","leavePayout.payoutAmount.negative");
175 		}
176 		
177 		if(payoutAmount.compareTo(balance) > 0 ) {
178 			isValid &= false;
179 			GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount", "maxBalance.amount.exceedsBalance", balance.toString());
180 		}	
181 		return isValid;
182 	}
183 
184 	private boolean validateMaxBalance() {
185 		//This validation could assert that the payout amount, together with forfeiture
186 		//brings the balance for the given accrual category back to, or under, the balance limit
187 		//without exceeding the total accrued balance.
188 		return true;
189 	}
190 	
191 	private boolean validateMaxCarryOver() {
192 		//This validation could assert that the payout amount, together with forfeiture
193 		//brings the balance for the given accrual category back to, or under, the max carry over limit
194 		//without exceeding the total accrued balance.
195 		return true;
196 	}
197 	
198 }