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