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.task.Task;
46 import org.kuali.hr.time.timeblock.TimeBlock;
47 import org.kuali.hr.time.timeblock.TimeBlockHistory;
48 import org.kuali.hr.time.timesheet.TimesheetDocument;
49 import org.kuali.hr.time.timesheet.web.TimesheetAction;
50 import org.kuali.hr.time.timesheet.web.TimesheetActionForm;
51 import org.kuali.hr.time.timesummary.AssignmentRow;
52 import org.kuali.hr.time.timesummary.EarnCodeSection;
53 import org.kuali.hr.time.timesummary.EarnGroupSection;
54 import org.kuali.hr.time.timesummary.TimeSummary;
55 import org.kuali.hr.time.util.TKContext;
56 import org.kuali.hr.time.util.TKUser;
57 import org.kuali.hr.time.util.TKUtils;
58 import org.kuali.hr.time.util.TkConstants;
59 import org.kuali.hr.time.util.TkTimeBlockAggregate;
60 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
61 import org.kuali.rice.kew.service.KEWServiceLocator;
62 import org.kuali.rice.krad.exception.AuthorizationException;
63 import org.kuali.rice.krad.util.GlobalVariables;
64
65 public class TimeDetailAction extends TimesheetAction {
66
67 @Override
68 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
69 super.checkTKAuthorization(form, methodToCall);
70 TKUser user = TKContext.getUser();
71 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
72 TimesheetDocument doc = TKContext.getCurrentTimesheetDocument();
73
74
75 if (StringUtils.equals(methodToCall, "addTimeBlock") || StringUtils.equals(methodToCall, "deleteTimeBlock") || StringUtils.equals(methodToCall, "updateTimeBlock")) {
76 if (!roles.isDocumentWritable(doc)) {
77 throw new AuthorizationException(roles.getPrincipalId(), "TimeDetailAction", "");
78 }
79 }
80 }
81
82 @Override
83 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
84 ActionForward forward = super.execute(mapping, form, request, response);
85 if (forward.getRedirect()) {
86 return forward;
87 }
88 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
89 tdaf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(TKContext.getCurrentTimesheetDocument(), false));
90
91
92
93 CalendarEntries payCalendarEntry = tdaf.getPayCalendarDates();
94 Calendar payCalendar = TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId());
95
96
97 List<TimeBlock> timeBlocks = TKContext.getCurrentTimesheetDocument().getTimeBlocks();
98
99 this.assignStypeClassMapForTimeSummary(tdaf,timeBlocks);
100
101 List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(payCalendarEntry);
102 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(timeBlocks, payCalendarEntry, payCalendar, true, intervals);
103 TkCalendar cal = TkCalendar.getCalendar(aggregate);
104 cal.assignAssignmentStyle(tdaf.getAssignStyleClassMap());
105 tdaf.setTkCalendar(cal);
106
107 this.populateCalendarAndPayPeriodLists(request, tdaf);
108
109 tdaf.setTimeBlockString(ActionFormUtils.getTimeBlocksJson(aggregate.getFlattenedTimeBlockList()));
110
111 tdaf.setOvertimeEarnCodes(TkServiceLocator.getEarnCodeService().getOvertimeEarnCodesStrs(TKContext.getCurrentTimesheetDocument().getAsOfDate()));
112
113 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) {
114 tdaf.setWorkingOnItsOwn("true");
115 }
116
117 tdaf.setDocEditable("false");
118 if (TKContext.getUser().isSystemAdmin()) {
119 tdaf.setDocEditable("true");
120 } else {
121 boolean docFinal = TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.FINAL);
122 if (!docFinal) {
123 if(StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
124 || TKContext.getUser().isSystemAdmin()
125 || TKContext.getUser().isLocationAdmin()
126 || TKContext.getUser().isDepartmentAdmin()
127 || TKContext.getUser().isReviewer()
128 || TKContext.getUser().isApprover()) {
129 tdaf.setDocEditable("true");
130 }
131
132
133 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
134 && TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)) {
135 Collection actions = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentId(), TkConstants.DOCUMENT_ACTIONS.APPROVE);
136 if(!actions.isEmpty()) {
137 tdaf.setDocEditable("false");
138 }
139 }
140 }
141 }
142
143 return forward;
144 }
145
146
147 private void assignStypeClassMapForTimeSummary(TimeDetailActionForm tdaf, List<TimeBlock> timeBlocks) throws Exception {
148 TimeSummary ts = TkServiceLocator.getTimeSummaryService().getTimeSummary(TKContext.getCurrentTimesheetDocument());
149 tdaf.setAssignStyleClassMap(ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks));
150 Map<String, String> aMap = tdaf.getAssignStyleClassMap();
151
152 for (EarnGroupSection earnGroupSection : ts.getSections()) {
153 for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) {
154 for (AssignmentRow assignRow : section.getAssignmentsRows()) {
155 if (assignRow.getAssignmentKey() != null && aMap.containsKey(assignRow.getAssignmentKey())) {
156 assignRow.setCssClass(aMap.get(assignRow.getAssignmentKey()));
157 } else {
158 assignRow.setCssClass("");
159 }
160 }
161 }
162
163 }
164 tdaf.setTimeSummary(ts);
165 ActionFormUtils.validateHourLimit(tdaf);
166 ActionFormUtils.addWarningTextFromEarnGroup(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
229 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size());
230 for (TimeBlock b : tdaf.getTimesheetDocument().getTimeBlocks()) {
231 referenceTimeBlocks.add(b.copy());
232 }
233
234
235 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
236 newTimeBlocks.remove(deletedTimeBlock);
237
238
239 TkServiceLocator.getTimeBlockService().deleteTimeBlock(deletedTimeBlock);
240
241 TimeBlockHistory tbh = new TimeBlockHistory(deletedTimeBlock);
242 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK);
243 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
244
245 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
246 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
247 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks);
248
249 return mapping.findForward("basic");
250 }
251
252
253
254
255
256
257
258 public ActionForward addTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
259 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
260 this.changeTimeBlocks(tdaf);
261
262 ActionFormUtils.validateHourLimit(tdaf);
263 ActionFormUtils.addWarningTextFromEarnGroup(tdaf);
264
265 return mapping.findForward("basic");
266 }
267
268 private void removeOldTimeBlock(TimeDetailActionForm tdaf) {
269 if (tdaf.getTkTimeBlockId() != null) {
270 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId());
271 if (tb != null) {
272 TimeBlockHistory tbh = new TimeBlockHistory(tb);
273 TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb);
274
275
276 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK);
277 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
278
279
280 tdaf.getTimesheetDocument().getTimeBlocks().remove(tb);
281 }
282 }
283 }
284
285
286
287 private void changeTimeBlocks(TimeDetailActionForm tdaf) {
288 Timestamp overtimeBeginTimestamp = null;
289 Timestamp overtimeEndTimestamp = null;
290
291
292
293 if (tdaf.getTkTimeBlockId() != null) {
294 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId());
295 if (StringUtils.isNotEmpty(tdaf.getOvertimePref())) {
296 overtimeBeginTimestamp = tb.getBeginTimestamp();
297 overtimeEndTimestamp = tb.getEndTimestamp();
298 }
299 this.removeOldTimeBlock(tdaf);
300 }
301
302 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
303
304
305
306 Timestamp startTime = TKUtils.convertDateStringToTimestamp(tdaf.getStartDate(), tdaf.getStartTime());
307 Timestamp endTime = TKUtils.convertDateStringToTimestamp(tdaf.getEndDate(), tdaf.getEndTime());
308
309
310
311 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size());
312 for (TimeBlock tb : tdaf.getTimesheetDocument().getTimeBlocks()) {
313 referenceTimeBlocks.add(tb.copy());
314 }
315
316
317
318 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
319 DateTime startTemp = new DateTime(startTime);
320 DateTime endTemp = new DateTime(endTime);
321
322 if (StringUtils.equals(tdaf.getAcrossDays(), "y")
323 && !(endTemp.getDayOfYear() - startTemp.getDayOfYear() <= 1
324 && endTemp.getHourOfDay() == 0)) {
325 newTimeBlocks.addAll(TkServiceLocator.getTimeBlockService().buildTimeBlocksSpanDates(assignment,
326 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime,
327 endTime, tdaf.getHours(), tdaf.getAmount(), false, Boolean.parseBoolean(tdaf.getLunchDeleted()), tdaf.getSpanningWeeks()));
328 } else {
329 newTimeBlocks.addAll(TkServiceLocator.getTimeBlockService().buildTimeBlocks(assignment,
330 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime,
331 endTime, tdaf.getHours(), tdaf.getAmount(), false, Boolean.parseBoolean(tdaf.getLunchDeleted())));
332 }
333
334
335 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
336
337
338 for (TimeBlock tb : newTimeBlocks) {
339 if (tb.getBeginTimestamp().equals(overtimeBeginTimestamp) && tb.getEndTimestamp().equals(overtimeEndTimestamp) && StringUtils.isNotEmpty(tdaf.getOvertimePref())) {
340 tb.setOvertimePref(tdaf.getOvertimePref());
341 }
342
343 }
344
345 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
346 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks);
347 }
348
349 public ActionForward updateTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
350
351 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
352 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
353
354
355 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
356 TimeBlock updatedTimeBlock = null;
357 for (TimeBlock tb : timeBlocks) {
358 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) {
359 updatedTimeBlock = tb;
360 tb.setJobNumber(assignment.getJobNumber());
361 tb.setWorkArea(assignment.getWorkArea());
362 tb.setTask(assignment.getTask());
363 tb.setTkWorkAreaId(assignment.getWorkAreaObj().getTkWorkAreaId());
364 tb.setHrJobId(assignment.getJob().getHrJobId());
365 String tkTaskId = "0";
366 for (Task task : assignment.getWorkAreaObj().getTasks()) {
367 if (task.getTask().compareTo(assignment.getTask()) == 0) {
368 tkTaskId = task.getTkTaskId();
369 break;
370 }
371 }
372 tb.setTkTaskId(tkTaskId);
373 break;
374 }
375 }
376
377 TkServiceLocator.getTimeBlockService().updateTimeBlock(updatedTimeBlock);
378
379 TimeBlockHistory tbh = new TimeBlockHistory(updatedTimeBlock);
380 tbh.setActionHistory(TkConstants.ACTIONS.UPDATE_TIME_BLOCK);
381 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
382 tdaf.setMethodToCall("addTimeBlock");
383 return mapping.findForward("basic");
384 }
385
386
387 public ActionForward actualTimeInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
388 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
389 return mapping.findForward("ati");
390 }
391
392 public ActionForward deleteLunchDeduction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
393
394 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
395 String timeHourDetailId = tdaf.getTkTimeHourDetailId();
396 TkServiceLocator.getTimeBlockService().deleteLunchDeduction(timeHourDetailId);
397
398 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
399 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
400
401 return mapping.findForward("basic");
402 }
403
404 public ActionForward gotoCurrentPayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
405 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId();
406 Date currentDate = TKUtils.getTimelessDate(null);
407 CalendarEntries pce = TkServiceLocator.getCalendarService().getCurrentCalendarDates(viewPrincipal, currentDate);
408 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce);
409 setupDocumentOnFormContext((TimesheetActionForm)form, td);
410 return mapping.findForward("basic");
411 }
412
413
414 public ActionForward changeCalendarYear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
415
416 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
417 if(request.getParameter("selectedCY") != null) {
418 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
419 }
420 return mapping.findForward("basic");
421 }
422
423
424 public ActionForward changePayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
425 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
426 if(request.getParameter("selectedPP") != null) {
427 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
428 CalendarEntries pce = TkServiceLocator.getCalendarEntriesService()
429 .getCalendarEntries(request.getParameter("selectedPP").toString());
430 if(pce != null) {
431 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId();
432 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce);
433 setupDocumentOnFormContext((TimesheetActionForm)form, td);
434 }
435 }
436 return mapping.findForward("basic");
437 }
438
439 }