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.leavepayout.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.leavepayout.LeavePayout;
027    import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
028    import org.kuali.hr.time.principal.PrincipalHRAttributes;
029    import org.kuali.hr.time.service.base.TkServiceLocator;
030    import org.kuali.hr.time.util.TKUtils;
031    import org.kuali.hr.time.util.TkConstants;
032    import org.kuali.rice.krad.util.GlobalVariables;
033    import org.kuali.rice.krad.util.ObjectUtils;
034    
035    public class LeavePayoutValidationUtils {
036    
037            public static boolean validateTransfer(LeavePayout leavePayout) {
038                    boolean isValid = true;
039                    String principalId = leavePayout.getPrincipalId();
040                    Date effectiveDate = leavePayout.getEffectiveDate();
041                    String fromAccrualCategory = leavePayout.getFromAccrualCategory();
042                    String payoutEarnCode = leavePayout.getEarnCode();
043                    AccrualCategory fromCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(fromAccrualCategory, effectiveDate);
044                    AccrualCategory toCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(payoutEarnCode, effectiveDate);
045                    PrincipalHRAttributes pha = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId,effectiveDate);
046                    
047                    if(ObjectUtils.isNotNull(pha)) {
048                            if(ObjectUtils.isNotNull(pha.getLeavePlan())) {
049                                    AccrualCategoryRule acr = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(fromCat, effectiveDate, pha.getServiceDate());
050                                    if(ObjectUtils.isNotNull(acr)) {
051                                            if(ObjectUtils.isNotNull(acr.getMaxBalFlag())
052                                                            && StringUtils.isNotBlank(acr.getMaxBalFlag())
053                                                            && StringUtils.isNotEmpty(acr.getMaxBalFlag())
054                                                            && StringUtils.equals(acr.getMaxBalFlag(), "Y")) {
055                                                    if(ObjectUtils.isNotNull(acr.getMaxPayoutEarnCode()) || StringUtils.equals(LMConstants.ACTION_AT_MAX_BAL.LOSE, acr.getActionAtMaxBalance())) {
056    /*                                                      isValid &= validatePrincipal(pha,principalId);
057                                                            isValid &= validateEffectiveDate(effectiveDate);
058                                                            isValid &= validateAgainstLeavePlan(pha,fromCat,toCat,effectiveDate);
059                                                            isValid &= validateTransferFromAccrualCategory(fromCat,principalId,effectiveDate,acr);
060                                                            isValid &= validateTransferToAccrualCategory(toCat,principalId,effectiveDate,acr);*/
061                                                            isValid &= validatePayoutAmount(leavePayout.getPayoutAmount(),fromCat,toCat, principalId, effectiveDate, acr);
062                                                    }
063                                                    else {
064                                                            //should never be the case if accrual category rules are validated correctly.
065                                                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
066                                                                            "leavePayout.fromAccrualCategory.rules.payoutToEarnCode",
067                                                                            fromAccrualCategory);
068                                                            isValid &= false;
069                                                    }
070                                            }
071                                            else {
072                                                    //max bal flag null, blank, empty, or "N"
073                                                    GlobalVariables.getMessageMap().putError("document.newMaintinableObject.fromAccrualCategory",
074                                                                    "leavePayout.fromAccrualCategory.rules.maxBalFlag", fromAccrualCategory);
075                                                    isValid &= false;
076                                            }
077                                    }
078                                    else {
079                                            //department admins must validate amount to transfer does not exceed current balance.
080                                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
081                                                            "leavePayout.fromAccrualCategory.rules.exist",fromCat.getAccrualCategory());
082                                            isValid &= false;
083                                    }
084                            }
085                            else {
086                                    //if the principal doesn't have a leave plan, there aren't any accrual categories that can be debited/credited.
087                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","leavePayout.principal.noLeavePlan");
088                                    isValid &=false;
089                            }
090                    }
091                    else  {
092                            //if the principal has no principal hr attributes, they're not a principal.
093                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","leavePayout.principal.noAttributes");
094                            isValid &= false;
095                    }
096    /*              }*/
097                    return isValid;
098    
099            }
100    
101            private static boolean validatePayoutAmount(BigDecimal payoutAmount,
102                            AccrualCategory fromCat, AccrualCategory toCat, String principalId,
103                            Date effectiveDate, AccrualCategoryRule accrualRule) {
104    
105                    //transfer amount must be less than the max transfer amount defined in the accrual category rule.
106                    //it cannot be negative.
107                    boolean isValid = true;
108                    BigDecimal maxPayoutAmount = null;
109                    BigDecimal adjustedMaxPayoutAmount = null;
110                    if(ObjectUtils.isNotNull(accrualRule.getMaxPayoutAmount())) {
111                            maxPayoutAmount = new BigDecimal(accrualRule.getMaxPayoutAmount());
112                            BigDecimal fullTimeEngagement = TkServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);
113                            adjustedMaxPayoutAmount = maxPayoutAmount.multiply(fullTimeEngagement);
114                    }
115                    
116                    //use override if one exists.
117                    List<EmployeeOverride> overrides = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverrides(principalId, effectiveDate);
118                    for(EmployeeOverride override : overrides) {
119                            if(override.getOverrideType().equals(TkConstants.EMPLOYEE_OVERRIDE_TYPE.get("MPA")))
120                                    adjustedMaxPayoutAmount = new BigDecimal(override.getOverrideValue());
121                    }
122                                    
123                    if(ObjectUtils.isNotNull(adjustedMaxPayoutAmount)) {
124                            if(payoutAmount.compareTo(adjustedMaxPayoutAmount) > 0) {
125                                    isValid &= false;
126                                    String fromUnitOfTime = TkConstants.UNIT_OF_TIME.get(fromCat.getUnitOfTime());
127                                    GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount","leavePayout.payoutAmount.maxPayoutAmount",adjustedMaxPayoutAmount.toString(),fromUnitOfTime);
128                            }
129                    }
130                    // check for a positive amount.
131                    if(payoutAmount.compareTo(BigDecimal.ZERO) < 0 ) {
132                            isValid &= false;
133                            GlobalVariables.getMessageMap().putError("leavePayout.payoutAmount","leavePayout.payoutAmount.negative");
134                    }
135                    return isValid;
136            }
137    
138            
139    }