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.leavecalendar.web; 017 018 import java.util.ArrayList; 019 import java.util.Comparator; 020 import java.util.HashSet; 021 import java.util.List; 022 import java.util.Map; 023 import java.util.Map.Entry; 024 import java.util.Set; 025 026 import org.apache.commons.lang.StringUtils; 027 import org.apache.commons.lang.time.DateUtils; 028 import org.apache.struts.action.ActionForm; 029 import org.apache.struts.action.ActionForward; 030 import org.apache.struts.action.ActionMapping; 031 import org.apache.struts.action.ActionRedirect; 032 import org.joda.time.Interval; 033 import org.kuali.hr.lm.LMConstants; 034 import org.kuali.hr.lm.accrual.AccrualCategory; 035 import org.kuali.hr.lm.accrual.AccrualCategoryRule; 036 import org.kuali.hr.lm.leaveblock.LeaveBlock; 037 import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument; 038 import org.kuali.hr.lm.leaveplan.LeavePlan; 039 import org.kuali.hr.lm.workflow.service.LeaveCalendarDocumentHeaderService; 040 import org.kuali.hr.time.base.web.TkAction; 041 import org.kuali.hr.time.calendar.Calendar; 042 import org.kuali.hr.time.principal.PrincipalHRAttributes; 043 import org.kuali.hr.time.roles.TkUserRoles; 044 import org.kuali.hr.time.roles.UserRoles; 045 import org.kuali.hr.time.service.base.TkServiceLocator; 046 import org.kuali.hr.time.util.TKContext; 047 import org.kuali.hr.time.util.TKUser; 048 import org.kuali.hr.time.util.TKUtils; 049 import org.kuali.hr.time.util.TkConstants; 050 import org.kuali.rice.kew.api.document.DocumentStatus; 051 import org.kuali.rice.krad.exception.AuthorizationException; 052 import org.kuali.rice.krad.util.GlobalVariables; 053 import org.kuali.rice.krad.util.ObjectUtils; 054 055 import edu.emory.mathcs.backport.java.util.Collections; 056 057 import javax.servlet.http.HttpServletRequest; 058 import javax.servlet.http.HttpServletResponse; 059 060 061 public class LeaveCalendarSubmitAction extends TkAction { 062 @Override 063 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException { 064 LeaveCalendarSubmitForm lcf = (LeaveCalendarSubmitForm)form; 065 066 String principal = TKContext.getPrincipalId(); 067 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()); 068 069 LeaveCalendarDocument document = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(lcf.getDocumentId()); 070 if (!roles.isDocumentWritable(document)) { 071 throw new AuthorizationException(principal, "LeaveCalendarSubmitAction", ""); 072 } 073 } 074 075 public ActionForward approveLeaveCalendar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 076 String documentId = request.getParameter("documentId"); 077 String action = request.getParameter("action"); 078 LeaveCalendarDocument document = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId); 079 080 // Switched to grab the target (chain, resolution: target -> backdoor -> actual) user. 081 // Approvals still using backdoor > actual 082 if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.ROUTE)) { 083 if (DocumentStatus.INITIATED.getCode().equals(document.getDocumentHeader().getDocumentStatus()) 084 || DocumentStatus.SAVED.getCode().equals(document.getDocumentHeader().getDocumentStatus())) { 085 086 Map<String,Set<LeaveBlock>> eligibilities = TkServiceLocator.getAccrualCategoryMaxBalanceService().getMaxBalanceViolations(document.getCalendarEntry(), document.getPrincipalId()); 087 088 ActionRedirect transferRedirect = new ActionRedirect(); 089 ActionRedirect payoutRedirect = new ActionRedirect(); 090 091 List<LeaveBlock> eligibleTransfers = new ArrayList<LeaveBlock>(); 092 List<LeaveBlock> eligiblePayouts = new ArrayList<LeaveBlock>(); 093 Interval interval = new Interval(document.getCalendarEntry().getBeginPeriodDate().getTime(), document.getCalendarEntry().getEndPeriodDate().getTime()); 094 for(Entry<String,Set<LeaveBlock>> entry : eligibilities.entrySet()) { 095 096 for(LeaveBlock lb : entry.getValue()) { 097 if(interval.contains(lb.getLeaveDate().getTime())) { 098 //maxBalanceViolations should, if a violation exists, return a leave block with leave date either current date, or the end period date - 1 days. 099 PrincipalHRAttributes pha = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(document.getPrincipalId(), lb.getLeaveDate()); 100 AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(lb.getAccrualCategoryRuleId()); 101 102 if(ObjectUtils.isNotNull(aRule) 103 && !StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND)) { 104 if(StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) 105 || (StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END) 106 && TkServiceLocator.getLeavePlanService().isLastCalendarPeriodOfLeavePlan(document.getCalendarEntry(),pha.getLeavePlan(),lb.getLeaveDate()))) 107 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.PAYOUT)) { 108 eligiblePayouts.add(lb); 109 } 110 else if(StringUtils.equals(aRule.getActionAtMaxBalance(), LMConstants.ACTION_AT_MAX_BAL.TRANSFER) 111 || StringUtils.equals(aRule.getActionAtMaxBalance(), LMConstants.ACTION_AT_MAX_BAL.LOSE)) { 112 eligibleTransfers.add(lb); 113 } 114 } 115 } 116 } 117 } 118 if(!eligibleTransfers.isEmpty()) { 119 transferRedirect.setPath("/BalanceTransfer.do?"+request.getQueryString()); 120 request.getSession().setAttribute("eligibilities", eligibleTransfers); 121 return transferRedirect; 122 } 123 if(!eligiblePayouts.isEmpty()) { 124 payoutRedirect.setPath("/LeavePayout.do?"+request.getQueryString()); 125 request.getSession().setAttribute("eligibilities", eligiblePayouts); 126 return payoutRedirect; 127 } 128 TkServiceLocator.getLeaveCalendarService().routeLeaveCalendar(TKContext.getTargetPrincipalId(), document); 129 } 130 } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.APPROVE)) { 131 if (TkServiceLocator.getLeaveCalendarService().isReadyToApprove(document)) { 132 if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) { 133 TkServiceLocator.getLeaveCalendarService().approveLeaveCalendar(TKContext.getPrincipalId(), document); 134 } 135 } else { 136 //ERROR!!!! 137 } 138 } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) { 139 if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) { 140 TkServiceLocator.getLeaveCalendarService().disapproveLeaveCalendar(TKContext.getPrincipalId(), document); 141 } 142 } 143 ActionRedirect rd = new ActionRedirect(mapping.findForward("leaveCalendarRedirect")); 144 TkServiceLocator.getTkSearchableAttributeService().updateSearchableAttribute(document, document.getAsOfDate()); 145 rd.addParameter("documentId", documentId); 146 147 return rd; 148 } 149 150 public ActionForward approveApprovalTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 151 LeaveCalendarSubmitForm lcf = (LeaveCalendarSubmitForm)form; 152 LeaveCalendarDocument document = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(lcf.getDocumentId()); 153 154 // Switched to grab the target (chain, resolution: target -> backdoor -> actual) user. 155 // Approvals still using backdoor > actual 156 if (StringUtils.equals(lcf.getAction(), TkConstants.DOCUMENT_ACTIONS.ROUTE)) { 157 if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.INITIATED.getCode())) { 158 TkServiceLocator.getLeaveCalendarService().routeLeaveCalendar(TKContext.getTargetPrincipalId(), document); 159 } 160 } else if (StringUtils.equals(lcf.getAction(), TkConstants.DOCUMENT_ACTIONS.APPROVE)) { 161 //Todo: check for unfinalized BalanceTransfer on current leave calendar. 162 if (TkServiceLocator.getLeaveCalendarService().isReadyToApprove(document)) { 163 if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) { 164 TkServiceLocator.getLeaveCalendarService().approveLeaveCalendar(TKContext.getPrincipalId(), document); 165 } 166 } else { 167 //ERROR!!!! 168 } 169 170 } else if (StringUtils.equals(lcf.getAction(), TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) { 171 if (document.getDocumentHeader().getDocumentStatus().equals(DocumentStatus.ENROUTE.getCode())) { 172 TkServiceLocator.getLeaveCalendarService().disapproveLeaveCalendar(TKContext.getPrincipalId(), document); 173 } 174 } 175 176 TKUser.clearTargetUser(); 177 return new ActionRedirect(mapping.findForward("approverRedirect")); 178 179 } 180 181 }