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.module.endow.document.web.struts; 017 018 import java.io.FileNotFoundException; 019 import java.io.IOException; 020 import java.util.Iterator; 021 import java.util.List; 022 import java.util.Properties; 023 024 import javax.servlet.http.HttpServletRequest; 025 import javax.servlet.http.HttpServletResponse; 026 027 import org.apache.commons.lang.StringUtils; 028 import org.apache.struts.action.ActionForm; 029 import org.apache.struts.action.ActionForward; 030 import org.apache.struts.action.ActionMapping; 031 import org.apache.struts.upload.FormFile; 032 import org.kuali.kfs.module.endow.EndowConstants; 033 import org.kuali.kfs.module.endow.EndowKeyConstants; 034 import org.kuali.kfs.module.endow.EndowPropertyConstants; 035 import org.kuali.kfs.module.endow.businessobject.EndowmentAccountingLine; 036 import org.kuali.kfs.module.endow.businessobject.EndowmentAccountingLineParser; 037 import org.kuali.kfs.module.endow.businessobject.KEMIDCurrentBalance; 038 import org.kuali.kfs.module.endow.businessobject.SourceEndowmentAccountingLine; 039 import org.kuali.kfs.module.endow.businessobject.TargetEndowmentAccountingLine; 040 import org.kuali.kfs.module.endow.document.EndowmentAccountingLinesDocument; 041 import org.kuali.kfs.module.endow.document.EndowmentAccountingLinesDocumentBase; 042 import org.kuali.kfs.module.endow.document.validation.event.AddEndowmentAccountingLineEvent; 043 import org.kuali.kfs.module.endow.document.validation.event.DeleteAccountingLineEvent; 044 import org.kuali.kfs.module.endow.exception.EndowmentAccountingLineException; 045 import org.kuali.kfs.sys.KFSConstants; 046 import org.kuali.kfs.sys.KFSKeyConstants; 047 import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader; 048 import org.kuali.kfs.sys.context.SpringContext; 049 import org.kuali.kfs.sys.document.AmountTotaling; 050 import org.kuali.rice.kns.service.KualiConfigurationService; 051 import org.kuali.rice.kns.service.KualiRuleService; 052 import org.kuali.rice.kns.util.GlobalVariables; 053 import org.kuali.rice.kns.util.KNSConstants; 054 import org.kuali.rice.kns.util.UrlFactory; 055 import org.kuali.rice.kns.web.struts.form.KualiForm; 056 057 public class EndowmentAccountingLinesDocumentActionBase extends EndowmentTransactionLinesDocumentActionBase { 058 protected static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(EndowmentAccountingLinesDocumentActionBase.class); 059 060 /** 061 * This action executes an insert of an TargetEndowmentAccountingLine into a document only after validating the Accounting line 062 * and checking any appropriate business rules. 063 * 064 * @param mapping 065 * @param form 066 * @param request 067 * @param response 068 * @return 069 * @throws Exception 070 */ 071 public ActionForward insertTargetAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 072 EndowmentAccountingLinesDocumentFormBase documentForm = (EndowmentAccountingLinesDocumentFormBase) form; 073 EndowmentAccountingLinesDocument endowmentDocument = (EndowmentAccountingLinesDocument) documentForm.getDocument(); 074 075 TargetEndowmentAccountingLine accLine = (TargetEndowmentAccountingLine) documentForm.getNewTargetAccountingLine(); 076 077 boolean rulePassed = true; 078 079 // check any business rules 080 rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddEndowmentAccountingLineEvent(EndowConstants.NEW_TARGET_ACC_LINE_PROPERTY_NAME, endowmentDocument, accLine)); 081 082 if (rulePassed) { 083 // add accountingLine 084 085 // SpringContext.getBean(PersistenceService.class).refreshAllNonUpdatingReferences(transLine); 086 insertAccountingLine(false, documentForm, accLine); 087 088 // clear the used newTargetLine 089 documentForm.setNewTargetAccountingLine(new TargetEndowmentAccountingLine()); 090 } 091 092 return mapping.findForward(KFSConstants.MAPPING_BASIC); 093 } 094 095 /** 096 * This action executes an insert of an SourceEndowmentAccountingLine into a document only after validating the Accounting line 097 * and checking any appropriate business rules. 098 * 099 * @param mapping 100 * @param form 101 * @param request 102 * @param response 103 * @return 104 * @throws Exception 105 */ 106 public ActionForward insertSourceAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 107 EndowmentAccountingLinesDocumentFormBase documentForm = (EndowmentAccountingLinesDocumentFormBase) form; 108 EndowmentAccountingLinesDocument endowmentDocument = (EndowmentAccountingLinesDocument) documentForm.getDocument(); 109 110 SourceEndowmentAccountingLine accLine = (SourceEndowmentAccountingLine) documentForm.getNewSourceAccountingLine(); 111 112 boolean rulePassed = true; 113 114 // check any business rules 115 rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddEndowmentAccountingLineEvent(EndowConstants.NEW_SOURCE_ACC_LINE_PROPERTY_NAME, endowmentDocument, accLine)); 116 117 if (rulePassed) { 118 // add accountingLine 119 // SpringContext.getBean(PersistenceService.class).refreshAllNonUpdatingReferences(transLine); 120 insertAccountingLine(true, documentForm, accLine); 121 122 // clear the used newTargetLine 123 documentForm.setNewSourceAccountingLine(new SourceEndowmentAccountingLine()); 124 } 125 126 return mapping.findForward(KFSConstants.MAPPING_BASIC); 127 } 128 129 /** 130 * Adds the given accountingLine to the appropriate form-related data structures. 131 * 132 * @param isSource 133 * @param etlDocumentForm 134 * @param line 135 */ 136 protected void insertAccountingLine(boolean isSource, EndowmentAccountingLinesDocumentFormBase etaDocumentForm, EndowmentAccountingLine line) { 137 EndowmentAccountingLinesDocumentBase etaDoc = etaDocumentForm.getEndowmentAccountingLinesDocumentBase(); 138 139 if (isSource) { 140 // add it to the document 141 etaDoc.addSourceAccountingLine((SourceEndowmentAccountingLine) line); 142 } 143 else { 144 // add it to the document 145 etaDoc.addTargetAccountingLine((TargetEndowmentAccountingLine) line); 146 } 147 148 // Update the doc total 149 if (etaDoc instanceof AmountTotaling) 150 ((FinancialSystemDocumentHeader) etaDocumentForm.getDocument().getDocumentHeader()).setFinancialDocumentTotalAmount(((AmountTotaling) etaDoc).getTotalDollarAmount()); 151 } 152 153 /** 154 * This action deletes an EndowmentSourceAccountingLine from a document. 155 * 156 * @param mapping 157 * @param form 158 * @param request 159 * @param response 160 * @return 161 * @throws Exception 162 */ 163 public ActionForward deleteSourceAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 164 EndowmentAccountingLinesDocumentFormBase etlForm = (EndowmentAccountingLinesDocumentFormBase) form; 165 EndowmentAccountingLinesDocument etlDoc = etlForm.getEndowmentAccountingLinesDocumentBase(); 166 167 int deleteIndex = getLineToDelete(request); 168 String errorPath = EndowPropertyConstants.EXISTING_SOURCE_ACCT_LINE_PREFIX + "[" + deleteIndex + "]"; 169 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteAccountingLineEvent(errorPath, etlDoc, etlDoc.getSourceAccountingLine(deleteIndex))); 170 171 // if the rule evaluation passed, let's delete it 172 if (rulePassed) { 173 deleteAccountingLine(true, etlForm, deleteIndex); 174 } 175 else { 176 String[] errorParams = new String[] { "source", Integer.toString(deleteIndex + 1) }; 177 GlobalVariables.getMessageMap().putError(errorPath, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_DELETING_ACCOUNTING_LINE, errorParams); 178 } 179 180 return mapping.findForward(KFSConstants.MAPPING_BASIC); 181 } 182 183 /** 184 * This action deletes an EndowmentTargetAccountingLine from a document. 185 * 186 * @param mapping 187 * @param form 188 * @param request 189 * @param response 190 * @return 191 * @throws Exception 192 */ 193 public ActionForward deleteTargetAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 194 EndowmentAccountingLinesDocumentFormBase etlForm = (EndowmentAccountingLinesDocumentFormBase) form; 195 EndowmentAccountingLinesDocument etlDoc = etlForm.getEndowmentAccountingLinesDocumentBase(); 196 197 int deleteIndex = getLineToDelete(request); 198 String errorPath = EndowPropertyConstants.EXISTING_TARGET_ACCT_LINE_PREFIX + "[" + deleteIndex + "]"; 199 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteAccountingLineEvent(errorPath, etlDoc, etlDoc.getTargetAccountingLine(deleteIndex))); 200 201 // if the rule evaluation passed, let's delete it 202 if (rulePassed) { 203 deleteAccountingLine(false, etlForm, deleteIndex); 204 } 205 else { 206 String[] errorParams = new String[] { "target", Integer.toString(deleteIndex + 1) }; 207 GlobalVariables.getMessageMap().putError(errorPath, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_DELETING_ACCOUNTING_LINE, errorParams); 208 } 209 210 return mapping.findForward(KFSConstants.MAPPING_BASIC); 211 } 212 213 /** 214 * Deletes a Accounting Line. 215 * 216 * @param isSource 217 * @param etlDocumentForm 218 * @param index 219 */ 220 protected void deleteAccountingLine(boolean isSource, EndowmentAccountingLinesDocumentFormBase etlDocumentForm, int index) { 221 if (isSource) { 222 // remove from document 223 etlDocumentForm.getEndowmentAccountingLinesDocumentBase().getSourceAccountingLines().remove(index); 224 225 } 226 else { 227 // remove from document 228 etlDocumentForm.getEndowmentAccountingLinesDocumentBase().getTargetAccountingLines().remove(index); 229 } 230 // update the doc total 231 EndowmentAccountingLinesDocument tdoc = etlDocumentForm.getEndowmentAccountingLinesDocumentBase(); 232 if (tdoc instanceof AmountTotaling) { 233 ((FinancialSystemDocumentHeader) etlDocumentForm.getDocument().getDocumentHeader()).setFinancialDocumentTotalAmount(((AmountTotaling) tdoc).getTotalDollarAmount()); 234 } 235 } 236 237 /** 238 * This method returns the balance inquiry for target accounting lines. 239 * 240 * @param mapping 241 * @param form 242 * @param request 243 * @param response 244 * @return 245 * @throws Exception 246 */ 247 public ActionForward performBalanceInquiryForTargetAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 248 return performBalanceInquiry(false, mapping, form, request, response); 249 } 250 251 /** 252 * This method returns the balance inquiry for source accounting lines. 253 * 254 * @param mapping 255 * @param form 256 * @param request 257 * @param response 258 * @return 259 * @throws Exception 260 */ 261 public ActionForward performBalanceInquiryForSourceAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 262 return performBalanceInquiry(true, mapping, form, request, response); 263 } 264 265 /** 266 * This method provides the KEMIDCurrentBalance as the default lookup object. If a different lookup is needed this method should 267 * be overriden. 268 * 269 * @param isSource 270 * @param mapping 271 * @param form 272 * @param request 273 * @param response 274 * @return 275 * @throws Exception 276 */ 277 public ActionForward performBalanceInquiry(boolean isSource, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 278 String boName = KEMIDCurrentBalance.class.getName(); 279 return performBalanceInquiry(isSource, boName, mapping, form, request, response); 280 } 281 282 /** 283 * This method is similar to org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase.performBalanceInquiry() 284 * 285 * @param isRevenue 286 * @param mapping 287 * @param form 288 * @param request 289 * @param response 290 * @return 291 * @throws Exception 292 */ 293 public ActionForward performBalanceInquiry(boolean isSource, String boName, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 294 final String docNumber; 295 296 // get the selected line, setup parms and redirect to balance inquiry 297 EndowmentAccountingLinesDocumentFormBase etlForm = (EndowmentAccountingLinesDocumentFormBase) form; 298 EndowmentAccountingLinesDocumentBase etlDoc = ((EndowmentAccountingLinesDocumentFormBase) form).getEndowmentAccountingLinesDocumentBase(); 299 300 301 // when we return from the lookup, our next request's method to call is going to be refresh 302 etlForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 303 304 EndowmentAccountingLine etLine; 305 if (isSource) { 306 etLine = etlDoc.getSourceAccountingLines().get(this.getSelectedLine(request)); 307 } 308 else { 309 etLine = etlDoc.getTargetAccountingLines().get(this.getSelectedLine(request)); 310 } 311 312 // build out base path for return location, use config service 313 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 314 315 // this hack sets the return anchor we want to return too after the inquiry 316 // do this here so it gets into the session stored form version 317 // refresh checks for this after and resets the anchor 318 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 319 etlForm.setBalanceInquiryReturnAnchor(((KualiForm) form).getAnchor()); 320 } 321 322 // build out the actual form key that will be used to retrieve the form on refresh 323 String callerDocFormKey = GlobalVariables.getUserSession().addObject(form); 324 325 // now add required parameters 326 Properties params = new Properties(); 327 params.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD); 328 // params.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, boName); 329 params.put(KFSConstants.BALANCE_INQUIRY_REPORT_MENU_CALLER_DOC_FORM_KEY, callerDocFormKey); 330 params.put(KFSConstants.DOC_FORM_KEY, callerDocFormKey); 331 // params.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true"); 332 params.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do"); 333 334 335 if (StringUtils.isNotBlank(etLine.getChartOfAccountsCode())) { 336 params.put("chartOfAccountsCode", etLine.getChartOfAccountsCode()); 337 } 338 if (StringUtils.isNotBlank(etLine.getAccountNumber())) { 339 params.put("accountNumber", etLine.getAccountNumber()); 340 } 341 if (StringUtils.isNotBlank(etLine.getFinancialObjectCode())) { 342 params.put("financialObjectCode", etLine.getFinancialObjectCode()); 343 } 344 if (StringUtils.isNotBlank(etLine.getSubAccountNumber())) { 345 params.put("subAccountNumber", etLine.getSubAccountNumber()); 346 } 347 if (StringUtils.isNotBlank(etLine.getFinancialSubObjectCode())) { 348 params.put("financialSubObjectCode", etLine.getFinancialSubObjectCode()); 349 } 350 if (StringUtils.isNotBlank(etLine.getProjectCode())) { 351 params.put("projectCode", etLine.getProjectCode()); 352 } 353 354 355 String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + KFSConstants.BALANCE_INQUIRY_REPORT_MENU_ACTION, params); 356 357 // register that we're going to come back w/ to this form w/ a refresh methodToCall 358 etlForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 359 360 return new ActionForward(lookupUrl, true); 361 } 362 363 /** 364 * This action executes a call to upload CSV accounting line values as TargetAccountingLines for a given transactional document. 365 * The "uploadAccountingLines()" method handles the multi-part request. 366 * 367 * @param mapping 368 * @param form 369 * @param request 370 * @param response 371 * @return ActionForward 372 * @throws Exception 373 */ 374 public ActionForward uploadTargetLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 375 376 // call method that sourceform and destination list 377 uploadAccountingLines(false, form); 378 379 return mapping.findForward(KFSConstants.MAPPING_BASIC); 380 } 381 382 383 /** 384 * This action executes a call to upload CSV accounting line values as SourceAccountingLines for a given transactional document. 385 * The "uploadAccountingLines()" method handles the multi-part request. 386 * 387 * @param mapping 388 * @param form 389 * @param request 390 * @param response 391 * @return ActionForward 392 * @throws FileNotFoundException 393 * @throws IOException 394 */ 395 public ActionForward uploadSourceLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws FileNotFoundException, IOException { 396 397 // call method that sourceform and destination list 398 uploadAccountingLines(true, form); 399 400 return mapping.findForward(KFSConstants.MAPPING_BASIC); 401 } 402 403 /** 404 * This method determines whether we are uploading source or target lines, and then calls uploadAccountingLines directly on the 405 * document object. This method handles retrieving the actual upload file as an input stream into the document. 406 * 407 * @param isSource 408 * @param form 409 * @throws FileNotFoundException 410 * @throws IOException 411 */ 412 protected void uploadAccountingLines(boolean isSource, ActionForm form) throws FileNotFoundException, IOException { 413 EndowmentAccountingLinesDocumentFormBase tmpForm = (EndowmentAccountingLinesDocumentFormBase) form; 414 415 List importedLines = null; 416 417 EndowmentAccountingLinesDocument financialDocument = tmpForm.getEndowmentAccountingLinesDocumentBase(); 418 EndowmentAccountingLineParser accountingLineParser = financialDocument.getEndowmentAccountingLineParser(); 419 420 // import the lines 421 String errorPathPrefix = null; 422 try { 423 if (isSource) { 424 errorPathPrefix = EndowPropertyConstants.EXISTING_SOURCE_ACCT_LINE_PREFIX; 425 FormFile sourceFile = tmpForm.getSourceFile(); 426 checkUploadFile(sourceFile); 427 importedLines = accountingLineParser.importSourceEndowmentAccountingLines(sourceFile.getFileName(), sourceFile.getInputStream(), financialDocument); 428 } 429 else { 430 errorPathPrefix = EndowPropertyConstants.EXISTING_TARGET_ACCT_LINE_PREFIX; 431 FormFile targetFile = tmpForm.getTargetFile(); 432 checkUploadFile(targetFile); 433 importedLines = accountingLineParser.importTargetEndowmentAccountingLines(targetFile.getFileName(), targetFile.getInputStream(), financialDocument); 434 } 435 } 436 catch (EndowmentAccountingLineException e) { 437 GlobalVariables.getMessageMap().putError(errorPathPrefix, e.getErrorKey(), e.getErrorParameters()); 438 } 439 440 // add line to list for those lines which were successfully imported 441 if (importedLines != null) { 442 for (Iterator i = importedLines.iterator(); i.hasNext();) { 443 EndowmentAccountingLine importedLine = (EndowmentAccountingLine) i.next(); 444 insertAccountingLine(isSource, tmpForm, importedLine); 445 } 446 } 447 } 448 449 /** 450 * This method... 451 * 452 * @param file 453 */ 454 protected void checkUploadFile(FormFile file) { 455 if (file == null) { 456 throw new EndowmentAccountingLineException("invalid (null) upload file", KFSKeyConstants.ERROR_UPLOADFILE_NULL); 457 } 458 } 459 460 461 }