1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.clocklog.service;
17
18 import java.math.BigDecimal;
19 import java.sql.Timestamp;
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24
25 import org.apache.commons.collections.CollectionUtils;
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.hr.lm.leaveblock.LeaveBlock;
28 import org.kuali.hr.time.assignment.Assignment;
29 import org.kuali.hr.time.calendar.CalendarEntries;
30 import org.kuali.hr.time.clocklog.ClockLog;
31 import org.kuali.hr.time.clocklog.dao.ClockLogDao;
32 import org.kuali.hr.time.service.base.TkServiceLocator;
33 import org.kuali.hr.time.timeblock.TimeBlock;
34 import org.kuali.hr.time.timesheet.TimesheetDocument;
35 import org.kuali.hr.time.util.TKContext;
36 import org.kuali.hr.time.util.TkConstants;
37 import org.kuali.rice.krad.service.KRADServiceLocator;
38
39 public class ClockLogServiceImpl implements ClockLogService {
40
41 private ClockLogDao clockLogDao;
42
43 public ClockLogServiceImpl() {
44 }
45
46 public ClockLog saveClockLog(ClockLog clockLog) {
47 return KRADServiceLocator.getBusinessObjectService().save(clockLog);
48 }
49
50 @Override
51 public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, boolean runRules, String principalId) {
52 return processClockLog(clockTimeStamp, assignment, pe, ip, asOfDate, td, clockAction, runRules, principalId, TKContext.getPrincipalId());
53 }
54
55 @Override
56 public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, boolean runRules, String principalId, String userPrincipalId) {
57
58 Timestamp roundedClockTimestamp = TkServiceLocator.getGracePeriodService().processGracePeriodRule(clockTimeStamp, new java.sql.Date(pe.getBeginPeriodDateTime().getTime()));
59
60 ClockLog clockLog = buildClockLog(roundedClockTimestamp, new Timestamp(System.currentTimeMillis()), assignment, td, clockAction, ip, userPrincipalId);
61
62 if (runRules) {
63 TkServiceLocator.getClockLocationRuleService().processClockLocationRule(clockLog, asOfDate);
64 }
65
66
67 if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT) || StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) {
68 processTimeBlock(clockLog, assignment, pe, td, clockAction, principalId, userPrincipalId);
69 } else {
70
71 KRADServiceLocator.getBusinessObjectService().save(clockLog);
72 }
73
74 return clockLog;
75 }
76
77 private void processTimeBlock(ClockLog clockLog, Assignment currentAssignment, CalendarEntries pe, TimesheetDocument td, String clockAction, String principalId, String userPrincipalId) {
78 ClockLog lastLog = null;
79 Timestamp lastClockTimestamp = null;
80 String beginClockLogId = null;
81 String endClockLogId = null;
82
83 if (StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) {
84 lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId, TkConstants.CLOCK_IN);
85 } else if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT)) {
86 lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId);
87 }
88 if (lastLog != null) {
89 lastClockTimestamp = lastLog.getClockTimestamp();
90 beginClockLogId = lastLog.getTkClockLogId();
91 }
92
93 KRADServiceLocator.getBusinessObjectService().save(clockLog);
94 endClockLogId = clockLog.getTkClockLogId();
95
96 long beginTime = lastClockTimestamp.getTime();
97 Timestamp beginTimestamp = new Timestamp(beginTime);
98 Timestamp endTimestamp = clockLog.getClockTimestamp();
99
100
101 List<TimeBlock> newTimeBlocks = td.getTimeBlocks();
102 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(td.getTimeBlocks().size());
103 for (TimeBlock tb : td.getTimeBlocks()) {
104 referenceTimeBlocks.add(tb.copy());
105 }
106
107
108 List<TimeBlock> aList = TkServiceLocator.getTimeBlockService().buildTimeBlocks(currentAssignment, currentAssignment.getJob().getPayTypeObj().getRegEarnCode(), td, beginTimestamp, endTimestamp, BigDecimal.ZERO, BigDecimal.ZERO, true, false, userPrincipalId);
109 for (TimeBlock tb : aList) {
110 tb.setClockLogBeginId(beginClockLogId);
111 tb.setClockLogEndId(endClockLogId);
112 }
113 newTimeBlocks.addAll(aList);
114
115 List<Assignment> assignments = td.getAssignments();
116 List<String> assignmentKeys = new ArrayList<String>();
117 for (Assignment assignment : assignments) {
118 assignmentKeys.add(assignment.getAssignmentKey());
119 }
120 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, td.getAsOfDate(), td.getDocEndDate(), assignmentKeys);
121
122
123 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks, td.getAsOfDate());
124
125
126 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.CLOCK_OUT, newTimeBlocks, leaveBlocks, pe, td, principalId);
127
128
129 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, userPrincipalId);
130 }
131
132 private ClockLog buildClockLog(Timestamp clockTimestamp, Timestamp originalTimestamp, Assignment assignment, TimesheetDocument timesheetDocument, String clockAction, String ip, String userPrincipalId) {
133 ClockLog clockLog = new ClockLog();
134 clockLog.setDocumentId(timesheetDocument.getDocumentId());
135 clockLog.setPrincipalId(timesheetDocument.getPrincipalId());
136 clockLog.setJob(timesheetDocument.getJob(assignment.getJobNumber()));
137 clockLog.setJobNumber(assignment.getJobNumber());
138 clockLog.setWorkArea(assignment.getWorkArea());
139 clockLog.setTask(assignment.getTask());
140 clockLog.setClockTimestampTimezone(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback().getID());
141 clockLog.setClockTimestamp(clockTimestamp);
142 clockLog.setClockAction(clockAction);
143 clockLog.setIpAddress(ip);
144 clockLog.setUserPrincipalId(userPrincipalId);
145
146 clockLog.setTimestamp(originalTimestamp);
147
148 return clockLog;
149 }
150
151 public void setClockLogDao(ClockLogDao clockLogDao) {
152 this.clockLogDao = clockLogDao;
153 }
154
155 public ClockLog getLastClockLog(String principalId) {
156 return clockLogDao.getLastClockLog(principalId);
157 }
158
159 public ClockLog getLastClockLog(String principalId, String clockAction) {
160 return clockLogDao.getLastClockLog(principalId, clockAction);
161 }
162
163 public ClockLog getLastClockLog(String principalId, String jobNumber, String workArea, String task, CalendarEntries calendarEntry) {
164 return clockLogDao.getLastClockLog(principalId, jobNumber, workArea, task, calendarEntry);
165 }
166
167 @Override
168 public ClockLog getClockLog(String tkClockLogId) {
169 return clockLogDao.getClockLog(tkClockLogId);
170 }
171
172 @Override
173 public void deleteClockLogsForDocumentId(String documentId) {
174 clockLogDao.deleteClockLogsForDocumentId(documentId);
175 }
176
177 public List<String> getUnapprovedIPWarning(List<TimeBlock> timeBlocks) {
178 List<String> warningMessages = new ArrayList<String>();
179 if (CollectionUtils.isNotEmpty(timeBlocks)) {
180 Set<String> aSet = new HashSet<String>();
181 for(TimeBlock tb : timeBlocks) {
182 if(tb.getClockLogCreated()) {
183 if(StringUtils.isNotEmpty(tb.getClockLogBeginId())){
184 ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(tb.getClockLogBeginId());
185 if(cl.getUnapprovedIP()) {
186 aSet.add(buildUnapprovedIPWarning(cl));
187 }
188 }
189 if(StringUtils.isNotEmpty(tb.getClockLogEndId())){
190 ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(tb.getClockLogEndId());
191 if(cl.getUnapprovedIP()) {
192 aSet.add(buildUnapprovedIPWarning(cl));
193 }
194 }
195 }
196 }
197 warningMessages.addAll(aSet);
198 }
199
200 return warningMessages;
201 }
202
203 public String buildUnapprovedIPWarning(ClockLog cl) {
204 String warning = "Warning: Action '" + TkConstants.CLOCK_ACTION_STRINGS.get(cl.getClockAction()) + "' taken at "
205 + cl.getClockTimestamp() + " was from an unapproved IP address - " + cl.getIpAddress();
206 return warning;
207 }
208
209 }