1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.hr.time.missedpunch.service;
17  
18  import java.math.BigDecimal;
19  import java.sql.Timestamp;
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import org.apache.commons.lang.StringUtils;
24  import org.apache.log4j.Logger;
25  import org.joda.time.DateTime;
26  import org.joda.time.DateTimeZone;
27  import org.joda.time.LocalTime;
28  import org.kuali.hr.time.assignment.Assignment;
29  import org.kuali.hr.time.clocklog.ClockLog;
30  import org.kuali.hr.time.missedpunch.MissedPunchDocument;
31  import org.kuali.hr.time.missedpunch.dao.MissedPunchDao;
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.TKUtils;
37  import org.kuali.hr.time.util.TkConstants;
38  import org.kuali.rice.core.api.config.property.ConfigContext;
39  import org.kuali.rice.kew.api.WorkflowDocument;
40  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
41  import org.kuali.rice.kim.api.identity.Person;
42  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
43  import org.kuali.rice.krad.service.KRADServiceLocator;
44  import org.kuali.rice.krad.util.GlobalVariables;
45  import org.kuali.rice.krad.util.KRADConstants;
46  
47  public class MissedPunchServiceImpl implements MissedPunchService {
48  	
49  	private static final Logger LOG = Logger.getLogger(MissedPunchServiceImpl.class);
50  
51      MissedPunchDao missedPunchDao;
52  
53      @Override
54      public MissedPunchDocument getMissedPunchByRouteHeader(String headerId) {
55          return missedPunchDao.getMissedPunchByRouteHeader(headerId);
56      }
57  
58      public void setMissedPunchDao(MissedPunchDao missedPunchDao) {
59          this.missedPunchDao = missedPunchDao;
60      }
61  
62      @Override
63      public void updateClockLogAndTimeBlockIfNecessary(MissedPunchDocument missedPunch) {
64          java.util.Date actionDate = missedPunch.getActionDate();
65          java.sql.Time actionTime = missedPunch.getActionTime();
66  
67          LocalTime actionTimeLocal = new LocalTime(actionTime.getTime());
68          DateTime actionDateTime = new DateTime(actionDate.getTime());
69  
70          actionDateTime = actionDateTime.plus(actionTimeLocal.getMillisOfDay());
71  
72          ClockLog cl = TkServiceLocator.getClockLogService().getClockLog(missedPunch.getTkClockLogId());
73          
74          
75          if(cl == null) {
76          	MissedPunchDocument mpd = TkServiceLocator.getMissedPunchService().getMissedPunchByRouteHeader(missedPunch.getDocumentNumber());
77          	if(mpd != null) {
78          		missedPunch.setTkClockLogId(mpd.getTkClockLogId());
79          		cl = TkServiceLocator.getClockLogService().getClockLog(missedPunch.getTkClockLogId());
80          	}
81          }
82  
83          if(cl != null && cl.getClockTimestamp().compareTo(new Timestamp(actionDateTime.getMillis())) != 0){
84          	
85          	
86          	String logEndId = null;
87          	String logBeginId = null;
88          	List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocksForClockLogEndId(cl.getTkClockLogId());
89          	if(timeBlocks.isEmpty()) {
90          		
91          		timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocksForClockLogBeginId(cl.getTkClockLogId());
92          		if(!timeBlocks.isEmpty()) {
93          			logEndId = timeBlocks.get(0).getClockLogEndId();
94          		}
95          	} else {
96          		logBeginId = timeBlocks.get(0).getClockLogBeginId();	
97          	}
98          	
99          	
100         	for(TimeBlock tb : timeBlocks){
101         		TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb);
102         	}
103         	KRADServiceLocator.getBusinessObjectService().delete(cl);
104         	
105         	addClockLogForMissedPunch(missedPunch, logEndId, logBeginId);
106         }
107     }
108 
109     @Override
110     public void addClockLogForMissedPunch(MissedPunchDocument missedPunch) {
111         java.util.Date actionDate = missedPunch.getActionDate();
112         java.sql.Time actionTime = missedPunch.getActionTime();
113 
114         LocalTime actionTimeLocal = new LocalTime(actionTime.getTime());
115         DateTime actionDateTime = new DateTime(actionDate.getTime());
116 
117         actionDateTime = actionDateTime.plus(actionTimeLocal.getMillisOfDay());
118         missedPunch.setActionDate(new java.util.Date(actionDateTime.getMillis()));
119         TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(missedPunch.getTimesheetDocumentId());
120         Assignment assign = TkServiceLocator.getAssignmentService().getAssignment(tdoc, missedPunch.getAssignment());
121         
122         
123         Timestamp ts = new Timestamp(missedPunch.getActionDate().getTime());
124         ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog(missedPunch.getPrincipalId());
125         Long zoneOffset = TkServiceLocator.getTimezoneService().getTimezoneOffsetFromServerTime(DateTimeZone.forID(lastClockLog.getClockTimestampTimezone()));
126         Timestamp clockLogTime = new Timestamp(ts.getTime() - zoneOffset); 
127 
128         ClockLog clockLog = TkServiceLocator.getClockLogService().buildClockLog(clockLogTime, clockLogTime,
129                 assign,
130                 tdoc,
131                 missedPunch.getClockAction(),
132                 TKUtils.getIPAddressFromRequest(TKContext.getHttpServletRequest()));
133 
134         TkServiceLocator.getClockLogService().saveClockLog(clockLog);
135         missedPunch.setTkClockLogId(clockLog.getTkClockLogId());
136 
137         if (StringUtils.equals(clockLog.getClockAction(), TkConstants.CLOCK_OUT) ||
138                 StringUtils.equals(clockLog.getClockAction(), TkConstants.LUNCH_OUT)) {
139             String earnCode = assign.getJob().getPayTypeObj().getRegEarnCode();
140             this.buildTimeBlockRunRules(lastClockLog, clockLog, tdoc, assign, earnCode, lastClockLog.getClockTimestamp(), clockLog.getClockTimestamp());
141         }
142     }
143 
144     @Override
145     
146 
147     public void addClockLogForMissedPunch(MissedPunchDocument missedPunch, String logEndId, String logBeginId) {
148         java.util.Date actionDate = missedPunch.getActionDate();
149         java.sql.Time actionTime = missedPunch.getActionTime();
150 
151         LocalTime actionTimeLocal = new LocalTime(actionTime.getTime());
152         DateTime actionDateTime = new DateTime(actionDate.getTime());
153 
154         actionDateTime = actionDateTime.plus(actionTimeLocal.getMillisOfDay());
155         missedPunch.setActionDate(new java.util.Date(actionDateTime.getMillis()));
156         TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(missedPunch.getTimesheetDocumentId());
157         Assignment assign = TkServiceLocator.getAssignmentService().getAssignment(tdoc, missedPunch.getAssignment());
158         
159         Timestamp ts = new Timestamp(missedPunch.getActionDate().getTime());
160         ClockLog lastLog = TkServiceLocator.getClockLogService().getLastClockLog(missedPunch.getPrincipalId());
161         Long zoneOffset = TkServiceLocator.getTimezoneService().getTimezoneOffsetFromServerTime(DateTimeZone.forID(lastLog.getClockTimestampTimezone()));
162         Timestamp clockLogTime = new Timestamp(ts.getTime() - zoneOffset); 
163 
164         ClockLog clockLog = TkServiceLocator.getClockLogService().buildClockLog(clockLogTime, clockLogTime,
165                 assign,
166                 tdoc,
167                 missedPunch.getClockAction(),
168                 TKUtils.getIPAddressFromRequest(TKContext.getHttpServletRequest()));
169         TkServiceLocator.getClockLogService().saveClockLog(clockLog);
170         missedPunch.setTkClockLogId(clockLog.getTkClockLogId());
171 
172 
173 
174         
175         
176         if(!(logEndId == null && logBeginId == null)) {
177 	        ClockLog endLog = null;
178 	        ClockLog beginLog = null;
179 	       if(logEndId != null) {
180 	    	   endLog = TkServiceLocator.getClockLogService().getClockLog(logEndId);
181 	       } else {
182 	    	   endLog = clockLog; 
183 	       }
184 	       if (logBeginId != null) {
185 	           beginLog = TkServiceLocator.getClockLogService().getClockLog(logBeginId);
186 	       } else {
187 	    	   beginLog = clockLog;
188 	       }
189 	        
190 	       if (beginLog != null && endLog != null && beginLog.getClockTimestamp().before(endLog.getClockTimestamp())) {
191 	           String earnCode = assign.getJob().getPayTypeObj().getRegEarnCode();
192 	           this.buildTimeBlockRunRules(beginLog, endLog, tdoc, assign, earnCode, beginLog.getClockTimestamp(), endLog.getClockTimestamp());
193 	       } else {
194 	        	
195 	    	   GlobalVariables.getMessageMap().putError("document.actionTime", "clock.mp.invalid.datetime");
196 	       }
197         }
198     }
199 
200     
201 
202 
203 
204     private void buildTimeBlockRunRules(ClockLog beginClockLog, ClockLog endClockLog, TimesheetDocument tdoc, Assignment assignment, String earnCode, Timestamp beginTimestamp, Timestamp endTimestamp) {
205         
206         List<TimeBlock> newTimeBlocks = tdoc.getTimeBlocks();
207         List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(newTimeBlocks);
208         for (TimeBlock tb : newTimeBlocks) {
209             referenceTimeBlocks.add(tb.copy());
210         }
211 
212         
213         List<TimeBlock> blocks = TkServiceLocator.getTimeBlockService().buildTimeBlocks(
214                 assignment, earnCode, tdoc, beginTimestamp,
215                 endTimestamp, BigDecimal.ZERO, BigDecimal.ZERO, true, false, TKContext.getPrincipalId());
216 
217 
218         
219         for (TimeBlock block : blocks) {
220             block.setClockLogBeginId(beginClockLog.getTkClockLogId());
221             block.setClockLogEndId(endClockLog.getTkClockLogId());
222         }
223 
224         newTimeBlocks.addAll(blocks);
225 
226         
227         TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
228         
229         TkServiceLocator.getTkRuleControllerService().applyRules(
230                 TkConstants.ACTIONS.CLOCK_OUT, newTimeBlocks,
231                 tdoc.getCalendarEntry(),
232                 tdoc, tdoc.getPrincipalId()
233         );
234 
235         TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, TKContext.getPrincipalId());
236     }
237     public MissedPunchDocument getMissedPunchByClockLogId(String clockLogId){
238     	return missedPunchDao.getMissedPunchByClockLogId(clockLogId);
239 
240     }
241 
242     @Override
243     public void approveMissedPunch(MissedPunchDocument document) {
244     	String batchUserPrincipalId = getBatchUserPrincipalId();
245         
246         if (batchUserPrincipalId != null) {
247 	        String rhid = document.getDocumentNumber();
248 	        WorkflowDocument wd = WorkflowDocumentFactory.loadDocument(batchUserPrincipalId, rhid);
249 	        wd.superUserBlanketApprove("Batch job superuser approving missed punch document.");
250         } else {
251         	String principalName = ConfigContext.getCurrentContextConfig().getProperty(TkConstants.BATCH_USER_PRINCIPAL_NAME);
252         	LOG.error("Could not approve missed punch document due to missing batch user " + principalName);
253         }
254     }
255     
256     private String getBatchUserPrincipalId() {
257     	String principalId = null;
258     	
259     	String principalName = ConfigContext.getCurrentContextConfig().getProperty(TkConstants.BATCH_USER_PRINCIPAL_NAME);
260         Person person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
261         if (person != null) {
262         	principalId = person.getPrincipalId();
263         }
264         
265         return principalId;
266     }
267     
268     @Override
269     public List<MissedPunchDocument> getMissedPunchDocsByTimesheetDocumentId(String timesheetDocumentId) {
270         return missedPunchDao.getMissedPunchDocsByTimesheetDocumentId(timesheetDocumentId);
271     }
272 
273 }