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