View Javadoc

1   /**
2    * Copyright 2004-2013 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.Comparator;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  
25  import javax.servlet.http.HttpServletRequest;
26  import javax.servlet.http.HttpServletResponse;
27  
28  import org.apache.commons.collections.CollectionUtils;
29  import org.apache.commons.lang.ObjectUtils;
30  import org.apache.commons.lang.StringUtils;
31  import org.apache.struts.action.ActionForm;
32  import org.apache.struts.action.ActionForward;
33  import org.apache.struts.action.ActionMapping;
34  import org.joda.time.LocalDate;
35  import org.joda.time.format.DateTimeFormat;
36  import org.joda.time.format.DateTimeFormatter;
37  import org.json.simple.JSONArray;
38  import org.json.simple.JSONValue;
39  import org.kuali.kpme.core.service.HrServiceLocator;
40  import org.kuali.kpme.core.util.HrContext;
41  import org.kuali.kpme.core.util.TKUtils;
42  import org.kuali.kpme.tklm.common.ApprovalFormAction;
43  import org.kuali.kpme.tklm.leave.block.LeaveBlock;
44  import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
45  import org.kuali.kpme.tklm.leave.workflow.LeaveRequestDocument;
46  import org.kuali.kpme.tklm.time.util.TkContext;
47  import org.kuali.rice.kew.api.KewApiServiceLocator;
48  import org.kuali.rice.kew.api.action.ActionItem;
49  import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
50  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
51  import org.kuali.rice.krad.exception.AuthorizationException;
52  import org.kuali.rice.krad.util.GlobalVariables;
53  
54  public class LeaveRequestApprovalAction extends ApprovalFormAction {
55  	
56      public static final String DOC_SEPARATOR = "----";	// separator for documents
57      public static final String ID_SEPARATOR = "____";	// separator for documentId and reason string
58      public static final String DOC_NOT_FOUND = "Leave request document not found with id ";
59      public static final String LEAVE_BLOCK_NOT_FOUND = "Leave Block not found for Leave request document ";
60      
61      @Override
62  	protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
63  		if (!HrContext.isReviewer() && !HrContext.isAnyApprover() && !HrContext.isSystemAdmin() && !TkContext.isLocationAdmin() 
64  				&& !HrContext.isGlobalViewOnly() && !TkContext.isDepartmentViewOnly() && !TkContext.isDepartmentAdmin()) {
65  			throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalId(), "ApprovalFormAction", "");
66  		}
67  	}
68  	
69  	@Override
70  	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
71          ActionForward forward = super.execute(mapping, form, request, response);
72  		
73          LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
74          
75          setSearchFields(leaveRequestApprovalActionForm);
76          
77  	    List<ActionItem> items = getActionItems(leaveRequestApprovalActionForm.getSelectedPayCalendarGroup(), leaveRequestApprovalActionForm.getSelectedDept(), getWorkAreas(leaveRequestApprovalActionForm));
78  		leaveRequestApprovalActionForm.setEmployeeRows(getEmployeeRows(items));
79  		
80  		return forward;
81  	}
82  	
83  	@Override
84  	protected List<String> getCalendars(List<String> principalIds) {
85  		return HrServiceLocator.getPrincipalHRAttributeService().getUniqueLeaveCalendars(principalIds);
86  	}
87  	
88  	public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
89  		return mapping.findForward("basic");
90  	}
91  	
92  	public ActionForward selectNewDept(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
93          LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
94          
95      	List<ActionItem> items = getActionItems(leaveRequestApprovalActionForm.getSelectedPayCalendarGroup(), leaveRequestApprovalActionForm.getSelectedDept(), getWorkAreas(leaveRequestApprovalActionForm));
96      	leaveRequestApprovalActionForm.setEmployeeRows(getEmployeeRows(items));	
97   	
98  		return mapping.findForward("basic");
99  	}
100 	
101 	public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
102         LeaveRequestApprovalActionForm leaveRequestApprovalActionForm = (LeaveRequestApprovalActionForm) form;
103         
104     	List<ActionItem> items = getActionItems(leaveRequestApprovalActionForm.getSelectedPayCalendarGroup(), leaveRequestApprovalActionForm.getSelectedDept(), getWorkAreas(leaveRequestApprovalActionForm));
105     	leaveRequestApprovalActionForm.setEmployeeRows(getEmployeeRows(items));	
106         
107 		return mapping.findForward("basic");
108 	}
109 	
110 	private List<ActionItem> getActionItems(String calGroup, String dept, List<String> workAreaList) {
111 		String principalId = HrContext.getTargetPrincipalId();
112 		List<ActionItem> actionList = KewApiServiceLocator.getActionListService().getActionItemsForPrincipal(principalId);
113 		List<ActionItem> resultsList = new ArrayList<ActionItem>();
114 
115 		LocalDate currentDate = LocalDate.now();
116 		List<String> principalIds = LmServiceLocator.getLeaveApprovalService()
117  			.getLeavePrincipalIdsWithSearchCriteria(workAreaList, calGroup, currentDate, currentDate, currentDate);    
118 		
119 		if(CollectionUtils.isNotEmpty(principalIds)) {
120 			for(ActionItem anAction : actionList) {
121 				String docId = anAction.getDocumentId();
122 				if(anAction.getDocName().equals(LeaveRequestDocument.LEAVE_REQUEST_DOCUMENT_TYPE)) {
123 					LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
124 					if(lrd != null) {
125 						LeaveBlock lb = lrd.getLeaveBlock();
126 						if(lb != null) {
127 							if(principalIds.contains(lb.getPrincipalId())) {
128 								resultsList.add(anAction);
129 							}
130 						}
131 					}
132 				}
133 			}
134 		}
135         
136         return resultsList;
137 	}
138 	
139 	public ActionForward takeActionOnEmployee(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
140 		LeaveRequestApprovalActionForm lraaForm = (LeaveRequestApprovalActionForm) form;
141 		
142 		if(StringUtils.isNotEmpty(lraaForm.getApproveList())) {
143 			String[] approveList = lraaForm.getApproveList().split(DOC_SEPARATOR);
144 			for(String eachAction : approveList){
145 				String[] fields = eachAction.split(ID_SEPARATOR);
146 				String docId = fields[0];	// leave request document id
147 				String reasonString = fields.length > 1 ? fields[1] : ""; 	// approve reason text, could be empty
148 				LmServiceLocator.getLeaveRequestDocumentService().approveLeave(docId, HrContext.getPrincipalId(), reasonString);
149 				// leave block's status is changed to "approved" in postProcessor of LeaveRequestDocument
150 			}
151 		}
152 		if(StringUtils.isNotEmpty(lraaForm.getDisapproveList())) {
153 			String[] disapproveList = lraaForm.getDisapproveList().split(DOC_SEPARATOR);
154 			for(String eachAction : disapproveList){
155 				String[] fields = eachAction.split(ID_SEPARATOR);
156 				String docId = fields[0];	// leave request document id
157 				String reasonString = fields.length > 1 ? fields[1] : ""; 	// disapprove reason
158 				LmServiceLocator.getLeaveRequestDocumentService().disapproveLeave(docId, HrContext.getPrincipalId(), reasonString);
159 				// leave block's status is changed to "disapproved" in postProcessor of LeaveRequestDocument	
160 			}
161 		}
162 		if(StringUtils.isNotEmpty(lraaForm.getDeferList())) {
163 			String[] deferList = lraaForm.getDeferList().split(DOC_SEPARATOR);
164 			for(String eachAction : deferList){
165 				String[] fields = eachAction.split(ID_SEPARATOR);
166 				String docId = fields[0];	// leave request document id
167 				String reasonString =  fields.length > 1 ? fields[1] : ""; 	// defer reason
168 				LmServiceLocator.getLeaveRequestDocumentService().deferLeave(docId, HrContext.getPrincipalId(), reasonString);
169 				// leave block's status is changed to "deferred" in postProcessor of LeaveRequestDocument	
170 			}
171 		}
172 		return mapping.findForward("basic");
173 	}
174 
175 	private List<LeaveRequestApprovalEmployeeRow> getEmployeeRows(List<ActionItem> actionList) {
176 		List<LeaveRequestApprovalEmployeeRow> empRowList = new ArrayList<LeaveRequestApprovalEmployeeRow>();
177 		Map<String, List<LeaveRequestDocument>> docMap = new HashMap<String, List<LeaveRequestDocument>>();
178 		for(ActionItem action : actionList) {
179 			if(action.getDocName().equals(LeaveRequestDocument.LEAVE_REQUEST_DOCUMENT_TYPE)) {
180 				String docId = action.getDocumentId();
181 				LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
182 				if(lrd != null) {
183 					LeaveBlock lb = lrd.getLeaveBlock();
184 					if(lb != null) {
185 						String lbPrincipalId = lb.getPrincipalId();
186 						List<LeaveRequestDocument> docList = docMap.get(lbPrincipalId) == null ? new ArrayList<LeaveRequestDocument>() : docMap.get(lbPrincipalId);
187 						docList.add(lrd);
188 						docMap.put(lbPrincipalId, docList);
189 					}
190 				}
191 				
192 			}
193 		}
194 		for (Map.Entry<String, List<LeaveRequestDocument>> entry : docMap.entrySet()) {
195 			LeaveRequestApprovalEmployeeRow aRow = this.getAnEmployeeRow(entry.getKey(), entry.getValue());
196 			if(aRow != null) {
197 				empRowList.add(aRow);
198 			}
199 		}
200 		// sort list by employee name
201 		Collections.sort(empRowList, new Comparator<LeaveRequestApprovalEmployeeRow>() {
202 			@Override
203 			public int compare(LeaveRequestApprovalEmployeeRow row1, LeaveRequestApprovalEmployeeRow row2) {
204 				return ObjectUtils.compare(row1.getEmployeeName(), row2.getEmployeeName());
205 			}
206     	});		
207 		
208 		return empRowList;
209 	}
210 	
211 	private LeaveRequestApprovalEmployeeRow getAnEmployeeRow(String principalId, List<LeaveRequestDocument> docList) {
212 		if(CollectionUtils.isEmpty(docList) || StringUtils.isEmpty(principalId)) {
213 			return null;
214 		}
215         EntityNamePrincipalName entityNamePrincipalName = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
216 		if(entityNamePrincipalName == null) {
217 			return null;
218 		}
219 		LeaveRequestApprovalEmployeeRow empRow = new LeaveRequestApprovalEmployeeRow();
220 		empRow.setPrincipalId(principalId);
221 		empRow.setEmployeeName(entityNamePrincipalName.getDefaultName() == null ? StringUtils.EMPTY : entityNamePrincipalName.getDefaultName().getCompositeName());
222 		List<LeaveRequestApprovalRow> rowList = new ArrayList<LeaveRequestApprovalRow>();
223 		for(LeaveRequestDocument lrd : docList) {
224 			if(lrd == null) {
225 				return null;
226 			}
227 			LeaveBlock lb = lrd.getLeaveBlock();
228 			if(lb == null) {
229 				return null;
230 			}
231 			LeaveRequestApprovalRow aRow = new LeaveRequestApprovalRow();
232 			aRow.setLeaveRequestDocId(lrd.getDocumentNumber());
233 			aRow.setLeaveCode(lb.getEarnCode());
234 			aRow.setRequestedDate(TKUtils.formatDate(lb.getLeaveLocalDate()));
235 			aRow.setRequestedHours(lb.getLeaveAmount().toString());
236 			aRow.setDescription(lrd.getDescription());
237 			DateTimeFormatter formatter = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
238 			aRow.setSubmittedTime(formatter.print(lrd.getDocumentHeader().getWorkflowDocument().getDateCreated()));
239 			rowList.add(aRow);
240 		}
241 		// sort list by date
242 		if(CollectionUtils.isNotEmpty(rowList)) {
243 			Collections.sort(rowList, new Comparator<LeaveRequestApprovalRow>() {
244 				@Override
245 				public int compare(LeaveRequestApprovalRow row1, LeaveRequestApprovalRow row2) {
246 					return ObjectUtils.compare(row1.getRequestedDate(), row2.getRequestedDate());
247 				}
248 	    	});
249 			empRow.setLeaveRequestList(rowList);
250 		}
251 		return empRow;
252 	}
253 
254 	@SuppressWarnings("unchecked")
255 	public ActionForward validateActions(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
256 		LeaveRequestApprovalActionForm lraaForm = (LeaveRequestApprovalActionForm) form;
257 		JSONArray errorMsgList = new JSONArray();
258         List<String> errors = new ArrayList<String>();
259         if(StringUtils.isEmpty(lraaForm.getApproveList()) 
260 	        	&& StringUtils.isEmpty(lraaForm.getDisapproveList())
261 	        	&& StringUtils.isEmpty(lraaForm.getDeferList())) {
262         	errors.add("No Actions selected. Please try again.");
263         } else {
264 			if(StringUtils.isNotEmpty(lraaForm.getApproveList())) {
265 				String[] approveList = lraaForm.getApproveList().split(DOC_SEPARATOR);
266 				for(String eachAction : approveList){
267 					String[] fields = eachAction.split(ID_SEPARATOR);
268 					String docId = fields[0];	// leave request document id
269 					LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
270 					if(lrd == null) {
271 						errors.add(DOC_NOT_FOUND + docId);
272 						break;
273 					} else {
274 						LeaveBlock lb = LmServiceLocator.getLeaveBlockService().getLeaveBlock(lrd.getLmLeaveBlockId());
275 						if(lb == null) {
276 							errors.add(LEAVE_BLOCK_NOT_FOUND + docId);
277 							break;
278 						}
279 					}
280 				}
281 			}
282 			if(StringUtils.isNotEmpty(lraaForm.getDisapproveList())) {
283 				String[] disapproveList = lraaForm.getDisapproveList().split(DOC_SEPARATOR);
284 				for(String eachAction : disapproveList){
285 					String[] fields = eachAction.split(ID_SEPARATOR);
286 					String docId = fields[0];	// leave request document id
287 					String reasonString = fields.length > 1 ? fields[1] : ""; 	// disapprove reason
288 					if(StringUtils.isEmpty(reasonString)) {
289 						errors.add("Reason is required for Disapprove action");
290 						break;
291 					} else {
292 						LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
293 						if(lrd == null) {
294 							errors.add(DOC_NOT_FOUND + docId);
295 							break;
296 						}else {
297 							LeaveBlock lb = LmServiceLocator.getLeaveBlockService().getLeaveBlock(lrd.getLmLeaveBlockId());
298 							if(lb == null) {
299 								errors.add(LEAVE_BLOCK_NOT_FOUND + docId);
300 								break;
301 							}
302 						}
303 					}
304 				}
305 			}
306 			if(StringUtils.isNotEmpty(lraaForm.getDeferList())) {
307 				String[] deferList = lraaForm.getDeferList().split(DOC_SEPARATOR);
308 				for(String eachAction : deferList){
309 					String[] fields = eachAction.split(ID_SEPARATOR);
310 					String docId = fields[0];	// leave request document id
311 					String reasonString =  fields.length > 1 ? fields[1] : ""; 	// defer reason
312 					if(StringUtils.isEmpty(reasonString)) {
313 						errors.add("Reason is required for Defer action");
314 						break;
315 					} else {
316 						LeaveRequestDocument lrd = LmServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocument(docId);
317 						if(lrd == null) {
318 							errors.add(DOC_NOT_FOUND + docId);
319 							break;
320 						}else {
321 							LeaveBlock lb = LmServiceLocator.getLeaveBlockService().getLeaveBlock(lrd.getLmLeaveBlockId());
322 							if(lb == null) {
323 								errors.add(LEAVE_BLOCK_NOT_FOUND + docId);
324 								break;
325 							}
326 						}
327 					}
328 				}
329 			}
330         }
331         errorMsgList.addAll(errors);
332         lraaForm.setOutputString(JSONValue.toJSONString(errorMsgList));
333         return mapping.findForward("ws");
334     }	
335 }