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.hr.time.approval.web;
17  
18  import org.apache.commons.lang.ObjectUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.commons.lang.math.NumberUtils;
21  import org.apache.struts.action.ActionForm;
22  import org.apache.struts.action.ActionForward;
23  import org.apache.struts.action.ActionMapping;
24  import org.displaytag.tags.TableTagParameters;
25  import org.displaytag.util.ParamEncoder;
26  import org.hsqldb.lib.StringUtil;
27  import org.kuali.hr.core.document.calendar.CalendarDocumentContract;
28  import org.kuali.hr.time.assignment.Assignment;
29  import org.kuali.hr.time.base.web.ApprovalAction;
30  import org.kuali.hr.time.base.web.ApprovalForm;
31  import org.kuali.hr.time.calendar.Calendar;
32  import org.kuali.hr.time.calendar.CalendarEntries;
33  import org.kuali.hr.time.detail.web.ActionFormUtils;
34  import org.kuali.hr.time.service.base.TkServiceLocator;
35  import org.kuali.hr.time.timesheet.TimesheetDocument;
36  import org.kuali.hr.time.util.TKContext;
37  import org.kuali.hr.time.util.TKUser;
38  import org.kuali.hr.time.util.TKUtils;
39  import org.kuali.hr.time.util.TkConstants;
40  import org.kuali.hr.time.workarea.WorkArea;
41  import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
42  
43  import javax.servlet.http.HttpServletRequest;
44  import javax.servlet.http.HttpServletResponse;
45  import java.sql.Date;
46  import java.text.SimpleDateFormat;
47  import java.util.*;
48  
49  public class TimeApprovalAction extends ApprovalAction{
50  	
51  	public ActionForward searchResult(ActionMapping mapping, ActionForm form,
52  			HttpServletRequest request, HttpServletResponse response)
53  			throws Exception {
54  		TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
55  		
56          if (StringUtils.equals("documentId", taaf.getSearchField())) {
57          	TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(taaf.getSearchTerm());
58          	taaf.setSearchTerm(tdh != null ? tdh.getPrincipalId() : StringUtils.EMPTY);
59          }
60          
61      	taaf.setSearchField("principalId");
62          List<String> principalIds = new ArrayList<String>();
63          principalIds.add(taaf.getSearchTerm());
64          
65          if (principalIds.isEmpty()) {
66          	taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
67          	taaf.setResultSize(0);
68          } else {
69          	taaf.setResultSize(principalIds.size());	
70  	        taaf.setApprovalRows(getApprovalRows(request, taaf, principalIds));
71  	        
72          	CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
73     	        taaf.setPayCalendarEntries(payCalendarEntries);
74     	        taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
75          	
76  	        List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(taaf.getSearchTerm(), payCalendarEntries.getEndPeriodDate());
77  	        if(!assignments.isEmpty()){
78  	        	 for(Long wa : taaf.getWorkAreaDescr().keySet()){
79  	        		for (Assignment assign : assignments) {
80  		             	if (assign.getWorkArea().toString().equals(wa.toString())) {
81  		             		taaf.setSelectedWorkArea(wa.toString());
82  		             		break;
83  		             	}
84  	        		}
85  	             }
86  	        }
87          }
88   
89  		return mapping.findForward("basic");
90  	}
91  	
92      public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
93          TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
94          //let's save the page we are on!
95          List<ApprovalTimeSummaryRow> lstApprovalRows = taaf.getApprovalRows();
96  
97          for (ApprovalTimeSummaryRow ar : lstApprovalRows) {
98              if (ar.isApprovable() && StringUtils.equals(ar.getSelected(), "on")) {
99                  String documentNumber = ar.getDocumentId();
100                 TimesheetDocument tDoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentNumber);
101                 TkServiceLocator.getTimesheetService().approveTimesheet(TKContext.getTargetPrincipalId(), tDoc);
102             }
103         }
104         return mapping.findForward("basic");
105     }
106     
107 	public ActionForward selectNewDept(ActionMapping mapping, ActionForm form,
108 			HttpServletRequest request, HttpServletResponse response)
109 			throws Exception {
110 		TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
111 		taaf.setSearchField(null);
112 		taaf.setSearchTerm(null);
113 
114         CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
115         taaf.setPayCalendarEntries(payCalendarEntries);
116         taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
117 
118 		taaf.getWorkAreaDescr().clear();
119     	List<WorkArea> workAreas = TkServiceLocator.getWorkAreaService().getWorkAreas(taaf.getSelectedDept(), new java.sql.Date(taaf.getPayBeginDate().getTime()));
120         for(WorkArea wa : workAreas){
121         	if (TKUser.getApproverWorkAreas().contains(wa.getWorkArea())
122         			|| TKUser.getReviewerWorkAreas().contains(wa.getWorkArea())) {
123         		taaf.getWorkAreaDescr().put(wa.getWorkArea(),wa.getDescription()+"("+wa.getWorkArea()+")");
124         	}
125         }
126 
127         List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf); 
128     	if (principalIds.isEmpty()) {
129     		taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
130     		taaf.setResultSize(0);
131     	}
132     	else {
133             List<ApprovalTimeSummaryRow> approvalTimeSummaryRows = getApprovalRows(request, taaf, principalIds);
134             setFormSubsetOfApprovalRows(taaf, getPage(request, taaf), approvalTimeSummaryRows);
135     	}
136     	
137     	this.populateCalendarAndPayPeriodLists(request, taaf);
138 		return mapping.findForward("basic");
139 	}
140 	
141 	public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form,
142 			HttpServletRequest request, HttpServletResponse response)
143 			throws Exception {
144 		TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
145 		taaf.setSearchField(null);
146 		taaf.setSearchTerm(null);
147 
148 	    CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
149         taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
150         
151         List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf); 
152 		if (principalIds.isEmpty()) {
153 			taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
154 			taaf.setResultSize(0);
155 		}
156 		else {
157             List<ApprovalTimeSummaryRow> approvalTimeSummaryRows = getApprovalRows(request, taaf, principalIds);
158             setFormSubsetOfApprovalRows(taaf, getPage(request, taaf), approvalTimeSummaryRows);
159 	    }
160 		return mapping.findForward("basic");
161 	}
162 	
163 	@Override
164 	public ActionForward loadApprovalTab(ActionMapping mapping, ActionForm form,
165 	HttpServletRequest request, HttpServletResponse response)
166 				throws Exception {
167 		ActionForward fwd = mapping.findForward("basic");
168         TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
169         Date currentDate = null;
170         CalendarEntries payCalendarEntries = null;
171         Calendar currentPayCalendar = null;
172         //String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
173         String page = getPage(request, taaf);
174 
175         //reset state
176         if(StringUtils.isBlank(taaf.getSelectedDept())){
177         	resetState(form, request);
178         }
179 
180         TimesheetDocument td = null;
181         if (taaf.getDocumentId() != null) {
182             td = TkServiceLocator.getTimesheetService().getTimesheetDocument(taaf.getDocumentId());
183         }
184 
185         // Set calendar groups
186         List<String> calGroups = TkServiceLocator.getPrincipalHRAttributeService().getUniqueTimePayGroups();
187         taaf.setPayCalendarGroups(calGroups);
188 
189         if (StringUtils.isBlank(taaf.getSelectedPayCalendarGroup())) {
190             if (td == null) {
191                 taaf.setSelectedPayCalendarGroup(calGroups.get(0));
192             } else {
193                 taaf.setSelectedPayCalendarGroup(td.getCalendarEntry().getCalendarName());
194             }
195         }
196         
197         // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
198         if (taaf.getHrPyCalendarEntriesId() != null) {
199         	payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
200         } else {
201             if (td == null) {
202                 currentDate = TKUtils.getTimelessDate(null);
203                 currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(taaf.getSelectedPayCalendarGroup());
204                 payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate);
205             } else {
206                 payCalendarEntries = td.getCalendarEntry();
207             }
208         }
209         taaf.setPayCalendarEntries(payCalendarEntries);
210         
211         
212         if(taaf.getPayCalendarEntries() != null) {
213 	        populateCalendarAndPayPeriodLists(request, taaf);
214         }
215 
216         setupDocumentOnFormContext(request,taaf,payCalendarEntries, page, td);
217         return fwd;
218 	}
219 
220 	@Override
221 	protected void setupDocumentOnFormContext(HttpServletRequest request, ApprovalForm form, CalendarEntries payCalendarEntries, String page, CalendarDocumentContract calDoc) {
222 		super.setupDocumentOnFormContext(request, form, payCalendarEntries, page, calDoc);
223 		TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
224 		taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
225 
226 		List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf);
227 		if (principalIds.isEmpty()) {
228 			taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
229 			taaf.setResultSize(0);
230 		} else {
231 		    List<ApprovalTimeSummaryRow> approvalRows = getApprovalRows(request, taaf, principalIds);
232             setFormSubsetOfApprovalRows(taaf, page, approvalRows);
233 		}
234 
235 
236 		taaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(taaf.getPayCalendarEntries()));
237 	}
238 
239     private void setFormSubsetOfApprovalRows(TimeApprovalActionForm taaf, String page, List<ApprovalTimeSummaryRow> approvalRows) {
240         Integer beginIndex = StringUtils.isBlank(page) || StringUtils.equals(page, "1") ? 0 : (Integer.parseInt(page) - 1)*TkConstants.PAGE_SIZE;
241         Integer endIndex = beginIndex + TkConstants.PAGE_SIZE > approvalRows.size() ? approvalRows.size() : beginIndex + TkConstants.PAGE_SIZE;
242         if (beginIndex > endIndex
243                 || beginIndex >= approvalRows.size()) {
244             beginIndex = StringUtils.isBlank(page) || StringUtils.equals(page, "1") ? 0 : (Integer.parseInt(page) - 1)*TkConstants.PAGE_SIZE;
245             endIndex = beginIndex + TkConstants.PAGE_SIZE > approvalRows.size() ? approvalRows.size() : beginIndex + TkConstants.PAGE_SIZE;
246         }
247         taaf.setApprovalRows(approvalRows.subList(beginIndex, endIndex));
248         taaf.setResultSize(approvalRows.size());
249     }
250 
251 
252 	
253 	public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form,
254 			HttpServletRequest request, HttpServletResponse response)
255 			throws Exception {
256 		// resets the common fields for approval pages
257 		super.resetMainFields(form);
258 		TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
259 		// KPME-909
260         taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
261 		return loadApprovalTab(mapping, form, request, response);
262 	}
263 	
264     /**
265      * Helper method to modify / manage the list of records needed to display approval data to the user.
266      *
267      * @param taaf
268      * @return
269      */
270     protected List<ApprovalTimeSummaryRow> getApprovalRows(HttpServletRequest request, TimeApprovalActionForm taaf, List<String> assignmentPrincipalIds  ) {
271         List<ApprovalTimeSummaryRow> approvalRows = TkServiceLocator.getTimeApproveService().getApprovalSummaryRows(taaf.getPayBeginDate(), taaf.getPayEndDate(), taaf.getSelectedPayCalendarGroup(), assignmentPrincipalIds, taaf.getPayCalendarLabels(), taaf.getPayCalendarEntries());
272         final String sortField = getSortField(request, taaf);
273         if (StringUtils.isEmpty(sortField) ||
274                 StringUtils.equals(sortField, "name")) {
275             final boolean sortNameAscending = isAscending(request, taaf);
276             Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
277                 @Override
278                 public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
279                     if (sortNameAscending) {
280                         return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName()));
281                     } else {
282                         return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName()));
283                     }
284                 }
285             });
286         } else if (StringUtils.equals(sortField, "documentID")) {
287             final boolean sortDocumentIdAscending = isAscending(request, taaf);
288             Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
289                 @Override
290                 public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
291                     if (sortDocumentIdAscending) {
292                         return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId()));
293                     } else {
294                         return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId()));
295                     }
296                 }
297             });
298         } else if (StringUtils.equals(sortField, "status")) {
299             final boolean sortStatusIdAscending = isAscending(request, taaf);
300             Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
301                 @Override
302                 public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
303                     if (sortStatusIdAscending) {
304                         return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus()));
305                     } else {
306                         return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus()));
307                     }
308                 }
309             });
310         }
311         return approvalRows;
312     }
313 	
314     public void resetState(ActionForm form, HttpServletRequest request) {
315     	  TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
316  	      //String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
317  	      String page = getPage(request, taaf);
318  	      if (StringUtils.isBlank(page)) {
319  			  taaf.getDepartments().clear();
320  			  taaf.getWorkAreaDescr().clear();
321  			  taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
322  			  taaf.setSelectedDept(null);
323  			  taaf.setSearchField(null);
324  			  taaf.setSearchTerm(null);
325  	      }
326 	}
327 	
328     @Override
329     protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) {
330     	TimeApprovalActionForm taaf = (TimeApprovalActionForm)taf;
331 		// set calendar year list
332 		Set<String> yearSet = new HashSet<String>();
333 		SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
334 		// if selected calendar year is passed in
335 		if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) {
336 			taaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
337 		} else {
338 			taaf.setSelectedCalendarYear(sdf.format(taaf.getPayCalendarEntries().getBeginPeriodDate()));
339 		}
340 		
341 		List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>();
342 		List<CalendarEntries> pceList = TkServiceLocator.getTimeApproveService()
343 			.getAllPayCalendarEntriesForApprover(TKContext.getPrincipalId(), TKUtils.getTimelessDate(null));
344 	    for(CalendarEntries pce : pceList) {
345 	    	yearSet.add(sdf.format(pce.getBeginPeriodDate()));
346 	    	if(sdf.format(pce.getBeginPeriodDate()).equals(taaf.getSelectedCalendarYear())) {
347 	    		pcListForYear.add(pce);
348 	    	}
349 	    }
350 	    List<String> yearList = new ArrayList<String>(yearSet);
351 	    Collections.sort(yearList);
352 	    Collections.reverse(yearList);	// newest on top
353 	    taaf.setCalendarYears(yearList);
354 		
355 		// set pay period list contents
356 		if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) {
357 			taaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
358 		} else {
359 			taaf.setSelectedPayPeriod(taaf.getPayCalendarEntries().getHrCalendarEntriesId());
360 			taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear, null));
361 		}
362 		if(taaf.getPayPeriodsMap().isEmpty()) {
363 		    taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear, null));
364 		}
365 	}
366     
367     private List<String> getPrincipalIdsToPopulateTable(TimeApprovalActionForm taf) {
368         if (taf.getPayBeginDate() == null
369                 && taf.getPayEndDate() == null) {
370             return Collections.emptyList();
371         }
372         List<String> workAreaList = new ArrayList<String>();
373         if(StringUtil.isEmpty(taf.getSelectedWorkArea())) {
374         	for(Long aKey : taf.getWorkAreaDescr().keySet()) {
375         		workAreaList.add(aKey.toString());
376         	}
377         } else {
378         	workAreaList.add(taf.getSelectedWorkArea());
379         }
380         java.sql.Date endDate = new java.sql.Date(taf.getPayEndDate().getTime());
381         java.sql.Date beginDate = new java.sql.Date(taf.getPayBeginDate().getTime());
382 
383         List<String> idList = TkServiceLocator.getTimeApproveService()
384         		.getTimePrincipalIdsWithSearchCriteria(workAreaList, taf.getSelectedPayCalendarGroup(), endDate, beginDate, endDate);      
385         return idList;
386 	}	
387 }