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.fp.document.web.struts;
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.kfs.coa.businessobject.BalanceType;
030 import org.kuali.kfs.coa.service.BalanceTypeService;
031 import org.kuali.kfs.fp.businessobject.VoucherAccountingLineHelper;
032 import org.kuali.kfs.fp.businessobject.VoucherAccountingLineHelperBase;
033 import org.kuali.kfs.fp.businessobject.VoucherSourceAccountingLine;
034 import org.kuali.kfs.fp.document.JournalVoucherDocument;
035 import org.kuali.kfs.fp.document.VoucherDocument;
036 import org.kuali.kfs.sys.KFSConstants;
037 import org.kuali.kfs.sys.KFSKeyConstants;
038 import org.kuali.kfs.sys.KFSPropertyConstants;
039 import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
040 import org.kuali.kfs.sys.context.SpringContext;
041 import org.kuali.rice.kew.exception.WorkflowException;
042 import org.kuali.rice.kns.question.ConfirmationQuestion;
043 import org.kuali.rice.kns.service.KualiConfigurationService;
044 import org.kuali.rice.kns.util.GlobalVariables;
045 import org.kuali.rice.kns.util.KualiDecimal;
046 import org.kuali.rice.kns.web.format.CurrencyFormatter;
047 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
048
049 /**
050 * This class piggy backs on all of the functionality in the FinancialSystemTransactionalDocumentActionBase but is necessary for
051 * this document type. The Journal Voucher is unique in that it defines several fields that aren't typically used by the other
052 * financial transaction processing eDocs (i.e. external system fields, object type override, credit and debit amounts).
053 */
054 public class JournalVoucherAction extends VoucherAction {
055
056 // used to determine which way the change balance type action is switching these are local constants only used within this
057 // action class these should not be used outside of this class
058 protected static final int CREDIT_DEBIT_TO_SINGLE_AMT_MODE = 0;
059 protected static final int SINGLE_AMT_TO_CREDIT_DEBIT_MODE = 1;
060 protected static final int EXT_ENCUMB_TO_NON_EXT_ENCUMB = 0;
061 protected static final int NON_EXT_ENCUMB_TO_EXT_ENCUMB = 1;
062 protected static final int NO_MODE_CHANGE = -1;
063
064 /**
065 * Overrides the parent and then calls the super method after building the array lists for valid accounting periods and balance
066 * types.
067 *
068 * @see org.kuali.rice.kns.web.struts.action.KualiAction#execute(ActionMapping mapping, ActionForm form, HttpServletRequest
069 * request, HttpServletResponse response)
070 */
071 @Override
072 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
073 JournalVoucherForm journalVoucherForm = (JournalVoucherForm) form;
074
075 populateBalanceTypeOneDocument(journalVoucherForm);
076
077 // now check to see if the balance type was changed and if so, we want to
078 // set the method to call so that the appropriate action can be invoked
079 // had to do it this way b/c the changing of the drop down causes the page to re-submit
080 // and couldn't use a hidden field called "methodToCall" b/c it screwed everything up
081 ActionForward returnForward;
082 if (StringUtils.isNotBlank(journalVoucherForm.getOriginalBalanceType()) && !journalVoucherForm.getSelectedBalanceType().getCode().equals(journalVoucherForm.getOriginalBalanceType())) {
083 returnForward = super.dispatchMethod(mapping, form, request, response, KFSConstants.CHANGE_JOURNAL_VOUCHER_BALANCE_TYPE_METHOD);
084 // must call this here, because execute in the super method will never have control for this particular action
085 // this is called in the parent by super.execute()
086 this.populateAuthorizationFields(journalVoucherForm);
087 }
088 else { // otherwise call the super
089 returnForward = super.execute(mapping, journalVoucherForm, request, response);
090 }
091 return returnForward;
092 }
093
094 /**
095 * Overrides the parent to first prompt the user appropriately to make sure that they want to submit and out of balance
096 * document, then calls super's route method.
097 *
098 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#route(org.apache.struts.action.ActionMapping,
099 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
100 */
101 @Override
102 public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
103 // process the question but we need to make sure there are lines and then check to see if it's not balanced
104 VoucherDocument vDoc = ((VoucherForm) form).getVoucherDocument();
105
106 KualiDecimal balance = vDoc.getCreditTotal().subtract(vDoc.getDebitTotal());
107 if (vDoc.getSourceAccountingLines().size() > 0 && balance.compareTo(KualiDecimal.ZERO) != 0) {
108 // it's not in "balance"
109 ActionForward returnForward = processRouteOutOfBalanceDocumentConfirmationQuestion(mapping, form, request, response);
110
111 // if not null, then the question component either has control of the flow and needs to ask its questions
112 // or the person chose the "cancel" or "no" button
113 // otherwise we have control
114 if (returnForward != null) {
115 return returnForward;
116 }
117 }
118 // now call the route method
119 return super.route(mapping, form, request, response);
120 }
121
122 /**
123 * This method handles grabbing the values from the form and pushing them into the document appropriately.
124 *
125 * @param journalVoucherForm
126 */
127 protected void populateBalanceTypeOneDocument(JournalVoucherForm journalVoucherForm) {
128 String selectedBalanceTypeCode = journalVoucherForm.getSelectedBalanceType().getCode();
129 BalanceType selectedBalanceType = getPopulatedBalanceTypeInstance(selectedBalanceTypeCode);
130 journalVoucherForm.getJournalVoucherDocument().setBalanceTypeCode(selectedBalanceTypeCode);
131 journalVoucherForm.getJournalVoucherDocument().setBalanceType(selectedBalanceType); // set the fully populated balance type
132 // object into the form's selected
133 // balance type
134 journalVoucherForm.setSelectedBalanceType(selectedBalanceType);
135 }
136
137
138 /**
139 * Overrides to call super, and then to repopulate the credit/debit amounts b/c the credit/debit code might change during a JV
140 * error correction.
141 *
142 * @see org.kuali.kfs.fp.document.web.struts.VoucherAction#correct(org.apache.struts.action.ActionMapping,
143 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
144 */
145 @Override
146 public ActionForward correct(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
147 ActionForward actionForward = super.correct(mapping, form, request, response);
148
149 JournalVoucherDocument jvDoc = (JournalVoucherDocument) ((JournalVoucherForm) form).getDocument();
150
151 jvDoc.refreshReferenceObject(KFSPropertyConstants.BALANCE_TYPE);
152 // only repopulate if this is a JV that was entered in debit/credit mode
153 if (jvDoc.getBalanceType().isFinancialOffsetGenerationIndicator()) {
154 // now make sure to repopulate credit/debit amounts
155 populateAllVoucherAccountingLineHelpers((JournalVoucherForm) form);
156 }
157
158 return actionForward;
159 }
160
161 /**
162 * This method processes a change in the balance type for a Journal Voucher document - from either a offset generation balance
163 * type to a non-offset generation balance type or visa-versa.
164 *
165 * @param mapping
166 * @param form
167 * @param request
168 * @param response
169 * @return ActionForward
170 * @throws Exception
171 */
172 public ActionForward changeBalanceType(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
173 JournalVoucherForm journalVoucherForm = (JournalVoucherForm) form;
174
175 // figure out which way the balance type is changing
176 int balanceTypeAmountChangeMode = determineBalanceTypeAmountChangeMode(journalVoucherForm);
177 int balanceTypeExternalEncumbranceChangeMode = determineBalanceTypeEncumbranceChangeMode(journalVoucherForm);
178
179 // process the question
180 if (balanceTypeAmountChangeMode != NO_MODE_CHANGE || balanceTypeExternalEncumbranceChangeMode != NO_MODE_CHANGE) {
181 ActionForward returnForward = processChangeBalanceTypeConfirmationQuestion(mapping, form, request, response);
182
183 // if not null, then the question component either has control of the flow and needs to ask its questions
184 // or the person choose the "cancel" or "no" button otherwise we have control
185 if (returnForward != null) {
186 return returnForward;
187 }
188 else {
189 // deal with balance type changes first amount change
190 if (balanceTypeAmountChangeMode == CREDIT_DEBIT_TO_SINGLE_AMT_MODE) {
191 switchFromCreditDebitModeToSingleAmountMode(journalVoucherForm);
192 }
193 else if (balanceTypeAmountChangeMode == SINGLE_AMT_TO_CREDIT_DEBIT_MODE) {
194 switchFromSingleAmountModeToCreditDebitMode(journalVoucherForm);
195 }
196
197 // then look to see if the external encumbrance was involved
198 if (balanceTypeExternalEncumbranceChangeMode == EXT_ENCUMB_TO_NON_EXT_ENCUMB) {
199 switchFromExternalEncumbranceModeToNonExternalEncumbrance(journalVoucherForm);
200 }
201 }
202 }
203
204 return mapping.findForward(KFSConstants.MAPPING_BASIC);
205 }
206
207 /**
208 * This method will determine which balance type amount mode to switch to. A change in the balance type selection will
209 * eventually invoke this mechanism, which looks at the old balance type value, and the new balance type value to determine what
210 * the next mode is.
211 *
212 * @param journalVoucherForm
213 * @throws Exception
214 */
215 protected int determineBalanceTypeAmountChangeMode(JournalVoucherForm journalVoucherForm) throws Exception {
216 int balanceTypeAmountChangeMode = NO_MODE_CHANGE;
217
218 // retrieve fully populated balance type instances
219 BalanceType origBalType = getPopulatedBalanceTypeInstance(journalVoucherForm.getOriginalBalanceType());
220 BalanceType newBalType = getPopulatedBalanceTypeInstance(journalVoucherForm.getSelectedBalanceType().getCode());
221
222 // figure out which ways we are switching the modes first deal with amount changes
223 if (origBalType.isFinancialOffsetGenerationIndicator() && !newBalType.isFinancialOffsetGenerationIndicator()) { // credit/debit
224 balanceTypeAmountChangeMode = CREDIT_DEBIT_TO_SINGLE_AMT_MODE;
225 }
226 else if (!origBalType.isFinancialOffsetGenerationIndicator() && newBalType.isFinancialOffsetGenerationIndicator()) { // single
227 balanceTypeAmountChangeMode = SINGLE_AMT_TO_CREDIT_DEBIT_MODE;
228 }
229
230 return balanceTypeAmountChangeMode;
231 }
232
233 /**
234 * This method will determine which balance type encumbrance mode to switch to. A change in the balance type selection will
235 * eventually invoke this mechanism, which looks at the old balance type value, and the new balance type value to determine what
236 * the next mode is.
237 *
238 * @param journalVoucherForm
239 * @throws Exception
240 */
241 protected int determineBalanceTypeEncumbranceChangeMode(JournalVoucherForm journalVoucherForm) throws Exception {
242 int balanceTypeExternalEncumbranceChangeMode = NO_MODE_CHANGE;
243
244 // retrieve fully populated balance type instances
245 BalanceType origBalType = getPopulatedBalanceTypeInstance(journalVoucherForm.getOriginalBalanceType());
246 BalanceType newBalType = getPopulatedBalanceTypeInstance(journalVoucherForm.getSelectedBalanceType().getCode());
247
248 // then deal with external encumbrance changes
249 if (origBalType.getCode().equals(KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE) && !newBalType.getCode().equals(KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE)) {
250 balanceTypeExternalEncumbranceChangeMode = EXT_ENCUMB_TO_NON_EXT_ENCUMB;
251 }
252 else if (!origBalType.getCode().equals(KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE) && newBalType.getCode().equals(KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE)) {
253 balanceTypeExternalEncumbranceChangeMode = NON_EXT_ENCUMB_TO_EXT_ENCUMB;
254 }
255
256 return balanceTypeExternalEncumbranceChangeMode;
257 }
258
259 /**
260 * This method takes control from the changeBalanceType action method in order to present a question prompt to the user so that
261 * they can confirm the change in balance type.
262 *
263 * @param mapping
264 * @param form
265 * @param request
266 * @param response
267 * @return ActionForward
268 * @throws Exception
269 */
270 protected ActionForward processChangeBalanceTypeConfirmationQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
271 JournalVoucherForm jvForm = (JournalVoucherForm) form;
272 JournalVoucherDocument jvDoc = jvForm.getJournalVoucherDocument();
273
274 // only want to present the confirmation question to the user if there are any
275 // accouting lines, because that is the only impact
276 if (jvDoc.getSourceAccountingLines().size() != 0) {
277 String question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
278 KualiConfigurationService kualiConfiguration = SpringContext.getBean(KualiConfigurationService.class);
279
280 if (question == null) { // question hasn't been asked
281 String message = buildBalanceTypeChangeConfirmationMessage(jvForm, kualiConfiguration);
282
283 // now transfer control over to the question component
284 return this.performQuestionWithoutInput(mapping, form, request, response, KFSConstants.JOURNAL_VOUCHER_CHANGE_BALANCE_TYPE_QUESTION, message, KFSConstants.CONFIRMATION_QUESTION, KFSConstants.CHANGE_JOURNAL_VOUCHER_BALANCE_TYPE_METHOD, "");
285 }
286 else {
287 String buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
288 if ((KFSConstants.JOURNAL_VOUCHER_CHANGE_BALANCE_TYPE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
289 // if no button clicked keep the old value and reload doc
290 BalanceType origBalType = getPopulatedBalanceTypeInstance(jvForm.getOriginalBalanceType());
291 jvForm.setSelectedBalanceType(origBalType);
292 jvDoc.setBalanceType(origBalType);
293 jvDoc.setBalanceTypeCode(origBalType.getCode());
294 return mapping.findForward(KFSConstants.MAPPING_BASIC);
295 }
296 }
297 }
298 return null;
299 }
300
301 /**
302 * This method will setup the message that will get displayed to the user when they are asked to confirm the balance type
303 * change. The message is tuned to the particular context, the value chosen, and also the previous value. It also combines with
304 * the core part of the message which is part of the ApplicationResources.properties file.
305 *
306 * @param jvForm
307 * @param kualiConfiguration
308 * @return The message to display to the user in the question prompt window.
309 * @throws Exception
310 */
311 protected String buildBalanceTypeChangeConfirmationMessage(JournalVoucherForm jvForm, KualiConfigurationService kualiConfiguration) throws Exception {
312 String message = new String("");
313
314 // figure out which way the balance type is changing
315 int balanceTypeAmountChangeMode = determineBalanceTypeAmountChangeMode(jvForm);
316 int balanceTypeExternalEncumbranceChangeMode = determineBalanceTypeEncumbranceChangeMode(jvForm);
317
318 // grab the right message from the ApplicationResources.properties file depending upon the balance type switching mode
319 if (balanceTypeAmountChangeMode == SINGLE_AMT_TO_CREDIT_DEBIT_MODE) {
320 message = kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_CHANGE_JV_BAL_TYPE_FROM_SINGLE_AMT_TO_CREDIT_DEBIT_MODE);
321 // see if we need the extra bit about the external encumbrance
322 String newMessage = new String("");
323 if (balanceTypeExternalEncumbranceChangeMode == NON_EXT_ENCUMB_TO_EXT_ENCUMB) {
324 newMessage = StringUtils.replace(message, "{3}", kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_CHANGE_JV_BAL_TYPE_FROM_SINGLE_AMT_TO_EXT_ENCUMB_CREDIT_DEBIT_MODE));
325 }
326 else {
327 newMessage = StringUtils.replace(message, "{3}", "");
328 }
329 message = new String(newMessage);
330 }
331 else if (balanceTypeAmountChangeMode == CREDIT_DEBIT_TO_SINGLE_AMT_MODE) {
332 message = kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_CHANGE_JV_BAL_TYPE_FROM_CREDIT_DEBIT_TO_SINGLE_AMT_MODE);
333 // see if we need the extra bit about the external encumbrance
334 String newMessage = new String("");
335 if (balanceTypeExternalEncumbranceChangeMode == EXT_ENCUMB_TO_NON_EXT_ENCUMB) {
336 newMessage = StringUtils.replace(message, "{3}", kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_CHANGE_JV_BAL_TYPE_FROM_EXT_ENCUMB_CREDIT_DEBIT_TO_SINGLE_AMT_MODE));
337 }
338 else {
339 newMessage = StringUtils.replace(message, "{3}", "");
340 }
341 message = new String(newMessage);
342 }
343 else if (balanceTypeExternalEncumbranceChangeMode == EXT_ENCUMB_TO_NON_EXT_ENCUMB) {
344 message = kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_CHANGE_JV_BAL_TYPE_FROM_EXT_ENCUMB_TO_NON_EXT_ENCUMB);
345 }
346 else if (balanceTypeExternalEncumbranceChangeMode == NON_EXT_ENCUMB_TO_EXT_ENCUMB) {
347 message = kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_CHANGE_JV_BAL_TYPE_FROM_NON_EXT_ENCUMB_TO_EXT_ENCUMB);
348 }
349
350 // retrieve fully populated balance type instances
351 BalanceType origBalType = getPopulatedBalanceTypeInstance(jvForm.getOriginalBalanceType());
352 BalanceType newBalType = getPopulatedBalanceTypeInstance(jvForm.getSelectedBalanceType().getCode());
353
354 // now complete building of the message
355 String replacement = "\"" + origBalType.getCode() + "-" + origBalType.getName() + "\"";
356 String newMessage = StringUtils.replace(message, "{0}", replacement);
357
358 replacement = "\"" + newBalType.getCode() + "-" + newBalType.getName() + "\"";
359 String finalMessage = StringUtils.replace(newMessage, "{1}", replacement);
360
361 return finalMessage;
362 }
363
364 /**
365 * This method will fully populate a balance type given the passed in code, by calling the business object service that
366 * retrieves the rest of the instances' information.
367 *
368 * @param balanceTypeCode
369 * @return BalanceTyp
370 */
371 protected BalanceType getPopulatedBalanceTypeInstance(String balanceTypeCode) {
372 // now we have to get the code and the name of the original and new balance types
373 return SpringContext.getBean(BalanceTypeService.class).getBalanceTypeByCode(balanceTypeCode);
374 }
375
376 /**
377 * This method will clear out the source line values that aren't needed for the "Single Amount" mode.
378 *
379 * @param journalVoucherForm
380 */
381 protected void switchFromSingleAmountModeToCreditDebitMode(JournalVoucherForm journalVoucherForm) {
382 // going from single amount to credit/debit view so we want to blank out the amount and the extra "reference" fields
383 // that the single amount view uses
384 JournalVoucherDocument jvDoc = (JournalVoucherDocument) journalVoucherForm.getTransactionalDocument();
385 ArrayList sourceLines = (ArrayList) jvDoc.getSourceAccountingLines();
386 ArrayList helperLines = (ArrayList) journalVoucherForm.getVoucherLineHelpers();
387 helperLines.clear(); // reset so we can add in fresh empty ones
388
389 // make sure that there is enough space in the list
390 helperLines.ensureCapacity(sourceLines.size());
391
392 for (int i = 0; i < sourceLines.size(); i++) {
393 VoucherSourceAccountingLine sourceLine = (VoucherSourceAccountingLine) sourceLines.get(i);
394 sourceLine.setAmount(KualiDecimal.ZERO);
395 sourceLine.setDebitCreditCode(KFSConstants.GL_DEBIT_CODE); // default to debit
396
397 helperLines.add(new VoucherAccountingLineHelperBase()); // populate with a fresh new empty object
398 }
399 }
400
401 /**
402 * This method will clear out the extra "reference" fields that the external encumbrance balance type uses, but will leave the
403 * amounts since we aren't changing the offset generation code stuff.
404 *
405 * @param journalVoucherForm
406 */
407 protected void switchFromExternalEncumbranceModeToNonExternalEncumbrance(JournalVoucherForm journalVoucherForm) {
408 // going from external encumbrance view to non external encumbrance view, so we want to blank out the extra "reference"
409 // fields
410 JournalVoucherDocument jvDoc = (JournalVoucherDocument) journalVoucherForm.getTransactionalDocument();
411 ArrayList sourceLines = (ArrayList) jvDoc.getSourceAccountingLines();
412
413 for (int i = 0; i < sourceLines.size(); i++) {
414 VoucherSourceAccountingLine sourceLine = (VoucherSourceAccountingLine) sourceLines.get(i);
415 sourceLine.setReferenceOriginCode(null); // won't be needed in this mode
416 sourceLine.setReferenceNumber(null); // won't be needed in this mode
417 sourceLine.setReferenceTypeCode(null); // won't be needed in this mode
418 }
419 }
420
421 /**
422 * This method will clear out the source line values that aren't needed for the "Credit/Debit" mode.
423 *
424 * @param journalVoucherForm
425 */
426 protected void switchFromCreditDebitModeToSingleAmountMode(JournalVoucherForm journalVoucherForm) {
427 // going from credit/debit view to single amount view so we don't need the debit and credit
428 // indicator set any more and we need to blank out the amount values to zero
429 JournalVoucherDocument jvDoc = journalVoucherForm.getJournalVoucherDocument();
430 ArrayList sourceLines = (ArrayList) jvDoc.getSourceAccountingLines();
431 ArrayList helperLines = (ArrayList) journalVoucherForm.getVoucherLineHelpers();
432
433 KualiDecimal ZERO = new KualiDecimal("0.00");
434 for (int i = 0; i < sourceLines.size(); i++) {
435 VoucherAccountingLineHelper helperLine = (VoucherAccountingLineHelper) helperLines.get(i);
436 SourceAccountingLine sourceLine = (SourceAccountingLine) sourceLines.get(i);
437 sourceLine.setAmount(ZERO);
438 sourceLine.setDebitCreditCode(KFSConstants.GL_DEBIT_CODE); // single sided is always debit
439
440 helperLine.setCredit(null); // won't be needed in this mode
441 helperLine.setDebit(null); // won't be needed in this mode
442 }
443 }
444
445 /**
446 * Overrides the parent to make sure that the JV specific accounting line helper forms are properly populated when the document
447 * is first loaded. This first calls super, then populates the helper objects.
448 *
449 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
450 */
451 @Override
452 protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
453 super.loadDocument(kualiDocumentFormBase);
454 JournalVoucherForm journalVoucherForm = (JournalVoucherForm) kualiDocumentFormBase;
455
456 // if the balance type is an offset generation balance type, then the user is able to enter the amount
457 // as either a debit or a credit, otherwise, they only need to deal with the amount field
458 JournalVoucherDocument journalVoucherDocument = (JournalVoucherDocument) journalVoucherForm.getTransactionalDocument();
459 if (journalVoucherDocument.getBalanceType().isFinancialOffsetGenerationIndicator()) {
460 populateAllVoucherAccountingLineHelpers(journalVoucherForm);
461 KualiDecimal ZERO = new KualiDecimal("0.00");
462 journalVoucherForm.setNewSourceLineCredit(ZERO);
463 journalVoucherForm.setNewSourceLineDebit(ZERO);
464 }
465
466 // always wipe out the new source line
467 journalVoucherForm.setNewSourceLine(null);
468
469 // reload the balance type and accounting period selections since now we have data in the document bo
470 populateSelectedJournalBalanceType(journalVoucherDocument, journalVoucherForm);
471 populateSelectedAccountingPeriod(journalVoucherDocument, journalVoucherForm);
472 }
473
474 /**
475 * This method grabs the value from the document bo and sets the selected balance type appropriately.
476 *
477 * @param journalVoucherDocument
478 * @param journalVoucherForm
479 */
480 protected void populateSelectedJournalBalanceType(JournalVoucherDocument journalVoucherDocument, JournalVoucherForm journalVoucherForm) {
481 journalVoucherForm.setSelectedBalanceType(journalVoucherDocument.getBalanceType());
482 if (StringUtils.isNotBlank(journalVoucherDocument.getBalanceTypeCode())) {
483 journalVoucherForm.setOriginalBalanceType(journalVoucherDocument.getBalanceTypeCode());
484 }
485 }
486
487 /**
488 * This helper method determines from the request object instance whether or not the user has been prompted about the journal
489 * being out of balance. If they haven't, then the method will build the appropriate message given the state of the document and
490 * return control to the question component so that the user receives the "yes"/"no" prompt. If the question has been asked, the
491 * we evaluate the user's answer and direct the flow appropriately. If they answer with a "No", then we build out a message
492 * stating that they chose that value and return an ActionForward of a MAPPING_BASIC which keeps them at the same page that they
493 * were on. If they choose "Yes", then we return a null ActionForward, which the calling action method recognizes as a "Yes" and
494 * continues on processing the "Route."
495 *
496 * @param mapping
497 * @param form
498 * @param request
499 * @param response
500 * @return ActionForward
501 * @throws Exception
502 */
503 @Override
504 protected ActionForward processRouteOutOfBalanceDocumentConfirmationQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
505 JournalVoucherForm jvForm = (JournalVoucherForm) form;
506 JournalVoucherDocument jvDoc = jvForm.getJournalVoucherDocument();
507
508 String question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
509 KualiConfigurationService kualiConfiguration = SpringContext.getBean(KualiConfigurationService.class);
510
511 if (question == null) { // question hasn't been asked
512 String currencyFormattedDebitTotal = (String) new CurrencyFormatter().format(jvDoc.getDebitTotal());
513 String currencyFormattedCreditTotal = (String) new CurrencyFormatter().format(jvDoc.getCreditTotal());
514 String currencyFormattedTotal = (String) new CurrencyFormatter().format(jvDoc.getTotalDollarAmount());
515 String message = "";
516 jvDoc.refreshReferenceObject(KFSPropertyConstants.BALANCE_TYPE);
517 if (jvDoc.getBalanceType().isFinancialOffsetGenerationIndicator()) {
518 message = StringUtils.replace(kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_ROUTE_OUT_OF_BALANCE_JV_DOC), "{0}", currencyFormattedDebitTotal);
519 message = StringUtils.replace(message, "{1}", currencyFormattedCreditTotal);
520 }
521 else {
522 message = StringUtils.replace(kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_ROUTE_OUT_OF_BALANCE_JV_DOC_SINGLE_AMT_MODE), "{0}", currencyFormattedTotal);
523 }
524
525 // now transfer control over to the question component
526 return this.performQuestionWithoutInput(mapping, form, request, response, KFSConstants.JOURNAL_VOUCHER_ROUTE_OUT_OF_BALANCE_DOCUMENT_QUESTION, message, KFSConstants.CONFIRMATION_QUESTION, KFSConstants.ROUTE_METHOD, "");
527 }
528 else {
529 String buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
530 if ((KFSConstants.JOURNAL_VOUCHER_ROUTE_OUT_OF_BALANCE_DOCUMENT_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
531 GlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_JV_CANCELLED_ROUTE);
532 return mapping.findForward(KFSConstants.MAPPING_BASIC);
533 }
534 }
535 return null;
536 }
537
538 /**
539 * This action executes a call to upload CSV accounting line values as SourceAccountingLines for a given transactional document.
540 * The "uploadAccountingLines()" method handles the multi-part request.
541 *
542 * @param mapping
543 * @param form
544 * @param request
545 * @param response
546 * @return ActionForward
547 * @throws FileNotFoundException
548 * @throws IOException
549 */
550 @Override
551 public ActionForward uploadSourceLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws FileNotFoundException, IOException {
552 // call method that sourceform and destination list
553 uploadAccountingLines(true, form);
554
555 return mapping.findForward(KFSConstants.MAPPING_BASIC);
556 }
557
558 /**
559 * This method determines whether we are uploading source or target lines, and then calls uploadAccountingLines directly on the
560 * document object. This method handles retrieving the actual upload file as an input stream into the document.
561 *
562 * @param isSource
563 * @param form
564 * @throws FileNotFoundException
565 * @throws IOException
566 */
567 @Override
568 protected void uploadAccountingLines(boolean isSource, ActionForm form) throws FileNotFoundException, IOException {
569 JournalVoucherForm jvForm = (JournalVoucherForm) form;
570 // JournalVoucherAccountingLineParser needs a fresh BalanceType BO in the JournalVoucherDocument.
571 jvForm.getJournalVoucherDocument().refreshReferenceObject(KFSPropertyConstants.BALANCE_TYPE);
572 super.uploadAccountingLines(isSource, jvForm);
573 }
574
575 }