001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.financial.web.struts.action;
017:
018: import java.io.FileNotFoundException;
019: import java.io.IOException;
020: import java.util.ArrayList;
021:
022: import javax.servlet.http.HttpServletRequest;
023: import javax.servlet.http.HttpServletResponse;
024:
025: import org.apache.commons.lang.StringUtils;
026: import org.apache.struts.action.ActionForm;
027: import org.apache.struts.action.ActionForward;
028: import org.apache.struts.action.ActionMapping;
029: import org.kuali.core.document.AmountTotaling;
030: import org.kuali.core.question.ConfirmationQuestion;
031: import org.kuali.core.service.KualiConfigurationService;
032: import org.kuali.core.util.GlobalVariables;
033: import org.kuali.core.util.KualiDecimal;
034: import org.kuali.core.web.format.CurrencyFormatter;
035: import org.kuali.core.web.struts.form.KualiDocumentFormBase;
036: import org.kuali.kfs.KFSConstants;
037: import org.kuali.kfs.KFSKeyConstants;
038: import org.kuali.kfs.bo.AccountingLine;
039: import org.kuali.kfs.bo.SourceAccountingLine;
040: import org.kuali.kfs.context.SpringContext;
041: import org.kuali.kfs.web.struts.action.KualiAccountingDocumentActionBase;
042: import org.kuali.kfs.web.struts.form.KualiAccountingDocumentFormBase;
043: import org.kuali.module.financial.bo.VoucherAccountingLineHelper;
044: import org.kuali.module.financial.bo.VoucherAccountingLineHelperBase;
045: import org.kuali.module.financial.document.VoucherDocument;
046: import org.kuali.module.financial.service.UniversityDateService;
047: import org.kuali.module.financial.web.struts.form.VoucherForm;
048:
049: import edu.iu.uis.eden.exception.WorkflowException;
050:
051: /**
052: * This class piggy backs on all of the functionality in the KualiTransactionalDocumentActionBase but is necessary for this document
053: * type. Vouchers are unique in that they define several fields that aren't typically used by the other financial transaction
054: * processing eDocs (i.e. external system fields, object type override, credit and debit amounts).
055: */
056: public class VoucherAction extends KualiAccountingDocumentActionBase {
057: // used to determine which way the change balance type action is switching
058: // these are local constants only used within this action class
059: // these should not be used outside of this class
060:
061: /**
062: * We want to keep the bad data for the voucher.
063: */
064: @Override
065: protected boolean revertAccountingLine(
066: KualiAccountingDocumentFormBase transForm, int revertIndex,
067: AccountingLine originalLine, AccountingLine brokenLine) {
068: boolean reverted = super .revertAccountingLine(transForm,
069: revertIndex, originalLine, brokenLine);
070:
071: if (reverted) {
072: VoucherForm vForm = (VoucherForm) transForm;
073: VoucherAccountingLineHelper helper = vForm
074: .getVoucherLineHelper(revertIndex);
075:
076: String debitCreditCode = originalLine.getDebitCreditCode();
077: if (StringUtils.equals(debitCreditCode,
078: KFSConstants.GL_DEBIT_CODE)) {
079: helper.setDebit(originalLine.getAmount());
080: helper.setCredit(KFSConstants.ZERO);
081: } else if (StringUtils.equals(debitCreditCode,
082: KFSConstants.GL_CREDIT_CODE)) {
083: helper.setDebit(KFSConstants.ZERO);
084: helper.setCredit(originalLine.getAmount());
085: }
086: // intentionally ignoring the case where debitCreditCode is neither debit nor credir
087: }
088:
089: return reverted;
090: }
091:
092: /**
093: * Overrides to call super, and then to repopulate the credit/debit amounts b/c the credit/debit code might change during a
094: * voucher error correction.
095: *
096: * @see org.kuali.core.web.struts.action.KualiTransactionalDocumentActionBase#correct(org.apache.struts.action.ActionMapping,
097: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
098: */
099: @Override
100: public ActionForward correct(ActionMapping mapping,
101: ActionForm form, HttpServletRequest request,
102: HttpServletResponse response) throws Exception {
103: ActionForward actionForward = super .correct(mapping, form,
104: request, response);
105:
106: VoucherForm vForm = (VoucherForm) form;
107:
108: // now make sure to repopulate credit/debit amounts
109: populateAllVoucherAccountingLineHelpers(vForm);
110:
111: return actionForward;
112: }
113:
114: /**
115: * Overrides parent to first populate the new source line with the correct debit or credit value, then it calls the parent's
116: * implementation.
117: *
118: * @see org.kuali.module.financial.web.struts.action.KualiFinancialDocumentActionBase#insertSourceLine(org.apache.struts.action.ActionMapping,
119: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
120: */
121: @Override
122: public ActionForward insertSourceLine(ActionMapping mapping,
123: ActionForm form, HttpServletRequest request,
124: HttpServletResponse response) throws Exception {
125: // cast the form to the right pojo
126: VoucherForm voucherForm = (VoucherForm) form;
127:
128: // call the super's method
129: ActionForward actionForward = super .insertSourceLine(mapping,
130: form, request, response);
131:
132: if (GlobalVariables.getErrorMap().getErrorCount() == 0) {
133: // since no exceptions were thrown, the add succeeded, so we have to re-init the new credit and debit
134: // attributes, and add a new instance of a helperLine to the helperLines list
135: VoucherAccountingLineHelper helperLine = populateNewVoucherAccountingLineHelper(voucherForm);
136: voucherForm.getVoucherLineHelpers().add(helperLine);
137:
138: // now reset the debit and credit fields for adds
139: voucherForm.setNewSourceLineDebit(KualiDecimal.ZERO);
140: voucherForm.setNewSourceLineCredit(KualiDecimal.ZERO);
141: }
142:
143: return actionForward;
144: }
145:
146: /**
147: * Overrides parent to remove the associated helper line also, and then it call the parent's implementation.
148: *
149: * @see org.kuali.module.financial.web.struts.action.KualiFinancialDocumentActionBase#deleteSourceLine(org.apache.struts.action.ActionMapping,
150: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
151: */
152: @Override
153: public ActionForward deleteSourceLine(ActionMapping mapping,
154: ActionForm form, HttpServletRequest request,
155: HttpServletResponse response) throws Exception {
156: // cast the form to the right pojo
157: VoucherForm voucherForm = (VoucherForm) form;
158:
159: // call the super's method
160: ActionForward actionForward = super .deleteSourceLine(mapping,
161: voucherForm, request, response);
162:
163: // now remove the associated helper line
164: int index = getLineToDelete(request);
165: if (voucherForm.getVoucherLineHelpers() != null
166: && voucherForm.getVoucherLineHelpers().size() > index) {
167: voucherForm.getVoucherLineHelpers().remove(
168: getLineToDelete(request));
169: }
170:
171: return actionForward;
172: }
173:
174: /**
175: * Overrides the parent to make sure that the AV specific accounting line helper forms are properly populated when the document
176: * is first loaded. This first calls super, then populates the helper objects.
177: *
178: * @see org.kuali.core.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.core.web.struts.form.KualiDocumentFormBase)
179: */
180: @Override
181: protected void loadDocument(
182: KualiDocumentFormBase kualiDocumentFormBase)
183: throws WorkflowException {
184: super .loadDocument(kualiDocumentFormBase);
185: VoucherForm voucherForm = (VoucherForm) kualiDocumentFormBase;
186:
187: populateAllVoucherAccountingLineHelpers(voucherForm);
188: voucherForm.setNewSourceLineCredit(KualiDecimal.ZERO);
189: voucherForm.setNewSourceLineDebit(KualiDecimal.ZERO);
190:
191: // always wipe out the new source line
192: voucherForm.setNewSourceLine(null);
193:
194: // reload the accounting period selections since now we have data in the document bo
195: populateSelectedAccountingPeriod(voucherForm
196: .getVoucherDocument(), voucherForm);
197: }
198:
199: /**
200: * This method parses the accounting period value from the bo and builds the right string to pass to the form object as the
201: * selected value.
202: *
203: * @param voucherDocument
204: * @param voucherForm
205: */
206: protected void populateSelectedAccountingPeriod(
207: VoucherDocument voucherDocument, VoucherForm voucherForm) {
208: if (StringUtils.isNotBlank(voucherDocument
209: .getPostingPeriodCode())) {
210: String selectedAccountingPeriod = voucherDocument
211: .getPostingPeriodCode();
212: if (null != voucherDocument.getPostingYear()) {
213: selectedAccountingPeriod += voucherDocument
214: .getPostingYear().toString();
215: } else {
216: selectedAccountingPeriod += SpringContext.getBean(
217: UniversityDateService.class)
218: .getCurrentFiscalYear().toString();
219: }
220: voucherForm
221: .setSelectedAccountingPeriod(selectedAccountingPeriod);
222: }
223: }
224:
225: /**
226: * This populates a new helperLine instance with the one that was just added so that the new instance can be added to the
227: * helperLines list.
228: *
229: * @param voucherForm
230: * @return VoucherAccountingLineHelper
231: */
232: protected VoucherAccountingLineHelper populateVoucherAccountingLineHelper(
233: VoucherForm voucherForm) {
234: VoucherAccountingLineHelper helperLine = new VoucherAccountingLineHelperBase();
235:
236: KualiDecimal debitAmount = voucherForm.getNewSourceLineDebit();
237: if (debitAmount != null
238: && StringUtils.isNotBlank(debitAmount.toString())) {
239: helperLine.setDebit(debitAmount);
240: }
241:
242: KualiDecimal creditAmount = voucherForm
243: .getNewSourceLineCredit();
244: if (creditAmount != null
245: && StringUtils.isNotBlank(creditAmount.toString())) {
246: helperLine.setCredit(creditAmount);
247: }
248:
249: return helperLine;
250: }
251:
252: /**
253: * This method builds the corresponding list of voucher acounting line helper objects so that a user can differentiate between
254: * credit and debit fields. It does this by iterating over each source accounting line (what the voucher uses) looking at the
255: * debit/credit code and then populateingLineHelpers a corresponding helper form instance with the amount in the appropriate
256: * amount field - credit or debit.
257: *
258: * @param voucherForm
259: */
260: protected void populateAllVoucherAccountingLineHelpers(
261: VoucherForm voucherForm) {
262: // make sure the journal voucher accounting line helper form list is populated properly
263: ArrayList voucherLineHelpers = (ArrayList) voucherForm
264: .getVoucherLineHelpers();
265:
266: // make sure the helper list is the right size
267: VoucherDocument vDoc = (VoucherDocument) voucherForm
268: .getTransactionalDocument();
269: int size = vDoc.getSourceAccountingLines().size();
270: voucherLineHelpers.ensureCapacity(size);
271:
272: // iterate through each source accounting line and initialize the helper form lines appropriately
273: for (int i = 0; i < size; i++) {
274: // get the bo's accounting line at the right index
275: SourceAccountingLine sourceAccountingLine = vDoc
276: .getSourceAccountingLine(i);
277:
278: // instantiate a new helper form to use for populating the helper form list
279: VoucherAccountingLineHelper avAcctLineHelperForm = voucherForm
280: .getVoucherLineHelper(i);
281:
282: // figure whether we need to set the credit amount or the debit amount
283: if (StringUtils.isNotBlank(sourceAccountingLine
284: .getDebitCreditCode())) {
285: if (sourceAccountingLine.getDebitCreditCode().equals(
286: KFSConstants.GL_DEBIT_CODE)) {
287: avAcctLineHelperForm.setDebit(sourceAccountingLine
288: .getAmount());
289: avAcctLineHelperForm.setCredit(KFSConstants.ZERO);
290: } else if (sourceAccountingLine.getDebitCreditCode()
291: .equals(KFSConstants.GL_CREDIT_CODE)) {
292: avAcctLineHelperForm.setCredit(sourceAccountingLine
293: .getAmount());
294: avAcctLineHelperForm.setDebit(KFSConstants.ZERO);
295: }
296: }
297: }
298: }
299:
300: /**
301: * This helper method determines from the request object instance whether or not the user has been prompted about the journal
302: * being out of balance. If they haven't, then the method will build the appropriate message given the state of the document and
303: * return control to the question component so that the user receives the "yes"/"no" prompt. If the question has been asked, the
304: * we evaluate the user's answer and direct the flow appropriately. If they answer with a "No", then we build out a message
305: * stating that they chose that value and return an ActionForward of a MAPPING_BASIC which keeps them at the same page that they
306: * were on. If they choose "Yes", then we return a null ActionForward, which the calling action method recognizes as a "Yes" and
307: * continues on processing the "Route."
308: *
309: * @param mapping
310: * @param form
311: * @param request
312: * @param response
313: * @return ActionForward
314: * @throws Exception
315: */
316: protected ActionForward processRouteOutOfBalanceDocumentConfirmationQuestion(
317: ActionMapping mapping, ActionForm form,
318: HttpServletRequest request, HttpServletResponse response)
319: throws Exception {
320: VoucherForm vForm = (VoucherForm) form;
321: VoucherDocument avDoc = vForm.getVoucherDocument();
322:
323: String question = request
324: .getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
325: KualiConfigurationService kualiConfiguration = SpringContext
326: .getBean(KualiConfigurationService.class);
327:
328: if (question == null) { // question hasn't been asked
329: String currencyFormattedDebitTotal = (String) new CurrencyFormatter()
330: .format(avDoc.getDebitTotal());
331: String currencyFormattedCreditTotal = (String) new CurrencyFormatter()
332: .format(avDoc.getCreditTotal());
333: String currencyFormattedTotal = (String) new CurrencyFormatter()
334: .format(((AmountTotaling) avDoc)
335: .getTotalDollarAmount());
336: String message = "";
337: message = StringUtils
338: .replace(
339: kualiConfiguration
340: .getPropertyString(KFSKeyConstants.QUESTION_ROUTE_OUT_OF_BALANCE_JV_DOC),
341: "{0}", currencyFormattedDebitTotal);
342: message = StringUtils.replace(message, "{1}",
343: currencyFormattedCreditTotal);
344:
345: // now transfer control over to the question component
346: return this
347: .performQuestionWithoutInput(
348: mapping,
349: form,
350: request,
351: response,
352: KFSConstants.JOURNAL_VOUCHER_ROUTE_OUT_OF_BALANCE_DOCUMENT_QUESTION,
353: message,
354: KFSConstants.CONFIRMATION_QUESTION,
355: KFSConstants.ROUTE_METHOD, "");
356: } else {
357: String buttonClicked = request
358: .getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
359: if ((KFSConstants.JOURNAL_VOUCHER_ROUTE_OUT_OF_BALANCE_DOCUMENT_QUESTION
360: .equals(question))
361: && ConfirmationQuestion.NO.equals(buttonClicked)) {
362: GlobalVariables.getMessageList().add(
363: KFSKeyConstants.MESSAGE_JV_CANCELLED_ROUTE);
364: return mapping.findForward(KFSConstants.MAPPING_BASIC);
365: }
366: }
367: return null;
368: }
369:
370: /**
371: * This populates a new helperLine instance with the one that was just added so that the new instance can be added to the
372: * helperLines list.
373: *
374: * @param voucherForm
375: * @return voucherAccountingLineHelper
376: */
377: protected VoucherAccountingLineHelper populateNewVoucherAccountingLineHelper(
378: VoucherForm voucherForm) {
379: VoucherAccountingLineHelper helperLine = new VoucherAccountingLineHelperBase();
380:
381: KualiDecimal debitAmount = voucherForm.getNewSourceLineDebit();
382: if (debitAmount != null
383: && StringUtils.isNotBlank(debitAmount.toString())) {
384: helperLine.setDebit(debitAmount);
385: }
386:
387: KualiDecimal creditAmount = voucherForm
388: .getNewSourceLineCredit();
389: if (creditAmount != null
390: && StringUtils.isNotBlank(creditAmount.toString())) {
391: helperLine.setCredit(creditAmount);
392: }
393:
394: return helperLine;
395: }
396:
397: /**
398: * This action executes a call to upload CSV accounting line values as SourceAccountingLines for a given transactional document.
399: * The "uploadAccountingLines()" method handles the multi-part request.
400: *
401: * @param mapping
402: * @param form
403: * @param request
404: * @param response
405: * @return ActionForward
406: * @throws FileNotFoundException
407: * @throws IOException
408: */
409: @Override
410: public ActionForward uploadSourceLines(ActionMapping mapping,
411: ActionForm form, HttpServletRequest request,
412: HttpServletResponse response) throws FileNotFoundException,
413: IOException {
414: // call method that sourceform and destination list
415: uploadAccountingLines(true, form);
416:
417: return mapping.findForward(KFSConstants.MAPPING_BASIC);
418: }
419:
420: /**
421: * This method determines whether we are uploading source or target lines, and then calls uploadAccountingLines directly on the
422: * document object. This method handles retrieving the actual upload file as an input stream into the document.
423: *
424: * @param isSource
425: * @param form
426: * @throws FileNotFoundException
427: * @throws IOException
428: */
429: @Override
430: protected void uploadAccountingLines(boolean isSource,
431: ActionForm form) throws FileNotFoundException, IOException {
432: super .uploadAccountingLines(isSource, form);
433:
434: populateAllVoucherAccountingLineHelpers((VoucherForm) form);
435: }
436:
437: }
|