1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.lm.leavecalendar.service;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.joda.time.DateTime;
22 import org.kuali.hr.job.Job;
23 import org.kuali.hr.lm.LMConstants;
24 import org.kuali.hr.lm.leaveblock.LeaveBlock;
25 import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
26 import org.kuali.hr.lm.leavecalendar.dao.LeaveCalendarDao;
27 import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
28 import org.kuali.hr.lm.workflow.LeaveRequestDocument;
29 import org.kuali.hr.time.assignment.Assignment;
30 import org.kuali.hr.time.calendar.CalendarEntries;
31 import org.kuali.hr.time.service.base.TkServiceLocator;
32 import org.kuali.hr.time.util.TKContext;
33 import org.kuali.hr.time.util.TKUser;
34 import org.kuali.hr.time.util.TKUtils;
35 import org.kuali.hr.time.util.TkConstants;
36 import org.kuali.rice.core.api.config.property.ConfigContext;
37 import org.kuali.rice.kew.api.KewApiServiceLocator;
38 import org.kuali.rice.kew.api.WorkflowDocument;
39 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
40 import org.kuali.rice.kew.api.exception.WorkflowException;
41 import org.kuali.rice.kew.api.note.Note;
42 import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
43 import org.kuali.rice.kim.api.identity.principal.Principal;
44 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
45 import org.kuali.rice.krad.service.KRADServiceLocator;
46
47 import java.math.BigDecimal;
48 import java.util.Date;
49 import java.util.List;
50
51 public class LeaveCalendarServiceImpl implements LeaveCalendarService {
52
53 private static final Logger LOG = Logger.getLogger(LeaveCalendarServiceImpl.class);
54
55 private LeaveCalendarDao leaveCalendarDao;
56
57 @Override
58 public LeaveCalendarDocument getLeaveCalendarDocument(String documentId) {
59 LeaveCalendarDocument lcd = null;
60 LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
61
62 if (lcdh != null) {
63 lcd = new LeaveCalendarDocument(lcdh);
64 CalendarEntries pce = TkServiceLocator.getCalendarService().getCalendarDatesByPayEndDate(lcdh.getPrincipalId(), lcdh.getEndDate(), LMConstants.LEAVE_CALENDAR_TYPE);
65 lcd.setCalendarEntry(pce);
66 } else {
67 throw new RuntimeException("Could not find LeaveCalendarDocumentHeader for DocumentID: " + documentId);
68 }
69
70 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForDocumentId(documentId);
71 lcd.setLeaveBlocks(leaveBlocks);
72
73
74 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(lcdh.getPrincipalId(), lcd.getCalendarEntry());
75 lcd.setAssignments(assignments);
76
77 return lcd;
78 }
79
80 @Override
81 public LeaveCalendarDocument openLeaveCalendarDocument(String principalId, CalendarEntries calEntry) throws WorkflowException {
82 LeaveCalendarDocument doc;
83
84 Date begin = calEntry.getBeginPeriodDateTime();
85 Date end = calEntry.getEndPeriodDateTime();
86
87 LeaveCalendarDocumentHeader header = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(principalId, begin, end);
88 if (header == null) {
89 EntityNamePrincipalName person = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
90 String principalName = person != null && person.getDefaultName() != null ? person.getDefaultName().getCompositeName() : StringUtils.EMPTY;
91 String beginDateString = TKUtils.formatDate(new java.sql.Date(begin.getTime()));
92 String endDateString = TKUtils.formatDate(new java.sql.Date(end.getTime()));
93 String leaveCalendarDocumentTitle = LeaveCalendarDocument.LEAVE_CALENDAR_DOCUMENT_TYPE + " - " + principalName + " (" + principalId + ") - " + beginDateString + "-" + endDateString;
94
95 doc = initiateWorkflowDocument(principalId, begin, end, calEntry, LeaveCalendarDocument.LEAVE_CALENDAR_DOCUMENT_TYPE, leaveCalendarDocumentTitle);
96 } else {
97 doc = getLeaveCalendarDocument(header.getDocumentId());
98 }
99 doc.setCalendarEntry(calEntry);
100
101 return doc;
102 }
103
104
105 public boolean shouldCreateLeaveDocument(String principalId, CalendarEntries calEntry){
106 if (StringUtils.isEmpty(principalId) || calEntry == null) {
107 return false;
108 }
109
110 boolean isPlanningCalendar = TkServiceLocator.getLeaveCalendarService().isLeavePlanningCalendar(principalId, calEntry.getBeginPeriodDateTime(), calEntry.getEndPeriodDateTime());
111 if (isPlanningCalendar) {
112 return false;
113 }
114
115 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByPayEntry(principalId, calEntry);
116 List<Assignment> results = TkServiceLocator.getAssignmentService().filterAssignments(assignments, TkConstants.FLSA_STATUS_EXEMPT, true);
117 return CollectionUtils.isNotEmpty(results);
118 }
119
120 protected LeaveCalendarDocument initiateWorkflowDocument(String principalId, Date payBeginDate, Date payEndDate, CalendarEntries calendarEntries, String documentType, String title) throws WorkflowException {
121 LeaveCalendarDocument leaveCalendarDocument = null;
122 WorkflowDocument workflowDocument = null;
123
124 workflowDocument = WorkflowDocumentFactory.createDocument(principalId, documentType, title);
125
126 String status = workflowDocument.getStatus().getCode();
127 LeaveCalendarDocumentHeader documentHeader = new LeaveCalendarDocumentHeader(workflowDocument.getDocumentId(), principalId, payBeginDate, payEndDate, status);
128
129 documentHeader.setDocumentId(workflowDocument.getDocumentId());
130 documentHeader.setDocumentStatus(TkConstants.ROUTE_STATUS.INITIATED);
131
132 KRADServiceLocator.getBusinessObjectService().save(documentHeader);
133
134 leaveCalendarDocument = new LeaveCalendarDocument(documentHeader);
135 leaveCalendarDocument.setCalendarEntry(calendarEntries);
136 loadLeaveCalendarDocumentData(leaveCalendarDocument, principalId, calendarEntries);
137 TkServiceLocator.getTkSearchableAttributeService().updateSearchableAttribute(leaveCalendarDocument, payEndDate);
138
139 updateLeaveBlockDocumentIds(principalId, payBeginDate, payEndDate, workflowDocument.getDocumentId());
140
141 updatePlannedLeaveBlocks(principalId, payBeginDate, payEndDate);
142
143 return leaveCalendarDocument;
144 }
145
146 private void updateLeaveBlockDocumentIds(String principalId, Date beginDate, Date endDate, String documentId) {
147 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId, beginDate, endDate);
148
149 for (LeaveBlock leaveBlock : leaveBlocks) {
150 leaveBlock.setDocumentId(documentId);
151 }
152
153 TkServiceLocator.getLeaveBlockService().saveLeaveBlocks(leaveBlocks);
154 }
155
156 private void updatePlannedLeaveBlocks(String principalId, Date beginDate, Date endDate) {
157 String batchUserPrincipalId = getBatchUserPrincipalId();
158
159 if (batchUserPrincipalId != null) {
160 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId, beginDate, endDate);
161
162 for (LeaveBlock leaveBlock : leaveBlocks) {
163 if (StringUtils.equals(leaveBlock.getRequestStatus(), LMConstants.REQUEST_STATUS.PLANNED)
164 || StringUtils.equals(leaveBlock.getRequestStatus(), LMConstants.REQUEST_STATUS.DEFERRED)) {
165 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlock.getLmLeaveBlockId(), batchUserPrincipalId);
166 } else if (StringUtils.equals(leaveBlock.getRequestStatus(), LMConstants.REQUEST_STATUS.REQUESTED)) {
167 if (StringUtils.equals(getInitiateLeaveRequestAction(), LMConstants.INITIATE_LEAVE_REQUEST_ACTION_OPTIONS.DELETE)) {
168 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlock.getLmLeaveBlockId(), batchUserPrincipalId);
169 } else if (StringUtils.equals(getInitiateLeaveRequestAction(), LMConstants.INITIATE_LEAVE_REQUEST_ACTION_OPTIONS.APPROVE)) {
170 List<LeaveRequestDocument> leaveRequestDocuments = TkServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocumentsByLeaveBlockId(leaveBlock.getLmLeaveBlockId());
171 for (LeaveRequestDocument leaveRequestDocument : leaveRequestDocuments) {
172 TkServiceLocator.getLeaveRequestDocumentService().suBlanketApproveLeave(leaveRequestDocument.getDocumentNumber(), batchUserPrincipalId);
173 }
174 }
175 }
176 }
177 } else {
178 String principalName = ConfigContext.getCurrentContextConfig().getProperty(TkConstants.BATCH_USER_PRINCIPAL_NAME);
179 LOG.error("Could not update leave request blocks due to missing batch user " + principalName);
180 }
181 }
182
183 private String getBatchUserPrincipalId() {
184 String principalName = ConfigContext.getCurrentContextConfig().getProperty(TkConstants.BATCH_USER_PRINCIPAL_NAME);
185 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(principalName);
186 return principal == null ? null : principal.getPrincipalId();
187 }
188
189 private String getInitiateLeaveRequestAction() {
190 return ConfigContext.getCurrentContextConfig().getProperty(LMConstants.INITIATE_LEAVE_REQUEST_ACTION);
191 }
192
193
194
195
196
197
198
199
200 protected void loadLeaveCalendarDocumentData(LeaveCalendarDocument ldoc, String principalId, CalendarEntries calEntry) {
201 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForDocumentId(ldoc.getDocumentId());
202 ldoc.setLeaveBlocks(leaveBlocks);
203 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(principalId, calEntry);
204 ldoc.setAssignments(assignments);
205 }
206
207 public LeaveCalendarDao getLeaveCalendarDao() {
208 return leaveCalendarDao;
209 }
210
211 public void setLeaveCalendarDao(LeaveCalendarDao leaveCalendarDao) {
212 this.leaveCalendarDao = leaveCalendarDao;
213 }
214
215 @Override
216 public LeaveCalendarDocument getLeaveCalendarDocument(
217 String principalId, CalendarEntries calendarEntry) {
218 LeaveCalendarDocument leaveCalendarDocument = new LeaveCalendarDocument(calendarEntry);
219 LeaveCalendarDocumentHeader lcdh = new LeaveCalendarDocumentHeader();
220 lcdh.setBeginDate(calendarEntry.getBeginPeriodDateTime());
221 lcdh.setEndDate(calendarEntry.getEndPeriodDateTime());
222 leaveCalendarDocument.setDocumentHeader(lcdh);
223
224 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(principalId, calendarEntry);
225 leaveCalendarDocument.setAssignments(assignments);
226 return leaveCalendarDocument;
227 }
228
229 @Override
230 public void routeLeaveCalendar(String principalId, LeaveCalendarDocument leaveCalendarDocument) {
231 leaveCalendarDocumentAction(TkConstants.DOCUMENT_ACTIONS.ROUTE, principalId, leaveCalendarDocument);
232 }
233
234 @Override
235 public void routeLeaveCalendar(String principalId, LeaveCalendarDocument leaveCalendarDocument, String action) {
236 leaveCalendarDocumentAction(action, principalId, leaveCalendarDocument);
237 }
238
239 @Override
240 public void approveLeaveCalendar(String principalId, LeaveCalendarDocument leaveCalendarDocument) {
241 leaveCalendarDocumentAction(TkConstants.DOCUMENT_ACTIONS.APPROVE, principalId, leaveCalendarDocument);
242 }
243
244 @Override
245 public void approveLeaveCalendar(String principalId, LeaveCalendarDocument leaveCalendarDocument, String action) {
246 leaveCalendarDocumentAction(action, principalId, leaveCalendarDocument);
247 }
248
249 @Override
250 public void disapproveLeaveCalendar(String principalId, LeaveCalendarDocument leaveCalendarDocument) {
251 leaveCalendarDocumentAction(TkConstants.DOCUMENT_ACTIONS.DISAPPROVE, principalId, leaveCalendarDocument);
252 }
253
254 public boolean isReadyToApprove(LeaveCalendarDocument document) {
255 if (document == null) {
256 return false;
257 }
258 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(document.getPrincipalId(),
259 document.getCalendarEntry().getBeginPeriodDate(), document.getCalendarEntry().getEndPeriodDate(), LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
260 leaveBlocks.addAll(TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(document.getPrincipalId(),
261 document.getCalendarEntry().getBeginPeriodDate(), document.getCalendarEntry().getEndPeriodDate(), LMConstants.LEAVE_BLOCK_TYPE.LEAVE_PAYOUT));
262 for(LeaveBlock lb : leaveBlocks) {
263 if(!StringUtils.equals(lb.getRequestStatus(),LMConstants.REQUEST_STATUS.APPROVED) &&
264 !StringUtils.equals(lb.getRequestStatus(), LMConstants.REQUEST_STATUS.DISAPPROVED))
265 return false;
266 }
267
268 LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getMinBeginDatePendingLeaveCalendar(document.getPrincipalId());
269 if (lcdh != null){
270
271 if (TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(document.getDocumentId()).getBeginDate().compareTo(lcdh.getEndDate()) >= 0){
272 return false;
273 }
274 }
275
276 return true;
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304 }
305
306 protected void leaveCalendarDocumentAction(String action, String principalId, LeaveCalendarDocument leaveCalendarDocument) {
307 WorkflowDocument wd = null;
308 if (leaveCalendarDocument != null) {
309 String rhid = leaveCalendarDocument.getDocumentId();
310 wd = WorkflowDocumentFactory.loadDocument(principalId, rhid);
311
312 if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.ROUTE)) {
313 wd.route("Routing for Approval");
314 } else if (StringUtils.equals(action, TkConstants.BATCH_JOB_ACTIONS.BATCH_JOB_ROUTE)) {
315 Note.Builder builder = Note.Builder.create(rhid, principalId);
316 builder.setCreateDate(new DateTime());
317 builder.setText("Routed via Employee Approval batch job");
318 KewApiServiceLocator.getNoteService().createNote(builder.build());
319
320 wd.route("Batch job routing leave calendar");
321 } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.APPROVE)) {
322 if (TKUser.getCurrentTargetRoles().isSystemAdmin() &&
323 !TKUser.getCurrentTargetRoles().isApproverForTimesheet(leaveCalendarDocument)) {
324 wd.superUserBlanketApprove("Superuser approving timesheet.");
325 } else {
326 wd.approve("Approving timesheet.");
327 }
328 } else if (StringUtils.equals(action, TkConstants.BATCH_JOB_ACTIONS.BATCH_JOB_APPROVE)) {
329 Note.Builder builder = Note.Builder.create(rhid, principalId);
330 builder.setCreateDate(new DateTime());
331 builder.setText("Approved via Supervisor Approval batch job");
332 KewApiServiceLocator.getNoteService().createNote(builder.build());
333
334 wd.superUserBlanketApprove("Batch job approving leave calendar");
335 } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) {
336 if (TKUser.getCurrentTargetRoles().isSystemAdmin()
337 && !TKUser.getCurrentTargetRoles().isApproverForTimesheet(leaveCalendarDocument)) {
338 wd.superUserDisapprove("Superuser disapproving timesheet.");
339 } else {
340 wd.disapprove("Disapproving timesheet.");
341 }
342 }
343 }
344 }
345
346 public boolean isLeavePlanningCalendar(String principalId, Date beginDate, Date endDate) {
347 Date today = new Date();
348
349 List<Job> jobs = TkServiceLocator.getJobService().getJobs(principalId, endDate);
350 for (Job job : jobs) {
351
352 if (job.isEligibleForLeave()) {
353
354 if (job.getFlsaStatus().equalsIgnoreCase(TkConstants.FLSA_STATUS_NON_EXEMPT)) {
355 return true;
356 } else {
357
358 if ( beginDate.after(today) ) {
359
360 return true;
361 } else {
362
363 return false;
364 }
365 }
366 } else {
367
368 return false;
369 }
370 }
371 return false;
372 }
373
374 }
375