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