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.leaverequest.service; 017 018 019 import java.util.ArrayList; 020 import java.util.HashMap; 021 import java.util.List; 022 import java.util.Map; 023 024 import org.apache.commons.lang.StringUtils; 025 import org.apache.log4j.Logger; 026 import org.kuali.hr.job.Job; 027 import org.kuali.hr.lm.leaveblock.LeaveBlock; 028 import org.kuali.hr.lm.leaverequest.LeaveRequestActionValue; 029 import org.kuali.hr.lm.leaverequest.dao.LeaveRequestDocumentDao; 030 import org.kuali.hr.lm.workflow.LeaveRequestDocument; 031 import org.kuali.hr.time.assignment.Assignment; 032 import org.kuali.hr.time.calendar.CalendarEntries; 033 import org.kuali.hr.time.service.base.TkServiceLocator; 034 import org.kuali.hr.time.util.TKContext; 035 import org.kuali.hr.time.util.TKUtils; 036 import org.kuali.hr.time.workarea.WorkArea; 037 import org.kuali.rice.kew.api.KewApiServiceLocator; 038 import org.kuali.rice.kew.api.WorkflowDocument; 039 import org.kuali.rice.kew.api.action.ActionTaken; 040 import org.kuali.rice.kew.api.action.ActionType; 041 import org.kuali.rice.kew.api.action.DocumentActionParameters; 042 import org.kuali.rice.kew.api.action.ValidActions; 043 import org.kuali.rice.kew.api.action.WorkflowDocumentActionsService; 044 import org.kuali.rice.kew.api.document.DocumentStatus; 045 import org.kuali.rice.kew.api.exception.WorkflowException; 046 import org.kuali.rice.kim.api.identity.Person; 047 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 048 import org.kuali.rice.krad.bo.DocumentHeader; 049 import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 050 import org.kuali.rice.krad.util.GlobalVariables; 051 052 public class LeaveRequestDocumentServiceImpl implements LeaveRequestDocumentService { 053 private static final Logger LOG = Logger.getLogger(LeaveRequestDocumentServiceImpl.class); 054 private LeaveRequestDocumentDao leaveRequestDocumentDao; 055 056 @Override 057 public LeaveRequestDocument getLeaveRequestDocument(String documentId) { 058 LeaveRequestDocument document = null; 059 try { 060 document = (LeaveRequestDocument)KRADServiceLocatorWeb.getDocumentService().getByDocumentHeaderId(documentId); 061 } catch (WorkflowException e) { 062 LOG.error("Document with documentId: " + documentId + " does not exist"); 063 } 064 return document; 065 } 066 067 @Override 068 public List<LeaveRequestDocument> getLeaveRequestDocumentsByLeaveBlockId(String leaveBlockId) { 069 List<LeaveRequestDocument> docList = getLeaveRequestDocumentDao().getLeaveRequestDocumentsByLeaveBlockId(leaveBlockId); 070 List<LeaveRequestDocument> results = new ArrayList<LeaveRequestDocument>(); 071 for(LeaveRequestDocument aDoc : docList) { 072 results.add(this.getLeaveRequestDocument(aDoc.getDocumentNumber())); 073 } 074 return results; 075 } 076 077 @Override 078 public LeaveRequestDocument saveLeaveRequestDocument(LeaveRequestDocument document) { 079 LeaveRequestDocument lrd = null; 080 try { 081 lrd = (LeaveRequestDocument)KRADServiceLocatorWeb.getDocumentService().saveDocument(document); 082 } catch (WorkflowException e) { 083 LOG.error(e.getStackTrace()); 084 return null; 085 } 086 return lrd; 087 } 088 089 @Override 090 public LeaveRequestDocument createLeaveRequestDocument(String leaveBlockId) { 091 LeaveRequestDocument lrd = initiateLeaveRequestDocument(TKContext.getTargetPrincipalId(), leaveBlockId); 092 093 return saveLeaveRequestDocument(lrd); 094 } 095 096 @Override 097 public void requestLeave(String documentId) { 098 LeaveRequestDocument doc = getLeaveRequestDocument(documentId); 099 doc.getDocumentHeader().getWorkflowDocument().route(""); 100 101 } 102 103 @Override 104 public void approveLeave(String documentId, String principalId, String reason) { 105 //verify principal has an action item to approve... 106 //KewApiServiceLocator. 107 LeaveRequestDocument doc = getLeaveRequestDocument(documentId); 108 109 //do we need to switch ids? 110 doc.getDocumentHeader().getWorkflowDocument().switchPrincipal(principalId); 111 ValidActions validActions = doc.getDocumentHeader().getWorkflowDocument().getValidActions(); 112 if (validActions.getValidActions().contains(ActionType.APPROVE)) { 113 if(StringUtils.isNotEmpty(reason)) { 114 doc.setDescription(reason); 115 saveLeaveRequestDocument(doc); 116 } 117 doc.getDocumentHeader().getWorkflowDocument().approve(""); 118 } 119 } 120 121 @Override 122 public void disapproveLeave(String documentId, String principalId, String reason) { 123 LeaveRequestDocument doc = getLeaveRequestDocument(documentId); 124 doc.getDocumentHeader().getWorkflowDocument().switchPrincipal(principalId); 125 ValidActions validActions = doc.getDocumentHeader().getWorkflowDocument().getValidActions(); 126 if (validActions.getValidActions().contains(ActionType.DISAPPROVE)) { 127 if(StringUtils.isNotEmpty(reason)) { 128 doc.setDescription(reason); 129 saveLeaveRequestDocument(doc); 130 } 131 doc.getDocumentHeader().getWorkflowDocument().disapprove(""); 132 } 133 } 134 135 @Override 136 public void deferLeave(String documentId, String principalId, String reason) { 137 LeaveRequestDocument doc = getLeaveRequestDocument(documentId); 138 doc.getDocumentHeader().getWorkflowDocument().switchPrincipal(principalId); 139 ValidActions validActions = doc.getDocumentHeader().getWorkflowDocument().getValidActions(); 140 if (validActions.getValidActions().contains(ActionType.CANCEL)) { 141 if(StringUtils.isNotEmpty(reason)) { 142 doc.setDescription(reason); 143 saveLeaveRequestDocument(doc); 144 } 145 doc.getDocumentHeader().getWorkflowDocument().cancel(""); 146 } 147 } 148 149 @Override 150 public void recallAndCancelLeave(String documentId, String principalId, String reason) { 151 LeaveRequestDocument doc = getLeaveRequestDocument(documentId); 152 if (principalId.equals(doc.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId())) { 153 doc.getDocumentHeader().getWorkflowDocument().switchPrincipal(principalId); 154 if(StringUtils.isNotEmpty(reason)) { 155 doc.setDescription(reason); 156 saveLeaveRequestDocument(doc); 157 } 158 doc.getDocumentHeader().getWorkflowDocument().recall("", true); 159 } 160 } 161 162 @Override 163 public void suBlanketApproveLeave(String documentId, String principalId) { 164 WorkflowDocumentActionsService docActionService = KewApiServiceLocator.getWorkflowDocumentActionsService(); 165 DocumentActionParameters parameters = DocumentActionParameters.create(documentId, principalId); 166 docActionService.superUserBlanketApprove(parameters, true); 167 } 168 169 public LeaveRequestDocumentDao getLeaveRequestDocumentDao() { 170 return leaveRequestDocumentDao; 171 } 172 173 public void setLeaveRequestDocumentDao(LeaveRequestDocumentDao leaveRequestDocumentDao) { 174 this.leaveRequestDocumentDao = leaveRequestDocumentDao; 175 } 176 177 private LeaveRequestDocument initiateLeaveRequestDocument(String principalId, String leaveBlockId) { 178 //LeaveRequestDocument leaveRequestDocument = new LeaveRequestDocument(leaveBlockId); 179 LeaveRequestDocument leaveRequestDocument = null; 180 try { 181 leaveRequestDocument = (LeaveRequestDocument) KRADServiceLocatorWeb.getDocumentService().getNewDocument(LeaveRequestDocument.LEAVE_REQUEST_DOCUMENT_TYPE); 182 } catch (WorkflowException e) { 183 LOG.error(e.getMessage()); 184 return null; 185 } 186 187 Person person = KimApiServiceLocator.getPersonService().getPerson(principalId); 188 LeaveBlock leaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId); 189 190 String principalName = person != null ? person.getName() : StringUtils.EMPTY; 191 String leaveRequestDateString = leaveBlock != null ? TKUtils.formatDate(leaveBlock.getLeaveDate()) : StringUtils.EMPTY; 192 String leaveRequestDocumentTitle = principalName + " (" + principalId + ") - " + leaveRequestDateString; 193 194 leaveRequestDocument.setLmLeaveBlockId(leaveBlockId); 195 leaveRequestDocument.getDocumentHeader().setDocumentDescription(leaveRequestDocumentTitle); 196 leaveRequestDocument.setDescription(leaveBlock != null ? leaveBlock.getDescription() : StringUtils.EMPTY); 197 leaveRequestDocument.setActionCode(LeaveRequestActionValue.NO_ACTION.getCode()); 198 initiateSearchableAttributes(leaveRequestDocument); 199 200 return leaveRequestDocument; 201 } 202 203 private void initiateSearchableAttributes(LeaveRequestDocument leaveRequestDocument) { 204 DocumentHeader dh = leaveRequestDocument.getDocumentHeader(); 205 WorkflowDocument workflowDocument = dh.getWorkflowDocument(); 206 if (!DocumentStatus.FINAL.equals(workflowDocument.getStatus())) { 207 try { 208 workflowDocument.setApplicationContent(createSearchableAttributeXml(leaveRequestDocument, leaveRequestDocument.getLeaveBlock())); 209 workflowDocument.saveDocument(""); 210 if (!"I".equals(workflowDocument.getStatus().getCode())) { 211 if (GlobalVariables.getUserSession() != null && workflowDocument.getInitiatorPrincipalId().equals(GlobalVariables.getUserSession().getPrincipalId())) { 212 workflowDocument.saveDocument(""); 213 } else{ 214 workflowDocument.saveDocumentData(); 215 } 216 } else{ 217 workflowDocument.saveDocument(""); 218 } 219 220 221 } catch (Exception e) { 222 LOG.warn("Exception during searchable attribute update."); 223 throw new RuntimeException(e); 224 } 225 } 226 } 227 228 private String createSearchableAttributeXml(LeaveRequestDocument document, LeaveBlock leaveBlock) { 229 List<Long> workAreas = new ArrayList<Long>(); 230 Map<String,List<Long>> deptToListOfWorkAreas = new HashMap<String,List<Long>>(); 231 List<String> salGroups = new ArrayList<String>(); 232 CalendarEntries ce = getCalendarEntry(leaveBlock); 233 if (ce != null) { 234 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(leaveBlock.getPrincipalId(), ce); 235 236 for(Assignment assign: assignments){ 237 if(!workAreas.contains(assign.getWorkArea())){ 238 workAreas.add(assign.getWorkArea()); 239 } 240 Job job = TkServiceLocator.getJobService().getJob(assign.getPrincipalId(), assign.getJobNumber(), leaveBlock.getLeaveDate()); 241 242 if(!salGroups.contains(job.getHrSalGroup())){ 243 salGroups.add(job.getHrSalGroup()); 244 } 245 } 246 } 247 for(Long workArea : workAreas){ 248 WorkArea workAreaObj = TkServiceLocator.getWorkAreaService().getWorkArea(workArea, TKUtils.getTimelessDate(leaveBlock.getLeaveDate())); 249 if(deptToListOfWorkAreas.containsKey(workAreaObj.getDept())){ 250 List<Long> deptWorkAreas = deptToListOfWorkAreas.get(workAreaObj.getDept()); 251 deptWorkAreas.add(workArea); 252 } else { 253 List<Long> deptWorkAreas = new ArrayList<Long>(); 254 deptWorkAreas.add(workArea); 255 deptToListOfWorkAreas.put(workAreaObj.getDept(), deptWorkAreas); 256 } 257 } 258 StringBuilder sb = new StringBuilder(); 259 String className = document.getClass().getSimpleName(); 260 sb.append("<documentContext><applicationContent><").append(className).append(">"); 261 sb.append("<DEPARTMENTS>"); 262 for(String dept : deptToListOfWorkAreas.keySet()){ 263 sb.append("<DEPARTMENT value=\""+dept+"\">"); 264 List<Long> deptWorkAreas = deptToListOfWorkAreas.get(dept); 265 for(Long workArea : deptWorkAreas){ 266 sb.append("<WORKAREA value=\""+workArea+"\"/>"); 267 } 268 sb.append("</DEPARTMENT>"); 269 } 270 sb.append("</DEPARTMENTS>"); 271 for(String salGroup : salGroups){ 272 sb.append("<SALGROUP value=\""+salGroup+"\"/>"); 273 } 274 275 sb.append("<PAYENDDATE value=\""+leaveBlock.getLeaveDate()+"\"/>"); 276 sb.append("</").append(className).append("></applicationContent></documentContext>"); 277 278 return sb.toString(); 279 } 280 281 private CalendarEntries getCalendarEntry(LeaveBlock leaveBlock) { 282 return TkServiceLocator.getCalendarEntriesService().getCalendarEntries(leaveBlock.getCalendarId()); 283 } 284 285 public List<String> getApproverIdList(String documentId) { 286 List<String> idList = new ArrayList<String>(); 287 List<ActionTaken> actions = KewApiServiceLocator.getWorkflowDocumentService().getActionsTaken(documentId); 288 for(ActionTaken anAction : actions) { 289 if(anAction.getActionTaken().getCode().equals(ActionType.APPROVE.getCode()) 290 && StringUtils.isNotEmpty(anAction.getPrincipalId()) ) { 291 idList.add(anAction.getPrincipalId()); 292 } 293 } 294 return idList; 295 } 296 297 }