001    /**
002     * Copyright 2004-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.hr.time.approval.web;
017    
018    import java.sql.Date;
019    import java.text.SimpleDateFormat;
020    import java.util.ArrayList;
021    import java.util.Collections;
022    import java.util.Comparator;
023    import java.util.HashSet;
024    import java.util.List;
025    import java.util.Set;
026    
027    import javax.servlet.http.HttpServletRequest;
028    import javax.servlet.http.HttpServletResponse;
029    
030    import org.apache.commons.lang.ObjectUtils;
031    import org.apache.commons.lang.StringUtils;
032    import org.apache.commons.lang.math.NumberUtils;
033    import org.apache.struts.action.ActionForm;
034    import org.apache.struts.action.ActionForward;
035    import org.apache.struts.action.ActionMapping;
036    import org.displaytag.tags.TableTagParameters;
037    import org.displaytag.util.ParamEncoder;
038    import org.hsqldb.lib.StringUtil;
039    import org.kuali.hr.time.assignment.Assignment;
040    import org.kuali.hr.time.base.web.ApprovalAction;
041    import org.kuali.hr.time.base.web.ApprovalForm;
042    import org.kuali.hr.time.calendar.Calendar;
043    import org.kuali.hr.time.calendar.CalendarEntries;
044    import org.kuali.hr.time.detail.web.ActionFormUtils;
045    import org.kuali.hr.time.person.TKPerson;
046    import org.kuali.hr.time.service.base.TkServiceLocator;
047    import org.kuali.hr.time.timesheet.TimesheetDocument;
048    import org.kuali.hr.time.util.TKContext;
049    import org.kuali.hr.time.util.TKUser;
050    import org.kuali.hr.time.util.TKUtils;
051    import org.kuali.hr.time.util.TkConstants;
052    import org.kuali.hr.time.workarea.WorkArea;
053    import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
054    
055    public class TimeApprovalAction extends ApprovalAction{
056            
057            public ActionForward searchResult(ActionMapping mapping, ActionForm form,
058                            HttpServletRequest request, HttpServletResponse response)
059                            throws Exception {
060                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
061                    
062            if (StringUtils.equals("documentId", taaf.getSearchField())) {
063                    TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(taaf.getSearchTerm());
064                    taaf.setSearchTerm(tdh != null ? tdh.getPrincipalId() : StringUtils.EMPTY);
065            }
066            
067            taaf.setSearchField("principalId");
068            List<String> principalIds = new ArrayList<String>();
069            principalIds.add(taaf.getSearchTerm());
070            List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
071            if (persons.isEmpty()) {
072                    taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
073                    taaf.setResultSize(0);
074            } else {
075                    taaf.setResultSize(persons.size());     
076                    taaf.setApprovalRows(getApprovalRows(taaf, persons));
077                    
078                    CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
079                    taaf.setPayCalendarEntries(payCalendarEntries);
080                    taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
081                    
082                    List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(taaf.getSearchTerm(), payCalendarEntries.getEndPeriodDate());
083                    if(!assignments.isEmpty()){
084                             for(Long wa : taaf.getWorkAreaDescr().keySet()){
085                                    for (Assignment assign : assignments) {
086                                    if (assign.getWorkArea().toString().equals(wa.toString())) {
087                                            taaf.setSelectedWorkArea(wa.toString());
088                                            break;
089                                    }
090                                    }
091                         }
092                    }
093            }
094     
095                    return mapping.findForward("basic");
096            }
097            
098        public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
099            TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
100            List<ApprovalTimeSummaryRow> lstApprovalRows = taaf.getApprovalRows();
101            for (ApprovalTimeSummaryRow ar : lstApprovalRows) {
102                if (ar.isApprovable() && StringUtils.equals(ar.getSelected(), "on")) {
103                    String documentNumber = ar.getDocumentId();
104                    TimesheetDocument tDoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentNumber);
105                    TkServiceLocator.getTimesheetService().approveTimesheet(TKContext.getPrincipalId(), tDoc);
106                }
107            }
108            return mapping.findForward("basic");
109        }
110        
111            public ActionForward selectNewDept(ActionMapping mapping, ActionForm form,
112                            HttpServletRequest request, HttpServletResponse response)
113                            throws Exception {
114                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
115                    taaf.setSearchField(null);
116                    taaf.setSearchTerm(null);
117    
118            CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
119            taaf.setPayCalendarEntries(payCalendarEntries);
120            taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
121    
122                    taaf.getWorkAreaDescr().clear();
123            List<WorkArea> workAreas = TkServiceLocator.getWorkAreaService().getWorkAreas(taaf.getSelectedDept(), new java.sql.Date(taaf.getPayBeginDate().getTime()));
124            for(WorkArea wa : workAreas){
125                    if (TKContext.getUser().getApproverWorkAreas().contains(wa.getWorkArea())
126                                    || TKContext.getUser().getReviewerWorkAreas().contains(wa.getWorkArea())) {
127                            taaf.getWorkAreaDescr().put(wa.getWorkArea(),wa.getDescription()+"("+wa.getWorkArea()+")");
128                    }
129            }
130    
131            List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf); 
132            if (principalIds.isEmpty()) {
133                    taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
134                    taaf.setResultSize(0);
135            }
136            else {
137                    List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
138                    Collections.sort(persons);
139                    taaf.setApprovalRows(getApprovalRows(taaf, getSubListPrincipalIds(request, persons)));
140                    taaf.setResultSize(persons.size());
141            }
142            
143            this.populateCalendarAndPayPeriodLists(request, taaf);
144                    return mapping.findForward("basic");
145            }
146            
147            public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form,
148                            HttpServletRequest request, HttpServletResponse response)
149                            throws Exception {
150                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
151                    taaf.setSearchField(null);
152                    taaf.setSearchTerm(null);
153    
154                CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
155            taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
156            
157            List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf); 
158                    if (principalIds.isEmpty()) {
159                            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
160                            taaf.setResultSize(0);
161                    }
162                    else {
163                    List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
164                    Collections.sort(persons);
165                    taaf.setApprovalRows(getApprovalRows(taaf, getSubListPrincipalIds(request, persons)));
166                    taaf.setResultSize(persons.size());
167                    }
168                    return mapping.findForward("basic");
169            }
170            
171            @Override
172            public ActionForward loadApprovalTab(ActionMapping mapping, ActionForm form,
173            HttpServletRequest request, HttpServletResponse response)
174                                    throws Exception {
175                    ActionForward fwd = mapping.findForward("basic");
176                    TKUser user = TKContext.getUser();
177            TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
178            Date currentDate = null;
179            CalendarEntries payCalendarEntries = null;
180            Calendar currentPayCalendar = null;
181            String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
182            
183            //reset state
184            if(StringUtils.isBlank(taaf.getSelectedDept())){
185                    resetState(form, request);
186            }
187            // Set calendar groups
188            List<String> calGroups = TkServiceLocator.getPrincipalHRAttributeService().getUniqueTimePayGroups();
189            taaf.setPayCalendarGroups(calGroups);
190    
191            if (StringUtils.isBlank(taaf.getSelectedPayCalendarGroup())) {
192                taaf.setSelectedPayCalendarGroup(calGroups.get(0));
193            }
194            
195            // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
196            if (taaf.getHrPyCalendarEntriesId() != null) {
197                    payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
198                currentDate = payCalendarEntries.getEndPeriodDate();
199            } else {
200                currentDate = TKUtils.getTimelessDate(null);
201                currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(taaf.getSelectedPayCalendarGroup());
202                payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate);
203            }
204            taaf.setPayCalendarEntries(payCalendarEntries);
205            
206            
207            if(taaf.getPayCalendarEntries() != null) {
208                    populateCalendarAndPayPeriodLists(request, taaf);
209            }
210            setupDocumentOnFormContext(request,taaf,payCalendarEntries, page);
211            return fwd;
212            }
213    
214            @Override
215            protected void setupDocumentOnFormContext(HttpServletRequest request,ApprovalForm form, CalendarEntries payCalendarEntries, String page) {
216                    super.setupDocumentOnFormContext(request, form, payCalendarEntries, page);
217                    TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
218                    taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
219    
220                    List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf);
221                    if (principalIds.isEmpty()) {
222                            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
223                            taaf.setResultSize(0);
224                    } else {
225                        List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
226                        List<ApprovalTimeSummaryRow> approvalRows = getApprovalRows(taaf, getSubListPrincipalIds(request, persons));
227                        
228                        final String sortField = request.getParameter("sortField");
229                        if (StringUtils.equals(sortField, "Name")) {
230                                final boolean sortNameAscending = Boolean.parseBoolean(request.getParameter("sortNameAscending"));
231                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
232                                            @Override
233                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
234                                                    if (sortNameAscending) {
235                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName()));
236                                                    } else {
237                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName()));
238                                                    }
239                                            }
240                            });
241                        } else if (StringUtils.equals(sortField, "DocumentID")) {
242                                final boolean sortDocumentIdAscending = Boolean.parseBoolean(request.getParameter("sortDocumentIDAscending"));
243                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
244                                            @Override
245                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
246                                                    if (sortDocumentIdAscending) {
247                                                            return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId()));
248                                                    } else {
249                                                            return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId()));
250                                                    }
251                                            }
252                            });
253                        } else if (StringUtils.equals(sortField, "Status")) {
254                                final boolean sortStatusIdAscending = Boolean.parseBoolean(request.getParameter("sortStatusAscending"));
255                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
256                                            @Override
257                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
258                                                    if (sortStatusIdAscending) {
259                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus()));
260                                                    } else {
261                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus()));
262                                                    }
263                                            }
264                            });
265                        }
266                        
267                        taaf.setApprovalRows(approvalRows);
268                        taaf.setResultSize(persons.size());
269                    }
270                    
271                    taaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(taaf.getPayCalendarEntries()));
272            }
273            
274            public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form,
275                            HttpServletRequest request, HttpServletResponse response)
276                            throws Exception {
277                    // resets the common fields for approval pages
278                    super.resetMainFields(form);
279                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
280                    // KPME-909
281            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
282                    return loadApprovalTab(mapping, form, request, response);
283            }
284            
285        /**
286         * Helper method to modify / manage the list of records needed to display approval data to the user.
287         *
288         * @param taaf
289         * @return
290         */
291        protected List<ApprovalTimeSummaryRow> getApprovalRows(TimeApprovalActionForm taaf, List<TKPerson> assignmentPrincipalIds) {
292            return TkServiceLocator.getTimeApproveService().getApprovalSummaryRows(taaf.getPayBeginDate(), taaf.getPayEndDate(), taaf.getSelectedPayCalendarGroup(), assignmentPrincipalIds, taaf.getPayCalendarLabels(), taaf.getPayCalendarEntries());
293        }
294            
295        public void resetState(ActionForm form, HttpServletRequest request) {
296              TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
297                  String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
298                  
299                  if (StringUtils.isBlank(page)) {
300                              taaf.getDepartments().clear();
301                              taaf.getWorkAreaDescr().clear();
302                              taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
303                              taaf.setSelectedDept(null);
304                              taaf.setSearchField(null);
305                              taaf.setSearchTerm(null);
306                  }
307            }
308            
309        @Override
310        protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) {
311            TimeApprovalActionForm taaf = (TimeApprovalActionForm)taf;
312                    // set calendar year list
313                    Set<String> yearSet = new HashSet<String>();
314                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
315                    // if selected calendar year is passed in
316                    if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) {
317                            taaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
318                    } else {
319                            taaf.setSelectedCalendarYear(sdf.format(taaf.getPayCalendarEntries().getBeginPeriodDate()));
320                    }
321                    
322                    List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>();
323                    List<CalendarEntries> pceList = TkServiceLocator.getTimeApproveService()
324                            .getAllPayCalendarEntriesForApprover(TKContext.getPrincipalId(), TKUtils.getTimelessDate(null));
325                for(CalendarEntries pce : pceList) {
326                    yearSet.add(sdf.format(pce.getBeginPeriodDate()));
327                    if(sdf.format(pce.getBeginPeriodDate()).equals(taaf.getSelectedCalendarYear())) {
328                            pcListForYear.add(pce);
329                    }
330                }
331                List<String> yearList = new ArrayList<String>(yearSet);
332                Collections.sort(yearList);
333                Collections.reverse(yearList);      // newest on top
334                taaf.setCalendarYears(yearList);
335                    
336                    // set pay period list contents
337                    if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) {
338                            taaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
339                    } else {
340                            taaf.setSelectedPayPeriod(taaf.getPayCalendarEntries().getHrCalendarEntriesId());
341                            taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear));
342                    }
343                    if(taaf.getPayPeriodsMap().isEmpty()) {
344                        taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear));
345                    }
346            }
347        
348        private List<String> getPrincipalIdsToPopulateTable(TimeApprovalActionForm taf) {
349            List<String> workAreaList = new ArrayList<String>();
350            if(StringUtil.isEmpty(taf.getSelectedWorkArea())) {
351                    for(Long aKey : taf.getWorkAreaDescr().keySet()) {
352                            workAreaList.add(aKey.toString());
353                    }
354            } else {
355                    workAreaList.add(taf.getSelectedWorkArea());
356            }
357            java.sql.Date endDate = new java.sql.Date(taf.getPayEndDate().getTime());
358            java.sql.Date beginDate = new java.sql.Date(taf.getPayBeginDate().getTime());
359    
360            List<String> idList = TkServiceLocator.getTimeApproveService()
361                            .getTimePrincipalIdsWithSearchCriteria(workAreaList, taf.getSelectedPayCalendarGroup(), endDate, beginDate, endDate);      
362            return idList;
363            }       
364    }