001    /*
002     * Copyright 2011 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.kfs.sys.batch.service.impl;
017    
018    import java.sql.Timestamp;
019    import java.text.ParseException;
020    import java.util.Calendar;
021    import java.util.Date;
022    import java.util.List;
023    
024    import org.kuali.kfs.sys.KFSConstants;
025    import org.kuali.kfs.sys.KFSParameterKeyConstants;
026    import org.kuali.kfs.sys.batch.AutoDisapproveDocumentsStep;
027    import org.kuali.kfs.sys.batch.service.AutoDisapproveDocumentsService;
028    import org.kuali.kfs.sys.context.SpringContext;
029    import org.kuali.kfs.sys.service.ReportWriterService;
030    import org.kuali.rice.kew.doctype.bo.DocumentType;
031    import org.kuali.rice.kew.doctype.service.DocumentTypeService;
032    import org.kuali.rice.kew.dto.DocumentSearchCriteriaDTO;
033    import org.kuali.rice.kew.dto.DocumentSearchResultDTO;
034    import org.kuali.rice.kew.dto.DocumentSearchResultRowDTO;
035    import org.kuali.rice.kew.dto.KeyValueDTO;
036    import org.kuali.rice.kew.exception.WorkflowException;
037    import org.kuali.rice.kew.service.WorkflowInfo;
038    import org.kuali.rice.kew.util.KEWConstants;
039    import org.kuali.rice.kim.bo.Person;
040    import org.kuali.rice.kim.service.PersonService;
041    import org.kuali.rice.kns.bo.Note;
042    import org.kuali.rice.kns.document.Document;
043    import org.kuali.rice.kns.exception.UnknownDocumentTypeException;
044    import org.kuali.rice.kns.service.DateTimeService;
045    import org.kuali.rice.kns.service.DocumentService;
046    import org.kuali.rice.kns.service.KNSServiceLocator;
047    import org.kuali.rice.kns.service.NoteService;
048    import org.kuali.rice.kns.service.ParameterEvaluator;
049    import org.kuali.rice.kns.service.ParameterService;
050    import org.kuali.rice.kns.util.ObjectUtils;
051    import org.springframework.transaction.annotation.Transactional;
052    
053    /**
054     * This class implements the AutoDisapproveDocumentsService batch job.
055     */
056    @Transactional
057    public class AutoDisapproveDocumentsServiceImpl implements AutoDisapproveDocumentsService {
058        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AutoDisapproveDocumentsServiceImpl.class);
059        public static final String WORKFLOW_DOCUMENT_HEADER_ID_SEARCH_RESULT_KEY = "routeHeaderId";
060        
061        private DocumentService documentService;
062        private DocumentTypeService documentTypeService;
063        
064        private DateTimeService dateTimeService;
065        private ParameterService parameterService;
066        
067        private NoteService noteService;
068        private PersonService<Person> personService;
069        
070        private ReportWriterService autoDisapproveErrorReportWriterService;
071        
072        /**
073         * Constructs a AutoDisapproveDocumentsServiceImpl instance
074         */
075        public AutoDisapproveDocumentsServiceImpl() {
076            
077        }
078    
079        /**
080         * Gathers all documents that are in ENROUTE status and auto disapproves them.
081         * @see org.kuali.kfs.sys.batch.service.autoDisapproveDocumentsInEnrouteStatus#autoDisapproveDocumentsInEnrouteStatus()
082         */
083        public boolean autoDisapproveDocumentsInEnrouteStatus() {
084            boolean success = true ;
085            
086            if (systemParametersForAutoDisapproveDocumentsJobExist()) {
087                if (canAutoDisapproveJobRun()) {
088                    LOG.debug("autoDisapproveDocumentsInEnrouteStatus() started");
089                    
090                    Person systemUser = getPersonService().getPersonByPrincipalName(KFSConstants.SYSTEM_USER);
091                    
092                    String principalId = systemUser.getPrincipalId();
093                    String annotationForAutoDisapprovalDocument = getParameterService().getParameterValue(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_ANNOTATION);                
094                    
095                    Date documentCompareDate = getDocumentCompareDateParameter();
096                    success = processAutoDisapproveDocuments(principalId, annotationForAutoDisapprovalDocument, documentCompareDate);
097                }
098            }
099            
100            return success;
101        }
102        
103        /**
104         * This method checks if the System parameters have been set up for this batch job.
105         * @result return true if the system parameters exist, else false
106         */
107        protected boolean systemParametersForAutoDisapproveDocumentsJobExist() {
108            LOG.info("systemParametersForAutoDisapproveDocumentsJobExist() started.");
109            
110            boolean systemParametersExists = true;
111            
112            systemParametersExists &= checkIfRunDateParameterExists();
113            systemParametersExists &= checkIfParentDocumentTypeParameterExists();  
114            systemParametersExists &= checkIfDocumentCompareCreateDateParameterExists();  
115            systemParametersExists &= checkIfDocumentTypesExceptionParameterExists();          
116            systemParametersExists &= checkIfAnnotationForDisapprovalParameterExists();
117            
118            return systemParametersExists;
119        }
120        
121        /**
122         * This method checks for the system parameter for YEAR_END_AUTO_DISAPPROVE_DOCUMENTS_RUN_DATE
123         * @param outputErrorFile_ps output error file stream to write any error messages.
124         * @return true if YEAR_END_AUTO_DISAPPROVE_DOCUMENTS_RUN_DATE exists else false
125         */
126        protected boolean checkIfRunDateParameterExists() {
127            boolean parameterExists = true;
128            
129            // check to make sure the system parameter for run date check has already been setup...
130            if (!getParameterService().parameterExists(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_DOCUMENT_STEP_RUN_DATE)) {
131                LOG.warn("YEAR_END_AUTO_DISAPPROVE_DOCUMENT_RUN_DATE System parameter does not exist in the parameters list.  The job can not continue without this parameter");
132                autoDisapproveErrorReportWriterService.writeFormattedMessageLine("YEAR_END_AUTO_DISAPPROVE_DOCUMENTS_RUN_DATE System parameter does not exist in the parameters list.  The job can not continue without this parameter");
133                return false;
134            }
135            
136            return parameterExists;
137        }
138    
139        /**
140         * This method checks for the system parameter for YEAR_END_AUTO_DISAPPROVE_PARENT_DOCUMENT_TYPE
141         * @param outputErrorFile_ps output error file stream to write any error messages.
142         * @return true if YEAR_END_AUTO_DISAPPROVE_PARENT_DOCUMENT_TYPE exists else false
143         */
144        protected boolean checkIfParentDocumentTypeParameterExists() {
145            boolean parameterExists = true;
146            
147            // check to make sure the system parameter for Parent Document Type = FP has been setup...
148            if (!getParameterService().parameterExists(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_PARENT_DOCUMENT_TYPE)) {
149                LOG.warn("YEAR_END_AUTO_DISAPPROVE_PARENT_DOCUMENT_TYPE System parameter does not exist in the parameters list.  The job can not continue without this parameter");
150                autoDisapproveErrorReportWriterService.writeFormattedMessageLine("YEAR_END_AUTO_DISAPPROVE_PARENT_DOCUMENT_TYPE System parameter does not exist in the parameters list.  The job can not continue without this parameter");
151                return false;
152            }
153            
154            return parameterExists;
155        }
156        
157        /**
158         * This method checks for the system parameter for YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE
159         * @param outputErrorFile_ps output error file stream to write any error messages.
160         * @return true if YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE exists else false
161         */
162        protected boolean checkIfDocumentCompareCreateDateParameterExists() {
163            boolean parameterExists = true;
164            
165            // check to make sure the system parameter for create date to compare has been setup...
166            if (!getParameterService().parameterExists(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE)) {
167              LOG.warn("YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE System parameter does not exist in the parameters list.  The job can not continue without this parameter");
168              autoDisapproveErrorReportWriterService.writeFormattedMessageLine("YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE System parameter does not exist in the parameters list.  The job can not continue without this parameter");
169              return false;
170            }
171            
172            return parameterExists;
173        }
174        
175        /**
176         * This method checks for the system parameter for YEAR_END_AUTO_DISAPPROVE_DOCUMENT_TYPES
177         * @param outputErrorFile_ps output error file stream to write any error messages.
178         * @return true if YEAR_END_AUTO_DISAPPROVE_DOCUMENT_TYPES exists else false
179         */
180        protected boolean checkIfDocumentTypesExceptionParameterExists() {
181            boolean parameterExists = true;
182            
183            // check to make sure the system parameter for Document Types that are exceptions has been setup...
184            if (!getParameterService().parameterExists(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_DOCUMENT_TYPES)) {
185              LOG.warn("YEAR_END_AUTO_DISAPPROVE_DOCUMENT_TYPES System parameter does not exist in the parameters list.  The job can not continue without this parameter");
186              autoDisapproveErrorReportWriterService.writeFormattedMessageLine("YEAR_END_AUTO_DISAPPROVE_DOCUMENT_TYPES System parameter does not exist in the parameters list.  The job can not continue without this parameter");
187              return false;
188            }
189            
190            return parameterExists;
191        }
192    
193        /**
194         * This method checks for the system parameter for YEAR_END_AUTO_DISAPPROVE_ANNOTATION
195         * @param outputErrorFile_ps output error file stream to write any error messages.
196         * @return true if YEAR_END_AUTO_DISAPPROVE_ANNOTATION exists else false
197         */
198        protected boolean checkIfAnnotationForDisapprovalParameterExists() {
199            boolean parameterExists = true;
200            
201            // check to make sure the system parameter for annotation for notes has been setup...
202            if (!getParameterService().parameterExists(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_ANNOTATION)) {
203              LOG.warn("YEAR_END_AUTO_DISAPPROVE_ANNOTATION System parameter does not exist in the parameters list.  The job can not continue without this parameter");
204              autoDisapproveErrorReportWriterService.writeFormattedMessageLine("YEAR_END_AUTO_DISAPPROVE_ANNOTATION System parameter does not exist in the parameters list.  The job can not continue without this parameter");
205              return false;
206            }        
207            
208            return parameterExists;
209        }
210        
211        /**
212         * This method will compare today's date to the system parameter for year end auto disapproval run date
213         * @return true if today's date equals to the system parameter run date
214         */
215        protected boolean canAutoDisapproveJobRun() {
216          boolean autoDisapproveCanRun = true;
217          
218          // IF trunc(SYSDATE - 14/24) = v_yec_cncl_doc_run_dt THEN...FIS CODE equivalent here...
219          String yearEndAutoDisapproveRunDate = getParameterService().getParameterValue(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_DOCUMENT_STEP_RUN_DATE);
220          
221          String today = getDateTimeService().toDateString(getDateTimeService().getCurrentDate());
222          
223          if (!yearEndAutoDisapproveRunDate.equals(today)) {
224              LOG.warn("YEAR_END_AUTO_DISAPPROVE_DOCUMENTS_RUN_DATE: Automatic disapproval bypassed. The date on which the auto disapproval step should run: " + yearEndAutoDisapproveRunDate + " does not equal to today's date: " + today);
225              String message = ("YEAR_END_AUTO_DISAPPROVE_DOCUMENTS_RUN_DATE: Automatic disapproval bypassed. The date on which the auto disapproval step should run: ").concat(yearEndAutoDisapproveRunDate).concat(" does not equal to today's date: ").concat(today);
226              autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message);          
227              autoDisapproveCanRun = false;
228          }
229          
230          return autoDisapproveCanRun;
231        }
232        
233        /**
234         * This method will use documentsearchcriteriaDTO to search for the documents that are in enroute status and disapproves them
235         * @param principalId The principal id which is KFS-SYS System user to run the process under.
236         * @param annotation The annotation to be set as note in the note of the document.
237         * @param documentCompareDate The document create date to compare to
238         */
239        protected boolean processAutoDisapproveDocuments(String principalId, String annotation, Date documentCompareDate) {
240            boolean success = true;
241            
242            WorkflowInfo workflowInfo = new WorkflowInfo();
243            
244            DocumentSearchCriteriaDTO documentSearchCriteriaDTO = new DocumentSearchCriteriaDTO();
245            documentSearchCriteriaDTO.setDocRouteStatus(KEWConstants.ROUTE_HEADER_ENROUTE_CD);
246            documentSearchCriteriaDTO.setSaveSearchForUser(false);
247            
248            try {
249                DocumentSearchResultDTO documentSearchResultDTO = workflowInfo.performDocumentSearch(principalId, documentSearchCriteriaDTO);
250                List<DocumentSearchResultRowDTO> autoDisapproveDocumentsList = documentSearchResultDTO.getSearchResults();
251    
252                String documentHeaderId = null;
253                
254                for (DocumentSearchResultRowDTO autoDisapproveDocument : autoDisapproveDocumentsList) {
255                    for (KeyValueDTO keyValueDTO : autoDisapproveDocument.getFieldValues()) {
256                        if (keyValueDTO.getKey().equals(WORKFLOW_DOCUMENT_HEADER_ID_SEARCH_RESULT_KEY)) {
257                            documentHeaderId = keyValueDTO.getUserDisplayValue();
258                        }
259                    }
260                    
261                    Document document = findDocumentForAutoDisapproval(documentHeaderId);
262                    if (document != null) {
263                        if (checkIfDocumentEligibleForAutoDispproval(document)) {
264                            if (!exceptionsToAutoDisapproveProcess(document, documentCompareDate)) {
265                                try {
266                                    autoDisapprovalYearEndDocument(document, annotation);
267                                    LOG.info("The document with header id: " + documentHeaderId + " is automatically disapproved by this job.");
268                                }
269                                catch (Exception e) {
270                                    LOG.error("Exception encountered trying to auto disapprove the document " + e.getMessage());
271                                    String message = ("Exception encountered trying to auto disapprove the document: ").concat(documentHeaderId);                                    
272                                    autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message); 
273                                }
274                            }
275                            else {
276                                LOG.info("Year End Auto Disapproval Exceptions:  The document: " + documentHeaderId + " is NOT AUTO DISAPPROVED.");
277                            }
278                        } 
279                    }
280                    else {
281                            LOG.error("Document is NULL.  It should never have been null");
282                            String message = ("Error: Document with id: ").concat(documentHeaderId).concat(" - Document is NULL.  It should never have been null");
283                            autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message);                         
284                    }
285                } 
286           } catch (WorkflowException wfe) {
287                success = false;
288                LOG.warn("Error with workflow search for documents for auto disapproval");
289                String message = ("Error with workflow search for documents for auto disapproval.  The auto disapproval job is stopped.");
290                autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message);                                     
291                }
292           
293           return success;
294        }
295            
296        /**
297         * This method will check the document's document type against the parent document type as specified in the system parameter
298         * @param document
299         * @return true if  document type of the document is a child of the parent document.
300         */
301        protected boolean checkIfDocumentEligibleForAutoDispproval(Document document) {
302            boolean documentEligible = false;
303         
304            String yearEndAutoDisapproveParentDocumentType = getParameterService().getParameterValue(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_PARENT_DOCUMENT_TYPE);
305         
306            DocumentType parentDocumentType = (DocumentType) getDocumentTypeService().findByName(yearEndAutoDisapproveParentDocumentType);
307            
308            String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentType();
309            DocumentType childDocumentType = (DocumentType) getDocumentTypeService().findByName(documentTypeName);
310         
311            documentEligible = parentDocumentType.isParentOf(childDocumentType);
312         
313            return documentEligible;
314        }
315        
316        /**
317         * This method finds the date in the system parameters that will be used to compare the create date.
318         * It then adds 23 hours, 59 minutes and 59 seconds to the compare date.
319         * @return  documentCompareDate returns YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE from the system parameter
320         */
321        protected Date getDocumentCompareDateParameter() {
322            Date documentCompareDate = null;
323            
324            String yearEndAutoDisapproveDocumentDate = getParameterService().getParameterValue(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE);
325            
326            if (ObjectUtils.isNull(yearEndAutoDisapproveDocumentDate)) {
327                LOG.warn("Exception: System Parameter YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE can not be determined.");
328                String message = ("Exception: The value for System Parameter YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE can not be determined.  The auto disapproval job is stopped.");
329                autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message);                         
330                throw new RuntimeException("Exception: AutoDisapprovalStep job stopped because System Parameter YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE is null");   
331            }
332            
333            try {
334                Date compareDate = getDateTimeService().convertToDate(yearEndAutoDisapproveDocumentDate);
335                Calendar calendar = Calendar.getInstance();
336                calendar.setTime(compareDate);
337                calendar.set(Calendar.HOUR, 23);
338                calendar.set(Calendar.MINUTE, 59);
339                calendar.set(Calendar.SECOND, 59);
340                documentCompareDate = calendar.getTime();
341            }
342            catch (ParseException pe) {
343                LOG.warn("ParseException: System Parameter YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE can not be determined.");
344                String message = ("ParseException: The value for System Parameter YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE is invalid.  The auto disapproval job is stopped.");
345                autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message);                         
346                throw new RuntimeException("ParseException: AutoDisapprovalStep job stopped because System Parameter YEAR_END_AUTO_DISAPPROVE_DOCUMENT_CREATE_DATE is invalid");   
347            }
348            
349            return documentCompareDate;
350        }
351        
352        /**
353         * This method finds the document for the given document header id
354         * @param documentHeaderId
355         * @return document The document in the workflow that matches the document header id.
356         */
357        protected Document findDocumentForAutoDisapproval(String documentHeaderId) {
358            Document document = null;
359            
360            try {
361                document = documentService.getByDocumentHeaderId(documentHeaderId);
362            }
363            catch (WorkflowException ex) {
364                LOG.error("Exception encountered on finding the document: " + documentHeaderId, ex );
365            } catch ( UnknownDocumentTypeException ex ) {
366                // don't blow up just because a document type is not installed (but don't return it either)
367                LOG.error("Exception encountered on finding the document: " + documentHeaderId, ex );
368            }
369            
370            return document;
371        }
372            
373        /**
374         * This method first checks the document's create date with system parameter date and then
375         * checks the document type name to the system parameter values and returns true if the type name exists
376         * @param document document to check for its document type,  documentCompareDate the system parameter specified date
377         * to compare the current date to this date.
378         * @return true if  document's create date is <= documentCompareDate and if document type is not in the
379         * system parameter document types that are set to disallow.
380         */
381        protected boolean exceptionsToAutoDisapproveProcess(Document document, Date documentCompareDate) {
382            boolean exceptionToDisapprove = true;
383            Date createDate = null;
384    
385            String documentNumber =  document.getDocumentHeader().getDocumentNumber();
386            
387            Timestamp documentCreateDate = document.getDocumentHeader().getWorkflowDocument().getCreateDate();
388            
389            Calendar calendar = Calendar.getInstance();
390            calendar.setTime(documentCompareDate);
391            String strCompareDate = calendar.getTime().toString();
392            
393            try {
394                createDate = getDateTimeService().convertToSqlDate(documentCreateDate);
395            }
396            catch (ParseException pe){
397                LOG.error("Document create date can not be determined.");
398                String message = ("Document create date can not be determined for the document: ").concat(documentNumber).concat(" - Message: ").concat(pe.getMessage());
399                autoDisapproveErrorReportWriterService.writeFormattedMessageLine(message);                         
400                return exceptionToDisapprove;
401            }
402            
403            calendar.setTime(createDate);
404            String strCreateDate = calendar.getTime().toString();
405            
406            if (createDate.before(documentCompareDate) || createDate.equals(documentCompareDate)) {
407                String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentType();
408                
409                ParameterEvaluator evaluatorDocumentType = getParameterService().getParameterEvaluator(AutoDisapproveDocumentsStep.class, KFSParameterKeyConstants.YearEndAutoDisapprovalConstants.YEAR_END_AUTO_DISAPPROVE_DOCUMENT_TYPES, documentTypeName);
410                exceptionToDisapprove = !evaluatorDocumentType.evaluationSucceeds();
411                if (exceptionToDisapprove) {
412                    LOG.info("Document Id: " + documentNumber + " - Exception to Auto Disapprove:  Document's type: " + documentTypeName + " is in the System Parameter For Document Types Exception List.");
413                }
414            }
415            else {
416                LOG.info("Document Id: " + documentNumber + " - Exception to Auto Disapprove:  Document's create date: " + strCreateDate + " is NOT less than or equal to System Parameter Compare Date: " + strCompareDate);            
417                exceptionToDisapprove = true;
418            }
419                    
420            return exceptionToDisapprove;
421        }
422        
423        /** autoDisapprovalYearEndDocument uses DocumentServiceImpl to  mark as disapproved by calling
424         *  DocumentServiceImpl's disapproveDocument method.
425         * 
426         *@param document The document that needs to be auto disapproved in this process
427         *@param annotationForAutoDisapprovalDocument The annotationForAutoDisapprovalDocument that is set as annotations when canceling the edoc.
428         *     
429         */
430        protected void autoDisapprovalYearEndDocument(Document document, String annotationForAutoDisapprovalDocument)  throws Exception {
431            Note approveNote = noteService.createNote(new Note(), document.getDocumentHeader());
432            approveNote.setNoteText(annotationForAutoDisapprovalDocument);
433    
434            Person systemUser = getPersonService().getPersonByPrincipalName(KFSConstants.SYSTEM_USER);
435            approveNote.setAuthorUniversalIdentifier(systemUser.getPrincipalId());
436            
437            noteService.save(approveNote);
438            
439            document.addNote(approveNote);
440            
441            documentService.superUserDisapproveDocument(document, "Disapproval of Outstanding Documents - Year End Cancelation Process");
442        }
443            
444        /**
445         * Sets the documentService attribute value.
446         * 
447         * @param documentService The documentService to set.
448         */    
449        public void setDocumentService(DocumentService documentService) {
450            this.documentService = documentService;
451        }
452        
453        /**
454         * Gets the documentService attribute.
455         * 
456         * @return Returns the documentService.
457         */
458        public DocumentService getDocumentService() {
459            return documentService;
460        }   
461        
462        /**
463         * Gets the parameterService attribute.
464         * 
465         * @return Returns the parameterService.
466         */    
467        protected ParameterService getParameterService() {
468            return parameterService;
469        }
470    
471        /**
472         * Sets the parameterService attribute value.
473         * 
474         * @param parameterService The parameterService to set.
475         */    
476        public void setParameterService(ParameterService parameterService) {
477            this.parameterService = parameterService;
478        }
479    
480        /**
481         * Gets the dateTimeService attribute.
482         * 
483         * @return Returns the dateTimeService.
484         */
485        protected DateTimeService getDateTimeService() {
486            return dateTimeService;
487        }
488    
489        /**
490         * Sets the dateTimeService attribute value.
491         * 
492         * @param dateTimeService The dateTimeService to set.
493         */
494        public void setDateTimeService(DateTimeService dateTimeService) {
495            this.dateTimeService = dateTimeService;
496        }
497        
498        /**
499         * Gets the NoteService, lazily initializing if necessary
500         * @return the NoteService
501         */
502        protected synchronized NoteService getNoteService() {
503            if (this.noteService == null) {
504                this.noteService = KNSServiceLocator.getNoteService();
505            }
506            return this.noteService;
507        }
508        
509        /**
510         * Sets the noteService attribute value.
511         * 
512         * @param noteService The noteService to set.
513         */
514        public void setNoteService(NoteService noteService) {
515            this.noteService = noteService;
516        }
517    
518        /**
519         * @return Returns the personService.
520         */
521        protected PersonService<Person> getPersonService() {
522            if(personService==null)
523                personService = SpringContext.getBean(PersonService.class);
524            return personService;
525        }
526        
527        /**
528         * Gets the documentTypeService attribute.
529         * 
530         * @return Returns the documentTypeService.
531         */
532        protected DocumentTypeService getDocumentTypeService() {
533            if(documentTypeService==null)
534                documentTypeService = SpringContext.getBean(DocumentTypeService.class);
535            return documentTypeService;
536        }
537        
538        /**
539         * Gets the autoDisapproveErrorReportWriterService attribute. 
540         * @return Returns the autoDisapproveErrorReportWriterService.
541         */
542        protected ReportWriterService getAutoDisapproveErrorReportWriterService() {
543            return autoDisapproveErrorReportWriterService;
544        }
545        
546        /**
547         * Sets the autoDisapproveErrorReportWriterService attribute value.
548         * @param autoDisapproveErrorReportWriterService The autoDisapproveErrorReportWriterService to set.
549         */
550        public void setAutoDisapproveErrorReportWriterService(ReportWriterService autoDisapproveErrorReportWriterService) {
551            this.autoDisapproveErrorReportWriterService = autoDisapproveErrorReportWriterService;
552        }
553        
554    }