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.time.batch; 017 018 import org.apache.commons.collections.CollectionUtils; 019 import org.apache.log4j.Logger; 020 import org.joda.time.DateTime; 021 import org.joda.time.LocalDate; 022 import org.joda.time.LocalDateTime; 023 import org.kuali.hr.lm.LMConstants; 024 import org.kuali.hr.lm.accrual.AccrualCategory; 025 import org.kuali.hr.lm.accrual.service.AccrualCategoryService; 026 import org.kuali.hr.lm.leaveSummary.LeaveSummary; 027 import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow; 028 import org.kuali.hr.lm.leaveSummary.service.LeaveSummaryService; 029 import org.kuali.hr.lm.leaveblock.LeaveBlock; 030 import org.kuali.hr.lm.leaveblock.service.LeaveBlockService; 031 import org.kuali.hr.lm.leaveplan.LeavePlan; 032 import org.kuali.hr.lm.leaveplan.service.LeavePlanService; 033 import org.kuali.hr.time.assignment.Assignment; 034 import org.kuali.hr.time.assignment.service.AssignmentService; 035 import org.kuali.hr.time.calendar.service.CalendarEntriesService; 036 import org.kuali.hr.time.principal.PrincipalHRAttributes; 037 import org.kuali.hr.time.principal.service.PrincipalHRAttributesService; 038 import org.kuali.hr.time.service.base.TkServiceLocator; 039 import org.kuali.hr.time.util.TKUtils; 040 import org.kuali.hr.time.util.TkConstants; 041 import org.kuali.rice.core.api.config.property.ConfigContext; 042 import org.kuali.rice.kim.api.identity.principal.Principal; 043 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 044 import org.quartz.Job; 045 import org.quartz.JobDataMap; 046 import org.quartz.JobExecutionContext; 047 import org.quartz.JobExecutionException; 048 049 import java.sql.Date; 050 import java.sql.Timestamp; 051 import java.util.*; 052 053 public class CarryOverJob implements Job{ 054 055 private static final Logger LOG = Logger.getLogger(CarryOverJob.class); 056 057 private AccrualCategoryService accrualCategoryService; 058 private AssignmentService assignmentService; 059 private LeavePlanService leavePlanService; 060 private PrincipalHRAttributesService principalHRAttributesService; 061 private LeaveSummaryService leaveSummaryService; 062 private CalendarEntriesService calendarEntriesService; 063 private LeaveBlockService leaveBlockService; 064 065 @Override 066 public void execute(JobExecutionContext context) throws JobExecutionException { 067 String batchUserPrincipalId = getBatchUserPrincipalId(); 068 069 if (batchUserPrincipalId != null) { 070 JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 071 String leavePlan = jobDataMap.getString("leavePlan"); 072 if (leavePlan!= null) { 073 074 Date asOfDate = TKUtils.getCurrentDate(); 075 LeavePlan leavePlanObj = getLeavePlanService().getLeavePlan(leavePlan, asOfDate); 076 List<Assignment> assignments = getAssignmentService().getActiveAssignments(asOfDate); 077 078 //holds a list of principalIds so this isn't run multiple time for the same person 079 Set<String> principalIds = new HashSet<String>(); 080 for (Assignment assignment : assignments) { 081 String principalId = assignment.getPrincipalId(); 082 if (assignment.getJob().isEligibleForLeave() && !principalIds.contains(principalId)) { 083 084 PrincipalHRAttributes principalHRAttributes = getPrincipalHRAttributesService().getPrincipalCalendar(principalId, asOfDate); 085 principalIds.add(principalId); 086 087 if (principalHRAttributes != null) { 088 Date serviceDate = principalHRAttributes.getServiceDate(); 089 if(serviceDate != null){ 090 091 if (leavePlanObj != null && leavePlanObj.getLeavePlan().equalsIgnoreCase(principalHRAttributes.getLeavePlan())) { 092 093 DateTime leavePlanStartDate = getLeavePlanService().getFirstDayOfLeavePlan(leavePlan, TKUtils.getCurrentDate()); 094 095 DateTime lpPreviousLastDay = (new LocalDateTime(leavePlanStartDate)).toDateTime().minus(1); 096 DateTime lpPreviousFirstDay = new DateTime(getLeavePlanService().getFirstDayOfLeavePlan(leavePlan, new Date(lpPreviousLastDay.toDateTime().toDateMidnight().getMillis()))); 097 098 List<LeaveBlock> prevYearCarryOverleaveBlocks = getLeaveBlockService().getLeaveBlocksWithType(principalId, lpPreviousFirstDay.toDateMidnight().toDate(), lpPreviousLastDay.toDateMidnight().toDate(), LMConstants.LEAVE_BLOCK_TYPE.CARRY_OVER); 099 LeaveSummary leaveSummary = getLeaveSummaryService().getLeaveSummaryAsOfDateWithoutFuture(principalId, new java.sql.Date(lpPreviousLastDay.getMillis())); 100 //no existing carry over blocks. just create new 101 if(CollectionUtils.isEmpty(prevYearCarryOverleaveBlocks)){ 102 getLeaveBlockService().saveLeaveBlocks(createCarryOverLeaveBlocks(principalId, lpPreviousLastDay, leaveSummary)); 103 } else { 104 Map<String, LeaveBlock> existingCarryOver = new HashMap<String, LeaveBlock>(prevYearCarryOverleaveBlocks.size()); 105 // just easier to get to things when in a map... 106 for (LeaveBlock lb : prevYearCarryOverleaveBlocks) { 107 existingCarryOver.put(lb.getAccrualCategory(), lb); 108 } 109 110 // update existing first 111 for (String ac : existingCarryOver.keySet()) { 112 LeaveBlock carryOverBlock = existingCarryOver.get(ac); 113 LeaveSummaryRow lsr = leaveSummary.getLeaveSummaryRowForAccrualCtgy(ac); 114 115 //update values 116 if(lsr.getAccruedBalance() != null) { 117 if(lsr.getMaxCarryOver() != null && lsr.getAccruedBalance().compareTo(lsr.getMaxCarryOver()) > 0 ){ 118 carryOverBlock.setLeaveAmount(lsr.getMaxCarryOver()); 119 } else { 120 carryOverBlock.setLeaveAmount(lsr.getAccruedBalance()); 121 } 122 } 123 getLeaveBlockService().updateLeaveBlock(carryOverBlock, batchUserPrincipalId); 124 //remove row from leave summary 125 leaveSummary.getLeaveSummaryRows().remove(lsr); 126 } 127 128 129 // create for any new accrual categories 130 getLeaveBlockService().saveLeaveBlocks(createCarryOverLeaveBlocks(principalId, lpPreviousLastDay, leaveSummary)); 131 } 132 } 133 } 134 } 135 } 136 } 137 } 138 } else { 139 String principalName = ConfigContext.getCurrentContextConfig().getProperty(TkConstants.BATCH_USER_PRINCIPAL_NAME); 140 LOG.error("Could not run batch jobs due to missing batch user " + principalName); 141 } 142 143 } 144 145 private AccrualCategoryService getAccrualCategoryService() { 146 if (accrualCategoryService == null) { 147 accrualCategoryService = TkServiceLocator.getAccrualCategoryService(); 148 } 149 return accrualCategoryService; 150 } 151 152 public void setAccrualCategoryService(AccrualCategoryService accrualCategoryService) { 153 this.accrualCategoryService = accrualCategoryService; 154 } 155 156 private AssignmentService getAssignmentService() { 157 if (assignmentService == null) { 158 assignmentService = TkServiceLocator.getAssignmentService(); 159 } 160 return assignmentService; 161 } 162 163 public void setAssignmentService(AssignmentService assignmentService) { 164 this.assignmentService = assignmentService; 165 } 166 167 public LeavePlanService getLeavePlanService() { 168 if (leavePlanService == null) { 169 leavePlanService = TkServiceLocator.getLeavePlanService(); 170 } 171 return leavePlanService; 172 } 173 174 public void setLeavePlanService(LeavePlanService leavePlanService) { 175 this.leavePlanService = leavePlanService; 176 } 177 178 private PrincipalHRAttributesService getPrincipalHRAttributesService() { 179 if (principalHRAttributesService == null) { 180 principalHRAttributesService = TkServiceLocator.getPrincipalHRAttributeService(); 181 } 182 return principalHRAttributesService; 183 } 184 185 public void setPrincipalHRAttributesService(PrincipalHRAttributesService principalHRAttributesService) { 186 this.principalHRAttributesService = principalHRAttributesService; 187 } 188 189 private LeaveSummaryService getLeaveSummaryService() { 190 if (leaveSummaryService == null) { 191 leaveSummaryService = TkServiceLocator.getLeaveSummaryService(); 192 } 193 return leaveSummaryService; 194 } 195 196 public void setLeaveSummaryService(LeaveSummaryService leaveSummaryService) { 197 this.leaveSummaryService = leaveSummaryService; 198 } 199 200 private CalendarEntriesService getCalendarEntriesService() { 201 if (calendarEntriesService == null) { 202 calendarEntriesService = TkServiceLocator.getCalendarEntriesService(); 203 } 204 return calendarEntriesService; 205 } 206 207 public void setCalendarEntriesService(CalendarEntriesService calendarEntriesService) { 208 this.calendarEntriesService = calendarEntriesService; 209 } 210 211 private LeaveBlockService getLeaveBlockService() { 212 if (leaveBlockService == null) { 213 leaveBlockService = TkServiceLocator.getLeaveBlockService(); 214 } 215 return leaveBlockService; 216 } 217 218 public void setLeaveBlockService(LeaveBlockService leaveBlockService) { 219 this.leaveBlockService = leaveBlockService; 220 } 221 222 private List<LeaveBlock> createCarryOverLeaveBlocks(String principalId, 223 DateTime prevCalEndDate, 224 LeaveSummary leaveSummary) { 225 226 List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>(); 227 List<LeaveSummaryRow> leaveSummaryRows = leaveSummary.getLeaveSummaryRows(); 228 if(leaveSummaryRows !=null && !leaveSummaryRows.isEmpty()){ 229 230 for(LeaveSummaryRow lsr : leaveSummaryRows){ 231 AccrualCategory accrualCategory = getAccrualCategoryService().getAccrualCategory(lsr.getAccrualCategoryId()); 232 233 LeaveBlock leaveBlock = new LeaveBlock(); 234 leaveBlock.setAccrualCategory(lsr.getAccrualCategory()); 235 leaveBlock.setLeaveDate(TKUtils.getTimelessDate(prevCalEndDate.toDateMidnight().toDate())); 236 leaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.CARRY_OVER); 237 238 //More than one earn code can be associated with an accrual category. Which one does this get? 239 if(accrualCategory != null && accrualCategory.getEarnCode() != null ){ 240 leaveBlock.setEarnCode(accrualCategory.getEarnCode()); 241 } 242 243 leaveBlock.setDateAndTime(new Timestamp(new java.util.Date().getTime())); 244 leaveBlock.setAccrualGenerated(true); 245 leaveBlock.setBlockId(0L); 246 247 // ASk--Set null 248 leaveBlock.setScheduleTimeOffId(null); 249 250 if(lsr.getAccruedBalance() != null) { 251 if(lsr.getMaxCarryOver() != null && lsr.getAccruedBalance().compareTo(lsr.getMaxCarryOver()) > 0 ){ 252 leaveBlock.setLeaveAmount(lsr.getMaxCarryOver()); 253 } else { 254 leaveBlock.setLeaveAmount(lsr.getAccruedBalance()); 255 } 256 } 257 258 leaveBlock.setPrincipalId(principalId); 259 leaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 260 261 // Set EarnCode 262 if(leaveBlock.getLeaveAmount() != null && leaveBlock.getEarnCode() != null) { 263 leaveBlocks.add(leaveBlock); 264 } 265 } 266 } 267 268 269 return leaveBlocks; 270 } 271 272 private String getBatchUserPrincipalId() { 273 String principalId = null; 274 275 String principalName = ConfigContext.getCurrentContextConfig().getProperty(TkConstants.BATCH_USER_PRINCIPAL_NAME); 276 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(principalName); 277 if (principal != null) { 278 principalId = principal.getPrincipalId(); 279 } 280 281 return principalId; 282 } 283 284 }