1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.timesheet.service;
17
18 import java.math.BigDecimal;
19 import java.sql.Timestamp;
20 import java.util.ArrayList;
21 import java.util.Date;
22 import java.util.LinkedList;
23 import java.util.List;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.log4j.Logger;
27 import org.kuali.hr.job.Job;
28 import org.kuali.hr.time.assignment.Assignment;
29 import org.kuali.hr.time.calendar.CalendarEntries;
30 import org.kuali.hr.time.holidaycalendar.HolidayCalendar;
31 import org.kuali.hr.time.holidaycalendar.HolidayCalendarDateEntry;
32 import org.kuali.hr.time.principal.PrincipalHRAttributes;
33 import org.kuali.hr.time.service.base.TkServiceLocator;
34 import org.kuali.hr.time.timeblock.TimeBlock;
35 import org.kuali.hr.time.timesheet.TimesheetDocument;
36 import org.kuali.hr.time.util.TKContext;
37 import org.kuali.hr.time.util.TKUser;
38 import org.kuali.hr.time.util.TKUtils;
39 import org.kuali.hr.time.util.TkConstants;
40 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
41 import org.kuali.rice.kew.api.WorkflowDocument;
42 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
43 import org.kuali.rice.kew.api.exception.WorkflowException;
44 import org.kuali.rice.kew.service.KEWServiceLocator;
45 import org.kuali.rice.kim.api.identity.Person;
46 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
47
48 public class TimesheetServiceImpl implements TimesheetService {
49
50 @SuppressWarnings("unused")
51 private static final Logger LOG = Logger.getLogger(TimesheetServiceImpl.class);
52
53 @Override
54 public void routeTimesheet(String principalId, TimesheetDocument timesheetDocument) {
55 routeTimesheet(TkConstants.DOCUMENT_ACTIONS.ROUTE, principalId, timesheetDocument);
56 }
57
58 @Override
59 public void routeTimesheet(String action, String principalId, TimesheetDocument timesheetDocument) {
60 timesheetAction(action, principalId, timesheetDocument);
61 }
62
63 @Override
64 public void approveTimesheet(String principalId, TimesheetDocument timesheetDocument) {
65 timesheetAction(TkConstants.DOCUMENT_ACTIONS.APPROVE, principalId, timesheetDocument);
66 }
67
68 @Override
69 public void approveTimesheet(String principalId, TimesheetDocument timesheetDocument, String action) {
70 timesheetAction(action, principalId, timesheetDocument);
71 }
72
73 @Override
74 public void disapproveTimesheet(String principalId, TimesheetDocument timesheetDocument) {
75 timesheetAction(TkConstants.DOCUMENT_ACTIONS.DISAPPROVE, principalId, timesheetDocument);
76 }
77
78 protected void timesheetAction(String action, String principalId, TimesheetDocument timesheetDocument) {
79 WorkflowDocument wd = null;
80 if (timesheetDocument != null) {
81 String rhid = timesheetDocument.getDocumentId();
82 wd = WorkflowDocumentFactory.loadDocument(principalId, rhid);
83
84 if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.ROUTE)) {
85 wd.route("Routing for Approval");
86 } else if (StringUtils.equals(action, TkConstants.BATCH_JOB_ACTIONS.BATCH_JOB_ROUTE)) {
87 wd.route("Batch job routing for Approval");
88 } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.APPROVE)) {
89 if (TKContext.getUser().getCurrentTargetRoles().isSystemAdmin() &&
90 !TKContext.getUser().getCurrentTargetRoles().isApproverForTimesheet(timesheetDocument)) {
91 wd.superUserBlanketApprove("Superuser approving timesheet.");
92 } else {
93 wd.approve("Approving timesheet.");
94 }
95 } else if (StringUtils.equals(action, TkConstants.BATCH_JOB_ACTIONS.BATCH_JOB_APPROVE)) {
96 wd.superUserBlanketApprove("Batch job superuser approving timesheet.");
97 } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) {
98 if (TKContext.getUser().getCurrentTargetRoles().isSystemAdmin()
99 && !TKContext.getUser().getCurrentTargetRoles().isApproverForTimesheet(timesheetDocument)) {
100 wd.superUserDisapprove("Superuser disapproving timesheet.");
101 } else {
102 wd.disapprove("Disapproving timesheet.");
103 }
104 }
105
106 String kewStatus = KEWServiceLocator.getRouteHeaderService().getDocumentStatus(timesheetDocument.getDocumentId());
107 if (!kewStatus.equals(timesheetDocument.getDocumentHeader().getDocumentStatus())) {
108 timesheetDocument.getDocumentHeader().setDocumentStatus(kewStatus);
109 TkServiceLocator.getTimesheetDocumentHeaderService().saveOrUpdate(timesheetDocument.getDocumentHeader());
110 }
111
112 }
113 }
114
115 @Override
116 public TimesheetDocument openTimesheetDocument(String principalId, CalendarEntries calendarDates) throws WorkflowException {
117 TimesheetDocument timesheetDocument = null;
118
119 Date begin = calendarDates.getBeginPeriodDateTime();
120 Date end = calendarDates.getEndPeriodDateTime();
121
122 TimesheetDocumentHeader header = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, begin, end);
123
124 if (header == null) {
125 List<Assignment> activeAssignments = TkServiceLocator.getAssignmentService().getAssignmentsByPayEntry(principalId, calendarDates);
126
127 if (activeAssignments.size() == 0) {
128 throw new RuntimeException("No active assignments for " + principalId + " for " + calendarDates.getEndPeriodDate());
129 }
130
131 Person person = KimApiServiceLocator.getPersonService().getPerson(principalId);
132 String principalName = person != null ? person.getName() : StringUtils.EMPTY;
133 String endDateString = TKUtils.formatDate(new java.sql.Date(end.getTime()));
134 String timesheetDocumentTitle = TimesheetDocument.TIMESHEET_DOCUMENT_TYPE + " - " + principalName + " (" + principalId + ") - " + endDateString;
135
136 timesheetDocument = this.initiateWorkflowDocument(principalId, begin, end, calendarDates, TimesheetDocument.TIMESHEET_DOCUMENT_TYPE, timesheetDocumentTitle);
137
138
139
140 this.loadHolidaysOnTimesheet(timesheetDocument, principalId, begin, end);
141 } else {
142 timesheetDocument = this.getTimesheetDocument(header.getDocumentId());
143 timesheetDocument.setPayCalendarEntry(calendarDates);
144 }
145
146 timesheetDocument.setTimeSummary(TkServiceLocator.getTimeSummaryService().getTimeSummary(timesheetDocument));
147 return timesheetDocument;
148 }
149
150 public void loadHolidaysOnTimesheet(TimesheetDocument timesheetDocument, String principalId, Date beginDate, Date endDate) {
151 PrincipalHRAttributes principalCalendar = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId, new java.sql.Date(beginDate.getTime()));
152 if (principalCalendar != null) {
153 HolidayCalendar holidayCalendar = TkServiceLocator.getHolidayCalendarService().getHolidayCalendarByGroup(principalCalendar.getHolidayCalendarGroup());
154 if (holidayCalendar != null) {
155 List<HolidayCalendarDateEntry> lstHolidays = TkServiceLocator.getHolidayCalendarService().getHolidayCalendarDateEntriesForPayPeriod(holidayCalendar.getHrHolidayCalendarId(),
156 beginDate, endDate);
157 for (HolidayCalendarDateEntry holiday : lstHolidays) {
158 Assignment holidayAssign = TkServiceLocator.getHolidayCalendarService().getAssignmentToApplyHolidays(timesheetDocument, TKUtils.getTimelessDate(endDate));
159 if (holidayAssign != null) {
160 BigDecimal holidayCalcHours = TkServiceLocator.getHolidayCalendarService().calculateHolidayHours(holidayAssign.getJob(), holiday.getHolidayHours());
161 TimeBlock timeBlock = TkServiceLocator.getTimeBlockService().createTimeBlock(timesheetDocument, new Timestamp(holiday.getHolidayDate().getTime()),
162 new Timestamp(holiday.getHolidayDate().getTime()), holidayAssign, TkConstants.HOLIDAY_EARN_CODE, holidayCalcHours, BigDecimal.ZERO, false, false);
163 timesheetDocument.getTimeBlocks().add(timeBlock);
164 }
165 }
166
167
168 if (!lstHolidays.isEmpty()) {
169 TkServiceLocator.getTimeBlockService().saveTimeBlocks(new LinkedList<TimeBlock>(), timesheetDocument.getTimeBlocks());
170 }
171 }
172 }
173
174 }
175
176 protected TimesheetDocument initiateWorkflowDocument(String principalId, Date payBeginDate, Date payEndDate, CalendarEntries calendarEntries, String documentType, String title) throws WorkflowException {
177 TimesheetDocument timesheetDocument = null;
178 WorkflowDocument workflowDocument = null;
179
180 workflowDocument = WorkflowDocumentFactory.createDocument(principalId, documentType, title);
181
182 String status = workflowDocument.getStatus().getCode();
183 TimesheetDocumentHeader documentHeader = new TimesheetDocumentHeader(workflowDocument.getDocumentId(), principalId, payBeginDate, payEndDate, status);
184
185 documentHeader.setDocumentId(workflowDocument.getDocumentId().toString());
186 documentHeader.setDocumentStatus("I");
187
188 TkServiceLocator.getTimesheetDocumentHeaderService().saveOrUpdate(documentHeader);
189 timesheetDocument = new TimesheetDocument(documentHeader);
190 timesheetDocument.setPayCalendarEntry(calendarEntries);
191 loadTimesheetDocumentData(timesheetDocument, principalId, calendarEntries);
192 TkServiceLocator.getTkSearchableAttributeService().updateSearchableAttribute(timesheetDocument, payEndDate);
193
194 return timesheetDocument;
195 }
196
197 public List<TimeBlock> getPrevDocumentTimeBlocks(String principalId, Date payBeginDate) {
198 TimesheetDocumentHeader prevTdh = TkServiceLocator.getTimesheetDocumentHeaderService().getPreviousDocumentHeader(principalId, payBeginDate);
199 if (prevTdh == null) {
200 return new ArrayList<TimeBlock>();
201 }
202 return TkServiceLocator.getTimeBlockService().getTimeBlocks(prevTdh.getDocumentId());
203 }
204
205 @Override
206 public TimesheetDocument getTimesheetDocument(String documentId) {
207 TimesheetDocument timesheetDocument = null;
208 TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
209
210 if (tdh != null) {
211 timesheetDocument = new TimesheetDocument(tdh);
212 CalendarEntries pce = TkServiceLocator.getCalendarService().getCalendarDatesByPayEndDate(tdh.getPrincipalId(), tdh.getPayEndDate(), null);
213 loadTimesheetDocumentData(timesheetDocument, tdh.getPrincipalId(), pce);
214
215 timesheetDocument.setPayCalendarEntry(pce);
216 } else {
217 throw new RuntimeException("Could not find TimesheetDocumentHeader for DocumentID: " + documentId);
218 }
219 return timesheetDocument;
220 }
221
222 protected void loadTimesheetDocumentData(TimesheetDocument tdoc, String principalId, CalendarEntries payCalEntry) {
223 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByPayEntry(principalId, payCalEntry);
224 List<Job> jobs = TkServiceLocator.getJobService().getJobs(principalId, TKUtils.getTimelessDate(payCalEntry.getEndPeriodDate()));
225 List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(tdoc.getDocumentHeader().getDocumentId());
226
227 tdoc.setAssignments(assignments);
228 tdoc.setJobs(jobs);
229 tdoc.setTimeBlocks(timeBlocks);
230 }
231
232 public boolean isSynchronousUser() {
233 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(TKUser.getCurrentTargetPerson().getPrincipalId(), TKUtils.getCurrentDate());
234 boolean isSynchronousUser = true;
235 for (Assignment assignment : assignments) {
236 isSynchronousUser &= assignment.isSynchronous();
237 }
238 return isSynchronousUser;
239 }
240
241
242 public void deleteTimesheet(String documentId) {
243 TkServiceLocator.getTimeBlockService().deleteTimeBlocksAssociatedWithDocumentId(documentId);
244 TkServiceLocator.getTimesheetDocumentHeaderService().deleteTimesheetHeader(documentId);
245 }
246
247 public TimeBlock resetWorkedHours(TimeBlock timeBlock) {
248 if (timeBlock.getBeginTime() != null && timeBlock.getEndTime() != null && StringUtils.equals(timeBlock.getEarnCodeType(), TkConstants.EARN_CODE_TIME)) {
249 BigDecimal hours = TKUtils.getHoursBetween(timeBlock.getBeginTime().getTime(), timeBlock.getEndTime().getTime());
250 timeBlock.setHours(hours);
251 }
252 return timeBlock;
253 }
254
255 @Override
256 public void resetTimeBlock(List<TimeBlock> timeBlocks) {
257 for (TimeBlock tb : timeBlocks) {
258 resetWorkedHours(tb);
259 }
260 TkServiceLocator.getTimeBlockService().resetTimeHourDetail(timeBlocks);
261 }
262
263 }