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 }