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.kpme.tklm.leave.accrual.bucket;
017    
018    import java.math.BigDecimal;
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.joda.time.DateTime;
023    import org.joda.time.LocalDate;
024    import org.kuali.kpme.core.accrualcategory.AccrualCategory;
025    import org.kuali.kpme.core.accrualcategory.rule.AccrualCategoryRule;
026    import org.kuali.kpme.core.earncode.EarnCode;
027    import org.kuali.kpme.core.principal.PrincipalHRAttributes;
028    import org.kuali.kpme.core.service.HrServiceLocator;
029    import org.kuali.kpme.core.util.HrConstants;
030    import org.kuali.kpme.tklm.api.leave.accrual.bucket.YearToDateUsageLeaveBalanceContract;
031    import org.kuali.kpme.tklm.leave.accrual.bucket.exception.MaximumBalanceException;
032    import org.kuali.kpme.tklm.leave.accrual.bucket.exception.NegativeBalanceException;
033    import org.kuali.kpme.tklm.leave.accrual.bucket.exception.UsageLimitException;
034    import org.kuali.kpme.tklm.leave.block.LeaveBlock;
035    import org.kuali.kpme.tklm.leave.override.EmployeeOverride;
036    import org.kuali.rice.krad.util.ObjectUtils;
037    
038    public class YearToDateUsageLeaveBalance extends LeaveBalance implements YearToDateUsageLeaveBalanceContract {
039    
040            private List<LeaveBlock> leaveBlocks;
041    
042            public YearToDateUsageLeaveBalance(AccrualCategory accrualCategory, PrincipalHRAttributes principalCalendar) {
043                    super(accrualCategory, principalCalendar);
044                    asOfDate = LocalDate.now();
045                    leaveBlocks = new ArrayList<LeaveBlock>();
046            }
047    
048            private final static String BALANCE_TYPE = "YTD_USAGE_BALANCE";
049            
050            @Override
051            public void add(LeaveBlock leaveBlock) throws UsageLimitException {
052    
053                    DateTime rolloverDate = HrServiceLocator.getLeavePlanService().getFirstDayOfLeavePlan(principalCalendar.getLeavePlan(), asOfDate);
054                    
055                    if(leaveBlock.getLeaveDate().compareTo(asOfDate.toDate()) <= 0 
056                                    && leaveBlock.getLeaveDate().compareTo(rolloverDate.toDate()) >= 0) {
057                    
058                            if(leaveBlock.getLeaveAmount().signum() < 0) {
059                                    EarnCode earnCode = HrServiceLocator.getEarnCodeService().getEarnCode(leaveBlock.getEarnCode(), LocalDate.fromDateFields(leaveBlock.getLeaveDate()));
060                                    if(earnCode != null) {
061                                            if(earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.USAGE)){
062                            
063                                                    AccrualCategoryRule accrualRule = getAccrualCategoryRuleForDate(leaveBlock.getLeaveLocalDate());
064                                                    
065                                                    if(accrualRule != null
066                                                                    && ObjectUtils.isNotNull(accrualRule.getMaxUsage())) {
067                                                            
068                                                            BigDecimal maxUsage = new BigDecimal(accrualRule.getMaxUsage());
069                                                            BigDecimal fteSum = HrServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(leaveBlock.getPrincipalId(), leaveBlock.getLeaveLocalDate());
070                                                            maxUsage = maxUsage.multiply(fteSum).setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING);
071                                                            
072                                                            EmployeeOverride employeeOverride = getEmployeeOverride(leaveBlock, "MU");
073                                                            if(employeeOverride != null)
074                                                                    maxUsage = new BigDecimal(employeeOverride.getOverrideValue());
075                                                            
076                                                            if(maxUsage.compareTo(this.balance.add(leaveBlock.getLeaveAmount().negate())) <= 0) {
077                                                                    add(leaveBlock.getLeaveAmount().negate());
078                                                                    leaveBlocks.add(leaveBlock);
079                                                                    //throw new UsageLimitException();
080                                                            }
081                                                            else {
082                                                                    add(leaveBlock.getLeaveAmount().negate());
083                                                                    leaveBlocks.add(leaveBlock);
084                                                            }
085                                                    }
086                                                    else {
087                                                            //no usage limit
088                                                            add(leaveBlock.getLeaveAmount().negate());
089                                                            leaveBlocks.add(leaveBlock);
090                                                    }
091                    
092                                            }
093                                            else if(earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.ADJUSTMENT)) {
094                                                    //does not validate against balances
095                                                    add(leaveBlock.getLeaveAmount().negate());
096                                                    leaveBlocks.add(leaveBlock);
097                                            }
098                                            else if(earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.NONE)) {
099                                                    //no balance validations, does not affect balances
100                                                    leaveBlocks.add(leaveBlock);
101                                            }
102                                    }
103                            }
104                    }
105            }
106    
107            @Override
108            public void remove(LeaveBlock leaveBlock) throws NegativeBalanceException {
109                    
110                    DateTime rolloverDate = HrServiceLocator.getLeavePlanService().getFirstDayOfLeavePlan(principalCalendar.getLeavePlan(), asOfDate);
111                    
112                    if(leaveBlock.getLeaveDate().compareTo(asOfDate.toDate()) <= 0 
113                                    && leaveBlock.getLeaveDate().compareTo(rolloverDate.toDate()) >= 0) {
114                            
115                            if(leaveBlock.getLeaveAmount().signum() < 0) {
116                                    EarnCode earnCode = HrServiceLocator.getEarnCodeService().getEarnCode(leaveBlock.getEarnCode(), LocalDate.fromDateFields(leaveBlock.getLeaveDate()));
117                                    if(earnCode != null) {
118                                            if(earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.USAGE)){
119            
120                                                    AccrualCategoryRule accrualRule = getAccrualCategoryRuleForDate(leaveBlock.getLeaveLocalDate());
121                                                    
122                                                    if(accrualRule != null
123                                                                    && ObjectUtils.isNotNull(accrualRule.getMaxUsage())) {
124                                                            
125                                                            BigDecimal maxUsage = new BigDecimal(accrualRule.getMaxUsage());
126                                                            BigDecimal fteSum = HrServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(leaveBlock.getPrincipalId(), leaveBlock.getLeaveLocalDate());
127                                                            maxUsage = maxUsage.multiply(fteSum).setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING);
128                                                            
129                                                            EmployeeOverride employeeOverride = getEmployeeOverride(leaveBlock, "MU");
130                                                            if(employeeOverride != null)
131                                                                    maxUsage = new BigDecimal(employeeOverride.getOverrideValue());
132                                                            
133                                                            if(BigDecimal.ZERO.compareTo(this.balance.subtract(leaveBlock.getLeaveAmount().negate())) > 0) {
134                                                                    remove(leaveBlock.getLeaveAmount().negate());
135                                                                    leaveBlocks.remove(leaveBlock);
136                                                                    //throw new NegativeBalanceException();
137                                                            }
138                                                            else {
139                                                                    remove(leaveBlock.getLeaveAmount().negate());
140                                                                    leaveBlocks.remove(leaveBlock);
141                                                            }
142                                                    }
143                                                    else {
144                                                            //no usage limit
145                                                            remove(leaveBlock.getLeaveAmount().negate());
146                                                            leaveBlocks.remove(leaveBlock);
147                                                    }
148                    
149                                            }
150                                            else if(earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.ADJUSTMENT)) {
151                                                    //does not validate against balances
152                                                    remove(leaveBlock.getLeaveAmount().negate());
153                                                    leaveBlocks.remove(leaveBlock);
154                                            }
155                                            else if(earnCode.getAccrualBalanceAction().equals(HrConstants.ACCRUAL_BALANCE_ACTION.NONE)) {
156                                                    //no balance validations, does not affect balances
157                                                    leaveBlocks.remove(leaveBlock);
158                                            }
159                                    }
160                            }
161                    }
162            }
163    
164            @Override
165            public String getBalanceType() {
166                    return BALANCE_TYPE;
167            }
168    
169            @Override
170            public void adjust(LeaveBlock leaveBlock) throws UsageLimitException,
171                            MaximumBalanceException, NegativeBalanceException {
172                    // TODO Auto-generated method stub
173                    
174            }
175    
176            @Override
177            public void clear() {
178                    leaveBlocks.clear();
179                    super.clear();
180            }
181    
182    }