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 (TKContext.getUser().getApproverWorkAreas().contains(wa.getWorkArea())
130                                    || TKContext.getUser().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                    TKUser user = TKContext.getUser();
234            LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form;
235            Date currentDate = null;
236            CalendarEntries payCalendarEntries = null;
237            Calendar currentPayCalendar = null;
238            String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
239    
240    
241            //reset state
242            if(StringUtils.isBlank(laaf.getSelectedDept())){
243                    resetState(form, request);
244            }
245    
246            // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
247            if (laaf.getHrPyCalendarEntriesId() != null) {
248                if(payCalendarEntries == null){
249                   payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
250                }
251                currentDate = payCalendarEntries.getEndPeriodDate();
252            } else {
253                currentDate = TKUtils.getTimelessDate(null);
254            }
255            Set<Long> workAreas = TkServiceLocator.getTkRoleService().getWorkAreasForApprover(TKContext.getPrincipalId(), currentDate);
256            // should we use all three roles to find work areas???
257    //        List<String> roleNameList = Arrays.asList(TkConstants.ROLE_TK_APPROVER, TkConstants.ROLE_TK_APPROVER_DELEGATE, TkConstants.ROLE_TK_REVIEWER);
258    //        Set<Long> workAreas = TkServiceLocator.getTkRoleService().getWorkAreasForRoleNames(TKContext.getPrincipalId(), roleNameList, currentDate);
259            
260            List<String> principalIds = new ArrayList<String>();
261            for (Long workArea : workAreas) {
262                List<Assignment> assignments = TkServiceLocator.getAssignmentService().getActiveAssignmentsForWorkArea(workArea, currentDate);
263                for (Assignment a : assignments) {
264                    principalIds.add(a.getPrincipalId());
265                }
266            }
267    
268            // Set calendar groups
269            List<String> calGroups =  new ArrayList<String>();
270            if (CollectionUtils.isNotEmpty(principalIds)) {
271                calGroups = TkServiceLocator.getLeaveApprovalService().getUniqueLeavePayGroupsForPrincipalIds(principalIds);
272            }
273            laaf.setPayCalendarGroups(calGroups);
274    
275            if (StringUtils.isBlank(laaf.getSelectedPayCalendarGroup())
276                    && CollectionUtils.isNotEmpty(calGroups)) {
277                laaf.setSelectedPayCalendarGroup(calGroups.get(0));
278    
279            }
280            
281            // Set current pay calendar entries if present. Decide if the current date should be today or the end period date
282            if (laaf.getHrPyCalendarEntriesId() != null) {
283                payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId());
284            } else {
285                currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(laaf.getSelectedPayCalendarGroup());
286                if (currentPayCalendar != null) {
287                    payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate);
288                }
289            }
290            laaf.setPayCalendarEntries(payCalendarEntries);
291            
292            
293            if(laaf.getPayCalendarEntries() != null) {
294                    populateCalendarAndPayPeriodLists(request, laaf);
295            }
296            setupDocumentOnFormContext(request,laaf,payCalendarEntries, page);
297            return fwd;
298            }
299    
300            @Override
301            protected void setupDocumentOnFormContext(HttpServletRequest request,ApprovalForm form, CalendarEntries payCalendarEntries, String page) {
302                    super.setupDocumentOnFormContext(request, form, payCalendarEntries, page);
303                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
304    
305            if (payCalendarEntries != null) {
306                        laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries));         
307                        List<String> principalIds = this.getPrincipalIdsToPopulateTable(laaf); 
308                this.setApprovalTables(laaf, principalIds, request, payCalendarEntries);
309                laaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(laaf.getPayCalendarEntries()));
310            }
311            }
312            
313            public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form,
314                            HttpServletRequest request, HttpServletResponse response)
315                            throws Exception {
316                    // resets the common fields for approval pages
317                    super.resetMainFields(form);
318                    LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form;
319            // KPME-909
320            laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>());
321                    
322                    return loadApprovalTab(mapping, form, request, response);
323            }
324               
325        protected List<ApprovalLeaveSummaryRow> getApprovalLeaveRows(LeaveApprovalActionForm laaf, List<TKPerson> assignmentPrincipalIds) {
326            return TkServiceLocator.getLeaveApprovalService().getLeaveApprovalSummaryRows
327                    (assignmentPrincipalIds, laaf.getPayCalendarEntries(), laaf.getLeaveCalendarDates());
328        }
329            
330        public void resetState(ActionForm form, HttpServletRequest request) {
331              LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form;
332                  String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
333                  
334                  if (StringUtils.isBlank(page)) {
335                              laaf.getDepartments().clear();
336                              laaf.getWorkAreaDescr().clear();
337                              laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>());
338                              laaf.setSelectedDept(null);
339                              laaf.setSearchField(null);
340                              laaf.setSearchTerm(null);
341                  }
342            }
343        
344        @Override
345        protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) {
346             LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) taf;
347                    // set calendar year list
348                    Set<String> yearSet = new HashSet<String>();
349                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
350                    // if selected calendar year is passed in
351                    if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) {
352                            laaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
353                    } else {
354                            laaf.setSelectedCalendarYear(sdf.format(laaf.getPayCalendarEntries().getBeginPeriodDate()));
355                    }
356                    
357                    List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>();
358                    List<CalendarEntries> pceList =  new ArrayList<CalendarEntries>();
359                    pceList.addAll(TkServiceLocator.getLeaveApprovalService()
360                            .getAllLeavePayCalendarEntriesForApprover(TKContext.getPrincipalId(), TKUtils.getTimelessDate(null)));
361                    
362                for(CalendarEntries pce : pceList) {
363                    yearSet.add(sdf.format(pce.getBeginPeriodDate()));
364                    if(sdf.format(pce.getBeginPeriodDate()).equals(laaf.getSelectedCalendarYear())) {
365                            pcListForYear.add(pce);
366                    }
367                }
368                List<String> yearList = new ArrayList<String>(yearSet);
369                Collections.sort(yearList);
370                Collections.reverse(yearList);      // newest on top
371                laaf.setCalendarYears(yearList);
372                    
373                    // set pay period list contents
374                    if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) {
375                            laaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
376                    } else {
377                            laaf.setSelectedPayPeriod(laaf.getPayCalendarEntries().getHrCalendarEntriesId());
378                            laaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear));
379                    }
380                    if(laaf.getPayPeriodsMap().isEmpty()) {
381                        laaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear));
382                    }
383            }
384    
385    }