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.service.HrServiceLocator;
29 import org.kuali.kpme.core.util.HrConstants;
30 import org.kuali.kpme.core.util.TKUtils;
31 import org.kuali.kpme.tklm.common.LMConstants;
32 import org.kuali.kpme.tklm.leave.block.LeaveBlock;
33 import org.kuali.kpme.tklm.leave.calendar.LeaveCalendarDocument;
34 import org.kuali.kpme.tklm.leave.calendar.dao.LeaveCalendarDao;
35 import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
36 import org.kuali.kpme.tklm.leave.workflow.LeaveCalendarDocumentHeader;
37 import org.kuali.kpme.tklm.leave.workflow.LeaveRequestDocument;
38 import org.kuali.kpme.tklm.time.service.TkServiceLocator;
39 import org.kuali.rice.core.api.config.property.ConfigContext;
40 import org.kuali.rice.kew.api.KewApiServiceLocator;
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.api.note.Note;
45 import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
46 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
47 import org.kuali.rice.krad.service.KRADServiceLocator;
48 import org.kuali.rice.krad.util.GlobalVariables;
49
50 import java.util.List;
51
52 public class LeaveCalendarServiceImpl implements LeaveCalendarService {
53
54 private static final Logger LOG = Logger.getLogger(LeaveCalendarServiceImpl.class);
55
56 private LeaveCalendarDao leaveCalendarDao;
57
58 @Override
59 public LeaveCalendarDocument getLeaveCalendarDocument(String documentId) {
60 LeaveCalendarDocument lcd = null;
61 LeaveCalendarDocumentHeader lcdh = LmServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
62
63 if (lcdh != null) {
64 lcd = new LeaveCalendarDocument(lcdh);
65 CalendarEntry pce = HrServiceLocator.getCalendarEntryService().getCalendarDatesByPayEndDate(lcdh.getPrincipalId(), lcdh.getEndDateTime(), HrConstants.LEAVE_CALENDAR_TYPE);
66 lcd.setCalendarEntry(pce);
67 } else {
68 LOG.error("Could not find LeaveCalendarDocumentHeader for DocumentID: " + documentId);
69 return null;
70 }
71
72 List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksForDocumentId(documentId);
73 lcd.setLeaveBlocks(leaveBlocks);
74
75
76 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(lcdh.getPrincipalId(), lcd.getCalendarEntry());
77 lcd.setAssignments(assignments);
78
79 return lcd;
80 }
81
82 @Override
83 public LeaveCalendarDocument openLeaveCalendarDocument(String principalId, CalendarEntry calEntry) throws WorkflowException {
84 LeaveCalendarDocument doc;
85
86 DateTime begin = calEntry.getBeginPeriodFullDateTime();
87 DateTime end = calEntry.getEndPeriodFullDateTime();
88
89 LeaveCalendarDocumentHeader header = LmServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(principalId, begin, end);
90 if (header == null) {
91 EntityNamePrincipalName person = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
92 String principalName = person != null && person.getDefaultName() != null ? person.getDefaultName().getCompositeName() : StringUtils.EMPTY;
93 String beginDateString = TKUtils.formatDate(begin.toLocalDate());
94 String endDateString = TKUtils.formatDate(end.toLocalDate());
95 String leaveCalendarDocumentTitle = LeaveCalendarDocument.LEAVE_CALENDAR_DOCUMENT_TYPE + " - " + principalName + " (" + principalId + ") - " + beginDateString + "-" + endDateString;
96
97 doc = initiateWorkflowDocument(principalId, begin, end, calEntry, LeaveCalendarDocument.LEAVE_CALENDAR_DOCUMENT_TYPE, leaveCalendarDocumentTitle);
98 } else {
99 doc = getLeaveCalendarDocument(header.getDocumentId());
100 }
101 if (doc != null) {
102 doc.setCalendarEntry(calEntry);
103 }
104
105 return doc;
106 }
107
108
109 public boolean shouldCreateLeaveDocument(String principalId, CalendarEntry calEntry){
110 if (StringUtils.isEmpty(principalId) || calEntry == null) {
111 return false;
112 }
113
114 boolean isPlanningCalendar = LmServiceLocator.getLeaveCalendarService().isLeavePlanningCalendar(principalId, calEntry.getBeginPeriodFullDateTime().toLocalDate(), calEntry.getEndPeriodFullDateTime().toLocalDate());
115 if (isPlanningCalendar) {
116 return false;
117 }
118
119 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignmentsByPayEntry(principalId, calEntry);
120 List<Assignment> results = HrServiceLocator.getAssignmentService().filterAssignments(assignments, HrConstants.FLSA_STATUS_EXEMPT, true);
121 return CollectionUtils.isNotEmpty(results);
122 }
123
124 protected LeaveCalendarDocument initiateWorkflowDocument(String principalId, DateTime payBeginDate, DateTime payEndDate, CalendarEntry calendarEntry, String documentType, String title) throws WorkflowException {
125 LeaveCalendarDocument leaveCalendarDocument = null;
126 WorkflowDocument workflowDocument = null;
127
128 workflowDocument = WorkflowDocumentFactory.createDocument(principalId, documentType, title);
129
130 String status = workflowDocument.getStatus().getCode();
131 LeaveCalendarDocumentHeader documentHeader = new LeaveCalendarDocumentHeader(workflowDocument.getDocumentId(), principalId, payBeginDate.toDate(), payEndDate.toDate(), status);
132
133 documentHeader.setDocumentId(workflowDocument.getDocumentId());
134 documentHeader.setDocumentStatus(HrConstants.ROUTE_STATUS.INITIATED);
135
136 KRADServiceLocator.getBusinessObjectService().save(documentHeader);
137
138 leaveCalendarDocument = new LeaveCalendarDocument(documentHeader);
139 leaveCalendarDocument.setCalendarEntry(calendarEntry);
140 loadLeaveCalendarDocumentData(leaveCalendarDocument, principalId, calendarEntry);
141 TkServiceLocator.getTkSearchableAttributeService().updateSearchableAttribute(leaveCalendarDocument, payEndDate.toLocalDate());
142
143 updateLeaveBlockDocumentIds(principalId, payBeginDate.toLocalDate(), payEndDate.toLocalDate(), workflowDocument.getDocumentId());
144
145 updatePlannedLeaveBlocks(principalId, payBeginDate.toLocalDate(), payEndDate.toLocalDate());
146
147 return leaveCalendarDocument;
148 }
149
150 private void updateLeaveBlockDocumentIds(String principalId, LocalDate beginDate, LocalDate endDate, String documentId) {
151 List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId, beginDate, endDate);
152
153 for (LeaveBlock leaveBlock : leaveBlocks) {
154 leaveBlock.setDocumentId(documentId);
155 }
156
157 LmServiceLocator.getLeaveBlockService().saveLeaveBlocks(leaveBlocks);
158 }
159
160 private void updatePlannedLeaveBlocks(String principalId, LocalDate beginDate, LocalDate endDate) {
161 String batchUserPrincipalId = BatchJobUtil.getBatchUserPrincipalId();
162
163 if (batchUserPrincipalId != null) {
164 List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId, beginDate, endDate);
165
166 for (LeaveBlock leaveBlock : leaveBlocks) {
167 if (StringUtils.equals(leaveBlock.getRequestStatus(), HrConstants.REQUEST_STATUS.PLANNED)
168 || StringUtils.equals(leaveBlock.getRequestStatus(), HrConstants.REQUEST_STATUS.DEFERRED)) {
169 LmServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlock.getLmLeaveBlockId(), batchUserPrincipalId);
170 } else if (StringUtils.equals(leaveBlock.getRequestStatus(), HrConstants.REQUEST_STATUS.REQUESTED)) {
171 if (StringUtils.equals(getInitiateLeaveRequestAction(), LMConstants.INITIATE_LEAVE_REQUEST_ACTION_OPTIONS.DELETE)) {
172 LmServiceLocator.getLeaveRequestDocumentService().suCancelLeave(
173 leaveBlock.getLeaveRequestDocumentId(), batchUserPrincipalId);
174 LmServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlock.getLmLeaveBlockId(), batchUserPrincipalId);
175 } else if (StringUtils.equals(getInitiateLeaveRequestAction(), LMConstants.INITIATE_LEAVE_REQUEST_ACTION_OPTIONS.APPROVE)) {
176 List<LeaveRequestDocument> leaveRequestDocuments = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocumentsByLeaveBlockId(leaveBlock.getLmLeaveBlockId());
177 for (LeaveRequestDocument leaveRequestDocument : leaveRequestDocuments) {
178 LmServiceLocator.getLeaveRequestDocumentService().suBlanketApproveLeave(leaveRequestDocument.getDocumentNumber(), batchUserPrincipalId);
179 }
180 }
181 }
182 }
183 } else {
184 String principalName = BatchJobUtil.getBatchUserPrincipalName();
185 LOG.error("Could not update leave request blocks due to missing batch user " + principalName);
186 }
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, CalendarEntry calEntry) {
201 List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksForDocumentId(ldoc.getDocumentId());
202 ldoc.setLeaveBlocks(leaveBlocks);
203 List<Assignment> assignments = HrServiceLocator.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, CalendarEntry 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 = HrServiceLocator.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(HrConstants.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(HrConstants.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(HrConstants.DOCUMENT_ACTIONS.DISAPPROVE, principalId, leaveCalendarDocument);
252 }
253
254 public boolean isReadyToApprove(CalendarDocument document) {
255 if (document == null) {
256 return false;
257 }
258 List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(document.getPrincipalId(),
259 document.getCalendarEntry().getBeginPeriodFullDateTime().toLocalDate(), document.getCalendarEntry().getEndPeriodFullDateTime().toLocalDate(), LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
260 leaveBlocks.addAll(LmServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(document.getPrincipalId(),
261 document.getCalendarEntry().getBeginPeriodFullDateTime().toLocalDate(), document.getCalendarEntry().getEndPeriodFullDateTime().toLocalDate(), LMConstants.LEAVE_BLOCK_TYPE.LEAVE_PAYOUT));
262 for(LeaveBlock lb : leaveBlocks) {
263 if(!StringUtils.equals(lb.getRequestStatus(),HrConstants.REQUEST_STATUS.APPROVED) &&
264 !StringUtils.equals(lb.getRequestStatus(), HrConstants.REQUEST_STATUS.DISAPPROVED))
265 return false;
266 }
267
268 LeaveCalendarDocumentHeader lcdh = LmServiceLocator.getLeaveCalendarDocumentHeaderService().getMinBeginDatePendingLeaveCalendar(document.getPrincipalId());
269 if (lcdh != null){
270
271 if (LmServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(document.getDocumentId()).getBeginDate().compareTo(lcdh.getEndDate()) >= 0){
272 return false;
273 }
274 }
275
276 return true;
277 }
278
279 protected void leaveCalendarDocumentAction(String action, String principalId, LeaveCalendarDocument leaveCalendarDocument) {
280 WorkflowDocument wd = null;
281 if (leaveCalendarDocument != null) {
282 String rhid = leaveCalendarDocument.getDocumentId();
283 wd = WorkflowDocumentFactory.loadDocument(principalId, rhid);
284
285 if (StringUtils.equals(action, HrConstants.DOCUMENT_ACTIONS.ROUTE)) {
286 wd.route("Routing for Approval");
287 } else if (StringUtils.equals(action, HrConstants.BATCH_JOB_ACTIONS.BATCH_JOB_ROUTE)) {
288 Note.Builder builder = Note.Builder.create(rhid, principalId);
289 builder.setCreateDate(new DateTime());
290 builder.setText("Routed via Employee Approval batch job");
291 KewApiServiceLocator.getNoteService().createNote(builder.build());
292
293 wd.route("Batch job routing leave calendar");
294 } else if (StringUtils.equals(action, HrConstants.DOCUMENT_ACTIONS.APPROVE)) {
295 if (HrServiceLocator.getHRPermissionService().canSuperUserAdministerCalendarDocument(GlobalVariables.getUserSession().getPrincipalId(), leaveCalendarDocument)
296 && !HrServiceLocator.getHRPermissionService().canApproveCalendarDocument(GlobalVariables.getUserSession().getPrincipalId(), leaveCalendarDocument)) {
297 wd.superUserBlanketApprove("Superuser approving timesheet.");
298 } else {
299 wd.approve("Approving timesheet.");
300 }
301 } else if (StringUtils.equals(action, HrConstants.BATCH_JOB_ACTIONS.BATCH_JOB_APPROVE)) {
302 Note.Builder builder = Note.Builder.create(rhid, principalId);
303 builder.setCreateDate(new DateTime());
304 builder.setText("Approved via Supervisor Approval batch job");
305 KewApiServiceLocator.getNoteService().createNote(builder.build());
306
307 wd.superUserBlanketApprove("Batch job approving leave calendar");
308 } else if (StringUtils.equals(action, HrConstants.DOCUMENT_ACTIONS.DISAPPROVE)) {
309 if (HrServiceLocator.getHRPermissionService().canSuperUserAdministerCalendarDocument(GlobalVariables.getUserSession().getPrincipalId(), leaveCalendarDocument)
310 && !HrServiceLocator.getHRPermissionService().canApproveCalendarDocument(GlobalVariables.getUserSession().getPrincipalId(), leaveCalendarDocument)) {
311 wd.superUserDisapprove("Superuser disapproving leave calendar.");
312 } else {
313 wd.disapprove("Disapproving timesheet.");
314 }
315 }
316 }
317 }
318
319 public boolean isLeavePlanningCalendar(String principalId, LocalDate beginDate, LocalDate endDate) {
320 LocalDate today = LocalDate.now();
321
322 List<Job> jobs = HrServiceLocator.getJobService().getJobs(principalId, endDate);
323 for (Job job : jobs) {
324
325 if (job.isEligibleForLeave()) {
326
327 if (job.getFlsaStatus().equalsIgnoreCase(HrConstants.FLSA_STATUS_NON_EXEMPT)) {
328 return true;
329 } else {
330
331 if ( beginDate.isAfter(today) ) {
332
333 return true;
334 } else {
335
336 return false;
337 }
338 }
339 } else {
340
341 return false;
342 }
343 }
344 return false;
345 }
346
347 }
348