1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.missedpunch;
17
18 import java.sql.Timestamp;
19 import java.text.ParseException;
20 import java.text.SimpleDateFormat;
21 import java.util.Date;
22 import java.util.HashSet;
23 import java.util.Set;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.joda.time.DateTime;
27 import org.joda.time.DateTimeZone;
28 import org.joda.time.LocalTime;
29 import org.kuali.hr.time.clocklog.ClockLog;
30 import org.kuali.hr.time.service.base.TkServiceLocator;
31 import org.kuali.hr.time.timesheet.TimesheetDocument;
32 import org.kuali.hr.time.util.TKUtils;
33 import org.kuali.hr.time.util.TkConstants;
34 import org.kuali.rice.kew.api.KewApiServiceLocator;
35 import org.kuali.rice.kew.api.document.DocumentStatus;
36 import org.kuali.rice.krad.document.Document;
37 import org.kuali.rice.krad.rules.TransactionalDocumentRuleBase;
38 import org.kuali.rice.krad.util.GlobalVariables;
39
40 public class MissedPunchValidation extends TransactionalDocumentRuleBase {
41
42 @Override
43 protected boolean processCustomRouteDocumentBusinessRules(Document document) {
44 boolean valid = true;
45
46 MissedPunchDocument missedPunchDocument = (MissedPunchDocument) document;
47 DocumentStatus documentStatus = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(missedPunchDocument.getDocumentNumber());
48
49 if (DocumentStatus.INITIATED.equals(DocumentStatus.fromCode(documentStatus.getCode()))
50 || DocumentStatus.SAVED.equals(DocumentStatus.fromCode(documentStatus.getCode()))) {
51 valid &= validateTimeSheet(missedPunchDocument);
52
53 if (valid) {
54 ClockLog lastClock = TkServiceLocator.getClockLogService().getLastClockLog(missedPunchDocument.getPrincipalId());
55 try {
56 valid &= validateClockAction(missedPunchDocument, lastClock);
57 valid &= validateClockTime(missedPunchDocument, lastClock);
58 } catch (ParseException e) {
59 e.printStackTrace();
60 }
61 }
62 }
63
64 return valid;
65 }
66
67
68 boolean validateTimeSheet(MissedPunchDocument mp) {
69 boolean valid = true;
70 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(mp.getTimesheetDocumentId());
71 if(tsd != null
72 && (tsd.getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)
73 || tsd.getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.FINAL))) {
74 GlobalVariables.getMessageMap().putError("document.timesheetDocumentId", "clock.mp.invalid.timesheet");
75 valid = false;
76 }
77
78 return valid;
79 }
80
81
82
83
84
85
86
87
88
89 boolean validateClockAction(MissedPunchDocument mp, ClockLog lastClock) {
90 boolean valid = true;
91 Set<String> validActions = (lastClock != null) ? TkConstants.CLOCK_ACTION_TRANSITION_MAP.get(lastClock.getClockAction()) : new HashSet<String>();
92
93
94 if (mp.getClockAction().equals(TkConstants.CLOCK_OUT) || mp.getClockAction().equals(TkConstants.LUNCH_OUT)) {
95 ClockLog lci = TkServiceLocator.getClockLogService().getLastClockLog(mp.getPrincipalId(),TkConstants.CLOCK_IN);
96 ClockLog lli = TkServiceLocator.getClockLogService().getLastClockLog(mp.getPrincipalId(),TkConstants.LUNCH_IN);
97 if (lci != null) {
98 MissedPunchDocument mpd = TkServiceLocator.getMissedPunchService().getMissedPunchByClockLogId(lci.getTkClockLogId());
99 if(mpd != null) {
100 GlobalVariables.getMessageMap().putError("document.clockAction", "clock.mp.onlyOne.action");
101 return false;
102 }
103 } else if(lli != null) {
104 MissedPunchDocument mpd = TkServiceLocator.getMissedPunchService().getMissedPunchByClockLogId(lli.getTkClockLogId());
105 if(mpd != null) {
106 GlobalVariables.getMessageMap().putError("document.clockAction", "clock.mp.onlyOne.action");
107 return false;
108 }
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121
122 if (!StringUtils.equals("A", mp.getDocumentStatus()) && !validActions.contains(mp.getClockAction())) {
123 GlobalVariables.getMessageMap().putError("document.clockAction", "clock.mp.invalid.action");
124 valid = false;
125 }
126
127 return valid;
128 }
129
130
131
132
133
134
135
136
137
138
139
140 boolean validateClockTime(MissedPunchDocument mp, ClockLog lastClock) throws ParseException {
141 boolean valid = true;
142
143 if (lastClock == null) {
144 return valid;
145 }
146
147
148 if(mp.getActionTime() == null || mp.getActionDate() == null)
149 return false;
150
151 DateTime clockLogDateTime = new DateTime(lastClock.getClockTimestamp().getTime());
152 DateTime boundaryMax = clockLogDateTime.plusDays(1);
153 DateTime nowTime = new DateTime(TKUtils.getCurrentDate());
154 long offset = TkServiceLocator.getTimezoneService().getTimezoneOffsetFromServerTime(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback());
155 long dateTimeLocal = new LocalTime(mp.getActionTime()).getMillisOfDay() + mp.getActionDate().getTime() - offset;
156
157
158 DateTime actionDateTime = new DateTime(dateTimeLocal);
159
160
161 if(actionDateTime.getYear()> nowTime.getYear()
162 || (actionDateTime.getYear()==nowTime.getYear() && actionDateTime.getDayOfYear() > nowTime.getDayOfYear())) {
163 GlobalVariables.getMessageMap().putError("document.actionDate", "clock.mp.future.date");
164 return false;
165 }
166
167
168 if(actionDateTime.getMillis() > nowTime.getMillis()) {
169 GlobalVariables.getMessageMap().putError("document.actionTime", "clock.mp.future.time");
170 return false;
171 }
172
173 if ((!StringUtils.equals(lastClock.getClockAction(), TkConstants.CLOCK_OUT) && actionDateTime.isAfter(boundaryMax))
174 || actionDateTime.isBefore(clockLogDateTime)) {
175 GlobalVariables.getMessageMap().putError("document.actionTime", "clock.mp.invalid.datetime");
176 valid = false;
177 }
178
179 return valid;
180 }
181
182 }