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