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.clocklog.service; 017 018 import org.apache.commons.collections.CollectionUtils; 019 import org.apache.commons.lang.StringUtils; 020 import org.kuali.hr.time.assignment.Assignment; 021 import org.kuali.hr.time.calendar.CalendarEntries; 022 import org.kuali.hr.time.clocklog.ClockLog; 023 import org.kuali.hr.time.clocklog.dao.ClockLogDao; 024 import org.kuali.hr.time.service.base.TkServiceLocator; 025 import org.kuali.hr.time.timeblock.TimeBlock; 026 import org.kuali.hr.time.timesheet.TimesheetDocument; 027 import org.kuali.hr.time.util.TKContext; 028 import org.kuali.hr.time.util.TkConstants; 029 030 import java.math.BigDecimal; 031 import java.sql.Timestamp; 032 import java.util.ArrayList; 033 import java.util.HashSet; 034 import java.util.List; 035 import java.util.Set; 036 037 public class ClockLogServiceImpl implements ClockLogService { 038 039 private ClockLogDao clockLogDao; 040 041 public ClockLogServiceImpl() { 042 } 043 044 public void saveClockLog(ClockLog clockLog) { 045 clockLogDao.saveOrUpdate(clockLog); 046 } 047 048 @Override 049 public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, String principalId) { 050 return processClockLog(clockTimeStamp, assignment, pe, ip, asOfDate, td, clockAction, principalId, TKContext.getPrincipalId()); 051 } 052 053 @Override 054 public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, String principalId, String userPrincipalId) { 055 // process rules 056 Timestamp roundedClockTimestamp = TkServiceLocator.getGracePeriodService().processGracePeriodRule(clockTimeStamp, new java.sql.Date(pe.getBeginPeriodDateTime().getTime())); 057 058 ClockLog clockLog = TkServiceLocator.getClockLogService().buildClockLog(roundedClockTimestamp, new Timestamp(System.currentTimeMillis()), assignment, td, clockAction, ip, userPrincipalId); 059 TkServiceLocator.getClockLocationRuleService().processClockLocationRule(clockLog, asOfDate); 060 061 // If the clock action is clock out or lunch out, create a time block besides the clock log 062 if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT) || StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) { 063 processTimeBlock(clockLog, assignment, pe, td, clockAction, principalId); 064 } else { 065 //Save current clock log to get id for timeblock building 066 TkServiceLocator.getClockLogService().saveClockLog(clockLog); 067 } 068 069 return clockLog; 070 } 071 072 private void processTimeBlock(ClockLog clockLog, Assignment assignment, CalendarEntries pe, TimesheetDocument td, String clockAction, String principalId) { 073 ClockLog lastLog = null; 074 Timestamp lastClockTimestamp = null; 075 String beginClockLogId = null; 076 String endClockLogId = null; 077 078 if (StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) { 079 lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId, TkConstants.CLOCK_IN); 080 } else if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT)) { 081 lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId); 082 } 083 if (lastLog != null) { 084 lastClockTimestamp = lastLog.getClockTimestamp(); 085 beginClockLogId = lastLog.getTkClockLogId(); 086 } 087 //Save current clock log to get id for timeblock building 088 TkServiceLocator.getClockLogService().saveClockLog(clockLog); 089 endClockLogId = clockLog.getTkClockLogId(); 090 091 long beginTime = lastClockTimestamp.getTime(); 092 Timestamp beginTimestamp = new Timestamp(beginTime); 093 Timestamp endTimestamp = clockLog.getClockTimestamp(); 094 095 // New Time Blocks, pointer reference 096 List<TimeBlock> newTimeBlocks = td.getTimeBlocks(); 097 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(td.getTimeBlocks().size()); 098 for (TimeBlock tb : td.getTimeBlocks()) { 099 referenceTimeBlocks.add(tb.copy()); 100 } 101 102 // Add TimeBlocks after we store our reference object! 103 List<TimeBlock> aList = TkServiceLocator.getTimeBlockService().buildTimeBlocks(assignment, assignment.getJob().getPayTypeObj().getRegEarnCode(), td, beginTimestamp, endTimestamp, BigDecimal.ZERO, BigDecimal.ZERO, true, false); 104 for (TimeBlock tb : aList) { 105 tb.setClockLogBeginId(beginClockLogId); 106 tb.setClockLogEndId(endClockLogId); 107 } 108 newTimeBlocks.addAll(aList); 109 110 //reset time block 111 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 112 113 //apply any rules for this action 114 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.CLOCK_OUT, newTimeBlocks, pe, td, principalId); 115 116 //call persist method that only saves added/deleted/changed timeblocks 117 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks); 118 } 119 120 @Override 121 public ClockLog buildClockLog(Timestamp clockTimestamp, Timestamp originalTimestamp, Assignment assignment, TimesheetDocument timesheetDocument, String clockAction, String ip) { 122 return buildClockLog(clockTimestamp, originalTimestamp, assignment, timesheetDocument, clockAction, ip, TKContext.getPrincipalId()); 123 } 124 125 @Override 126 public ClockLog buildClockLog(Timestamp clockTimestamp, Timestamp originalTimestamp, Assignment assignment, TimesheetDocument timesheetDocument, String clockAction, String ip, String userPrincipalId) { 127 String principalId = timesheetDocument.getPrincipalId(); 128 129 ClockLog clockLog = new ClockLog(); 130 clockLog.setPrincipalId(principalId); 131 // AssignmentDescriptionKey assignmentDesc = TkServiceLocator.getAssignmentService().getAssignmentDescriptionKey(selectedAssign); 132 // Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(timesheetDocument, selectedAssign); 133 clockLog.setJob(timesheetDocument.getJob(assignment.getJobNumber())); 134 clockLog.setJobNumber(assignment.getJobNumber()); 135 clockLog.setWorkArea(assignment.getWorkArea()); 136 clockLog.setTask(assignment.getTask()); 137 clockLog.setClockTimestampTimezone(TkServiceLocator.getTimezoneService().getUserTimezone()); 138 clockLog.setClockTimestamp(clockTimestamp); 139 clockLog.setClockAction(clockAction); 140 clockLog.setIpAddress(ip); 141 clockLog.setUserPrincipalId(userPrincipalId); 142 // timestamp should be the original time without Grace Period rule applied 143 clockLog.setTimestamp(originalTimestamp); 144 145 return clockLog; 146 } 147 148 public void setClockLogDao(ClockLogDao clockLogDao) { 149 this.clockLogDao = clockLogDao; 150 } 151 152 public ClockLog getLastClockLog(String principalId) { 153 return clockLogDao.getLastClockLog(principalId); 154 } 155 156 public ClockLog getLastClockLog(String principalId, String clockAction) { 157 return clockLogDao.getLastClockLog(principalId, clockAction); 158 } 159 160 public List<ClockLog> getOpenClockLogs( CalendarEntries payCalendarEntry) { 161 return clockLogDao.getOpenClockLogs(payCalendarEntry); 162 } 163 164 @Override 165 public ClockLog getClockLog(String tkClockLogId) { 166 return clockLogDao.getClockLog(tkClockLogId); 167 } 168 169 public List<String> getUnapprovedIPWarning(List<TimeBlock> timeBlocks) { 170 List<String> warningMessages = new ArrayList<String>(); 171 if (CollectionUtils.isNotEmpty(timeBlocks)) { 172 Set<String> aSet = new HashSet<String>(); 173 for(TimeBlock tb : timeBlocks) { 174 if(tb.getClockLogCreated()) { 175 if(StringUtils.isNotEmpty(tb.getClockLogBeginId())){ 176 ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(tb.getClockLogBeginId()); 177 if(cl.getUnapprovedIP()) { 178 aSet.add(buildUnapprovedIPWarning(cl)); 179 } 180 } 181 if(StringUtils.isNotEmpty(tb.getClockLogEndId())){ 182 ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(tb.getClockLogEndId()); 183 if(cl.getUnapprovedIP()) { 184 aSet.add(buildUnapprovedIPWarning(cl)); 185 } 186 } 187 } 188 } 189 warningMessages.addAll(aSet); 190 } 191 192 return warningMessages; 193 } 194 195 public String buildUnapprovedIPWarning(ClockLog cl) { 196 String warning = "Warning: Action '" + TkConstants.CLOCK_ACTION_STRINGS.get(cl.getClockAction()) + "' taken at " 197 + cl.getClockTimestamp() + " was from an unapproved IP address - " + cl.getIpAddress(); 198 return warning; 199 } 200 201 }