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.document;
017    
018    import java.util.Set;
019    
020    import org.apache.log4j.Logger;
021    import org.kuali.kfs.sys.KFSConstants;
022    import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader;
023    import org.kuali.kfs.sys.context.SpringContext;
024    import org.kuali.kfs.sys.document.dataaccess.FinancialSystemDocumentHeaderDao;
025    import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
026    import org.kuali.rice.kew.exception.WorkflowException;
027    import org.kuali.rice.kew.exception.WorkflowRuntimeException;
028    import org.kuali.rice.kns.bo.DocumentHeader;
029    import org.kuali.rice.kns.document.TransactionalDocumentBase;
030    import org.kuali.rice.kns.service.DateTimeService;
031    import org.kuali.rice.kns.service.DocumentHelperService;
032    import org.kuali.rice.kns.util.GlobalVariables;
033    
034    /**
035     * This class is a KFS specific TransactionalDocumentBase class
036     */
037    public class FinancialSystemTransactionalDocumentBase extends TransactionalDocumentBase implements FinancialSystemTransactionalDocument {
038        protected static final Logger LOG = Logger.getLogger(FinancialSystemTransactionalDocumentBase.class);
039    
040        protected FinancialSystemDocumentHeader documentHeader;
041    
042        /**
043         * Constructs a FinancialSystemTransactionalDocumentBase.java.
044         */
045        public FinancialSystemTransactionalDocumentBase() {
046            super();
047        }
048    
049        /**
050         * @see org.kuali.rice.kns.document.DocumentBase#getDocumentHeader()
051         */
052        @Override
053        public FinancialSystemDocumentHeader getDocumentHeader() {
054            return documentHeader;
055        }
056    
057        /**
058         * @see org.kuali.rice.kns.document.DocumentBase#setDocumentHeader(org.kuali.rice.kns.bo.DocumentHeader)
059         */
060        @Override
061        public void setDocumentHeader(DocumentHeader documentHeader) {
062            if ((documentHeader != null) && (!FinancialSystemDocumentHeader.class.isAssignableFrom(documentHeader.getClass()))) {
063                throw new IllegalArgumentException("document header of class '" + documentHeader.getClass() + "' is not assignable from financial document header class '" + FinancialSystemDocumentHeader.class + "'");
064            }
065            this.documentHeader = (FinancialSystemDocumentHeader) documentHeader;
066        }
067    
068        /**
069         * If the document has a total amount, call method on document to get the total and set in doc header.
070         * 
071         * @see org.kuali.rice.kns.document.Document#prepareForSave()
072         */
073        @Override
074        public void prepareForSave() {
075            if (this instanceof AmountTotaling) {
076                getDocumentHeader().setFinancialDocumentTotalAmount(((AmountTotaling) this).getTotalDollarAmount());
077            }
078            super.prepareForSave();
079        }
080    
081        /**
082         * This is the default implementation which ensures that document note attachment references are loaded.
083         * 
084         * @see org.kuali.rice.kns.document.Document#processAfterRetrieve()
085         */
086        @Override
087        public void processAfterRetrieve() {
088            // set correctedByDocumentId manually, since OJB doesn't maintain that relationship
089            try {
090                DocumentHeader correctingDocumentHeader = SpringContext.getBean(FinancialSystemDocumentHeaderDao.class).getCorrectingDocumentHeader(getDocumentHeader().getWorkflowDocument().getRouteHeaderId().toString());
091                if (correctingDocumentHeader != null) {
092                    getDocumentHeader().setCorrectedByDocumentId(correctingDocumentHeader.getDocumentNumber());
093                }
094            } catch (WorkflowException e) {
095                LOG.error("Received WorkflowException trying to get route header id from workflow document");
096                throw new WorkflowRuntimeException(e);
097            }
098            // set the ad hoc route recipients too, since OJB doesn't maintain that relationship
099            // TODO - see KULNRVSYS-1054
100    
101            super.processAfterRetrieve();
102        }
103    
104        /**
105         * This is the default implementation which checks for a different workflow statuses, and updates the Kuali status accordingly.
106         * 
107         * @see org.kuali.rice.kns.document.Document#doRouteStatusChange()
108         */
109        @Override
110        public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) {
111            if (getDocumentHeader().getWorkflowDocument().stateIsCanceled()) {
112                getDocumentHeader().setFinancialDocumentStatusCode(KFSConstants.DocumentStatusCodes.CANCELLED);
113            }
114            else if (getDocumentHeader().getWorkflowDocument().stateIsEnroute()) {
115                getDocumentHeader().setFinancialDocumentStatusCode(KFSConstants.DocumentStatusCodes.ENROUTE);
116            }
117            if (getDocumentHeader().getWorkflowDocument().stateIsDisapproved()) {
118                getDocumentHeader().setFinancialDocumentStatusCode(KFSConstants.DocumentStatusCodes.DISAPPROVED);
119            }
120            if (getDocumentHeader().getWorkflowDocument().stateIsProcessed()) {
121                getDocumentHeader().setFinancialDocumentStatusCode(KFSConstants.DocumentStatusCodes.APPROVED);
122            }
123            if ( LOG.isInfoEnabled() ) {
124                LOG.info("Document: " + statusChangeEvent.getRouteHeaderId() + " -- Status is: " + getDocumentHeader().getFinancialDocumentStatusCode());
125            }
126           
127            super.doRouteStatusChange(statusChangeEvent);
128        }
129        
130    
131        /**
132         * @see org.kuali.kfs.sys.document.Correctable#toErrorCorrection()
133         */
134        public void toErrorCorrection() throws WorkflowException, IllegalStateException {
135            DocumentHelperService documentHelperService = SpringContext.getBean(DocumentHelperService.class);
136            final Set<String> documentActionsFromPresentationController = documentHelperService.getDocumentPresentationController(this).getDocumentActions(this);
137            final Set<String> documentActionsFromAuthorizer = documentHelperService.getDocumentAuthorizer(this).getDocumentActions(this, GlobalVariables.getUserSession().getPerson(), documentActionsFromPresentationController);
138            if (!documentActionsFromAuthorizer.contains(KFSConstants.KFS_ACTION_CAN_ERROR_CORRECT)) {
139                throw new IllegalStateException(this.getClass().getName() + " does not support document-level error correction");
140            }
141    
142            String sourceDocumentHeaderId = getDocumentNumber();
143            setNewDocumentHeader();
144            getDocumentHeader().setFinancialDocumentInErrorNumber(sourceDocumentHeaderId);
145            addCopyErrorDocumentNote("error-correction for document " + sourceDocumentHeaderId);
146        }
147    
148        public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
149            throw new UnsupportedOperationException("No split node logic defined for split node "+nodeName+" on " + this.getClass().getSimpleName());
150        }
151    }