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 }