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.lm.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.collections.CollectionUtils;
031    import org.apache.commons.lang.ObjectUtils;
032    import org.apache.commons.lang.StringUtils;
033    import org.apache.commons.lang.math.NumberUtils;
034    import org.apache.struts.action.ActionForm;
035    import org.apache.struts.action.ActionForward;
036    import org.apache.struts.action.ActionMapping;
037    import org.displaytag.tags.TableTagParameters;
038    import org.displaytag.util.ParamEncoder;
039    import org.hsqldb.lib.StringUtil;
040    import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
041    import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
042    import org.kuali.hr.time.approval.web.ApprovalLeaveSummaryRow;
043    import org.kuali.hr.time.assignment.Assignment;
044    import org.kuali.hr.time.base.web.ApprovalAction;
045    import org.kuali.hr.time.base.web.ApprovalForm;
046    import org.kuali.hr.time.calendar.Calendar;
047    import org.kuali.hr.time.calendar.CalendarEntries;
048    import org.kuali.hr.time.detail.web.ActionFormUtils;
049    import org.kuali.hr.time.person.TKPerson;
050    import org.kuali.hr.time.service.base.TkServiceLocator;
051    import org.kuali.hr.time.util.TKContext;
052    import org.kuali.hr.time.util.TKUser;
053    import org.kuali.hr.time.util.TKUtils;
054    import org.kuali.hr.time.util.TkConstants;
055    import org.kuali.hr.time.workarea.WorkArea;
056    
057    public class LeaveApprovalAction extends ApprovalAction{
058            
059            public ActionForward searchResult(ActionMapping mapping, ActionForm form,
060                            HttpServletRequest request, HttpServletResponse response)
061                            throws Exception {
062                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
063                    
064            if (StringUtils.equals("documentId", laaf.getSearchField())) {
065                    LeaveCalendarDocumentHeader lcd = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(laaf.getSearchTerm());
066                    laaf.setSearchTerm(lcd != null ? lcd.getPrincipalId() : StringUtils.EMPTY);
067            }
068            
069            laaf.setSearchField("principalId");
070            List<String> principalIds = new ArrayList<String>();
071            principalIds.add(laaf.getSearchTerm());
072            List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
073            CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
074            if (persons.isEmpty()) {
075                    laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>());
076                    laaf.setResultSize(0);
077            } else {
078                    this.setApprovalTables(laaf, principalIds, request, payCalendarEntries);
079                    
080                    laaf.setPayCalendarEntries(payCalendarEntries);
081                    laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries));
082                    
083                    List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(laaf.getSearchTerm(), payCalendarEntries.getEndPeriodDate());
084                    if(!assignments.isEmpty()){
085                             for(Long wa : laaf.getWorkAreaDescr().keySet()){
086                                    for (Assignment assign : assignments) {
087                                    if (assign.getWorkArea().toString().equals(wa.toString())) {
088                                            laaf.setSelectedWorkArea(wa.toString());
089                                            break;
090                                    }
091                                    }
092                         }
093                    }
094            }
095     
096                    return mapping.findForward("basic");
097            }
098            
099        public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
100            LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form;
101           
102            List<ApprovalLeaveSummaryRow> lstLeaveRows = laaf.getLeaveApprovalRows();
103            for (ApprovalLeaveSummaryRow ar : lstLeaveRows) {
104                if (ar.isApprovable() && StringUtils.equals(ar.getSelected(), "on")) {
105                    String documentNumber = ar.getDocumentId();
106                    LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentNumber);
107                    TkServiceLocator.getLeaveCalendarService().approveLeaveCalendar(TKContext.getPrincipalId(), lcd);
108                }
109            }  
110            
111            return mapping.findForward("basic");
112        }
113            
114            public ActionForward selectNewDept(ActionMapping mapping, ActionForm form,
115                            HttpServletRequest request, HttpServletResponse response)
116                            throws Exception {
117                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
118                    laaf.setSearchField(null);
119                    laaf.setSearchTerm(null);
120    
121            CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
122            laaf.setPayCalendarEntries(payCalendarEntries);
123            laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries));
124    
125                    laaf.getWorkAreaDescr().clear();
126                    laaf.setSelectedWorkArea("");
127            List<WorkArea> workAreas = TkServiceLocator.getWorkAreaService().getWorkAreas(laaf.getSelectedDept(), new java.sql.Date(laaf.getPayBeginDate().getTime()));
128            for(WorkArea wa : workAreas){
129                    if (TKUser.getApproverWorkAreas().contains(wa.getWorkArea())
130                                    || TKUser.getReviewerWorkAreas().contains(wa.getWorkArea())) {
131                            laaf.getWorkAreaDescr().put(wa.getWorkArea(),wa.getDescription()+"("+wa.getWorkArea()+")");
132                    }
133            }
134            
135            List<String> principalIds = this.getPrincipalIdsToPopulateTable(laaf);
136            this.setApprovalTables(laaf, principalIds, request, payCalendarEntries);
137            
138            this.populateCalendarAndPayPeriodLists(request, laaf);
139                    return mapping.findForward("basic");
140            }
141            
142            public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form,
143                            HttpServletRequest request, HttpServletResponse response)
144                            throws Exception {
145                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
146                    laaf.setSearchField(null);
147                    laaf.setSearchTerm(null);
148    
149                CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
150            laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries));
151       
152            List<String> idList = this.getPrincipalIdsToPopulateTable(laaf);
153            this.setApprovalTables(laaf, idList , request, payCalendarEntries);
154            
155                    return mapping.findForward("basic");
156            }       
157    
158            private List<String> getPrincipalIdsToPopulateTable(LeaveApprovalActionForm laaf) {
159            List<String> workAreaList = new ArrayList<String>();
160            if(StringUtil.isEmpty(laaf.getSelectedWorkArea())) {
161                    for(Long aKey : laaf.getWorkAreaDescr().keySet()) {
162                            workAreaList.add(aKey.toString());
163                    }
164            } else {
165                    workAreaList.add(laaf.getSelectedWorkArea());
166            }
167            java.sql.Date endDate = new java.sql.Date(laaf.getPayEndDate().getTime());
168            java.sql.Date beginDate = new java.sql.Date(laaf.getPayBeginDate().getTime());
169    
170            List<String> idList = TkServiceLocator.getLeaveApprovalService()
171                            .getLeavePrincipalIdsWithSearchCriteria(workAreaList, laaf.getSelectedPayCalendarGroup(), endDate, beginDate, endDate);      
172            return idList;
173            }       
174            
175            private void setApprovalTables(LeaveApprovalActionForm laaf, List<String> principalIds, HttpServletRequest request, CalendarEntries payCalendarEntries) {
176                    laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries));
177                    
178                    if (principalIds.isEmpty()) {
179                            laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>());
180                            laaf.setResultSize(0);
181                    } else {
182                            List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds);
183                            List<ApprovalLeaveSummaryRow> approvalRows = getApprovalLeaveRows(laaf, getSubListPrincipalIds(request, persons)); 
184                        
185                            final String sortField = request.getParameter("sortField");                 
186                        if (StringUtils.equals(sortField, "Name")) {
187                                final boolean sortNameAscending = Boolean.parseBoolean(request.getParameter("sortNameAscending"));
188                            Collections.sort(approvalRows, new Comparator<ApprovalLeaveSummaryRow>() {
189                                            @Override
190                                            public int compare(ApprovalLeaveSummaryRow row1, ApprovalLeaveSummaryRow row2) {
191                                                    if (sortNameAscending) {
192                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName()));
193                                                    } else {
194                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName()));
195                                                    }
196                                            }
197                            });
198                        } else if (StringUtils.equals(sortField, "DocumentID")) {
199                                final boolean sortDocumentIdAscending = Boolean.parseBoolean(request.getParameter("sortDocumentIDAscending"));
200                            Collections.sort(approvalRows, new Comparator<ApprovalLeaveSummaryRow>() {
201                                            @Override
202                                            public int compare(ApprovalLeaveSummaryRow row1, ApprovalLeaveSummaryRow row2) {
203                                                    if (sortDocumentIdAscending) {
204                                                            return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId()));
205                                                    } else {
206                                                            return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId()));
207                                                    }
208                                            }
209                            });
210                        } else if (StringUtils.equals(sortField, "Status")) {
211                                final boolean sortStatusIdAscending = Boolean.parseBoolean(request.getParameter("sortStatusAscending"));
212                            Collections.sort(approvalRows, new Comparator<ApprovalLeaveSummaryRow>() {
213                                            @Override
214                                            public int compare(ApprovalLeaveSummaryRow row1, ApprovalLeaveSummaryRow row2) {
215                                                    if (sortStatusIdAscending) {
216                                                            return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus()));
217                                                    } else {
218                                                            return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus()));
219                                                    }
220                                            }
221                            });
222                        }
223                        
224                            laaf.setLeaveApprovalRows(approvalRows);
225                        laaf.setResultSize(persons.size());
226                    }
227            }
228            
229            @Override
230            public ActionForward loadApprovalTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
231                                    throws Exception {
232                    ActionForward fwd = mapping.findForward("basic");
233            LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form;
234            Date currentDate = null;
235            CalendarEntries payCalendarEntries = null;
236            Calendar currentPayCalendar = null;
237            String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
238    
239    
240            //reset state
241            if(StringUtils.isBlank(laaf.getSelectedDept())){
242                    resetState(form, request);
243            }
244    
245            // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
246            if (laaf.getHrPyCalendarEntriesId() != null) {
247                if(payCalendarEntries == null){
248                   payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
249                }
250                currentDate = payCalendarEntries.getEndPeriodDate();
251            } else {
252                currentDate = TKUtils.getTimelessDate(null);
253            }
254            Set<Long> workAreas = TkServiceLocator.getTkRoleService().getWorkAreasForApprover(TKContext.getPrincipalId(), currentDate);
255            // should we use all three roles to find work areas???
256    //        List<String> roleNameList = Arrays.asList(TkConstants.ROLE_TK_APPROVER, TkConstants.ROLE_TK_APPROVER_DELEGATE, TkConstants.ROLE_TK_REVIEWER);
257    //        Set<Long> workAreas = TkServiceLocator.getTkRoleService().getWorkAreasForRoleNames(TKContext.getPrincipalId(), roleNameList, currentDate);
258            
259            List<String> principalIds = new ArrayList<String>();
260            for (Long workArea : workAreas) {
261                List<Assignment> assignments = TkServiceLocator.getAssignmentService().getActiveAssignmentsForWorkArea(workArea, currentDate);
262                for (Assignment a : assignments) {
263                    principalIds.add(a.getPrincipalId());
264                }
265            }
266    
267            // Set calendar groups
268            List<String> calGroups =  new ArrayList<String>();
269            if (CollectionUtils.isNotEmpty(principalIds)) {
270                calGroups = TkServiceLocator.getLeaveApprovalService().getUniqueLeavePayGroupsForPrincipalIds(principalIds);
271            }
272            laaf.setPayCalendarGroups(calGroups);
273    
274            if (StringUtils.isBlank(laaf.getSelectedPayCalendarGroup())
275                    && CollectionUtils.isNotEmpty(calGroups)) {
276                laaf.setSelectedPayCalendarGroup(calGroups.get(0));
277    
278            }
279            
280            // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
281            if (laaf.getHrPyCalendarEntriesId() != null) {
282                payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
283            } else {
284                currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(laaf.getSelectedPayCalendarGroup());
285                if (currentPayCalendar != null) {
286                    payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate);
287                }
288            }
289            laaf.setPayCalendarEntries(payCalendarEntries);
290            
291            
292            if(laaf.getPayCalendarEntries() != null) {
293                    populateCalendarAndPayPeriodLists(request, laaf);
294            }
295            setupDocumentOnFormContext(request,laaf,payCalendarEntries, page);
296            return fwd;
297            }
298    
299            @Override
300            protected void setupDocumentOnFormContext(HttpServletRequest request,ApprovalForm form, CalendarEntries payCalendarEntries, String page) {
301                    super.setupDocumentOnFormContext(request, form, payCalendarEntries, page);
302                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
303    
304            if (payCalendarEntries != null) {
305                        laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries));         
306                        List<String> principalIds = this.getPrincipalIdsToPopulateTable(laaf); 
307                this.setApprovalTables(laaf, principalIds, request, payCalendarEntries);
308                laaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(laaf.getPayCalendarEntries()));
309            }
310            }
311            
312            public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form,
313                            HttpServletRequest request, HttpServletResponse response)
314                            throws Exception {
315                    // resets the common fields for approval pages
316                    super.resetMainFields(form);
317                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
318            // KPME-909
319            laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>());
320                    
321                    return loadApprovalTab(mapping, form, request, response);
322            }
323               
324        protected List<ApprovalLeaveSummaryRow> getApprovalLeaveRows(LeaveApprovalActionForm laaf, List<TKPerson> assignmentPrincipalIds) {
325            return TkServiceLocator.getLeaveApprovalService().getLeaveApprovalSummaryRows
326                    (assignmentPrincipalIds, laaf.getPayCalendarEntries(), laaf.getLeaveCalendarDates());
327        }
328            
329        public void resetState(ActionForm form, HttpServletRequest request) {
330              LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form;
331                  String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
332                  
333                  if (StringUtils.isBlank(page)) {
334                              laaf.getDepartments().clear();
335                              laaf.getWorkAreaDescr().clear();
336                              laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>());
337                              laaf.setSelectedDept(null);
338                              laaf.setSearchField(null);
339                              laaf.setSearchTerm(null);
340                  }
341            }
342        
343        @Override
344        protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) {
345             LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) taf;
346                    // set calendar year list
347                    Set<String> yearSet = new HashSet<String>();
348                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
349                    // if selected calendar year is passed in
350                    if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) {
351                            laaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
352                    } else {
353                            laaf.setSelectedCalendarYear(sdf.format(laaf.getPayCalendarEntries().getBeginPeriodDate()));
354                    }
355                    
356                    List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>();
357                    List<CalendarEntries> pceList =  new ArrayList<CalendarEntries>();
358                    pceList.addAll(TkServiceLocator.getLeaveApprovalService()
359                            .getAllLeavePayCalendarEntriesForApprover(TKContext.getPrincipalId(), TKUtils.getTimelessDate(null)));
360                    
361                for(CalendarEntries pce : pceList) {
362                    yearSet.add(sdf.format(pce.getBeginPeriodDate()));
363                    if(sdf.format(pce.getBeginPeriodDate()).equals(laaf.getSelectedCalendarYear())) {
364                            pcListForYear.add(pce);
365                    }
366                }
367                List<String> yearList = new ArrayList<String>(yearSet);
368                Collections.sort(yearList);
369                Collections.reverse(yearList);      // newest on top
370                laaf.setCalendarYears(yearList);
371                    
372                    // set pay period list contents
373                    if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) {
374                            laaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
375                    } else {
376                            laaf.setSelectedPayPeriod(laaf.getPayCalendarEntries().getHrCalendarEntriesId());
377                            laaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear, null));
378                    }
379                    if(laaf.getPayPeriodsMap().isEmpty()) {
380                        laaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear, null));
381                    }
382            }
383    
384    }