1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.detail.web;
17
18 import java.sql.Date;
19 import java.sql.Timestamp;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.apache.commons.lang.StringUtils;
33 import org.apache.struts.action.ActionForm;
34 import org.apache.struts.action.ActionForward;
35 import org.apache.struts.action.ActionMapping;
36 import org.joda.time.DateTime;
37 import org.joda.time.Interval;
38 import org.kuali.hr.time.assignment.Assignment;
39 import org.kuali.hr.time.calendar.Calendar;
40 import org.kuali.hr.time.calendar.CalendarEntries;
41 import org.kuali.hr.time.calendar.TkCalendar;
42 import org.kuali.hr.time.roles.TkUserRoles;
43 import org.kuali.hr.time.roles.UserRoles;
44 import org.kuali.hr.time.service.base.TkServiceLocator;
45 import org.kuali.hr.time.timeblock.TimeBlock;
46 import org.kuali.hr.time.timeblock.TimeBlockHistory;
47 import org.kuali.hr.time.timesheet.TimesheetDocument;
48 import org.kuali.hr.time.timesheet.web.TimesheetAction;
49 import org.kuali.hr.time.timesheet.web.TimesheetActionForm;
50 import org.kuali.hr.time.timesummary.AssignmentRow;
51 import org.kuali.hr.time.timesummary.EarnCodeSection;
52 import org.kuali.hr.time.timesummary.EarnGroupSection;
53 import org.kuali.hr.time.timesummary.TimeSummary;
54 import org.kuali.hr.time.util.TKContext;
55 import org.kuali.hr.time.util.TKUser;
56 import org.kuali.hr.time.util.TKUtils;
57 import org.kuali.hr.time.util.TkConstants;
58 import org.kuali.hr.time.util.TkTimeBlockAggregate;
59 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
60 import org.kuali.rice.kew.service.KEWServiceLocator;
61 import org.kuali.rice.krad.exception.AuthorizationException;
62 import org.kuali.rice.krad.util.GlobalVariables;
63
64 public class TimeDetailAction extends TimesheetAction {
65
66 @Override
67 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
68 super.checkTKAuthorization(form, methodToCall);
69 TKUser user = TKContext.getUser();
70 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
71 TimesheetDocument doc = TKContext.getCurrentTimesheetDocument();
72
73
74 if (StringUtils.equals(methodToCall, "addTimeBlock") || StringUtils.equals(methodToCall, "deleteTimeBlock") || StringUtils.equals(methodToCall, "updateTimeBlock")) {
75 if (!roles.isDocumentWritable(doc)) {
76 throw new AuthorizationException(roles.getPrincipalId(), "TimeDetailAction", "");
77 }
78 }
79 }
80
81 @Override
82 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
83 ActionForward forward = super.execute(mapping, form, request, response);
84 if (forward.getRedirect()) {
85 return forward;
86 }
87 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
88 tdaf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(TKContext.getCurrentTimesheetDocument(), false));
89
90
91
92 CalendarEntries payCalendarEntry = tdaf.getPayCalendarDates();
93 Calendar payCalendar = TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId());
94
95
96 List<TimeBlock> timeBlocks = TKContext.getCurrentTimesheetDocument().getTimeBlocks();
97
98 this.assignStypeClassMapForTimeSummary(tdaf,timeBlocks);
99
100 List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(payCalendarEntry);
101 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(timeBlocks, payCalendarEntry, payCalendar, true, intervals);
102 TkCalendar cal = TkCalendar.getCalendar(aggregate);
103 cal.assignAssignmentStyle(tdaf.getAssignStyleClassMap());
104 tdaf.setTkCalendar(cal);
105
106 this.populateCalendarAndPayPeriodLists(request, tdaf);
107
108 tdaf.setTimeBlockString(ActionFormUtils.getTimeBlocksJson(aggregate.getFlattenedTimeBlockList()));
109
110 tdaf.setOvertimeEarnCodes(TkServiceLocator.getEarnCodeService().getOvertimeEarnCodesStrs(TKContext.getCurrentTimesheetDocument().getAsOfDate()));
111
112 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) {
113 tdaf.setWorkingOnItsOwn("true");
114 }
115
116 tdaf.setDocEditable("false");
117 if (TKContext.getUser().isSystemAdmin()) {
118 tdaf.setDocEditable("true");
119 } else {
120 boolean docFinal = TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.FINAL);
121 if (!docFinal) {
122 if(StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
123 || TKContext.getUser().isSystemAdmin()
124 || TKContext.getUser().isLocationAdmin()
125 || TKContext.getUser().isDepartmentAdmin()
126 || TKContext.getUser().isReviewer()
127 || TKContext.getUser().isApprover()) {
128 tdaf.setDocEditable("true");
129 }
130
131
132 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
133 && TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)) {
134 Collection actions = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentId(), TkConstants.DOCUMENT_ACTIONS.APPROVE);
135 if(!actions.isEmpty()) {
136 tdaf.setDocEditable("false");
137 }
138 }
139 }
140 }
141
142 return forward;
143 }
144
145
146 private void assignStypeClassMapForTimeSummary(TimeDetailActionForm tdaf, List<TimeBlock> timeBlocks) throws Exception {
147 TimeSummary ts = TkServiceLocator.getTimeSummaryService().getTimeSummary(TKContext.getCurrentTimesheetDocument());
148 tdaf.setAssignStyleClassMap(ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks));
149 Map<String, String> aMap = tdaf.getAssignStyleClassMap();
150
151 for (EarnGroupSection earnGroupSection : ts.getSections()) {
152 for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) {
153 for (AssignmentRow assignRow : section.getAssignmentsRows()) {
154 if (assignRow.getAssignmentKey() != null && aMap.containsKey(assignRow.getAssignmentKey())) {
155 assignRow.setCssClass(aMap.get(assignRow.getAssignmentKey()));
156 } else {
157 assignRow.setCssClass("");
158 }
159 }
160 }
161
162 }
163 tdaf.setTimeSummary(ts);
164 ActionFormUtils.validateHourLimit(tdaf);
165 ActionFormUtils.addWarningTextFromEarnGroup(tdaf);
166 ActionFormUtils.addUnapprovedIPWarningFromClockLog(tdaf);
167 }
168
169 private void populateCalendarAndPayPeriodLists(HttpServletRequest request, TimeDetailActionForm tdaf) {
170 List<TimesheetDocumentHeader> documentHeaders = (List<TimesheetDocumentHeader>) TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeadersForPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
171 SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
172 if(tdaf.getCalendarYears().isEmpty()) {
173
174 Set<String> yearSet = new HashSet<String>();
175
176 for(TimesheetDocumentHeader tdh : documentHeaders) {
177 yearSet.add(sdf.format(tdh.getPayBeginDate()));
178 }
179 List<String> yearList = new ArrayList<String>(yearSet);
180 Collections.sort(yearList);
181 Collections.reverse(yearList);
182 tdaf.setCalendarYears(yearList);
183 }
184
185 if(request.getParameter("selectedCY")!= null) {
186 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
187 }
188
189 if(StringUtils.isEmpty(tdaf.getSelectedCalendarYear())) {
190 tdaf.setSelectedCalendarYear(sdf.format(tdaf.getPayCalendarDates().getBeginPeriodDate()));
191 }
192 if(tdaf.getPayPeriodsMap().isEmpty()) {
193 List<CalendarEntries> payPeriodList = new ArrayList<CalendarEntries>();
194 for(TimesheetDocumentHeader tdh : documentHeaders) {
195 if(sdf.format(tdh.getPayBeginDate()).equals(tdaf.getSelectedCalendarYear())) {
196 CalendarEntries pe = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(tdh.getPayBeginDate(), tdh.getPayEndDate());
197 payPeriodList.add(pe);
198 }
199 }
200 tdaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(payPeriodList));
201 }
202 if(request.getParameter("selectedPP")!= null) {
203 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
204 }
205 if(StringUtils.isEmpty(tdaf.getSelectedPayPeriod())) {
206 tdaf.setSelectedPayPeriod(tdaf.getPayCalendarDates().getHrCalendarEntriesId());
207 }
208 }
209
210
211
212
213
214
215
216
217 public ActionForward deleteTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
218 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
219
220 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
221 TimeBlock deletedTimeBlock = null;
222 for (TimeBlock tb : timeBlocks) {
223 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) {
224 deletedTimeBlock = tb;
225 break;
226 }
227 }
228 if (deletedTimeBlock == null) {
229 return mapping.findForward("basic");
230 }
231
232 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size());
233 for (TimeBlock b : tdaf.getTimesheetDocument().getTimeBlocks()) {
234 referenceTimeBlocks.add(b.copy());
235 }
236
237
238 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
239 newTimeBlocks.remove(deletedTimeBlock);
240
241
242 TkServiceLocator.getTimeBlockService().deleteTimeBlock(deletedTimeBlock);
243
244 TimeBlockHistory tbh = new TimeBlockHistory(deletedTimeBlock);
245 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK);
246 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
247
248 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
249 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
250 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks);
251
252 return mapping.findForward("basic");
253 }
254
255
256
257
258
259
260
261 public ActionForward addTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
262 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
263 this.changeTimeBlocks(tdaf);
264
265 ActionFormUtils.validateHourLimit(tdaf);
266 ActionFormUtils.addWarningTextFromEarnGroup(tdaf);
267
268 return mapping.findForward("basic");
269 }
270
271 private void removeOldTimeBlock(TimeDetailActionForm tdaf) {
272 if (tdaf.getTkTimeBlockId() != null) {
273 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId());
274 if (tb != null) {
275 TimeBlockHistory tbh = new TimeBlockHistory(tb);
276 TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb);
277
278
279 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK);
280 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
281
282
283 tdaf.getTimesheetDocument().getTimeBlocks().remove(tb);
284 }
285 }
286 }
287
288
289
290 private void changeTimeBlocks(TimeDetailActionForm tdaf) {
291 Timestamp overtimeBeginTimestamp = null;
292 Timestamp overtimeEndTimestamp = null;
293 boolean isClockLogCreated = false;
294
295
296
297 if (tdaf.getTkTimeBlockId() != null) {
298 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId());
299 if (tb != null) {
300 isClockLogCreated = tb.getClockLogCreated();
301 if (StringUtils.isNotEmpty(tdaf.getOvertimePref())) {
302 overtimeBeginTimestamp = tb.getBeginTimestamp();
303 overtimeEndTimestamp = tb.getEndTimestamp();
304 }
305 }
306 this.removeOldTimeBlock(tdaf);
307 }
308
309 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
310
311
312
313 Timestamp startTime = TKUtils.convertDateStringToTimestamp(tdaf.getStartDate(), tdaf.getStartTime());
314 Timestamp endTime = TKUtils.convertDateStringToTimestamp(tdaf.getEndDate(), tdaf.getEndTime());
315
316
317
318 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size());
319 for (TimeBlock tb : tdaf.getTimesheetDocument().getTimeBlocks()) {
320 referenceTimeBlocks.add(tb.copy());
321 }
322
323
324
325 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
326 DateTime startTemp = new DateTime(startTime);
327 DateTime endTemp = new DateTime(endTime);
328
329 if (StringUtils.equals(tdaf.getAcrossDays(), "y")
330 && !(endTemp.getDayOfYear() - startTemp.getDayOfYear() <= 1
331 && endTemp.getHourOfDay() == 0)) {
332 List<TimeBlock> timeBlocksToAdd = TkServiceLocator.getTimeBlockService().buildTimeBlocksSpanDates(assignment,
333 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime,
334 endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), tdaf.getSpanningWeeks());
335 for (TimeBlock tb : timeBlocksToAdd) {
336 if (!newTimeBlocks.contains(tb)) {
337 newTimeBlocks.add(tb);
338 }
339 }
340 } else {
341 List<TimeBlock> timeBlocksToAdd = TkServiceLocator.getTimeBlockService().buildTimeBlocks(assignment,
342 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime,
343 endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()));
344 for (TimeBlock tb : timeBlocksToAdd) {
345 if (!newTimeBlocks.contains(tb)) {
346 newTimeBlocks.add(tb);
347 }
348 }
349 }
350
351
352 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
353
354
355 for (TimeBlock tb : newTimeBlocks) {
356 if (tb.getBeginTimestamp().equals(overtimeBeginTimestamp) && tb.getEndTimestamp().equals(overtimeEndTimestamp) && StringUtils.isNotEmpty(tdaf.getOvertimePref())) {
357 tb.setOvertimePref(tdaf.getOvertimePref());
358 }
359
360 }
361
362 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
363 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks);
364 }
365
366 public ActionForward updateTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
367
368 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
369 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
370
371
372 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
373 TimeBlock updatedTimeBlock = null;
374 for (TimeBlock tb : timeBlocks) {
375 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) {
376 updatedTimeBlock = tb;
377 tb.setJobNumber(assignment.getJobNumber());
378 tb.setWorkArea(assignment.getWorkArea());
379 tb.setTask(assignment.getTask());
380 break;
381 }
382 }
383
384 TkServiceLocator.getTimeBlockService().updateTimeBlock(updatedTimeBlock);
385
386 TimeBlockHistory tbh = new TimeBlockHistory(updatedTimeBlock);
387 tbh.setActionHistory(TkConstants.ACTIONS.UPDATE_TIME_BLOCK);
388 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
389 tdaf.setMethodToCall("addTimeBlock");
390 return mapping.findForward("basic");
391 }
392
393
394 public ActionForward actualTimeInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
395 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
396 return mapping.findForward("ati");
397 }
398
399 public ActionForward deleteLunchDeduction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
400
401 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
402 String timeHourDetailId = tdaf.getTkTimeHourDetailId();
403 TkServiceLocator.getTimeBlockService().deleteLunchDeduction(timeHourDetailId);
404
405 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
406
407 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
408
409
410 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
411 TkServiceLocator.getTimeBlockService().saveTimeBlocks(newTimeBlocks);
412 TKContext.getCurrentTimesheetDocument().setTimeBlocks(newTimeBlocks);
413
414 return mapping.findForward("basic");
415 }
416
417 public ActionForward gotoCurrentPayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
418 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId();
419 Date currentDate = TKUtils.getTimelessDate(null);
420 CalendarEntries pce = TkServiceLocator.getCalendarService().getCurrentCalendarDates(viewPrincipal, currentDate);
421 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce);
422 setupDocumentOnFormContext((TimesheetActionForm)form, td);
423 return mapping.findForward("basic");
424 }
425
426
427 public ActionForward changeCalendarYear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
428
429 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
430 if(request.getParameter("selectedCY") != null) {
431 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
432 }
433 return mapping.findForward("basic");
434 }
435
436
437 public ActionForward changePayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
438 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
439 if(request.getParameter("selectedPP") != null) {
440 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
441 CalendarEntries pce = TkServiceLocator.getCalendarEntriesService()
442 .getCalendarEntries(request.getParameter("selectedPP").toString());
443 if(pce != null) {
444 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId();
445 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce);
446 setupDocumentOnFormContext((TimesheetActionForm)form, td);
447 }
448 }
449 return mapping.findForward("basic");
450 }
451
452 }