View Javadoc
1   package org.kuali.ole.sys.form;
2   
3   import org.apache.commons.lang.StringUtils;
4   import org.apache.struts.upload.FormFile;
5   import org.kuali.ole.coa.businessobject.Account;
6   import org.kuali.ole.coa.businessobject.ObjectCode;
7   import org.kuali.ole.coa.businessobject.SubAccount;
8   import org.kuali.ole.coa.businessobject.SubObjectCode;
9   import org.kuali.ole.olekrad.form.OLEKRADTransactionalForm;
10  import org.kuali.ole.sys.OLEConstants;
11  import org.kuali.ole.sys.OLEPropertyConstants;
12  import org.kuali.ole.sys.businessobject.*;
13  import org.kuali.ole.sys.context.SpringContext;
14  import org.kuali.ole.sys.document.AccountingDocument;
15  import org.kuali.ole.sys.document.OLEAccountingDocument;
16  import org.kuali.ole.sys.document.web.form.OLEFinancialSystemTransactionalDocumentFormBase;
17  import org.kuali.ole.sys.service.impl.OleParameterConstants;
18  import org.kuali.rice.core.api.config.property.ConfigurationService;
19  import org.kuali.rice.core.web.format.CurrencyFormatter;
20  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
21  import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
22  import org.kuali.rice.krad.service.DataDictionaryService;
23  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
24  import org.kuali.rice.krad.util.KRADConstants;
25  import org.kuali.rice.krad.util.ObjectUtils;
26  import org.kuali.rice.krad.web.form.TransactionalDocumentFormBase;
27  import org.springframework.web.multipart.commons.CommonsMultipartResolver;
28  
29  import javax.servlet.http.HttpServletRequest;
30  import java.util.*;
31  
32  /**
33   * This class is the base action form for all financial documents.
34   */
35  public class OLEKualiAccountingDocumentFormBase extends OLEFinancialSystemTransactionalDocumentFormBase {
36      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OLEKualiAccountingDocumentFormBase.class);
37  
38      protected SourceAccountingLine newSourceLine;
39      protected TargetAccountingLine newTargetLine;
40  
41  
42  
43      protected Map editableAccounts;
44      protected Map forcedLookupOptionalFields;
45  
46      // TODO: FormFile isn't Serializable, so mark these fields need as transient or create a Serializable subclass of FormFile
47      protected FormFile sourceFile;
48      protected FormFile targetFile;
49      protected boolean hideDetails = false;
50  
51      /**
52       * This constructor sets up empty instances for the dependent objects...
53       */
54      public OLEKualiAccountingDocumentFormBase() {
55          super();
56  
57          // create an empty editableAccounts map, for safety's sake
58          editableAccounts = new HashMap();
59          //forcedReadOnlyFields = new HashMap();
60          forcedLookupOptionalFields = new HashMap();
61      }
62  
63  
64      /**
65       * Overrides the parent to call super.populate and then to call the accounting lines populate method that is specific to loading
66       * the two select lists on the page.
67       *
68       * @see
69       */
70     // @Override
71      public void populate(HttpServletRequest request) {
72         // super.populate(request);
73          final String methodToCall = this.getMethodToCall();
74          final Map parameterMap = request.getParameterMap();
75  
76          populateAccountingLinesForResponse(methodToCall, parameterMap);
77  
78          setDocTypeName(((DataDictionaryService) KRADServiceLocatorWeb.getDataDictionaryService()).getDataDictionary().getDocumentEntry(getDocument().getClass().getName()).getDocumentTypeName());
79      }
80  
81      /**
82       * Populates the accounting lines which need to be updated to successfully complete a response to the request
83       * @param methodToCall the method to call in the action to complete this request transaction
84       * @param parameterMap the map of parameters which came in with the transaction
85       */
86      protected void populateAccountingLinesForResponse(String methodToCall, Map parameterMap) {
87          populateSourceAccountingLine(getNewSourceLine(), OLEPropertyConstants.NEW_SOURCE_LINE, parameterMap);
88          populateTargetAccountingLine(getNewTargetLine(), OLEPropertyConstants.NEW_TARGET_LINE, parameterMap);
89  
90          // don't call populateAccountingLines if you are copying or errorCorrecting a document,
91          // since you want the accountingLines in the copy to be "identical" to those in the original
92          if (!StringUtils.equals(methodToCall, OLEConstants.COPY_METHOD) && !StringUtils.equals(methodToCall, OLEConstants.ERRORCORRECT_METHOD)) {
93              populateAccountingLines(parameterMap);
94          }
95      }
96  
97      /**
98       * This method iterates over all of the source lines and all of the target lines in a transactional document, and calls
99       * prepareAccountingLineForValidationAndPersistence on each one. This is called because a user could have updated already
100      * existing accounting lines that had blank values in composite key fields.
101      *
102      * @param parameterMap the map of parameters that were sent in with the request
103      */
104     protected void populateAccountingLines(Map parameterMap) {
105         Iterator sourceLines = getFinancialDocument().getSourceAccountingLines().iterator();
106         int count = 0;
107         while (sourceLines.hasNext()) {
108             SourceAccountingLine sourceLine = (SourceAccountingLine) sourceLines.next();
109             populateSourceAccountingLine(sourceLine, OLEPropertyConstants.DOCUMENT+"."+OLEPropertyConstants.SOURCE_ACCOUNTING_LINE+"["+count+"]", parameterMap);
110             count += 1;
111         }
112 
113         Iterator targetLines = getFinancialDocument().getTargetAccountingLines().iterator();
114         count = 0;
115         while (targetLines.hasNext()) {
116             TargetAccountingLine targetLine = (TargetAccountingLine) targetLines.next();
117             populateTargetAccountingLine(targetLine, OLEPropertyConstants.DOCUMENT+"."+OLEPropertyConstants.TARGET_ACCOUNTING_LINE+"["+count+"]", parameterMap);
118             count += 1;
119         }
120     }
121 
122     /**
123      * Populates a source accounting line bo using values from the struts form. This is in place to make sure that all of the
124      * composite key objects have the correct values in them. This should be overridden by children forms in the situation where
125      * document level attributes need to be pushed down into the accounting lines.
126      *
127      * @param sourceLine
128      * @param accountingLinePropertyName the property path from the form to the accounting line
129      * @param parameterMap the map of parameters that were sent in with the request
130      */
131     public void populateSourceAccountingLine(SourceAccountingLine sourceLine, String accountingLinePropertyName, Map parameterMap) {
132         populateAccountingLine(sourceLine, accountingLinePropertyName, parameterMap);
133     }
134 
135     /**
136      * Populates a target accounting line bo using values from the struts form. This is in place to make sure that all of the
137      * composite key objects have the correct values in them. This should be overridden by children forms in the situation where
138      * document level attributes need to be pushed down into the accounting lines.
139      *
140      * @param targetLine
141      * @param accountingLinePropertyName the property path from the form to the accounting line
142      * @param parameterMap the map of parameters that were sent in with the request
143      */
144     public void populateTargetAccountingLine(TargetAccountingLine targetLine, String accountingLinePropertyName, Map parameterMap) {
145         populateAccountingLine(targetLine, accountingLinePropertyName, parameterMap);
146     }
147 
148     /**
149      * Populates the dependent fields of objects contained within the given accountingLine
150      *
151      * @param line
152      * @param accountingLinePropertyName the property path from the form to the accounting line
153      * @param parameterMap the map of parameters that were sent in with the request
154      */
155     @SuppressWarnings("deprecation")
156     protected void populateAccountingLine(AccountingLine line, String accountingLinePropertyName, Map parameterMap) {
157         SpringContext.getBean(BusinessObjectDictionaryService.class).performForceUppercase(line);
158 
159         line.setDocumentNumber(getDocument().getDocumentNumber());
160 
161         if (ObjectUtils.isNull(line.getAccount())) {
162             line.setAccount(new Account());
163         }
164         line.getAccount().setChartOfAccountsCode(line.getChartOfAccountsCode());
165 
166         if (ObjectUtils.isNull(line.getObjectCode())) {
167             line.setObjectCode(new ObjectCode());
168         }
169         line.getObjectCode().setUniversityFiscalYear(getFinancialDocument().getPostingYear());
170         line.getObjectCode().setChartOfAccountsCode(line.getChartOfAccountsCode());
171 
172         if (ObjectUtils.isNull(line.getSubAccount())) {
173             line.setSubAccount(new SubAccount());
174         }
175         line.getSubAccount().setChartOfAccountsCode(line.getChartOfAccountsCode());
176         line.getSubAccount().setAccountNumber(line.getAccountNumber());
177 
178         if (ObjectUtils.isNull(line.getSubObjectCode())) {
179             line.setSubObjectCode(new SubObjectCode());
180         }
181         line.getSubObjectCode().setChartOfAccountsCode(line.getChartOfAccountsCode());
182         line.getSubObjectCode().setAccountNumber(line.getAccountNumber());
183         line.getSubObjectCode().setFinancialObjectCode(line.getFinancialObjectCode());
184         line.getSubObjectCode().setUniversityFiscalYear(getFinancialDocument().getPostingYear());
185 
186         repopulateOverrides(line, accountingLinePropertyName, parameterMap);
187 
188         AccountingLineOverride.populateFromInput(line);
189     }
190 
191     /**
192      * This repopulates the override values from the request
193      * @param line the line to repopulate override values for
194      * @param accountingLinePropertyName the property path from the form to the accounting line
195      * @param parameterMap the map of parameters that were sent in with the request
196      */
197     protected void repopulateOverrides(AccountingLine line, String accountingLinePropertyName, Map parameterMap) {
198         OLEAccountingLineOverride.determineNeededOverrides(getFinancialDocument(), line);
199         if (line.getAccountExpiredOverrideNeeded()) {
200             if (LOG.isDebugEnabled()) {
201                 StringUtils.join(parameterMap.keySet(), "\n");
202             }
203             if (parameterMap.containsKey(accountingLinePropertyName+".accountExpiredOverride.present")) {
204                 line.setAccountExpiredOverride(parameterMap.containsKey(accountingLinePropertyName+".accountExpiredOverride"));
205             }
206         } else {
207             line.setAccountExpiredOverride(false);
208         }
209         if (line.isObjectBudgetOverrideNeeded()) {
210             if (parameterMap.containsKey(accountingLinePropertyName+".objectBudgetOverride.present")) {
211                 line.setObjectBudgetOverride(parameterMap.containsKey(accountingLinePropertyName+".objectBudgetOverride"));
212             }
213         } else {
214             line.setObjectBudgetOverride(false);
215         }
216     }
217 
218     /**
219      * This method retrieves an instance of the form.
220      *
221      * @return
222      */
223     public OLEAccountingDocument getFinancialDocument() {
224         return (OLEAccountingDocument) getDocument();
225     }
226 
227     /**
228      * @return Returns the newTargetLine.
229      */
230     public TargetAccountingLine getNewTargetLine() {
231         if (newTargetLine == null) {
232             newTargetLine = createNewTargetAccountingLine(getFinancialDocument());
233         }
234         return newTargetLine;
235     }
236 
237     /**
238      * @param newExpenseLine The newTargetLine to set.
239      */
240     public void setNewTargetLine(TargetAccountingLine newExpenseLine) {
241         this.newTargetLine = newExpenseLine;
242     }
243 
244     /**
245      * @return Returns the newSourceLine.
246      */
247     public SourceAccountingLine getNewSourceLine() {
248         if (newSourceLine == null) {
249             newSourceLine = createNewSourceAccountingLine(getFinancialDocument());
250         }
251         return newSourceLine;
252     }
253 
254     /**
255      * @param newIncomeLine The newSourceLine to set.
256      */
257     public void setNewSourceLine(SourceAccountingLine newIncomeLine) {
258         this.newSourceLine = newIncomeLine;
259     }
260 
261     /**
262      * @return Returns the sourceFile.
263      */
264     public FormFile getSourceFile() {
265         return sourceFile;
266     }
267 
268     /**
269      * @param sourceFile The sourceFile to set.
270      */
271     public void setSourceFile(FormFile sourceFile) {
272         this.sourceFile = sourceFile;
273     }
274 
275     /**
276      * @return Returns the targetFile.
277      */
278     public FormFile getTargetFile() {
279         return targetFile;
280     }
281 
282     /**
283      * @param targetFile The targetFile to set.
284      */
285     public void setTargetFile(FormFile targetFile) {
286         this.targetFile = targetFile;
287     }
288 
289 
290     /**
291      * @return current Map of editableAccounts
292      */
293     public Map getEditableAccounts() {
294         return editableAccounts;
295     }
296 
297     /**
298      * @param editableAccounts the account Map to set
299      */
300     public void setEditableAccounts(Map editableAccounts) {
301         this.editableAccounts = editableAccounts;
302     }
303 
304     /**
305      * @return hideDetails attribute
306      */
307     public boolean isHideDetails() {
308         return hideDetails;
309     }
310 
311     /**
312      * @return hideDetails attribute
313      * @see #isHideDetails()
314      */
315     public boolean getHideDetails() {
316         return isHideDetails();
317     }
318 
319     /**
320      * @param hideDetails
321      */
322     public void setHideDetails(boolean hideDetails) {
323         this.hideDetails = hideDetails;
324     }
325 
326     /**
327      * Retrieves the source accounting lines total in a currency format with commas.
328      *
329      * @return String
330      */
331     public String getCurrencyFormattedSourceTotal() {
332         return (String) new CurrencyFormatter().format(getFinancialDocument().getSourceTotal());
333     }
334 
335     /**
336      * Retrieves the source accounting lines total in a currency format with commas.
337      *
338      * @return String
339      */
340     public String getCurrencyFormattedTargetTotal() {
341         return (String) new CurrencyFormatter().format(getFinancialDocument().getTargetTotal());
342     }
343 
344     /**
345      * @return the URL to the accounting line import instructions
346      */
347     public String getAccountingLineImportInstructionsUrl() {
348         return SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.EXTERNALIZABLE_HELP_URL_KEY) + SpringContext.getBean(ParameterService.class).getParameterValueAsString(OleParameterConstants.FINANCIAL_SYSTEM_DOCUMENT.class, OLEConstants.FinancialApcParms.ACCOUNTING_LINE_IMPORT_HELP);
349     }
350 
351     /**
352      * @param financialDocument
353      * @return a new source accounting line for the document
354      */
355     protected SourceAccountingLine createNewSourceAccountingLine(OLEAccountingDocument financialDocument) {
356         if (financialDocument == null) {
357             throw new IllegalArgumentException("invalid (null) document");
358         }
359         try {
360             return (SourceAccountingLine) financialDocument.getSourceAccountingLineClass().newInstance();
361         }
362         catch (Exception e) {
363             throw new IllegalArgumentException("unable to create a new source accounting line", e);
364         }
365     }
366 
367     /**
368      * @param financialDocument
369      * @return a new target accounting line for the documet
370      */
371     protected TargetAccountingLine createNewTargetAccountingLine(OLEAccountingDocument financialDocument) {
372         if (financialDocument == null) {
373             throw new IllegalArgumentException("invalid (null) document");
374         }
375         try {
376             return (TargetAccountingLine) financialDocument.getTargetAccountingLineClass().newInstance();
377         }
378         catch (Exception e) {
379             throw new IllegalArgumentException("unable to create a new target accounting line", e);
380         }
381     }
382 
383     /**
384      * This method takes a generic list, hopefully with some AccountingLine objects in it, and returns a list of AccountingLine
385      * objects, because Java generics are just so wonderful.
386      *
387      * @param lines a list of objects
388      * @return a list of the accounting lines that were in the lines parameter
389      */
390     protected List<AccountingLine> harvestAccountingLines(List lines) {
391         List<AccountingLine> accountingLines = new ArrayList<AccountingLine>();
392         for (Object o : lines) {
393             if (o instanceof AccountingLine) {
394                 accountingLines.add((AccountingLine) o);
395             }
396         }
397         return accountingLines;
398     }
399 
400     /**
401      * A <code>{@link Map}</code> of names of optional accounting line fields that require a quickfinder.
402      *
403      * @return a Map of fields
404      */
405     public void setForcedLookupOptionalFields(Map fieldMap) {
406         forcedLookupOptionalFields = fieldMap;
407     }
408 
409     /**
410      * A <code>{@link Map}</code> of names of optional accounting line fields that require a quickfinder.
411      *
412      * @return a Map of fields
413      */
414     public Map getForcedLookupOptionalFields() {
415         return forcedLookupOptionalFields;
416     }
417 
418     /**
419      * Adds the accounting line file size to the list of max file sizes.
420      *
421      * @see org.kuali.rice.kns.web.struts.form.pojo.PojoFormBase#customInitMaxUploadSizes()
422      */
423     //@Override
424     protected void customInitMaxUploadSizes() {
425         long maxUploadSize = ((CommonsMultipartResolver)SpringContext.getBean("multipartResolver")).getFileUpload().getSizeMax();
426        // addMaxUploadSize(SpringContext.getBean(ParameterService.class).getParameterValueAsString(OleParameterConstants.FINANCIAL_SYSTEM_DOCUMENT.class, OLEConstants.ACCOUNTING_LINE_IMPORT_MAX_FILE_SIZE_PARM_NM));
427     }
428 
429     /**
430      * @see org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase#shouldMethodToCallParameterBeUsed(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest)
431      */
432    // @Override
433     public boolean shouldMethodToCallParameterBeUsed(String methodToCallParameterName, String methodToCallParameterValue, HttpServletRequest request) {
434         if(StringUtils.equals(methodToCallParameterName, KRADConstants.DISPATCH_REQUEST_PARAMETER)) {
435             if(this.getExcludedmethodToCall().contains(methodToCallParameterValue)) {
436                 return true;
437             }
438         }
439        // return super.shouldMethodToCallParameterBeUsed(methodToCallParameterName, methodToCallParameterValue, request);
440         return false;
441     }
442 
443     /**
444      * get the names of the methods to call that can be excluded from the "be used" check.
445      * @return the names of the methods to call that can be excluded from the "be used" check
446      */
447     protected List<String> getExcludedmethodToCall() {
448         return new ArrayList<String>();
449     }
450 }