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 }