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.hr.time.workflow.TimesheetDocumentHeader;
38  import org.kuali.rice.krad.service.KRADServiceLocator;
39  
40  public class ClockLogServiceImpl implements ClockLogService {
41  
42      private ClockLogDao clockLogDao;
43  
44      public ClockLogServiceImpl() {
45      }
46  
47      public ClockLog saveClockLog(ClockLog clockLog) {
48          return KRADServiceLocator.getBusinessObjectService().save(clockLog);
49      }
50  
51      @Override
52      public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, boolean runRules, String principalId) {
53          return processClockLog(clockTimeStamp, assignment, pe, ip, asOfDate, td, clockAction, runRules, principalId, TKContext.getPrincipalId());
54      }
55  
56      @Override
57      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) {
58          // process rules
59          Timestamp roundedClockTimestamp = TkServiceLocator.getGracePeriodService().processGracePeriodRule(clockTimeStamp, new java.sql.Date(pe.getBeginPeriodDateTime().getTime()));
60  
61          ClockLog clockLog = buildClockLog(roundedClockTimestamp, new Timestamp(System.currentTimeMillis()), assignment, td, clockAction, ip, userPrincipalId);
62          
63          if (runRules) {
64          	TkServiceLocator.getClockLocationRuleService().processClockLocationRule(clockLog, asOfDate);
65          }
66          
67          // If the clock action is clock out or lunch out, create a time block besides the clock log
68          if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT) || StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) {
69              processTimeBlock(clockLog, assignment, pe, td, clockAction, principalId, userPrincipalId);
70          } else {
71              //Save current clock log to get id for timeblock building
72              KRADServiceLocator.getBusinessObjectService().save(clockLog);
73          }
74  
75          return clockLog;
76      }
77  
78      private void processTimeBlock(ClockLog clockLog, Assignment currentAssignment, CalendarEntries pe, TimesheetDocument td, String clockAction, String principalId, String userPrincipalId) {
79          ClockLog lastLog = null;
80          Timestamp lastClockTimestamp = null;
81          String beginClockLogId = null;
82          String endClockLogId = null;
83  
84          if (StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) {
85              lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId, TkConstants.CLOCK_IN);
86          } else if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT)) {
87              lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId);
88          }
89          if (lastLog != null) {
90              lastClockTimestamp = lastLog.getClockTimestamp();
91              beginClockLogId = lastLog.getTkClockLogId();
92          }
93          //Save current clock log to get id for timeblock building
94          KRADServiceLocator.getBusinessObjectService().save(clockLog);
95          endClockLogId = clockLog.getTkClockLogId();
96  
97          long beginTime = lastClockTimestamp.getTime();
98          Timestamp beginTimestamp = new Timestamp(beginTime);
99          Timestamp endTimestamp = clockLog.getClockTimestamp();
100 
101         // New Time Blocks, pointer reference
102         List<TimeBlock> newTimeBlocks = td.getTimeBlocks();
103         List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(td.getTimeBlocks().size());
104         for (TimeBlock tb : td.getTimeBlocks()) {
105             referenceTimeBlocks.add(tb.copy());
106         }
107 
108         // Add TimeBlocks after we store our reference object!
109         List<TimeBlock> aList = TkServiceLocator.getTimeBlockService().buildTimeBlocks(currentAssignment, currentAssignment.getJob().getPayTypeObj().getRegEarnCode(), td, beginTimestamp, endTimestamp, BigDecimal.ZERO, BigDecimal.ZERO, true, false, userPrincipalId);
110         for (TimeBlock tb : aList) {
111             tb.setClockLogBeginId(beginClockLogId);
112             tb.setClockLogEndId(endClockLogId);
113         }
114         newTimeBlocks.addAll(aList);
115         
116         List<Assignment> assignments = td.getAssignments();
117         List<String> assignmentKeys = new ArrayList<String>();
118         for (Assignment assignment : assignments) {
119         	assignmentKeys.add(assignment.getAssignmentKey());
120         }
121         List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, td.getAsOfDate(), td.getDocEndDate(), assignmentKeys);
122 
123         //reset time block
124         TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks, td.getAsOfDate());
125 
126         //apply any rules for this action
127         TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.CLOCK_OUT, newTimeBlocks, leaveBlocks, pe, td, principalId);
128 
129         //call persist method that only saves added/deleted/changed timeblocks
130         TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, userPrincipalId);
131     }
132 
133     private ClockLog buildClockLog(Timestamp clockTimestamp, Timestamp originalTimestamp, Assignment assignment, TimesheetDocument timesheetDocument, String clockAction, String ip, String userPrincipalId) {
134         ClockLog clockLog = new ClockLog();
135         clockLog.setDocumentId(timesheetDocument.getDocumentId());
136         clockLog.setPrincipalId(timesheetDocument.getPrincipalId());
137         clockLog.setJob(timesheetDocument.getJob(assignment.getJobNumber()));
138         clockLog.setJobNumber(assignment.getJobNumber());
139         clockLog.setWorkArea(assignment.getWorkArea());
140         clockLog.setTask(assignment.getTask());
141         clockLog.setClockTimestampTimezone(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback().getID());
142         clockLog.setClockTimestamp(clockTimestamp);
143         clockLog.setClockAction(clockAction);
144         clockLog.setIpAddress(ip);
145         clockLog.setUserPrincipalId(userPrincipalId);
146         // timestamp should be the original time without Grace Period rule applied
147         clockLog.setTimestamp(originalTimestamp);
148 
149         return clockLog;
150     }
151 
152     public void setClockLogDao(ClockLogDao clockLogDao) {
153         this.clockLogDao = clockLogDao;
154     }
155 
156     public ClockLog getLastClockLog(String principalId) {
157         return clockLogDao.getLastClockLog(principalId);
158     }
159 
160     public ClockLog getLastClockLog(String principalId, String clockAction) {
161         return clockLogDao.getLastClockLog(principalId, clockAction);
162     }
163 
164     public ClockLog getLastClockLog(String principalId, String jobNumber, String workArea, String task, CalendarEntries calendarEntry) {
165         //return clockLogDao.getLastClockLog(principalId, jobNumber, workArea, task, calendarEntry);
166         TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, calendarEntry.getBeginPeriodDateTime(), calendarEntry.getEndPeriodDateTime());
167         if (tdh == null) {
168             return null;
169         }
170         return clockLogDao.getLastClockLog(principalId, jobNumber, workArea, task, tdh.getDocumentId());
171     }
172 
173     @Override
174     public ClockLog getClockLog(String tkClockLogId) {
175         return clockLogDao.getClockLog(tkClockLogId);
176     }
177     
178 	@Override
179 	public void deleteClockLogsForDocumentId(String documentId) {
180 		clockLogDao.deleteClockLogsForDocumentId(documentId);
181 	}
182 
183     public List<String> getUnapprovedIPWarning(List<TimeBlock> timeBlocks) {
184 		 List<String> warningMessages = new ArrayList<String>();
185 		 if (CollectionUtils.isNotEmpty(timeBlocks)) {
186 		     Set<String> aSet = new HashSet<String>();
187 		     for(TimeBlock tb : timeBlocks) {
188 		    	 if(tb.getClockLogCreated()) {
189 		    		 if(StringUtils.isNotEmpty(tb.getClockLogBeginId())){
190 		    			 ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(tb.getClockLogBeginId());
191 		    			 if(cl.getUnapprovedIP()) {
192 		    				 aSet.add(buildUnapprovedIPWarning(cl));
193 		    			 }
194 		    		 }
195 		    		 if(StringUtils.isNotEmpty(tb.getClockLogEndId())){
196 		    			 ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(tb.getClockLogEndId());
197 		    			 if(cl.getUnapprovedIP()) {
198 		    				 aSet.add(buildUnapprovedIPWarning(cl));
199 		    			 }
200 		    		 }		
201 		    	 }
202 		     }
203 		     warningMessages.addAll(aSet);
204 		}
205 		
206 		return warningMessages;
207     }
208 
209 	public String buildUnapprovedIPWarning(ClockLog cl) {
210 		String warning = "Warning: Action '" + TkConstants.CLOCK_ACTION_STRINGS.get(cl.getClockAction()) + "' taken at " 
211 			+ cl.getClockTimestamp() + " was from an unapproved IP address - " + cl.getIpAddress();
212 		return warning;
213 	}
214 
215 }