View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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          // process rules
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          // If the clock action is clock out or lunch out, create a time block besides the clock log
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              //Save current clock log to get id for timeblock building
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          //Save current clock log to get id for timeblock building
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         // New Time Blocks, pointer reference
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         // Add TimeBlocks after we store our reference object!
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         //reset time block
123         TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks, td.getAsOfDate());
124 
125         //apply any rules for this action
126         TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.CLOCK_OUT, newTimeBlocks, leaveBlocks, pe, td, principalId);
127 
128         //call persist method that only saves added/deleted/changed timeblocks
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         // timestamp should be the original time without Grace Period rule applied
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 }