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 }