001/* 002 * Copyright 2008 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 */ 016package org.kuali.ole.sys.document; 017 018import java.util.Map; 019import java.util.Set; 020 021import org.apache.log4j.Logger; 022import org.kuali.ole.sys.OLEConstants; 023import org.kuali.ole.sys.businessobject.FinancialSystemDocumentHeader; 024import org.kuali.ole.sys.context.SpringContext; 025import org.kuali.ole.sys.document.dataaccess.FinancialSystemDocumentHeaderDao; 026import org.kuali.ole.sys.document.service.FinancialSystemDocumentService; 027import org.kuali.ole.sys.service.impl.OleParameterConstants; 028import org.kuali.rice.core.api.util.type.KualiDecimal; 029import org.kuali.rice.coreservice.framework.parameter.ParameterService; 030import org.kuali.rice.kew.api.WorkflowRuntimeException; 031import org.kuali.rice.kew.api.exception.WorkflowException; 032import org.kuali.rice.kew.framework.postprocessor.DocumentRouteLevelChange; 033import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange; 034import org.kuali.rice.kns.service.DocumentHelperService; 035import org.kuali.rice.krad.bo.DocumentHeader; 036import org.kuali.rice.krad.document.TransactionalDocumentBase; 037import org.kuali.rice.krad.service.BusinessObjectService; 038import org.kuali.rice.krad.util.GlobalVariables; 039 040/** 041 * This class is a OLE specific TransactionalDocumentBase class 042 */ 043public class FinancialSystemTransactionalDocumentBase extends TransactionalDocumentBase implements FinancialSystemTransactionalDocument { 044 private static final Logger LOG = Logger.getLogger(FinancialSystemTransactionalDocumentBase.class); 045 046 protected static final String UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_PARAMETER_NAME = "UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_IND"; 047 048 private static transient BusinessObjectService businessObjectService; 049 private static transient FinancialSystemDocumentService financialSystemDocumentService; 050 private static transient ParameterService parameterService; 051 052 private transient Map<String,Boolean> canEditCache; 053 054 /** 055 * Constructs a FinancialSystemTransactionalDocumentBase.java. 056 */ 057 public FinancialSystemTransactionalDocumentBase() { 058 super(); 059 } 060 061 @Override 062 public FinancialSystemDocumentHeader getFinancialSystemDocumentHeader() { 063 return (FinancialSystemDocumentHeader) documentHeader; 064 } 065 066 /** 067 * @see org.kuali.rice.krad.document.DocumentBase#setDocumentHeader(org.kuali.rice.krad.bo.DocumentHeader) 068 */ 069 @Override 070 public void setDocumentHeader(DocumentHeader documentHeader) { 071 if ((documentHeader != null) && (!FinancialSystemDocumentHeader.class.isAssignableFrom(documentHeader.getClass()))) { 072 throw new IllegalArgumentException("document header of class '" + documentHeader.getClass() + "' is not assignable from financial document header class '" + FinancialSystemDocumentHeader.class + "'"); 073 } 074 this.documentHeader = documentHeader; 075 } 076 077 /** 078 * If the document has a total amount, call method on document to get the total and set in doc header. 079 * 080 * @see org.kuali.rice.krad.document.Document#prepareForSave() 081 */ 082 @Override 083 public void prepareForSave() { 084 if (this instanceof AmountTotaling) { 085 getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(((AmountTotaling) this).getTotalDollarAmount()); 086 } 087 super.prepareForSave(); 088 } 089 090 /** 091 * This is the default implementation which ensures that document note attachment references are loaded. 092 * 093 * @see org.kuali.rice.krad.document.Document#processAfterRetrieve() 094 */ 095 @Override 096 public void processAfterRetrieve() { 097 // set correctedByDocumentId manually, since OJB doesn't maintain that relationship 098 try { 099 DocumentHeader correctingDocumentHeader = SpringContext.getBean(FinancialSystemDocumentHeaderDao.class).getCorrectingDocumentHeader(getFinancialSystemDocumentHeader().getDocumentNumber()); 100 if (correctingDocumentHeader != null) { 101 getFinancialSystemDocumentHeader().setCorrectedByDocumentId(correctingDocumentHeader.getDocumentNumber()); 102 } 103 } catch (Exception e) { 104 LOG.error("Received WorkflowException trying to get route header id from workflow document.", e); 105 throw new WorkflowRuntimeException(e); 106 } 107 // set the ad hoc route recipients too, since OJB doesn't maintain that relationship 108 // TODO - see KULNRVSYS-1054 109 110 super.processAfterRetrieve(); 111 } 112 113 /** 114 * This is the default implementation which checks for a different workflow statuses, and updates the Kuali status accordingly. 115 * 116 * @see org.kuali.rice.krad.document.Document#doRouteStatusChange() 117 */ 118 @Override 119 public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) { 120 if (getDocumentHeader().getWorkflowDocument().isCanceled()) { 121 getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(OLEConstants.DocumentStatusCodes.CANCELLED); 122 } 123 else if (getDocumentHeader().getWorkflowDocument().isEnroute()) { 124 getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(OLEConstants.DocumentStatusCodes.ENROUTE); 125 } 126 if (getDocumentHeader().getWorkflowDocument().isDisapproved()) { 127 getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(OLEConstants.DocumentStatusCodes.DISAPPROVED); 128 } 129 if (getDocumentHeader().getWorkflowDocument().isProcessed()) { 130 getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(OLEConstants.DocumentStatusCodes.APPROVED); 131 } 132 if ( LOG.isInfoEnabled() ) { 133 LOG.info("Document: " + statusChangeEvent.getDocumentId() + " -- Status is: " + getFinancialSystemDocumentHeader().getFinancialDocumentStatusCode()); 134 } 135 136 super.doRouteStatusChange(statusChangeEvent); 137 } 138 139 /** 140 * This is the default implementation which, if parameter KFS-SYS / Document / UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_IND is on, updates the document 141 * and resaves if needed 142 * @see org.kuali.rice.kns.document.DocumentBase#doRouteLevelChange(org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO) 143 */ 144 @Override 145 public void doRouteLevelChange(DocumentRouteLevelChange levelChangeEvent) { 146 if (this instanceof AmountTotaling 147 && getDocumentHeader() != null 148 && getParameterService() != null 149 && getBusinessObjectService() != null 150 && getParameterService().parameterExists(OleParameterConstants.FINANCIAL_SYSTEM_DOCUMENT.class, UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_PARAMETER_NAME) 151 && getParameterService().getParameterValueAsBoolean(OleParameterConstants.FINANCIAL_SYSTEM_DOCUMENT.class, UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_PARAMETER_NAME)) { 152 final KualiDecimal currentTotal = ((AmountTotaling)this).getTotalDollarAmount(); 153 if (!currentTotal.equals(getFinancialSystemDocumentHeader().getFinancialDocumentTotalAmount())) { 154 getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(currentTotal); 155 getBusinessObjectService().save(getFinancialSystemDocumentHeader()); 156 } 157 } 158 super.doRouteLevelChange(levelChangeEvent); 159 } 160 161 /** 162 * @see org.kuali.ole.sys.document.Correctable#toErrorCorrection() 163 */ 164 public void toErrorCorrection() throws WorkflowException, IllegalStateException { 165 DocumentHelperService documentHelperService = SpringContext.getBean(DocumentHelperService.class); 166 final Set<String> documentActionsFromPresentationController = documentHelperService.getDocumentPresentationController(this).getDocumentActions(this); 167 final Set<String> documentActionsFromAuthorizer = documentHelperService.getDocumentAuthorizer(this).getDocumentActions(this, GlobalVariables.getUserSession().getPerson(), documentActionsFromPresentationController); 168 if (!documentActionsFromAuthorizer.contains(OLEConstants.KFS_ACTION_CAN_ERROR_CORRECT)) { 169 throw new IllegalStateException(this.getClass().getName() + " does not support document-level error correction"); 170 } 171 172 String sourceDocumentHeaderId = getDocumentNumber(); 173 setNewDocumentHeader(); 174 getFinancialSystemDocumentHeader().setFinancialDocumentInErrorNumber(sourceDocumentHeaderId); 175 addCopyErrorDocumentNote("error-correction for document " + sourceDocumentHeaderId); 176 } 177 178 @Override 179 public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException { 180 throw new UnsupportedOperationException("No split node logic defined for split node "+nodeName+" on " + this.getClass().getSimpleName()); 181 } 182 183 /** 184 * @return the default implementation of the ParameterService 185 */ 186 protected ParameterService getParameterService() { 187 if (parameterService == null) { 188 parameterService = SpringContext.getBean(ParameterService.class); 189 } 190 return parameterService; 191 } 192 193 /** 194 * @return the default implementation of the BusinessObjectService 195 */ 196 protected BusinessObjectService getBusinessObjectService() { 197 if (businessObjectService == null) { 198 businessObjectService = SpringContext.getBean(BusinessObjectService.class); 199 } 200 return businessObjectService; 201 } 202 203 protected FinancialSystemDocumentService getFinancialSystemDocumentService() { 204 if (financialSystemDocumentService == null) { 205 financialSystemDocumentService = SpringContext.getBean(FinancialSystemDocumentService.class); 206 } 207 return financialSystemDocumentService; 208 } 209 210 @Override 211 public void toCopy() throws WorkflowException, IllegalStateException { 212 FinancialSystemDocumentHeader oldDocumentHeader = getFinancialSystemDocumentHeader(); 213 super.toCopy(); 214 215 getFinancialSystemDocumentService().prepareToCopy(oldDocumentHeader, this); 216 } 217 218 /** 219 * Updates status of this document and saves the workflow data 220 * 221 * @param applicationDocumentStatus is the app doc status to save 222 * @throws WorkflowException 223 */ 224 public void updateAndSaveAppDocStatus(String applicationDocumentStatus) throws WorkflowException { 225 getFinancialSystemDocumentHeader().updateAndSaveAppDocStatus(applicationDocumentStatus); 226 } 227 228 /** 229 * Gets the applicationDocumentStatus attribute. 230 * 231 * @return Returns the applicationDocumentStatus 232 */ 233 234 public String getApplicationDocumentStatus() { 235 return getFinancialSystemDocumentHeader().getApplicationDocumentStatus(); 236 } 237 238 /** 239 * Sets the applicationDocumentStatus attribute. 240 * 241 * @param applicationDocumentStatus The applicationDocumentStatus to set. 242 */ 243 public void setApplicationDocumentStatus(String applicationDocumentStatus) { 244 getFinancialSystemDocumentHeader().setApplicationDocumentStatus(applicationDocumentStatus); 245 } 246}