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.kuali.hr.time.assignment.Assignment;
039    import org.kuali.hr.time.base.web.ApprovalAction;
040    import org.kuali.hr.time.base.web.ApprovalForm;
041    import org.kuali.hr.time.calendar.Calendar;
042    import org.kuali.hr.time.calendar.CalendarEntries;
043    import org.kuali.hr.time.detail.web.ActionFormUtils;
044    import org.kuali.hr.time.person.TKPerson;
045    import org.kuali.hr.time.service.base.TkServiceLocator;
046    import org.kuali.hr.time.timesheet.TimesheetDocument;
047    import org.kuali.hr.time.util.TKContext;
048    import org.kuali.hr.time.util.TKUser;
049    import org.kuali.hr.time.util.TKUtils;
050    import org.kuali.hr.time.util.TkConstants;
051    import org.kuali.hr.time.workarea.WorkArea;
052    import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
053    
054    public class TimeApprovalAction extends ApprovalAction{
055            
056            public ActionForward searchResult(ActionMapping mapping, ActionForm form,
057                            HttpServletRequest request, HttpServletResponse response)
058                            throws Exception {
059                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
060                    
061            if (StringUtils.equals("documentId", taaf.getSearchField())) {
062                    TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(taaf.getSearchTerm());
063                    taaf.setSearchTerm(tdh != null ? tdh.getPrincipalId() : StringUtils.EMPTY);
064            }
065            
066            taaf.setSearchField("principalId");
067            List<String> principalIds = new ArrayList<String>();
068            principalIds.add(taaf.getSearchTerm());
069            List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
070            if (persons.isEmpty()) {
071                    taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
072                    taaf.setResultSize(0);
073            } else {
074                    taaf.setResultSize(persons.size());     
075                    taaf.setApprovalRows(getApprovalRows(taaf, persons));
076                    
077                    CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
078                    taaf.setPayCalendarEntries(payCalendarEntries);
079                    taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
080                    
081                    List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(taaf.getSearchTerm(), payCalendarEntries.getEndPeriodDate());
082                    if(!assignments.isEmpty()){
083                             for(Long wa : taaf.getWorkAreaDescr().keySet()){
084                                    for (Assignment assign : assignments) {
085                                    if (assign.getWorkArea().toString().equals(wa.toString())) {
086                                            taaf.setSelectedWorkArea(wa.toString());
087                                            break;
088                                    }
089                                    }
090                         }
091                    }
092            }
093     
094                    return mapping.findForward("basic");
095            }
096            
097        public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
098            TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
099            List<ApprovalTimeSummaryRow> lstApprovalRows = taaf.getApprovalRows();
100            for (ApprovalTimeSummaryRow ar : lstApprovalRows) {
101                if (ar.isApprovable() && StringUtils.equals(ar.getSelected(), "on")) {
102                    String documentNumber = ar.getDocumentId();
103                    TimesheetDocument tDoc = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentNumber);
104                    TkServiceLocator.getTimesheetService().approveTimesheet(TKContext.getPrincipalId(), tDoc);
105                }
106            }
107            return mapping.findForward("basic");
108        }
109        
110            public ActionForward selectNewDept(ActionMapping mapping, ActionForm form,
111                            HttpServletRequest request, HttpServletResponse response)
112                            throws Exception {
113                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
114                    taaf.setSearchField(null);
115                    taaf.setSearchTerm(null);
116    
117            CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
118            taaf.setPayCalendarEntries(payCalendarEntries);
119            taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
120    
121                    taaf.getWorkAreaDescr().clear();
122            List<WorkArea> workAreas = TkServiceLocator.getWorkAreaService().getWorkAreas(taaf.getSelectedDept(), new java.sql.Date(taaf.getPayBeginDate().getTime()));
123            for(WorkArea wa : workAreas){
124                    if (TKContext.getUser().getApproverWorkAreas().contains(wa.getWorkArea())
125                                    || TKContext.getUser().getReviewerWorkAreas().contains(wa.getWorkArea())) {
126                            taaf.getWorkAreaDescr().put(wa.getWorkArea(),wa.getDescription()+"("+wa.getWorkArea()+")");
127                    }
128            }
129            
130            List<String> principalIds = TkServiceLocator.getTimeApproveService().getPrincipalIdsByDeptWorkAreaRolename(taaf.getRoleName(), taaf.getSelectedDept(), taaf.getSelectedWorkArea(), new java.sql.Date(taaf.getPayBeginDate().getTime()), new java.sql.Date(taaf.getPayEndDate().getTime()), taaf.getSelectedPayCalendarGroup());
131            if (principalIds.isEmpty()) {
132                    taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
133                    taaf.setResultSize(0);
134            }
135            else {
136                    List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
137                    Collections.sort(persons);
138                    taaf.setApprovalRows(getApprovalRows(taaf, getSubListPrincipalIds(request, persons)));
139                    taaf.setResultSize(persons.size());
140            }
141            
142            this.populateCalendarAndPayPeriodLists(request, taaf);
143                    return mapping.findForward("basic");
144            }
145            
146            public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form,
147                            HttpServletRequest request, HttpServletResponse response)
148                            throws Exception {
149                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
150                    taaf.setSearchField(null);
151                    taaf.setSearchTerm(null);
152    
153                CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(taaf.getHrPyCalendarEntriesId());
154            taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
155            
156            List<String> principalIds = TkServiceLocator.getTimeApproveService().getPrincipalIdsByDeptWorkAreaRolename(taaf.getRoleName(), taaf.getSelectedDept(), taaf.getSelectedWorkArea(), new java.sql.Date(taaf.getPayBeginDate().getTime()), new java.sql.Date(taaf.getPayEndDate().getTime()), taaf.getSelectedPayCalendarGroup());
157                    if (principalIds.isEmpty()) {
158                            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
159                            taaf.setResultSize(0);
160                    }
161                    else {
162                    List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
163                    Collections.sort(persons);
164                    taaf.setApprovalRows(getApprovalRows(taaf, getSubListPrincipalIds(request, persons)));
165                    taaf.setResultSize(persons.size());
166                    }
167                    return mapping.findForward("basic");
168            }
169            
170            @Override
171            public ActionForward loadApprovalTab(ActionMapping mapping, ActionForm form,
172            HttpServletRequest request, HttpServletResponse response)
173                                    throws Exception {
174                    ActionForward fwd = mapping.findForward("basic");
175                    TKUser user = TKContext.getUser();
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.getTimeApproveService().getUniquePayGroups();
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                currentDate = payCalendarEntries.getEndPeriodDate();
198            } else {
199                currentDate = TKUtils.getTimelessDate(null);
200                currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(taaf.getSelectedPayCalendarGroup());
201                payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate);
202            }
203            taaf.setPayCalendarEntries(payCalendarEntries);
204            
205            
206            if(taaf.getPayCalendarEntries() != null) {
207                    populateCalendarAndPayPeriodLists(request, taaf);
208            }
209            setupDocumentOnFormContext(request,taaf,payCalendarEntries, page);
210            return fwd;
211            }
212    
213            @Override
214            protected void setupDocumentOnFormContext(HttpServletRequest request,ApprovalForm form, CalendarEntries payCalendarEntries, String page) {
215                    super.setupDocumentOnFormContext(request, form, payCalendarEntries, page);
216                    TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
217                    taaf.setPayCalendarLabels(TkServiceLocator.getTimeSummaryService().getHeaderForSummary(payCalendarEntries, new ArrayList<Boolean>()));
218                    
219                    List<String> principalIds = TkServiceLocator.getTimeApproveService().getPrincipalIdsByDeptWorkAreaRolename(taaf.getRoleName(), taaf.getSelectedDept(), taaf.getSelectedWorkArea(), new java.sql.Date(taaf.getPayBeginDate().getTime()), new java.sql.Date(taaf.getPayEndDate().getTime()), taaf.getSelectedPayCalendarGroup());
220                    if (principalIds.isEmpty()) {
221                            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
222                            taaf.setResultSize(0);
223                    } else {
224                        List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
225                        List<ApprovalTimeSummaryRow> approvalRows = getApprovalRows(taaf, getSubListPrincipalIds(request, persons));
226                        
227                        final String sortField = request.getParameter("sortField");
228                        if (StringUtils.equals(sortField, "Name")) {
229                                final boolean sortNameAscending = Boolean.parseBoolean(request.getParameter("sortNameAscending"));
230                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
231                                            @Override
232                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
233                                                    if (sortNameAscending) {
234                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName()));
235                                                    } else {
236                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName()));
237                                                    }
238                                            }
239                            });
240                        } else if (StringUtils.equals(sortField, "DocumentID")) {
241                                final boolean sortDocumentIdAscending = Boolean.parseBoolean(request.getParameter("sortDocumentIDAscending"));
242                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
243                                            @Override
244                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
245                                                    if (sortDocumentIdAscending) {
246                                                            return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId()));
247                                                    } else {
248                                                            return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId()));
249                                                    }
250                                            }
251                            });
252                        } else if (StringUtils.equals(sortField, "Status")) {
253                                final boolean sortStatusIdAscending = Boolean.parseBoolean(request.getParameter("sortStatusAscending"));
254                            Collections.sort(approvalRows, new Comparator<ApprovalTimeSummaryRow>() {
255                                            @Override
256                                            public int compare(ApprovalTimeSummaryRow row1, ApprovalTimeSummaryRow row2) {
257                                                    if (sortStatusIdAscending) {
258                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus()));
259                                                    } else {
260                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus()));
261                                                    }
262                                            }
263                            });
264                        }
265                        
266                        taaf.setApprovalRows(approvalRows);
267                        taaf.setResultSize(persons.size());
268                    }
269                    
270                    taaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(taaf.getPayCalendarEntries()));
271            }
272            
273            public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form,
274                            HttpServletRequest request, HttpServletResponse response)
275                            throws Exception {
276                    // resets the common fields for approval pages
277                    super.resetMainFields(form);
278                    TimeApprovalActionForm taaf = (TimeApprovalActionForm)form;
279                    // KPME-909
280            taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
281                    return loadApprovalTab(mapping, form, request, response);
282            }
283            
284        /**
285         * Helper method to modify / manage the list of records needed to display approval data to the user.
286         *
287         * @param taaf
288         * @return
289         */
290        protected List<ApprovalTimeSummaryRow> getApprovalRows(TimeApprovalActionForm taaf, List<TKPerson> assignmentPrincipalIds) {
291            return TkServiceLocator.getTimeApproveService().getApprovalSummaryRows(taaf.getPayBeginDate(), taaf.getPayEndDate(), taaf.getSelectedPayCalendarGroup(), assignmentPrincipalIds, taaf.getPayCalendarLabels(), taaf.getPayCalendarEntries());
292        }
293            
294        public void resetState(ActionForm form, HttpServletRequest request) {
295              TimeApprovalActionForm taaf = (TimeApprovalActionForm) form;
296                  String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
297                  
298                  if (StringUtils.isBlank(page)) {
299                              taaf.getDepartments().clear();
300                              taaf.getWorkAreaDescr().clear();
301                              taaf.setApprovalRows(new ArrayList<ApprovalTimeSummaryRow>());
302                              taaf.setSelectedDept(null);
303                              taaf.setSearchField(null);
304                              taaf.setSearchTerm(null);
305                  }
306            }
307            
308        @Override
309        protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) {
310            TimeApprovalActionForm taaf = (TimeApprovalActionForm)taf;
311                    // set calendar year list
312                    Set<String> yearSet = new HashSet<String>();
313                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
314                    // if selected calendar year is passed in
315                    if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) {
316                            taaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
317                    } else {
318                            taaf.setSelectedCalendarYear(sdf.format(taaf.getPayCalendarEntries().getBeginPeriodDate()));
319                    }
320                    
321                    List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>();
322                    List<CalendarEntries> pceList = TkServiceLocator.getTimeApproveService()
323                            .getAllPayCalendarEntriesForApprover(TKContext.getPrincipalId(), TKUtils.getTimelessDate(null));
324                for(CalendarEntries pce : pceList) {
325                    yearSet.add(sdf.format(pce.getBeginPeriodDate()));
326                    if(sdf.format(pce.getBeginPeriodDate()).equals(taaf.getSelectedCalendarYear())) {
327                            pcListForYear.add(pce);
328                    }
329                }
330                List<String> yearList = new ArrayList<String>(yearSet);
331                Collections.sort(yearList);
332                Collections.reverse(yearList);      // newest on top
333                taaf.setCalendarYears(yearList);
334                    
335                    // set pay period list contents
336                    if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) {
337                            taaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
338                    } else {
339                            taaf.setSelectedPayPeriod(taaf.getPayCalendarEntries().getHrCalendarEntriesId());
340                            taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear));
341                    }
342                    if(taaf.getPayPeriodsMap().isEmpty()) {
343                        taaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear));
344                    }
345            }
346    }