View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.time.detail.web;
17  
18  
19  import java.util.ArrayList;
20  import java.util.Comparator;
21  import java.util.HashSet;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Map.Entry;
25  import java.util.Set;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  import org.apache.commons.lang.StringUtils;
31  import org.apache.commons.lang.time.DateUtils;
32  import org.apache.struts.action.ActionForm;
33  import org.apache.struts.action.ActionForward;
34  import org.apache.struts.action.ActionMapping;
35  import org.apache.struts.action.ActionRedirect;
36  import org.displaytag.tags.TableTagParameters;
37  import org.displaytag.util.ParamEncoder;
38  import org.joda.time.DateTime;
39  import org.joda.time.Interval;
40  import org.kuali.hr.lm.LMConstants;
41  import org.kuali.hr.lm.accrual.AccrualCategoryRule;
42  import org.kuali.hr.lm.leaveblock.LeaveBlock;
43  import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
44  import org.kuali.hr.lm.leaveplan.LeavePlan;
45  import org.kuali.hr.time.base.web.TkAction;
46  import org.kuali.hr.time.calendar.Calendar;
47  import org.kuali.hr.time.calendar.CalendarEntries;
48  import org.kuali.hr.time.principal.PrincipalHRAttributes;
49  import org.kuali.hr.time.roles.TkUserRoles;
50  import org.kuali.hr.time.roles.UserRoles;
51  import org.kuali.hr.time.service.base.TkServiceLocator;
52  import org.kuali.hr.time.timesheet.TimesheetDocument;
53  import org.kuali.hr.time.util.TKContext;
54  import org.kuali.hr.time.util.TKUser;
55  import org.kuali.hr.time.util.TKUtils;
56  import org.kuali.hr.time.util.TkConstants;
57  import org.kuali.rice.kew.api.document.DocumentStatus;
58  import org.kuali.rice.krad.exception.AuthorizationException;
59  import org.kuali.rice.krad.util.GlobalVariables;
60  import org.kuali.rice.krad.util.ObjectUtils;
61  
62  import edu.emory.mathcs.backport.java.util.Collections;
63  
64  public class TimesheetSubmitAction extends TkAction {
65  
66      @Override
67      protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
68          TimesheetSubmitActionForm tsaf = (TimesheetSubmitActionForm)form;
69  
70          String principal = TKContext.getPrincipalId();
71          UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
72  
73          TimesheetDocument document = TkServiceLocator.getTimesheetService().getTimesheetDocument(tsaf.getDocumentId());
74          if (!roles.isDocumentWritable(document)) {
75              throw new AuthorizationException(principal, "TimesheetSubmitAction", "");
76          }
77      }
78  
79  
80  
81  
82      public ActionForward approveTimesheet(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
83          TimesheetSubmitActionForm tsaf = (TimesheetSubmitActionForm)form;
84          TimesheetDocument document = TkServiceLocator.getTimesheetService().getTimesheetDocument(tsaf.getDocumentId());
85  
86          // Switched to grab the target (chain, resolution: target -> backdoor -> actual) user.
87          // Approvals still using backdoor > actual
88          if (StringUtils.equals(tsaf.getAction(), TkConstants.DOCUMENT_ACTIONS.ROUTE)) {
89              if (DocumentStatus.INITIATED.getCode().equals(document.getDocumentHeader().getDocumentStatus())
90                      || DocumentStatus.SAVED.getCode().equals(document.getDocumentHeader().getDocumentStatus())) {
91              	
92              	boolean nonExemptLE = TkServiceLocator.getLeaveApprovalService().isActiveAssignmentFoundOnJobFlsaStatus(document.getPrincipalId(),
93              				TkConstants.FLSA_STATUS_NON_EXEMPT, true);
94              	if(nonExemptLE) {
95              		Map<String,Set<LeaveBlock>> eligibilities = TkServiceLocator.getAccrualCategoryMaxBalanceService().getMaxBalanceViolations(document.getCalendarEntry(), document.getPrincipalId());
96              		PrincipalHRAttributes pha = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(document.getPrincipalId(), document.getCalendarEntry().getEndPeriodDate());
97  					Calendar cal = pha.getLeaveCalObj();
98  					if(cal == null) {
99  						//non exempt leave eligible employee without a leave calendar?
100 						throw new RuntimeException("Principal is without a leave calendar");
101                     }
102     				List<LeaveBlock> eligibleTransfers = new ArrayList<LeaveBlock>();
103     				List<LeaveBlock> eligiblePayouts = new ArrayList<LeaveBlock>();
104             		Interval interval = new Interval(document.getCalendarEntry().getBeginPeriodDate().getTime(), document.getCalendarEntry().getEndPeriodDate().getTime());
105 
106 	        		for(Entry<String,Set<LeaveBlock>> entry : eligibilities.entrySet()) {
107 	        			
108 	            		for(LeaveBlock lb : entry.getValue()) {
109 	            			if(interval.contains(lb.getLeaveDate().getTime())) {
110 	            				//maxBalanceViolations should, if a violation exists, return a leave block with leave date either current date, or the end period date - 1 days.
111 		        				AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(lb.getAccrualCategoryRuleId());
112 	
113 		            			if(ObjectUtils.isNotNull(aRule)
114 		            					&& !StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND)) {
115 		            				if(StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
116 		            					DateTime rollOverDate = TkServiceLocator.getLeavePlanService().getRolloverDayOfLeavePlan(pha.getLeavePlan(), document.getCalendarEntry().getBeginPeriodDate());
117 		            					//the final calendar period of the leave plan should end within this time sheet 
118 		            					if(interval.contains(rollOverDate.minusDays(1).getMillis())) {
119 		            						//only leave blocks belonging to the calendar entry being submitted may reach this point
120 		            						//if the infraction occurs before the relative end date of the leave plan year, then action will be executed.
121 			            					if(lb.getLeaveDate().before(rollOverDate.toDate())) {
122 						            			if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.PAYOUT)) {
123 						            				eligiblePayouts.add(lb);
124 						            			}
125 						            			else if(StringUtils.equals(aRule.getActionAtMaxBalance(), LMConstants.ACTION_AT_MAX_BAL.TRANSFER)
126 						            					|| StringUtils.equals(aRule.getActionAtMaxBalance(), LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
127 						            				eligibleTransfers.add(lb);
128 						            			}
129 			            					}
130 		            					}
131 		            				}
132 		            				if(StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE)) {
133 		            					//a leave period should end within the time period.
134 		            					CalendarEntries leaveEntry = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(cal.getHrCalendarId(), lb.getLeaveDate());
135 		            					if(ObjectUtils.isNotNull(leaveEntry)) {
136 		            						//only leave blocks belonging to the calendar entry being submitted may reach this point.
137 		            						//if the infraction occurs before the end of the leave calendar entry, then action will be executed.
138 			            					if(interval.contains(DateUtils.addDays(leaveEntry.getEndPeriodDate(),-1).getTime())) {
139 
140 						            			if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.PAYOUT)) {
141 						            				eligiblePayouts.add(lb);
142 						            			}
143 						            			else if(StringUtils.equals(aRule.getActionAtMaxBalance(), LMConstants.ACTION_AT_MAX_BAL.TRANSFER)
144 						            					|| StringUtils.equals(aRule.getActionAtMaxBalance(), LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
145 						            				eligibleTransfers.add(lb);
146 						            			}
147 			            					}
148 		            					}
149 		            				}
150 		            			}
151 	            			}
152 	            		}
153 	        		}
154             		ActionRedirect transferRedirect = new ActionRedirect();
155             		ActionRedirect payoutRedirect = new ActionRedirect();
156             		if(!eligibleTransfers.isEmpty()) {
157                 		transferRedirect.setPath("/BalanceTransfer.do?"+request.getQueryString());
158                 		request.getSession().setAttribute("eligibilities", eligibleTransfers);
159                 		return transferRedirect;
160             		}
161             		if(!eligiblePayouts.isEmpty()) {
162                 		payoutRedirect.setPath("/LeavePayout.do?"+request.getQueryString());
163                 		request.getSession().setAttribute("eligibilities", eligiblePayouts);
164                 		return payoutRedirect;           			
165             		}
166             	}
167                 TkServiceLocator.getTimesheetService().routeTimesheet(TKContext.getTargetPrincipalId(), document);
168             }
169         } else if (StringUtils.equals(tsaf.getAction(), TkConstants.DOCUMENT_ACTIONS.APPROVE)) {
170         	if(TkServiceLocator.getTimesheetService().isReadyToApprove(document)) {
171 	            if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) {
172 	                TkServiceLocator.getTimesheetService().approveTimesheet(TKContext.getPrincipalId(), document);
173 	            }
174         	} else {
175         		//ERROR!!!
176         	}
177         } else if (StringUtils.equals(tsaf.getAction(), TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) {
178             if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) {
179                 TkServiceLocator.getTimesheetService().disapproveTimesheet(TKContext.getPrincipalId(), document);
180             }
181         }
182         
183         TkServiceLocator.getTkSearchableAttributeService().updateSearchableAttribute(document, document.getAsOfDate());
184         ActionRedirect rd = new ActionRedirect(mapping.findForward("timesheetRedirect"));
185         rd.addParameter("documentId", tsaf.getDocumentId());
186 
187         return rd;
188     }
189 
190     public ActionForward approveApprovalTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
191     	TimesheetSubmitActionForm tsaf = (TimesheetSubmitActionForm)form;
192         TimesheetDocument document = TkServiceLocator.getTimesheetService().getTimesheetDocument(tsaf.getDocumentId());
193 
194         // Switched to grab the target (chain, resolution: target -> backdoor -> actual) user.
195         // Approvals still using backdoor > actual
196         if (StringUtils.equals(tsaf.getAction(), TkConstants.DOCUMENT_ACTIONS.ROUTE)) {
197             if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.INITIATED.getCode())) {
198                 TkServiceLocator.getTimesheetService().routeTimesheet(TKContext.getTargetPrincipalId(), document);
199             }
200         } else if (StringUtils.equals(tsaf.getAction(), TkConstants.DOCUMENT_ACTIONS.APPROVE)) {
201         	if(TkServiceLocator.getTimesheetService().isReadyToApprove(document)) {
202 	            if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) {
203 	                TkServiceLocator.getTimesheetService().approveTimesheet(TKContext.getPrincipalId(), document);
204 	            }
205         	} else {
206         		//ERROR!!!
207         	}
208         } else if (StringUtils.equals(tsaf.getAction(), TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) {
209             if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) {
210                 TkServiceLocator.getTimesheetService().disapproveTimesheet(TKContext.getPrincipalId(), document);
211             }
212         }
213         TKUser.clearTargetUser();
214         String page = new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE);
215         String pageVal = request.getParameter(page);
216 
217 
218         ActionRedirect ar = new ActionRedirect(mapping.findForward("approverRedirect"));
219         if (StringUtils.isNotEmpty(pageVal)) {
220             ar.addParameter(page, pageVal);
221         }
222         return ar;
223 
224 
225     }
226 }