View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.pdp.web.struts;
17  
18  import java.text.MessageFormat;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Properties;
23  
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpServletResponse;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.struts.action.ActionForm;
29  import org.apache.struts.action.ActionForward;
30  import org.apache.struts.action.ActionMapping;
31  import org.kuali.ole.pdp.PdpKeyConstants;
32  import org.kuali.ole.pdp.PdpParameterConstants;
33  import org.kuali.ole.pdp.PdpPropertyConstants;
34  import org.kuali.ole.pdp.businessobject.PaymentDetail;
35  import org.kuali.ole.pdp.businessobject.PaymentGroup;
36  import org.kuali.ole.pdp.businessobject.lookup.PaymentDetailLookupableHelperService;
37  import org.kuali.ole.pdp.service.PaymentMaintenanceService;
38  import org.kuali.ole.pdp.util.PdpPaymentDetailQuestionCallback;
39  import org.kuali.ole.sys.OLEConstants;
40  import org.kuali.ole.sys.context.SpringContext;
41  import org.kuali.rice.core.api.config.property.ConfigurationService;
42  import org.kuali.rice.kim.api.identity.Person;
43  import org.kuali.rice.kns.question.ConfirmationQuestion;
44  import org.kuali.rice.kns.web.struts.action.KualiAction;
45  import org.kuali.rice.krad.service.BusinessObjectService;
46  import org.kuali.rice.krad.util.ErrorMessage;
47  import org.kuali.rice.krad.util.GlobalVariables;
48  import org.kuali.rice.krad.util.KRADConstants;
49  import org.kuali.rice.krad.util.MessageMap;
50  import org.kuali.rice.krad.util.ObjectUtils;
51  import org.kuali.rice.krad.util.UrlFactory;
52  
53  /**
54   * This class defines actions for Payment
55   */
56  public class PaymentDetailAction extends KualiAction {
57  
58      private PaymentMaintenanceService paymentMaintenanceService;
59      private BusinessObjectService businessObjectService;
60  
61      /**
62       * Constructs a PaymentDetailAction.java.
63       */
64      public PaymentDetailAction() {
65          setPaymentMaintenanceService(SpringContext.getBean(PaymentMaintenanceService.class));
66          setBusinessObjectService(SpringContext.getBean(BusinessObjectService.class));
67  
68      }
69  
70      /**
71       * This method confirms and cancels a payment.
72       * @param mapping
73       * @param form
74       * @param request
75       * @param response
76       * @return
77       * @throws Exception
78       */
79      public ActionForward confirmAndCancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
80  
81          PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
82              public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
83                  return performCancel(paymentDetailId, changeText, user);
84              }
85          };
86  
87          return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_PAYMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_PAYMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.PAYMENT_SUCCESSFULLY_CANCELED, "confirmAndCancel", callback);
88      }
89  
90      /**
91       * This method cancels a payment.
92       * @param paymentDetailId the payment detail id.
93       * @param changeText the text of the change
94       * @param user the user that perfomed the change
95       * @return true if payment successfully canceled, false otherwise
96       */
97      private boolean performCancel(int paymentDetailId, String changeText, Person user) {
98  
99          Map keyMap = new HashMap();
100         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
101 
102         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
103         if (ObjectUtils.isNotNull(paymentDetail)) {
104             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
105             return paymentMaintenanceService.cancelPendingPayment(paymentGroupId, paymentDetailId, changeText, user);
106         }
107         else {
108             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
109             return false;
110         }
111     }
112 
113     /**
114      * This method confirms and holds a payment
115      * 
116      * @param mapping
117      * @param form
118      * @param request
119      * @param response
120      * @return
121      * @throws Exception
122      */
123     public ActionForward confirmAndHold(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
124         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
125             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
126                 return performHold(paymentDetailId, changeText, user);
127             }
128         };
129         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.HOLD_PAYMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.HOLD_PAYMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.PAYMENT_SUCCESSFULLY_HOLD, "confirmAndHold", callback);
130     }
131 
132     /**
133 
134      */
135     /**
136      * This method performs a hold on a payment.
137      * @param paymentDetailId the payment detail id
138      * @param changeText the text of the user change
139      * @param user the user that performed the change
140      * @return true if payment successfully held, false otherwise
141      */
142     private boolean performHold(int paymentDetailId, String changeText, Person user) {
143 
144         Map keyMap = new HashMap();
145         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
146 
147         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
148         if (ObjectUtils.isNotNull(paymentDetail)) {
149             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
150             return paymentMaintenanceService.holdPendingPayment(paymentGroupId, changeText, user);
151         }
152         else {
153             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
154             return false;
155         }
156     }
157 
158     /**
159      * This method confirms and removes a hold on a payment.
160      * 
161      * @param mapping
162      * @param form
163      * @param request
164      * @param response
165      * @return an ActionForward
166      * @throws Exception
167      */
168     public ActionForward confirmAndRemoveHold(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
169         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
170             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
171                 return performRemoveHold(paymentDetailId, changeText, user);
172             }
173         };
174         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.REMOVE_HOLD_PAYMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.REMOVE_HOLD_PAYMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.HOLD_SUCCESSFULLY_REMOVED_ON_PAYMENT, "confirmAndRemoveHold", callback);
175     }
176 
177     /**
178      * This method removes a hold on payment.
179      * @param paymentDetailId the payment detail id
180      * @param changeText the text of the user change
181      * @param user the user that performs the change
182      * @return true if hold successfully removed from payment, false otherwise
183      */
184     private boolean performRemoveHold(int paymentDetailId, String changeText, Person user) {
185 
186         Map keyMap = new HashMap();
187         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
188 
189         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
190         if (ObjectUtils.isNotNull(paymentDetail)) {
191             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
192             return paymentMaintenanceService.removeHoldPendingPayment(paymentGroupId, changeText, user);
193         }
194         else {
195             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
196             return false;
197         }
198     }
199 
200     /**
201      * This method confirms and sets the immediate flag.
202      * @param mapping
203      * @param form
204      * @param request
205      * @param response
206      * @return an ActionForward
207      * @throws Exception
208      */
209     public ActionForward confirmAndSetImmediate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
210 
211         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
212             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
213                 return performSetImmediate(paymentDetailId, changeText, user);
214 
215             }
216         };
217         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.CHANGE_IMMEDIATE_PAYMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.CHANGE_IMMEDIATE_PAYMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.PAYMENT_SUCCESSFULLY_SET_AS_IMMEDIATE, "confirmAndSetImmediate", callback);
218     }
219 
220     /**
221      * This method sets the immediate flag
222      * @param paymentDetailId the payment detail id
223      * @param changeText the text of the change
224      * @param user the user that performed the change
225      * @return true if flag successfully set on payment, false otherwise
226      */
227     private boolean performSetImmediate(int paymentDetailId, String changeText, Person user) {
228         Map keyMap = new HashMap();
229         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
230 
231         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
232         if (ObjectUtils.isNotNull(paymentDetail)) {
233             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
234             paymentMaintenanceService.changeImmediateFlag(paymentGroupId, changeText, user);
235             return true;
236         }
237         else {
238             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
239             return false;
240         }
241 
242     }
243 
244     /**
245      * This method confirms and removes the immediate flag.
246      * @param mapping
247      * @param form
248      * @param request
249      * @param response
250      * @return
251      * @throws Exception
252      */
253     public ActionForward confirmAndRemoveImmediate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
254         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
255             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
256                 return performSetImmediate(paymentDetailId, changeText, user);
257 
258             }
259         };
260         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.CHANGE_IMMEDIATE_PAYMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.CHANGE_IMMEDIATE_PAYMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.IMMEDIATE_SUCCESSFULLY_REMOVED_ON_PAYMENT, "confirmAndRemoveImmediate", callback);
261     }
262 
263     /**
264      * This method confirms and cancels a disbursement.
265      * 
266      * @param mapping
267      * @param form
268      * @param request
269      * @param response
270      * @return an ActionForward
271      * @throws Exception
272      */
273     public ActionForward confirmAndCancelDisbursement(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
274         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
275             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
276                 return performCancelDisbursement(paymentDetailId, changeText, user);
277             }
278         };
279         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_DISBURSEMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_DISBURSEMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.DISBURSEMENT_SUCCESSFULLY_CANCELED, "confirmAndRemoveHold", callback);
280     }
281 
282     /**
283      * This method cancels a disbursement
284      * @param paymentDetailId the payment detail id
285      * @param changeText the text entered by user
286      * @param user the user that canceled the disbursement
287      * @return true if disbursement successfully canceled, false otherwise
288      */
289     private boolean performCancelDisbursement(int paymentDetailId, String changeText, Person user) {
290         Map keyMap = new HashMap();
291         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
292 
293         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
294         if (ObjectUtils.isNotNull(paymentDetail)) {
295             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
296             return paymentMaintenanceService.cancelDisbursement(paymentGroupId, paymentDetailId, changeText, user);
297         }
298         else {
299             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
300             return false;
301         }
302     }
303 
304     /**
305      * This method confirms an reissues/cancels a disbursement.
306      * @param mapping
307      * @param form
308      * @param request
309      * @param response
310      * @return
311      * @throws Exception
312      */
313     public ActionForward confirmAndReIssue(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
314         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
315             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
316                 return performReIssueWithoutCancelDisbursement(paymentDetailId, changeText, user);
317             }
318         };
319         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_REISSUE_DISBURSEMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.REISSUE_DISBURSEMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.DISBURSEMENT_SUCCESSFULLY_REISSUED, "confirmAndReissue", callback);
320     }
321 
322     /**
323      * This method reissue a disbursement
324      * @param paymentDetailId the payment detail id
325      * @param changeText the text entered by the user
326      * @param user the user that canceled the disbursement
327      * @return true if disbursement successfully reissued/canceled, false otherwise
328      */
329     private boolean performReIssueWithoutCancelDisbursement(int paymentDetailId, String changeText, Person user) {
330         Map keyMap = new HashMap();
331         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
332 
333         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
334         if (ObjectUtils.isNotNull(paymentDetail)) {
335             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
336             return paymentMaintenanceService.reissueDisbursement(paymentGroupId, changeText, user);
337         }
338         else {
339             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
340             return false;
341         }
342     }
343 
344     /**
345      * This method confirms an reissues/cancels a disbursement.
346      * @param mapping
347      * @param form
348      * @param request
349      * @param response
350      * @return
351      * @throws Exception
352      */
353     public ActionForward confirmAndReIssueCancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
354         PdpPaymentDetailQuestionCallback callback = new PdpPaymentDetailQuestionCallback() {
355             public boolean doPostQuestion(int paymentDetailId, String changeText, Person user) {
356                 return performReIssueDisbursement(paymentDetailId, changeText, user);
357             }
358         };
359         return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_REISSUE_DISBURSEMENT_QUESTION, PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_REISSUE_DISBURSEMENT_MESSAGE, PdpKeyConstants.PaymentDetail.Messages.DISBURSEMENT_SUCCESSFULLY_CANCELED, "confirmAndReissueCancel", callback);
360     }
361 
362     /**
363      * This method reissue/cancels a disbursement
364      * @param paymentDetailId the payment detail id
365      * @param changeText the text entered by the user
366      * @param user the user that canceled the disbursement
367      * @return true if disbursement successfully reissued/canceled, false otherwise
368      */
369     private boolean performReIssueDisbursement(int paymentDetailId, String changeText, Person user) {
370         Map keyMap = new HashMap();
371         keyMap.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
372 
373         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findByPrimaryKey(PaymentDetail.class, keyMap);
374         if (ObjectUtils.isNotNull(paymentDetail)) {
375             int paymentGroupId = paymentDetail.getPaymentGroupId().intValue();
376             return paymentMaintenanceService.cancelReissueDisbursement(paymentGroupId, changeText, user);
377         }
378         else {
379             GlobalVariables.getMessageMap().putError(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
380             return false;
381         }
382     }
383 
384     /**
385      * This method prompts for a reason to perform an action on a payment detail.
386      * 
387      * @param mapping
388      * @param form
389      * @param request
390      * @param response
391      * @param confirmationQuestion
392      * @param confirmationText
393      * @param caller
394      * @param callback
395      * @return
396      * @throws Exception
397      */
398     private ActionForward askQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String confirmationQuestion, String confirmationText, String successMessage, String caller, PdpPaymentDetailQuestionCallback callback) throws Exception {
399         Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
400         String reason = request.getParameter(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME);
401         String noteText = OLEConstants.EMPTY_STRING;
402         Person person = GlobalVariables.getUserSession().getPerson();
403         boolean actionStatus;
404         String message = OLEConstants.EMPTY_STRING;
405 
406         String paymentDetailId = request.getParameter(PdpParameterConstants.PaymentDetail.DETAIL_ID_PARAM);
407         if (paymentDetailId == null) {
408             paymentDetailId = request.getParameter(KRADConstants.QUESTION_CONTEXT);
409         }
410 
411         PaymentDetail paymentDetail = (PaymentDetail) businessObjectService.findBySinglePrimaryKey(PaymentDetail.class, paymentDetailId);
412         PaymentGroup paymentGroup = paymentDetail.getPaymentGroup();
413         int paymentsInGroup = paymentGroup.getPaymentDetails().size() - 1;
414         int paymentsInDisbursement = paymentDetail.getNbrOfPaymentsInDisbursement() - 1;
415 
416         ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
417         String confirmationTextValue = kualiConfiguration.getPropertyValueAsString(confirmationText);
418 
419         if (confirmationText.equals(PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_PAYMENT_MESSAGE)) {
420             confirmationText = MessageFormat.format(confirmationTextValue, paymentsInGroup, paymentGroup.getId().toString());
421             if (paymentsInGroup == 0) {
422                 int start = confirmationText.indexOf(".") + 2;
423                 confirmationText = confirmationText.substring(start);
424             }
425         }
426         else if (confirmationText.equals(PdpKeyConstants.PaymentDetail.Confirmation.CANCEL_DISBURSEMENT_MESSAGE)) {
427             confirmationText = MessageFormat.format(confirmationTextValue, paymentsInDisbursement, paymentGroup.getDisbursementNbr().toString());
428             if (paymentsInDisbursement == 0) {
429                 int start = confirmationText.indexOf(".") + 2;
430                 confirmationText = confirmationText.substring(start);
431             }
432 
433         }
434         else {
435             confirmationText = MessageFormat.format(confirmationTextValue, paymentDetailId);
436         }
437 
438         if (question == null) {
439 
440             // ask question if not already asked
441             return this.performQuestionWithInput(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, caller, paymentDetailId);
442         }
443         else {
444             Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
445             if ((confirmationQuestion.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
446                 actionStatus = false;
447             }
448             else {
449                 noteText = reason;
450                 int noteTextLength = (reason == null) ? 0 : noteText.length();
451                 int noteTextMaxLength = PdpKeyConstants.BatchConstants.Confirmation.NOTE_TEXT_MAX_LENGTH;
452 
453                 if (StringUtils.isBlank(reason)) {
454 
455                     if (reason == null) {
456                         // prevent a NPE by setting the reason to a blank string
457                         reason = OLEConstants.EMPTY_STRING;
458                     }
459                     return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, OLEConstants.MAPPING_BASIC, paymentDetailId, reason, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_NOTE_EMPTY, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, "");
460                 }
461                 else if (noteTextLength > noteTextMaxLength) {
462                     return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, OLEConstants.MAPPING_BASIC, paymentDetailId, reason, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_NOTE_TOO_LONG, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, "");
463                 }
464 
465                 actionStatus = callback.doPostQuestion(Integer.parseInt(paymentDetailId), noteText, person);
466                 if (actionStatus) {
467                     message = successMessage;
468                 }
469 
470             }
471         }
472 
473         String returnUrl = buildUrl(paymentDetailId, actionStatus, message, buildErrorMesageKeyList());
474         return new ActionForward(returnUrl, true);
475     }
476 
477     /**
478      * This method builds the forward url.
479      * 
480      * @param paymentDetailId the payment detail id
481      * @param success action status: true if success, false otherwise
482      * @param message the message for the user
483      * @return the build url
484      */
485     private String buildUrl(String paymentDetailId, boolean success, String message, String errorList) {
486         // build url to return user back to PaymentDetail Search with fields filled in as user inputted
487         String lookupUrl = (String) GlobalVariables.getUserSession().retrieveObject(PaymentDetailLookupableHelperService.PDP_PAYMENTDETAIL_KEY);
488         if (lookupUrl != null) {
489             GlobalVariables.getUserSession().removeObject(PaymentDetailLookupableHelperService.PDP_PAYMENTDETAIL_KEY);
490 
491             Properties parameters = new Properties();
492             parameters.put(PdpParameterConstants.ACTION_SUCCESSFUL_PARAM, String.valueOf(success));
493             if (message != null && !message.equalsIgnoreCase(OLEConstants.EMPTY_STRING)) {
494                 parameters.put(PdpParameterConstants.MESSAGE_PARAM, message);
495             }
496 
497             if (StringUtils.isNotEmpty(errorList)) {
498                 parameters.put(PdpParameterConstants.ERROR_KEY_LIST_PARAM, errorList);
499             }
500 
501             lookupUrl = lookupUrl + UrlFactory.parameterizeUrl("&", parameters);
502         }
503         else {
504             // session expired -  resort to alternative plan
505             String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.APPLICATION_URL_KEY);
506 
507             Properties parameters = new Properties();
508             parameters.put(OLEConstants.DISPATCH_REQUEST_PARAMETER, OLEConstants.SEARCH_METHOD);
509             parameters.put(OLEConstants.BACK_LOCATION, basePath + "/" + OLEConstants.MAPPING_PORTAL + ".do");
510             parameters.put(KRADConstants.DOC_FORM_KEY, "88888888");
511             parameters.put(OLEConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, PaymentDetail.class.getName());
512             parameters.put(OLEConstants.HIDE_LOOKUP_RETURN_LINK, "true");
513             parameters.put(OLEConstants.SUPPRESS_ACTIONS, "false");
514             parameters.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
515             parameters.put(PdpParameterConstants.ACTION_SUCCESSFUL_PARAM, String.valueOf(success));
516             if (message != null && !message.equalsIgnoreCase(OLEConstants.EMPTY_STRING)) {
517                 parameters.put(PdpParameterConstants.MESSAGE_PARAM, message);
518             }
519 
520             if (StringUtils.isNotEmpty(errorList)) {
521                 parameters.put(PdpParameterConstants.ERROR_KEY_LIST_PARAM, errorList);
522             }
523 
524             lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + OLEConstants.LOOKUP_ACTION, parameters);
525         }
526         return lookupUrl;
527     }
528 
529     /**
530      * This method build a string list of error message keys out of the error map in GlobalVariables
531      * 
532      * @return a String representing the list of error message keys
533      */
534     private String buildErrorMesageKeyList() {
535         MessageMap errorMap = GlobalVariables.getMessageMap();
536         StringBuffer errorList = new StringBuffer();
537 
538         for (String errorKey : (List<String>) errorMap.getPropertiesWithErrors()) {
539             for (ErrorMessage errorMessage : (List<ErrorMessage>) errorMap.getMessages(errorKey)) {
540 
541                 errorList.append(errorMessage.getErrorKey());
542                 errorList.append(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR);
543             }
544         }
545         if (errorList.length() > 0) {
546             errorList.replace(errorList.lastIndexOf(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR), errorList.lastIndexOf(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR) + PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR.length(), "");
547         }
548 
549         return errorList.toString();
550     }
551 
552     /**
553      * This method gets the payment maintenance service
554      * @return the paymentMaintenanceService
555      */
556     public PaymentMaintenanceService getPaymentMaintenanceService() {
557         return paymentMaintenanceService;
558     }
559 
560     /**
561      * This method sets the payment maintenance service
562      * @param paymentMaintenanceService
563      */
564     public void setPaymentMaintenanceService(PaymentMaintenanceService paymentMaintenanceService) {
565         this.paymentMaintenanceService = paymentMaintenanceService;
566     }
567 
568     /**
569      * This method gets the business object service
570      * @return the businessObjectService
571      */
572     public BusinessObjectService getBusinessObjectService() {
573         return businessObjectService;
574     }
575 
576     /**
577      * This method sets the business object service.
578      * @param businessObjectService
579      */
580     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
581         this.businessObjectService = businessObjectService;
582     }
583 
584 }