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.time.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.HashSet;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  import org.apache.commons.lang.ObjectUtils;
31  import org.apache.commons.lang.StringUtils;
32  import org.apache.commons.lang.math.NumberUtils;
33  import org.apache.struts.action.ActionForm;
34  import org.apache.struts.action.ActionForward;
35  import org.apache.struts.action.ActionMapping;
36  import org.apache.struts.action.ActionRedirect;
37  import org.displaytag.tags.TableTagParameters;
38  import org.displaytag.util.ParamEncoder;
39  import org.hsqldb.lib.StringUtil;
40  import org.joda.time.LocalDate;
41  import org.kuali.kpme.core.api.calendar.Calendar;
42  import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
43  import org.kuali.kpme.core.api.namespace.KPMENamespace;
44  import org.kuali.kpme.core.permission.KPMEPermissionTemplate;
45  import org.kuali.kpme.core.role.KPMERoleMemberAttribute;
46  import org.kuali.kpme.core.service.HrServiceLocator;
47  import org.kuali.kpme.core.util.HrConstants;
48  import org.kuali.kpme.core.util.HrContext;
49  import org.kuali.kpme.tklm.api.time.missedpunch.MissedPunch;
50  import org.kuali.kpme.tklm.common.CalendarApprovalFormAction;
51  import org.kuali.kpme.tklm.time.approval.summaryrow.ApprovalTimeSummaryRow;
52  import org.kuali.kpme.tklm.time.missedpunch.MissedPunchDocument;
53  import org.kuali.kpme.tklm.time.missedpunch.document.MissedPunchDocumentService;
54  import org.kuali.kpme.tklm.time.service.TkServiceLocator;
55  import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
56  import org.kuali.rice.core.api.config.property.ConfigContext;
57  import org.kuali.rice.kim.api.KimConstants;
58  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
59  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
60  import org.springframework.util.CollectionUtils;
61  
62  public class TimeApprovalAction extends CalendarApprovalFormAction {
63  	
64  	@Override
65  	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
66          ActionForward actionForward = super.execute(mapping, form, request, response);
67          
68          TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
69          String documentId = timeApprovalActionForm.getDocumentId();
70          
71          setSearchFields(timeApprovalActionForm);
72  
73          CalendarEntry calendarEntry = null;
74          if (StringUtils.isNotBlank(documentId)) {
75          	TimesheetDocument timesheetDocument = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
76  
77  			if (timesheetDocument != null) {
78  				calendarEntry = timesheetDocument.getCalendarEntry();
79  				timeApprovalActionForm.setCalendarDocument(timesheetDocument);
80  			}
81          } else if (StringUtils.isNotBlank(timeApprovalActionForm.getHrCalendarEntryId())) {
82          	calendarEntry =  HrServiceLocator.getCalendarEntryService().getCalendarEntry(timeApprovalActionForm.getHrCalendarEntryId());
83          } else if (StringUtils.isNotBlank(timeApprovalActionForm.getSelectedPayPeriod())) {
84          	calendarEntry =  HrServiceLocator.getCalendarEntryService().getCalendarEntry(timeApprovalActionForm.getSelectedPayPeriod());
85          } else {
86              Calendar calendar = HrServiceLocator.getCalendarService().getCalendarByGroup(timeApprovalActionForm.getSelectedPayCalendarGroup());
87              if (calendar != null) {
88                  calendarEntry =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarEntryByCalendarId(calendar.getHrCalendarId(), LocalDate.now().toDateTimeAtStartOfDay());
89              }
90          }
91  
92          if (calendarEntry != null) {
93          	timeApprovalActionForm.setHrCalendarEntryId(calendarEntry.getHrCalendarEntryId());
94          	timeApprovalActionForm.setCalendarEntry(calendarEntry);
95          	timeApprovalActionForm.setBeginCalendarEntryDate(calendarEntry.getBeginPeriodFullDateTime().toDate());
96          	timeApprovalActionForm.setEndCalendarEntryDate(calendarEntry.getEndPeriodFullDateTime().minusMillis(-1).toDate());
97  		
98  			CalendarEntry prevCalendarEntry =  HrServiceLocator.getCalendarEntryService().getPreviousCalendarEntryByCalendarId(calendarEntry.getHrCalendarId(), calendarEntry);
99  			timeApprovalActionForm.setPrevHrCalendarEntryId(prevCalendarEntry != null ? prevCalendarEntry.getHrCalendarEntryId() : null);
100 			
101 			CalendarEntry nextCalendarEntry =  HrServiceLocator.getCalendarEntryService().getNextCalendarEntryByCalendarId(calendarEntry.getHrCalendarId(), calendarEntry);
102 			timeApprovalActionForm.setNextHrCalendarEntryId(nextCalendarEntry != null ? nextCalendarEntry.getHrCalendarEntryId() : null);
103 			
104 	        setCalendarFields(timeApprovalActionForm);
105 	        
106 			timeApprovalActionForm.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(timeApprovalActionForm.getCalendarEntry(), new ArrayList<Boolean>()));
107 
108 
109             //TkServiceLocator.getMissedPunchDocumentService().getMissedPunchDocumentsByTimesheetDocumentId()
110 
111 			List<String> allPIdsList = getPrincipalIds(timeApprovalActionForm);
112 			List<String> pidList = new ArrayList<String>();
113 			pidList.addAll(allPIdsList);
114 			
115 			String docIdSearchTerm = "";
116 			if(StringUtils.equals(timeApprovalActionForm.getMethodToCall(), "searchResult") ) {
117 				if(StringUtils.equals(timeApprovalActionForm.getSearchField(), "principalName") ) {	            
118 		            if (StringUtils.isNotBlank(timeApprovalActionForm.getSearchTerm())) {
119 		            	String searchTerm = timeApprovalActionForm.getSearchTerm();
120 		            	pidList = new ArrayList<String>();
121 		            	for(String anId : allPIdsList) {
122 		            		if(anId.contains(searchTerm)) {
123 		            			pidList.add(anId);
124 		            		}
125 		            	}
126 		            }
127 			      }
128 				
129 				if(StringUtils.equals(timeApprovalActionForm.getSearchField(), "documentId") )	            
130 		            docIdSearchTerm = timeApprovalActionForm.getSearchTerm();
131 			}
132 				
133 	        setApprovalTables(timeApprovalActionForm, request, pidList, docIdSearchTerm);
134         }
135         setMessages(timeApprovalActionForm);
136         return actionForward;
137 	}
138 	
139 	@Override
140 	protected List<String> getCalendars(List<String> principalIds) {
141 		return HrServiceLocator.getPrincipalHRAttributeService().getUniquePayCalendars(principalIds);
142 	}
143 	
144 	public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
145 		TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
146 		CalendarEntry calendarEntry = null;
147         Calendar calendar = HrServiceLocator.getCalendarService().getCalendarByGroup(timeApprovalActionForm.getSelectedPayCalendarGroup());
148         
149 		if (calendar != null) {
150             calendarEntry =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarEntryByCalendarId(calendar.getHrCalendarId(), LocalDate.now().toDateTimeAtStartOfDay());
151         }
152         
153         if (calendarEntry != null) {
154         	timeApprovalActionForm.setHrCalendarEntryId(calendarEntry.getHrCalendarEntryId());
155         	timeApprovalActionForm.setCalendarEntry(calendarEntry);
156         	// change pay period map 
157         	this.setCalendarFields(timeApprovalActionForm);
158         }
159 		
160 		timeApprovalActionForm.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
161 		
162 		return mapping.findForward("basic");
163 	}
164 	
165 	public ActionForward selectNewDept(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
166 		TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
167 		setApprovalTables(timeApprovalActionForm, request, getPrincipalIds(timeApprovalActionForm), "");
168     	
169 		return mapping.findForward("basic");
170 	}
171 	
172 	public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
173 		TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
174 		setApprovalTables(timeApprovalActionForm, request, getPrincipalIds(timeApprovalActionForm), "");
175     	
176 		return mapping.findForward("basic");
177 	}
178 	
179 
180 	public ActionForward searchResult(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
181 		TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
182 		
183 		if(StringUtils.isBlank(timeApprovalActionForm.getSearchField()) 
184 				&& StringUtils.isNotBlank(request.getParameter("searchField"))) {
185 			timeApprovalActionForm.setSearchField(request.getParameter("searchField"));
186 		}
187 		if(StringUtils.isBlank(timeApprovalActionForm.getSearchTerm()) 
188 				&& StringUtils.isNotBlank(request.getParameter("searchValue"))) {
189 			timeApprovalActionForm.setSearchTerm(request.getParameter("searchValue"));
190 		}		
191 		if(StringUtils.isBlank(timeApprovalActionForm.getSelectedPayPeriod()) 
192 				&& StringUtils.isNotBlank(request.getParameter("selectedPayPeriod"))) {
193 			timeApprovalActionForm.setSelectedPayPeriod(request.getParameter("selectedPayPeriod"));
194 		}		
195 		return mapping.findForward("basic");
196 	}
197 	
198 	public ActionForward resetSearch(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
199 		TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
200 		timeApprovalActionForm.setSearchField("");
201 		timeApprovalActionForm.setSearchTerm("");
202 		return mapping.findForward("basic");
203 	}
204 	
205 	public ActionForward goToCurrentPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
206 		TimeApprovalActionForm timeApprovalActionForm = (TimeApprovalActionForm) form;
207 		timeApprovalActionForm.setSearchField("");
208 		timeApprovalActionForm.setSearchTerm("");
209 		timeApprovalActionForm.setSelectedPayPeriod("");
210 		timeApprovalActionForm.setHrCalendarEntryId("");
211 		return mapping.findForward("basic");
212 	}
213 	
214     private List<String> getPrincipalIds(TimeApprovalActionForm timeApprovalActionForm) {
215         List<String> workAreas = new ArrayList<String>();
216         if (StringUtil.isEmpty(timeApprovalActionForm.getSelectedWorkArea())) {
217         	for (Long workAreaKey : timeApprovalActionForm.getWorkAreaDescr().keySet()) {
218         		workAreas.add(workAreaKey.toString());
219         	}
220         } else {
221         	workAreas.add(timeApprovalActionForm.getSelectedWorkArea());
222         }
223         String calendar = timeApprovalActionForm.getSelectedPayCalendarGroup();
224         if (timeApprovalActionForm.getCalendarEntry() == null) {
225             return Collections.emptyList();
226         }
227 
228         LocalDate endDate = timeApprovalActionForm.getCalendarEntry().getEndPeriodFullDateTime().toLocalDate();
229         LocalDate beginDate = timeApprovalActionForm.getCalendarEntry().getBeginPeriodFullDateTime().toLocalDate();
230         
231         List<String> pList1 = TkServiceLocator.getTimeApproveService().getTimePrincipalIdsWithSearchCriteria(workAreas, calendar, beginDate, beginDate, endDate);
232         List<String> pList2 = TkServiceLocator.getTimeApproveService().getTimePrincipalIdsWithSearchCriteria(workAreas, calendar, endDate, beginDate, endDate);
233         Set<String> pIdSet = new HashSet<String>();
234         pIdSet.addAll(pList1);
235         pIdSet.addAll(pList2);
236         List<String> finalList = new ArrayList<String>(pIdSet);
237         return finalList;
238 //        return TkServiceLocator.getTimeApproveService().getTimePrincipalIdsWithSearchCriteria(workAreas, calendar, beginDate, beginDate, endDate);
239 
240 	}
241     
242 	protected void setApprovalTables(TimeApprovalActionForm timeApprovalActionForm, HttpServletRequest request, List<String> principalIds, String docIdSearchTerm) {
243 		if (principalIds.isEmpty()) {
244 			timeApprovalActionForm.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
245 			timeApprovalActionForm.setResultSize(0);
246 			timeApprovalActionForm.setOutputString(null);
247 		} else {
248 		    List<ApprovalTimeSummaryRow> approvalRows = getApprovalRows(timeApprovalActionForm, principalIds, docIdSearchTerm);
249 		    timeApprovalActionForm.setOutputString(!CollectionUtils.isEmpty(approvalRows) ? approvalRows.get(0).getOutputString() : null);
250 		    final String sortField = getSortField(request);
251 		    if (StringUtils.isEmpty(sortField) || StringUtils.equals(sortField, "name")) {
252 		    	final boolean sortNameAscending = getAscending(request);
253 		    	Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
254 					@Override
255 					public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
256 						if (sortNameAscending) {
257 							return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName()));
258 						} else {
259 							return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName()));
260 						}
261 					}
262                 		    	});
263 		    } else if (StringUtils.equals(sortField, "documentID")) {
264 		    	final boolean sortDocumentIdAscending = getAscending(request);
265 		    	Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
266 					@Override
267 					public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
268 						if (sortDocumentIdAscending) {
269 							return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId()));
270 						} else {
271 							return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId()));
272 						}
273 					}
274                 		    	});
275 		    } else if (StringUtils.equals(sortField, "status")) {
276 		    	final boolean sortStatusIdAscending = getAscending(request);;
277 		    	Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
278 					@Override
279 					public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
280 						if (sortStatusIdAscending) {
281 							return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus()));
282 						} else {
283 							return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus()));
284 						}
285 					}
286                 		    	});
287 		    }
288 		    
289 		    String page = request.getParameter((new ParamEncoder(HrConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
290 		    Integer beginIndex = StringUtils.isBlank(page) || StringUtils.equals(page, "1") ? 0 : (Integer.parseInt(page) - 1) * timeApprovalActionForm.getPageSize();
291 		    Integer endIndex = beginIndex + timeApprovalActionForm.getPageSize() > approvalRows.size() ? approvalRows.size() : beginIndex + timeApprovalActionForm.getPageSize();
292 		    for (ApprovalTimeSummaryRow approvalTimeSummaryRow : approvalRows) {
293  	 	 	 	approvalTimeSummaryRow.setMissedPunchList(getMissedPunches(approvalTimeSummaryRow.getDocumentId()));
294 		    }
295 
296             MissedPunchDocumentService mpds;
297             mpds = TkServiceLocator.getMissedPunchDocumentService();
298 
299             Map<String, Boolean> missedPunchPermissions = new HashMap<String, Boolean>();
300 
301             for (ApprovalTimeSummaryRow approvalTimeSummaryRow : approvalRows) {
302                 for (MissedPunch mp: approvalTimeSummaryRow.getMissedPunchList()) {
303                     MissedPunchDocument mpd = (MissedPunchDocument) mpds.getMissedPunchDocumentByMissedPunchId(mp.getTkMissedPunchId());
304 
305                     String groupKey = mpd.getGroupKeyCode();
306                     Long workArea = mpd.getWorkArea();
307                     String department = mpd.getDepartment();
308                     String location = mpd.getGroupKey() != null ? mpd.getGroupKey().getLocationId() : HrServiceLocator.getHrGroupKeyService().getHrGroupKey(mpd.getGroupKeyCode(), mpd.getMissedPunch().getActionLocalDate()).getLocationId();
309 
310                     String principalId = HrContext.getPrincipalId();
311                     Map<String, String> roleQualification = new HashMap<String, String>();
312                     roleQualification.put(KimConstants.AttributeConstants.PRINCIPAL_ID, principalId);
313                     roleQualification.put(KPMERoleMemberAttribute.DEPARTMENT.getRoleMemberAttributeName(), department);
314                     roleQualification.put(KPMERoleMemberAttribute.WORK_AREA.getRoleMemberAttributeName(), workArea.toString());
315                     roleQualification.put(KPMERoleMemberAttribute.GROUP_KEY_CODE.getRoleMemberAttributeName(), groupKey);
316                     roleQualification.put(KPMERoleMemberAttribute.LOCATION.getRoleMemberAttributeName(), location);
317 
318                     Map<String, String> permissionDetails = new HashMap<String, String>();
319                     permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, KRADServiceLocatorWeb.getDocumentDictionaryService().getDocumentTypeByClass(MissedPunchDocument.class));
320 
321                     boolean canView = (KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(principalId, KPMENamespace.KPME_WKFLW.getNamespaceCode(),
322                             KPMEPermissionTemplate.VIEW_KPME_RECORD.getPermissionTemplateName(), permissionDetails, roleQualification));
323 
324                     missedPunchPermissions.put(mp.getMissedPunchDocId(), canView);
325                 }
326             }
327 
328             timeApprovalActionForm.setMissedPunchPermissions(missedPunchPermissions);
329 
330             List<ApprovalTimeSummaryRow> sublist = new ArrayList<ApprovalTimeSummaryRow>();
331             sublist.addAll(approvalRows.subList(beginIndex, endIndex));
332 		    timeApprovalActionForm.setApprovalRows(sublist);
333 		    timeApprovalActionForm.setResultSize(approvalRows.size());
334 		}		
335 	}
336 	
337 	private List<MissedPunch> getMissedPunches(String documentId) {
338 		return TkServiceLocator.getMissedPunchService().getMissedPunchByTimesheetDocumentId(documentId);
339 	}
340 	
341 	protected List<ApprovalTimeSummaryRow> getApprovalRows(TimeApprovalActionForm timeApprovalActionForm, List<String> assignmentPrincipalIds, String docIdSearchTerm) {
342     	return (List<ApprovalTimeSummaryRow>)TkServiceLocator.getTimeApproveService().getApprovalSummaryRows(timeApprovalActionForm.getSelectedPayCalendarGroup(), assignmentPrincipalIds, timeApprovalActionForm.getPayCalendarLabels(), timeApprovalActionForm.getCalendarEntry(), docIdSearchTerm);
343     }
344 
345     public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
346         TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
347         List<ApprovalTimeSummaryRow> lstApprovalRows = taaf.getApprovalRows();
348         List<String> errorList = new ArrayList<String>();
349         for (ApprovalTimeSummaryRow ar : lstApprovalRows) {
350             if (ar.isApprovable() && StringUtils.equals(ar.getSelected(), "on")) {
351                 String documentNumber = ar.getDocumentId();
352                 TimesheetDocument tDoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentNumber);
353                 if (tDoc != null) {
354                     if(TkServiceLocator.getTimesheetService().isTimesheetValid(tDoc)) {
355                         TkServiceLocator.getTimesheetService().approveTimesheet(HrContext.getPrincipalId(), tDoc);
356                     } else {
357                         errorList.add( "Timesheet " + tDoc.getDocumentId() + " could not be approved as it contains errors, see time detail for more info");
358                     }
359                 }
360             }
361         }
362         ActionRedirect redirect = new ActionRedirect(mapping.findForward("basicRedirect"));
363         redirect.addParameter("selectedDept", taaf.getSelectedDept());
364         redirect.addParameter("selectedPayCalendarGroup", taaf.getSelectedPayCalendarGroup());
365         redirect.addParameter("selectedWorkArea", taaf.getSelectedWorkArea());
366         redirect.addParameter("selectedPayPeriod", taaf.getSelectedPayPeriod());
367         redirect.addParameter("errorMessageList", errorList);
368         
369         return redirect;
370     }
371 
372     protected void setMessages(TimeApprovalActionForm taaf) {
373         List<ApprovalTimeSummaryRow> lstApprovalRows = taaf.getApprovalRows();
374         List<String> errorList = new ArrayList<String>();
375         for (ApprovalTimeSummaryRow ar : lstApprovalRows) {
376             String documentNumber = ar.getDocumentId();
377             TimesheetDocument tDoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentNumber);
378             if (tDoc != null && !TkServiceLocator.getTimesheetService().isTimesheetValid(tDoc)) {
379                     errorList.add("Timesheet " + tDoc.getDocumentId() + " could not be approved as it contains errors, see time detail for more info");
380             }
381         }
382         taaf.setErrorMessageList(errorList);
383     }
384 }