View Javadoc
1   /**
2    * Copyright 2004-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.kpme.tklm.leave.request.approval.web;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpServletResponse;
26  
27  import org.apache.commons.collections.CollectionUtils;
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.struts.action.ActionForm;
30  import org.apache.struts.action.ActionForward;
31  import org.apache.struts.action.ActionMapping;
32  import org.joda.time.DateMidnight;
33  import org.joda.time.DateTime;
34  import org.joda.time.DateTimeConstants;
35  import org.joda.time.LocalDate;
36  import org.json.simple.JSONArray;
37  import org.json.simple.JSONValue;
38  import org.kuali.kpme.core.service.HrServiceLocator;
39  import org.kuali.kpme.core.util.HrConstants;
40  import org.kuali.kpme.core.util.HrContext;
41  import org.kuali.kpme.core.util.TKUtils;
42  import org.kuali.kpme.tklm.api.leave.block.LeaveBlock;
43  import org.kuali.kpme.tklm.common.ApprovalFormAction;
44  import org.kuali.kpme.tklm.common.LMConstants;
45  import org.kuali.kpme.tklm.leave.block.LeaveBlockHistory;
46  import org.kuali.kpme.tklm.leave.calendar.LeaveRequestCalendar;
47  import org.kuali.kpme.tklm.leave.calendar.web.LeaveActionFormUtils;
48  import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
49  import org.kuali.kpme.tklm.leave.workflow.LeaveRequestDocument;
50  import org.kuali.kpme.tklm.time.util.TkContext;
51  import org.kuali.rice.kew.api.KewApiServiceLocator;
52  import org.kuali.rice.kew.api.action.ActionItem;
53  import org.kuali.rice.krad.exception.AuthorizationException;
54  import org.kuali.rice.krad.util.GlobalVariables;
55  
56  public class LeaveRequestApprovalAction extends ApprovalFormAction {
57  	
58      public static final String DOC_SEPARATOR = "----";	// separator for documents
59      public static final String ID_SEPARATOR = "____";	// separator for documentId and reason string
60      public static final String DOC_NOT_FOUND = "Leave request document not found with id ";
61      public static final String LEAVE_BLOCK_NOT_FOUND = "Leave Block not found for Leave request document ";
62      public static final String APPROVE_ACTION = "Approve";	
63      public static final String DISAPPROVE_ACTION = "Disapprove";
64      public static final String DEFER_ACTION = "Defer";
65      
66      @Override
67  	protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
68  		if (!HrContext.isReviewer() && !HrContext.isAnyApprover() && !HrContext.isSystemAdmin() && !TkContext.isLocationAdmin() 
69  				&& !HrContext.isGlobalViewOnly() && !TkContext.isDepartmentViewOnly() && !TkContext.isDepartmentAdmin()) {
70  			throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalId(), "ApprovalFormAction", "");
71  		}
72  	}
73  	
74  	@Override
75  	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
76          ActionForward forward = super.execute(mapping, form, request, response);
77          LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
78          
79          setSearchFields(leaveRequestApprovalActionForm);
80          if(leaveRequestApprovalActionForm.getSelectedCalendarType() == null) {
81          	leaveRequestApprovalActionForm.setSelectedCalendarType("M");
82          }
83          setUpLeaveRequestApprovalFieldsForm(leaveRequestApprovalActionForm, false);
84  		return forward;
85  	}
86  	
87      protected List<LeaveBlock> getLeaveBlocks(String principalId, LocalDate beginDate, LocalDate endDate) {
88          return LmServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(principalId, beginDate, endDate, Collections.<String>emptyList());
89      }
90  	
91  	public ActionForward selectNewDept(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
92          LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
93          setUpLeaveRequestApprovalFieldsForm(leaveRequestApprovalActionForm, false);
94  		return mapping.findForward("basic");
95  	}
96  	
97  	public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
98          LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
99          setUpLeaveRequestApprovalFieldsForm(leaveRequestApprovalActionForm, false);
100 		return mapping.findForward("basic");
101 	}
102 	
103 	public ActionForward selectNewCalendarType(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
104 		LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
105 		setUpLeaveRequestApprovalFieldsForm(leaveRequestApprovalActionForm, true);
106 		return mapping.findForward("basic");
107 	}
108 	
109 	private Map<String, List<LeaveRequestDocument>> getLeaveRequestDocsMap(List<String> principalIds, String dept, List<String> workAreaList, LocalDate beginDate, LocalDate endDate) {
110 		String principalId = HrContext.getTargetPrincipalId();
111 		List<ActionItem> actionList = KewApiServiceLocator.getActionListService().getActionItemsForPrincipal(principalId);
112 		Map<String, List<LeaveRequestDocument>> resultsMap = new HashMap<String, List<LeaveRequestDocument>>();
113 
114 		List<LeaveRequestDocument> leaveReqDocs = new ArrayList<LeaveRequestDocument>();
115 		if(CollectionUtils.isNotEmpty(principalIds)) {
116 			for(ActionItem anAction : actionList) {
117 				String docId = anAction.getDocumentId();
118 				if(anAction.getDocName().equals(LeaveRequestDocument.LEAVE_REQUEST_DOCUMENT_TYPE)) {
119 					LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
120 					if(lrd != null) {
121 						LeaveBlock lb = lrd.getLeaveBlock();
122 						if(lb != null) {
123 							if(principalIds.contains(lb.getPrincipalId())) {
124 								String key = lb.getLeaveLocalDate().toString();
125 								if(resultsMap.containsKey(key)) {
126 									leaveReqDocs = resultsMap.get(key);
127 								} else {
128 									leaveReqDocs = new ArrayList<LeaveRequestDocument>();
129 								}
130 								leaveReqDocs.add(lrd);
131 								resultsMap.put(key, leaveReqDocs);
132 							}
133 						}
134 					}
135 				}
136 			}
137 		}
138         return resultsMap;
139 	}
140 	
141 	private Map<String,List<LeaveBlock>> getLeaveBlocksForDisplay(List<String> principalIds, String dept, List<String> workAreaList, LocalDate beginDate, LocalDate endDate) {
142 		Map<String, List<LeaveBlock>> leaveBlockMaps = new HashMap<String, List<LeaveBlock>>();
143 		List<LeaveBlock> leaveBlocksForDisplay = new ArrayList<LeaveBlock>();
144 		List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();
145 		if(CollectionUtils.isNotEmpty(principalIds)) {
146 			for(String userId : principalIds) {
147 				leaveBlocksForDisplay = getLeaveBlocks(userId, beginDate, endDate);
148 				for(LeaveBlock lb : leaveBlocksForDisplay) {
149 					if(lb.getLeaveBlockType().equalsIgnoreCase(LMConstants.LEAVE_BLOCK_TYPE.LEAVE_CALENDAR) && 
150 					   (lb.getRequestStatus().equalsIgnoreCase(HrConstants.REQUEST_STATUS.REQUESTED) || 
151 					   lb.getRequestStatus().equalsIgnoreCase(HrConstants.REQUEST_STATUS.APPROVED) ||
152 					   lb.getRequestStatus().equalsIgnoreCase(HrConstants.REQUEST_STATUS.USAGE))) {
153 							String key = lb.getLeaveLocalDate().toString();
154 							if(leaveBlockMaps.containsKey(key)) {
155 								leaveBlocks = leaveBlockMaps.get(key);
156 							} else {
157 								leaveBlocks = new ArrayList<LeaveBlock>();
158 							}
159 							leaveBlocks.add(lb);
160 							leaveBlockMaps.put(key, leaveBlocks);
161 					}
162 				}
163 			}
164 		}
165         return leaveBlockMaps;
166 	}
167 
168 	
169 
170 	public ActionForward takeAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
171 		LeaveRequestApprovalActionForm lraaForm = (LeaveRequestApprovalActionForm) form;
172 		String action =  lraaForm.getAction();
173 		if(StringUtils.isNotEmpty(action) && StringUtils.isNotEmpty(lraaForm.getActionList())) {
174 			String[] actionList = lraaForm.getActionList().split(DOC_SEPARATOR);
175 			for(String docId : actionList){
176 				if(StringUtils.isNotEmpty(docId) && !StringUtils.equals(docId, DOC_SEPARATOR)) {
177 					String reasonString = lraaForm.getReason(); 	// approve reason text, could be empty
178 					if(StringUtils.equals(action, APPROVE_ACTION)) {
179 						LmServiceLocator.getLeaveRequestDocumentService().approveLeave(docId, HrContext.getPrincipalId(), reasonString);
180 						// leave block's status is changed to "approved" in postProcessor of LeaveRequestDocument
181 					} else if (StringUtils.equals(action, DISAPPROVE_ACTION)) {
182 						LmServiceLocator.getLeaveRequestDocumentService().disapproveLeave(docId, HrContext.getPrincipalId(), reasonString);
183 						// leave block's status is changed to "disapproved" in postProcessor of LeaveRequestDocument
184 					} else if (StringUtils.equals(action, DEFER_ACTION)) {
185 						LmServiceLocator.getLeaveRequestDocumentService().deferLeave(docId, HrContext.getPrincipalId(), reasonString);
186 						// leave block's status is changed to "deferred" in postProcessor of LeaveRequestDocument
187 					}
188 				}
189 			}
190 		}
191 		lraaForm.setDocumentId(null);
192 		return mapping.findForward("basic");
193 	}
194 	
195 	@Override
196 	protected List<String> getCalendars(List<String> principalIds) {
197 		return HrServiceLocator.getPrincipalHRAttributeService().getUniqueLeaveCalendars(principalIds);
198 	}
199 
200 	public ActionForward validateNewActions(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
201 		LeaveRequestApprovalActionForm lraaForm = (LeaveRequestApprovalActionForm) form;
202 		JSONArray errorMsgList = new JSONArray();
203         List<String> errors = new ArrayList<String>();
204         if(StringUtils.isEmpty(lraaForm.getActionList())){ 
205         	errors.add("No Actions selected. Please try again.");
206         } else {
207 			if(StringUtils.isNotEmpty(lraaForm.getActionList())) {
208 				String[] actionList = lraaForm.getActionList().split(DOC_SEPARATOR);
209 				for(String docId : actionList){
210 					if(StringUtils.isNotEmpty(docId) && !StringUtils.equals(docId, DOC_SEPARATOR)) {
211 						LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
212 						if(lrd == null) {
213 							errors.add(DOC_NOT_FOUND + docId);
214 							break;
215 						} else {
216 							LeaveBlock lb = LmServiceLocator.getLeaveBlockService().getLeaveBlock(lrd.getLmLeaveBlockId());
217 							if(lb == null) {
218 								errors.add(LEAVE_BLOCK_NOT_FOUND + docId);
219 								break;
220 							}
221 						}
222 					}
223 				}
224 			}
225         }
226         errorMsgList.addAll(errors);
227         lraaForm.setOutputString(JSONValue.toJSONString(errorMsgList));
228         return mapping.findForward("ws");
229     }
230 	
231 	
232 	private void setUpLeaveRequestApprovalFieldsForm(LeaveRequestApprovalActionForm leaveRequestApprovalActionForm, boolean isCalendarTypeChanged) {
233         String calendarType = leaveRequestApprovalActionForm.getSelectedCalendarType();
234         String bString = leaveRequestApprovalActionForm.getBeginDateString();
235         String eString = leaveRequestApprovalActionForm.getEndDateString();
236         String navigationString = leaveRequestApprovalActionForm.getNavigationAction();
237         DateTime beginDateTime = null;
238         DateTime endDateTime = null;
239         String selectedPrincipal = leaveRequestApprovalActionForm.getSelectedPrincipal();
240         
241         List<String> principalIds = new ArrayList<String>();
242         if(bString != null && eString != null) {
243         	beginDateTime = TKUtils.formatDateTimeStringNoTimezone(leaveRequestApprovalActionForm.getBeginDateString());
244         	endDateTime = TKUtils.formatDateTimeStringNoTimezone(leaveRequestApprovalActionForm.getEndDateString());
245         } else {
246         	DateMidnight dtFirst = new DateMidnight().withDayOfMonth(1);
247         	dtFirst = dtFirst.plusMonths(1);
248         	beginDateTime = new DateTime(dtFirst.getMillis());
249         	endDateTime = beginDateTime.plusMonths(1);
250         }
251     	if(isCalendarTypeChanged) {
252     		beginDateTime = beginDateTime.withDayOfMonth(1);
253     		if(calendarType.equalsIgnoreCase("W")) {
254     			if(beginDateTime.getDayOfWeek() != DateTimeConstants.SUNDAY) {
255     				endDateTime = beginDateTime.withDayOfWeek(7);
256     				beginDateTime = beginDateTime.withDayOfWeek(1).minusDays(1);
257     			} else {
258     				endDateTime = beginDateTime.plusDays(1).withDayOfWeek(7);
259     				beginDateTime = beginDateTime.withDayOfWeek(1).minusDays(1);    				
260     			}
261     		} else {
262     			endDateTime = beginDateTime.plusMonths(1);
263     		}
264     	} 
265     	// check navigation String
266     	if(navigationString != null) {
267         	if(navigationString.equalsIgnoreCase("PREV")) {
268         		if(calendarType.equalsIgnoreCase("W")) {
269         			beginDateTime = beginDateTime.minusWeeks(1);
270         			if(beginDateTime.getDayOfWeek() != DateTimeConstants.SUNDAY) {
271         				endDateTime = beginDateTime.withDayOfWeek(7);
272         			} else {
273         				endDateTime = beginDateTime.plusDays(1).withDayOfWeek(7);
274         			}
275         		} else {
276         			beginDateTime = beginDateTime.minusMonths(1);
277         			endDateTime = beginDateTime.plusMonths(1);
278         		}
279         	} else if(navigationString.equalsIgnoreCase("NEXT")) {
280         		if(calendarType.equalsIgnoreCase("W")) {
281         			beginDateTime = beginDateTime.plusWeeks(1);
282         			if(beginDateTime.getDayOfWeek() != DateTimeConstants.SUNDAY) {
283         				endDateTime = beginDateTime.withDayOfWeek(7);
284         			} else {
285         				endDateTime = beginDateTime.plusDays(1).withDayOfWeek(7);
286         			}
287         		} else {
288         			beginDateTime = beginDateTime.plusMonths(1);
289         			endDateTime = beginDateTime.plusMonths(1);
290         		}
291         	}
292         	leaveRequestApprovalActionForm.setNavigationAction(null);
293     	}
294 
295     	beginDateTime = beginDateTime.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
296     	endDateTime = endDateTime.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
297     	
298     	List<String> principalIdsToSearch = new ArrayList<String>();
299     	
300 //        DateTime beginDateTime =  currentCE.getBeginPeriodLocalDateTime().toDateTime(HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback());
301 //        DateTime endDateTime = currentCE.getEndPeriodLocalDateTime().toDateTime(HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback());
302         if(selectedPrincipal == null || StringUtils.isEmpty(selectedPrincipal)) {
303         	List<String> leaveCalendars = leaveRequestApprovalActionForm.getPayCalendarGroups();
304         	for(String calendar : leaveCalendars) {
305             	principalIds.addAll(LmServiceLocator.getLeaveApprovalService()
306         	 			.getLeavePrincipalIdsWithSearchCriteria(getWorkAreas(leaveRequestApprovalActionForm), calendar, LocalDate.now(), beginDateTime.toLocalDate(), endDateTime.toLocalDate()));
307             	Collections.sort(principalIds);
308             	leaveRequestApprovalActionForm.setPrincipalIds(principalIds);
309         	}
310         	principalIdsToSearch = new ArrayList<String>(principalIds);
311         } else {
312         	principalIdsToSearch = Collections.singletonList(selectedPrincipal);
313         }
314         
315 		// set LeaveCalendar
316 		Map<String, List<LeaveRequestDocument>> leaveReqDocsMap = getLeaveRequestDocsMap(principalIdsToSearch, leaveRequestApprovalActionForm.getSelectedDept(), getWorkAreas(leaveRequestApprovalActionForm), beginDateTime.toLocalDate(), endDateTime.plusDays(1).toLocalDate());
317 		Map<String, List<LeaveBlock>> leaveBlocksMap = getLeaveBlocksForDisplay(principalIdsToSearch, leaveRequestApprovalActionForm.getSelectedDept(), getWorkAreas(leaveRequestApprovalActionForm), beginDateTime.toLocalDate(), endDateTime.plusDays(1).toLocalDate());
318 		Map<String,List<LeaveBlockHistory>> disapprovedLBMap = getDisapprovedLeaveBlockHistory(principalIdsToSearch, beginDateTime.minusDays(1).toLocalDate());
319 		leaveRequestApprovalActionForm.setLeaveRequestCalendar(new LeaveRequestCalendar(beginDateTime, endDateTime, leaveReqDocsMap, leaveBlocksMap, disapprovedLBMap, calendarType));
320 
321 		// generate json
322 		leaveRequestApprovalActionForm.setLeaveRequestString(LeaveActionFormUtils.getLeaveRequestsJson(leaveRequestApprovalActionForm.getLeaveRequestCalendar().getRequestList()));
323 		
324 		// set begin and end date time string
325 		leaveRequestApprovalActionForm.setBeginDateString(TKUtils.formatDateTimeLong(leaveRequestApprovalActionForm.getLeaveRequestCalendar().getBeginDateTime()));
326 		leaveRequestApprovalActionForm.setEndDateString(TKUtils.formatDateTimeLong(leaveRequestApprovalActionForm.getLeaveRequestCalendar().getEndDateTime()));		
327     	
328 	}
329 	
330 	
331     private Map<String,List<LeaveBlockHistory>> getDisapprovedLeaveBlockHistory(List<String> principalIds, LocalDate currentDate) {
332         Map<String, List<LeaveBlockHistory>> leaveBlockMaps = new HashMap<String, List<LeaveBlockHistory>>();
333 		List<LeaveBlockHistory> historyList = new ArrayList<LeaveBlockHistory>();
334 		List<LeaveBlockHistory> leaveBlocks = new ArrayList<LeaveBlockHistory>();
335 		if(CollectionUtils.isNotEmpty(principalIds)) {
336 			for(String userId : principalIds) {
337 				historyList = LmServiceLocator.getLeaveBlockHistoryService()
338 			        	.getLeaveBlockHistories(userId, HrConstants.REQUEST_STATUS.DISAPPROVED, HrConstants.ACTION.DELETE, currentDate);
339 				for(LeaveBlockHistory lb : historyList) {
340 					if(lb.getLeaveBlockType().equalsIgnoreCase(LMConstants.LEAVE_BLOCK_TYPE.LEAVE_CALENDAR)) {
341 							String key = lb.getLeaveLocalDate().toString();
342 							if(leaveBlockMaps.containsKey(key)) {
343 								leaveBlocks = leaveBlockMaps.get(key);
344 							} else {
345 								leaveBlocks = new ArrayList<LeaveBlockHistory>();
346 							}
347 							leaveBlocks.add(lb);
348 							leaveBlockMaps.put(key, leaveBlocks);
349 					}
350 				}
351 			}
352 		}
353         return leaveBlockMaps;
354     }
355 
356 
357 }