View Javadoc
1   /**
2    * Copyright 2004-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.kpme.tklm.leave.request.service;
17  
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.log4j.Logger;
21  import org.kuali.kpme.core.api.assignment.Assignment;
22  import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
23  import org.kuali.kpme.core.api.job.Job;
24  import org.kuali.kpme.core.api.job.JobContract;
25  import org.kuali.kpme.core.api.workarea.WorkArea;
26  import org.kuali.kpme.core.calendar.entry.CalendarEntryBo;
27  import org.kuali.kpme.core.service.HrServiceLocator;
28  import org.kuali.kpme.core.util.HrContext;
29  import org.kuali.kpme.core.util.TKUtils;
30  import org.kuali.kpme.tklm.api.leave.block.LeaveBlock;
31  import org.kuali.kpme.tklm.leave.request.LeaveRequestActionValue;
32  import org.kuali.kpme.tklm.leave.request.dao.LeaveRequestDocumentDao;
33  import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
34  import org.kuali.kpme.tklm.leave.workflow.LeaveRequestDocument;
35  import org.kuali.rice.kew.api.KewApiServiceLocator;
36  import org.kuali.rice.kew.api.WorkflowDocument;
37  import org.kuali.rice.kew.api.action.*;
38  import org.kuali.rice.kew.api.document.DocumentStatus;
39  import org.kuali.rice.kew.api.exception.WorkflowException;
40  import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
41  import org.kuali.rice.kim.api.identity.principal.Principal;
42  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
43  import org.kuali.rice.krad.bo.DocumentHeader;
44  import org.kuali.rice.krad.exception.UnknownDocumentIdException;
45  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
46  import org.kuali.rice.krad.util.GlobalVariables;
47  
48  import java.util.ArrayList;
49  import java.util.HashMap;
50  import java.util.List;
51  import java.util.Map;
52  
53  public class LeaveRequestDocumentServiceImpl implements LeaveRequestDocumentService {
54      private static final Logger LOG = Logger.getLogger(LeaveRequestDocumentServiceImpl.class);
55      private LeaveRequestDocumentDao leaveRequestDocumentDao;
56  
57      @Override
58      public LeaveRequestDocument getLeaveRequestDocument(String documentId) {
59          LeaveRequestDocument document = null;
60          try {
61              document = (LeaveRequestDocument)KRADServiceLocatorWeb.getDocumentService().getByDocumentHeaderId(documentId);
62          } catch (WorkflowException e) {
63              LOG.error("Document with documentId: " + documentId + " does not exist");
64          } catch (UnknownDocumentIdException e) {
65          	LOG.error("Document with documentId: " + documentId + " does not exist");
66              return document;
67          }
68          return document;
69      }
70      
71      @Override
72      public List<LeaveRequestDocument> getLeaveRequestDocumentsByLeaveBlockId(String leaveBlockId) {
73      	List<LeaveRequestDocument> docList = getLeaveRequestDocumentDao().getLeaveRequestDocumentsByLeaveBlockId(leaveBlockId);
74      	List<LeaveRequestDocument> results = new ArrayList<LeaveRequestDocument>();
75      	for(LeaveRequestDocument aDoc : docList) {
76      		LeaveRequestDocument lrd = this.getLeaveRequestDocument(aDoc.getDocumentNumber());    		
77      		if(lrd != null){
78      			results.add(lrd);
79      		}
80      	}
81      	return results;
82      }
83  
84      @Override
85      public LeaveRequestDocument saveLeaveRequestDocument(LeaveRequestDocument document) {
86          LeaveRequestDocument lrd = null;
87          try {
88              lrd = (LeaveRequestDocument)KRADServiceLocatorWeb.getDocumentService().saveDocument(document);
89          } catch (WorkflowException e) {
90              LOG.error(e.getStackTrace());
91              return null;
92          }
93          return lrd;
94      }
95  
96      @Override
97      public LeaveRequestDocument createLeaveRequestDocument(String leaveBlockId) {
98          LeaveRequestDocument lrd = initiateLeaveRequestDocument(HrContext.getTargetPrincipalId(), leaveBlockId);
99  
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 }