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    }