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.getTargetPrincipalId(), 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 (TKUser.getApproverWorkAreas().contains(wa.getWorkArea())
126                                    || TKUser.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            TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
177            Date currentDate = null;
178            CalendarEntries payCalendarEntries = null;
179            Calendar currentPayCalendar = null;
180            String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
181            
182            //reset state
183            if(StringUtils.isBlank(taaf.getSelectedDept())){
184                    resetState(form, request);
185            }
186            // Set calendar groups
187            List<String> calGroups = TkServiceLocator.getPrincipalHRAttributeService().getUniqueTimePayGroups();
188            taaf.setPayCalendarGroups(calGroups);
189    
190            if (StringUtils.isBlank(taaf.getSelectedPayCalendarGroup())) {
191                taaf.setSelectedPayCalendarGroup(calGroups.get(0));
192            }
193            
194            // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
195            if (taaf.getHrPyCalendarEntriesId() != null) {
196                    payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
197            } else {
198                currentDate = TKUtils.getTimelessDate(null);
199                currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(taaf.getSelectedPayCalendarGroup());
200                payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate);
201            }
202            taaf.setPayCalendarEntries(payCalendarEntries);
203            
204            
205            if(taaf.getPayCalendarEntries() != null) {
206                    populateCalendarAndPayPeriodLists(request, taaf);
207            }
208            setupDocumentOnFormContext(request,taaf,payCalendarEntries, page);
209            return fwd;
210            }
211    
212            @Override
213            protected void setupDocumentOnFormContext(HttpServletRequest request,ApprovalForm form, CalendarEntries payCalendarEntries, String page) {
214                    super.setupDocumentOnFormContext(request, form, payCalendarEntries, page);
215                    TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
216                    taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
217    
218                    List<String> principalIds = this.getPrincipalIdsToPopulateTable(taaf);
219                    if (principalIds.isEmpty()) {
220                            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
221                            taaf.setResultSize(0);
222                    } else {
223                        List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
224                        List<ApprovalTimeSummaryRow> approvalRows = getApprovalRows(taaf, getSubListPrincipalIds(request, persons));
225                        
226                        final String sortField = request.getParameter("sortField");
227                        if (StringUtils.equals(sortField, "Name")) {
228                                final boolean sortNameAscending = Boolean.parseBoolean(request.getParameter("sortNameAscending"));
229                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
230                                            @Override
231                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
232                                                    if (sortNameAscending) {
233                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName()));
234                                                    } else {
235                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName()));
236                                                    }
237                                            }
238                            });
239                        } else if (StringUtils.equals(sortField, "DocumentID")) {
240                                final boolean sortDocumentIdAscending = Boolean.parseBoolean(request.getParameter("sortDocumentIDAscending"));
241                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
242                                            @Override
243                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
244                                                    if (sortDocumentIdAscending) {
245                                                            return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId()));
246                                                    } else {
247                                                            return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId()));
248                                                    }
249                                            }
250                            });
251                        } else if (StringUtils.equals(sortField, "Status")) {
252                                final boolean sortStatusIdAscending = Boolean.parseBoolean(request.getParameter("sortStatusAscending"));
253                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
254                                            @Override
255                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
256                                                    if (sortStatusIdAscending) {
257                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus()));
258                                                    } else {
259                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus()));
260                                                    }
261                                            }
262                            });
263                        }
264                        
265                        taaf.setApprovalRows(approvalRows);
266                        taaf.setResultSize(persons.size());
267                    }
268                    
269                    taaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(taaf.getPayCalendarEntries()));
270            }
271            
272            public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form,
273                            HttpServletRequest request, HttpServletResponse response)
274                            throws Exception {
275                    // resets the common fields for approval pages
276                    super.resetMainFields(form);
277                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
278                    // KPME-909
279            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
280                    return loadApprovalTab(mapping, form, request, response);
281            }
282            
283        /**
284         * Helper method to modify / manage the list of records needed to display approval data to the user.
285         *
286         * @param taaf
287         * @return
288         */
289        protected List<ApprovalTimeSummaryRow> getApprovalRows(TimeApprovalActionForm taaf, List<TKPerson> assignmentPrincipalIds) {
290            return TkServiceLocator.getTimeApproveService().getApprovalSummaryRows(taaf.getPayBeginDate(), taaf.getPayEndDate(), taaf.getSelectedPayCalendarGroup(), assignmentPrincipalIds, taaf.getPayCalendarLabels(), taaf.getPayCalendarEntries());
291        }
292            
293        public void resetState(ActionForm form, HttpServletRequest request) {
294              TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
295                  String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
296                  
297                  if (StringUtils.isBlank(page)) {
298                              taaf.getDepartments().clear();
299                              taaf.getWorkAreaDescr().clear();
300                              taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
301                              taaf.setSelectedDept(null);
302                              taaf.setSearchField(null);
303                              taaf.setSearchTerm(null);
304                  }
305            }
306            
307        @Override
308        protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) {
309            TimeApprovalActionForm taaf = (TimeApprovalActionForm)taf;
310                    // set calendar year list
311                    Set<String> yearSet = new HashSet<String>();
312                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
313                    // if selected calendar year is passed in
314                    if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) {
315                            taaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
316                    } else {
317                            taaf.setSelectedCalendarYear(sdf.format(taaf.getPayCalendarEntries().getBeginPeriodDate()));
318                    }
319                    
320                    List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>();
321                    List<CalendarEntries> pceList = TkServiceLocator.getTimeApproveService()
322                            .getAllPayCalendarEntriesForApprover(TKContext.getTargetPrincipalId(), TKUtils.getTimelessDate(null));
323                for(CalendarEntries pce : pceList) {
324                    yearSet.add(sdf.format(pce.getBeginPeriodDate()));
325                    if(sdf.format(pce.getBeginPeriodDate()).equals(taaf.getSelectedCalendarYear())) {
326                            pcListForYear.add(pce);
327                    }
328                }
329                List<String> yearList = new ArrayList<String>(yearSet);
330                Collections.sort(yearList);
331                Collections.reverse(yearList);      // newest on top
332                taaf.setCalendarYears(yearList);
333                    
334                    // set pay period list contents
335                    if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) {
336                            taaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
337                    } else {
338                            taaf.setSelectedPayPeriod(taaf.getPayCalendarEntries().getHrCalendarEntriesId());
339                            taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear, null));
340                    }
341                    if(taaf.getPayPeriodsMap().isEmpty()) {
342                        taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear, null));
343                    }
344            }
345        
346        private List<String> getPrincipalIdsToPopulateTable(TimeApprovalActionForm taf) {
347            if (taf.getPayBeginDate() == null
348                    && taf.getPayEndDate() == null) {
349                return Collections.emptyList();
350            }
351            List<String> workAreaList = new ArrayList<String>();
352            if(StringUtil.isEmpty(taf.getSelectedWorkArea())) {
353                    for(Long aKey : taf.getWorkAreaDescr().keySet()) {
354                            workAreaList.add(aKey.toString());
355                    }
356            } else {
357                    workAreaList.add(taf.getSelectedWorkArea());
358            }
359            java.sql.Date endDate = new java.sql.Date(taf.getPayEndDate().getTime());
360            java.sql.Date beginDate = new java.sql.Date(taf.getPayBeginDate().getTime());
361    
362            List<String> idList = TkServiceLocator.getTimeApproveService()
363                            .getTimePrincipalIdsWithSearchCriteria(workAreaList, taf.getSelectedPayCalendarGroup(), endDate, beginDate, endDate);      
364            return idList;
365            }       
366    }