View Javadoc
1   /*
2    * Copyright 2006 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.fp.document.web.struts;
17  
18  import java.util.Map;
19  import java.util.Properties;
20  
21  import javax.servlet.http.HttpServletRequest;
22  import javax.servlet.http.HttpServletResponse;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.apache.log4j.Logger;
26  import org.apache.struts.action.ActionForm;
27  import org.apache.struts.action.ActionForward;
28  import org.apache.struts.action.ActionMapping;
29  import org.kuali.ole.fp.businessobject.Check;
30  import org.kuali.ole.fp.businessobject.Deposit;
31  import org.kuali.ole.fp.document.CashManagementDocument;
32  import org.kuali.ole.fp.document.service.CashManagementService;
33  import org.kuali.ole.fp.document.service.CashReceiptService;
34  import org.kuali.ole.fp.document.validation.event.AddCheckEvent;
35  import org.kuali.ole.fp.document.validation.event.CashieringTransactionApplicationEventBase;
36  import org.kuali.ole.fp.document.validation.event.DeleteCheckEvent;
37  import org.kuali.ole.fp.document.web.struts.CashManagementForm.CashDrawerSummary;
38  import org.kuali.ole.fp.exception.CashDrawerStateException;
39  import org.kuali.ole.fp.service.CashDrawerService;
40  import org.kuali.ole.sys.OLEConstants;
41  import org.kuali.ole.sys.OLEConstants.CashDrawerConstants;
42  import org.kuali.ole.sys.OLEConstants.DepositConstants;
43  import org.kuali.ole.sys.OLEKeyConstants;
44  import org.kuali.ole.sys.OLEKeyConstants.CashManagement;
45  import org.kuali.ole.sys.OleAuthorizationConstants;
46  import org.kuali.ole.sys.context.SpringContext;
47  import org.kuali.rice.core.api.config.property.ConfigurationService;
48  import org.kuali.rice.kew.api.WorkflowDocument;
49  import org.kuali.rice.kew.api.exception.WorkflowException;
50  import org.kuali.rice.kim.api.identity.Person;
51  import org.kuali.rice.kns.util.KNSGlobalVariables;
52  import org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase;
53  import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
54  import org.kuali.rice.krad.service.DocumentService;
55  import org.kuali.rice.krad.service.KualiRuleService;
56  import org.kuali.rice.krad.util.GlobalVariables;
57  import org.kuali.rice.krad.util.UrlFactory;
58  
59  /**
60   * Action class for CashManagementForm
61   */
62  public class CashManagementAction extends KualiTransactionalDocumentActionBase {
63      protected static Logger LOG = Logger.getLogger(CashManagementAction.class);
64      protected static final String CASH_MANAGEMENT_STATUS_PAGE = "/cashManagementStatus.do";
65  
66      /**
67       * Default constructor
68       */
69      public CashManagementAction() {
70      }
71  
72  
73      /**
74       * Overrides to call super, but also make sure the helpers are populated.
75       * 
76       * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#execute(org.apache.struts.action.ActionMapping,
77       *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
78       */
79      @Override
80      public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
81          ActionForward dest = null;
82          
83          try {
84              dest = super.execute(mapping, form, request, response);
85  
86              CashManagementForm cmf = (CashManagementForm) form;
87              cmf.populateDepositHelpers();
88              WorkflowDocument kwd = cmf.getDocument().getDocumentHeader().getWorkflowDocument();
89              if (kwd.isEnroute() || kwd.isFinal()) {
90                  cmf.setCashDrawerSummary(null);
91              }
92              else {
93                  if (cmf.getCashDrawerSummary() == null) {
94                      cmf.populateCashDrawerSummary();
95                  }
96              }
97              // put any recently closed items in process in the form
98              cmf.setRecentlyClosedItemsInProcess(SpringContext.getBean(CashManagementService.class).getRecentlyClosedItemsInProcess(cmf.getCashManagementDocument()));
99          } catch (CashDrawerStateException cdse) {
100             dest = new ActionForward(UrlFactory.parameterizeUrl(CASH_MANAGEMENT_STATUS_PAGE, cdse.toProperties()), true);
101         }
102         
103         return dest;
104     }
105 
106     /**
107      * Overrides the default document-creation code to auto-save new documents upon creation: since creating a CMDoc changes the
108      * CashDrawer's state as a side-effect, we need all CMDocs to be docsearchable so that someone can relocate and use or cancel
109      * whatever the current CMDoc is.
110      * 
111      * @param kualiDocumentFormBase
112      * @throws WorkflowException
113      */
114     @Override
115     protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
116         Person user = GlobalVariables.getUserSession().getPerson();
117         String campusCode = SpringContext.getBean(CashReceiptService.class).getCashReceiptVerificationUnitForUser(user);
118 
119         String defaultDescription = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(CashManagement.DEFAULT_DOCUMENT_DESCRIPTION);
120         defaultDescription = StringUtils.replace(defaultDescription, "{0}", campusCode);
121         defaultDescription = StringUtils.substring(defaultDescription, 0, 39);
122 
123         // create doc
124         CashManagementDocument cmDoc = SpringContext.getBean(CashManagementService.class).createCashManagementDocument(campusCode, defaultDescription, null);
125 
126         // update form
127         kualiDocumentFormBase.setDocument(cmDoc);
128         kualiDocumentFormBase.setDocTypeName(cmDoc.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
129     }
130 
131     /**
132      * @param mapping
133      * @param form
134      * @param request
135      * @param response
136      * @return ActionForward
137      * @throws Exception
138      */
139     public ActionForward addInterimDeposit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
140         CashManagementForm cmForm = (CashManagementForm) form;
141         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
142 
143         checkDepositAuthorization(cmForm, cmDoc);
144 
145         String wizardUrl = buildDepositWizardUrl(cmDoc, DepositConstants.DEPOSIT_TYPE_INTERIM);
146         return new ActionForward(wizardUrl, true);
147     }
148 
149     /**
150      * @param mapping
151      * @param form
152      * @param request
153      * @param response
154      * @return ActionForward
155      * @throws Exception
156      */
157     public ActionForward addFinalDeposit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
158         CashManagementForm cmForm = (CashManagementForm) form;
159         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
160 
161         checkDepositAuthorization(cmForm, cmDoc);
162 
163         String wizardUrl = buildDepositWizardUrl(cmDoc, DepositConstants.DEPOSIT_TYPE_FINAL);
164         return new ActionForward(wizardUrl, true);
165     }
166 
167     /**
168      * Throws a DocumentAuthorizationException if the current user is not authorized to add a deposit of the given type to the given
169      * document.
170      * 
171      * @param cmDoc
172      * @param cmForm
173      */
174     protected void checkDepositAuthorization(CashManagementForm cmForm, CashManagementDocument cmDoc) {
175         //deposits can only be added if the CashDrawer is open
176         if (!cmDoc.getCashDrawerStatus().equals(CashDrawerConstants.STATUS_OPEN)) {
177             throw new IllegalStateException("CashDrawer '" + cmDoc.getCampusCode() + "' must be open for deposits to be made");
178         }
179         
180         //verify user's ability to add a deposit
181         Map<String, String> documentActions = cmForm.getEditingMode();
182         if (!documentActions.containsKey(OleAuthorizationConstants.CashManagementEditMode.ALLOW_ADDITIONAL_DEPOSITS)) {
183             throw buildAuthorizationException("add a deposit", cmDoc);
184         }
185     }
186 
187     /**
188      * @param cmDoc
189      * @param depositTypeCode
190      * @return URL for passing control to the DepositWizard
191      */
192     protected String buildDepositWizardUrl(CashManagementDocument cmDoc, String depositTypeCode) {
193         Properties params = new Properties();
194         params.setProperty("methodToCall", "startWizard");
195         params.setProperty("cmDocId", cmDoc.getDocumentNumber());
196         params.setProperty("depositTypeCode", depositTypeCode);
197 
198         String wizardActionUrl = UrlFactory.parameterizeUrl("depositWizard.do", params);
199         return wizardActionUrl;
200     }
201 
202 
203     /**
204      * @param mapping
205      * @param form
206      * @param request
207      * @param response
208      * @return ActionForward
209      * @throws Exception
210      */
211     public ActionForward cancelDeposit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
212         CashManagementForm cmForm = (CashManagementForm) form;
213         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
214 
215         // validate cancelability
216         int depositIndex = getSelectedLine(request);
217         Deposit deposit = cmDoc.getDeposit(depositIndex);
218         if (StringUtils.equals(deposit.getDepositTypeCode(), DepositConstants.DEPOSIT_TYPE_INTERIM) && cmDoc.hasFinalDeposit()) {
219             throw new IllegalStateException("interim deposits cannot be canceled if the document already has a final deposit");
220         }
221 
222         // cancel the deposit
223         deposit = cmDoc.removeDeposit(depositIndex);
224         SpringContext.getBean(CashManagementService.class).cancelDeposit(deposit);
225 
226         // update the form
227         cmForm.removeDepositHelper(depositIndex);
228 
229         // open the CashDrawer so that user can add new deposits
230         cmDoc.getCashDrawer().setStatusCode(OLEConstants.CashDrawerConstants.STATUS_OPEN);
231 
232         // display status message
233         KNSGlobalVariables.getMessageList().add(CashManagement.STATUS_DEPOSIT_CANCELED);
234         
235         ((CashManagementForm) form).getCashDrawerSummary().resummarize(cmDoc);
236 
237         return mapping.findForward(OLEConstants.MAPPING_BASIC);
238     }
239 
240 
241     /**
242      * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#reload(org.apache.struts.action.ActionMapping,
243      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
244      */
245     @Override
246     public ActionForward reload(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
247         ActionForward dest = super.reload(mapping, form, request, response);
248 
249         // refresh the CashDrawerSummary, just in case
250         CashManagementForm cmForm = (CashManagementForm) form;
251         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
252 
253         CashDrawerSummary cms = cmForm.getCashDrawerSummary();
254         if (cms != null) {
255             cms.resummarize(cmDoc);
256         }
257 
258         return dest;
259     }
260 
261 
262     /**
263      * @param mapping
264      * @param form
265      * @param request
266      * @param response
267      * @return ActionForward
268      * @throws Exception
269      */
270     public ActionForward refreshSummary(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
271         CashManagementForm cmForm = (CashManagementForm) form;
272         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
273         
274         if (cmForm.getCashDrawerSummary() != null) {
275             cmForm.getCashDrawerSummary().resummarize(cmDoc);
276         }
277 
278         return mapping.findForward(OLEConstants.MAPPING_BASIC);
279     }
280 
281 
282     /**
283      * Saves the document, then opens the cash drawer
284      * 
285      * @param mapping
286      * @param form
287      * @param request
288      * @param response
289      * @return
290      * @throws Exception
291      */
292     public ActionForward openCashDrawer(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
293         CashManagementForm cmForm = (CashManagementForm) form;
294         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
295 
296         if (!cmDoc.getDocumentHeader().getWorkflowDocument().isInitiated()) {
297             throw new IllegalStateException("openCashDrawer should only be called on documents which haven't yet been saved");
298         }
299 
300         // open the CashDrawer
301         CashDrawerService cds = SpringContext.getBean(CashDrawerService.class);
302         cds.openCashDrawer(cmDoc.getCashDrawer(), cmDoc.getDocumentNumber());
303         // now that the cash drawer is open, let's create currency/coin detail records for this document
304         // create and save the cumulative cash receipt, deposit, money in and money out curr/coin details
305         SpringContext.getBean(CashManagementService.class).createNewCashDetails(cmDoc, OLEConstants.CurrencyCoinSources.CASH_RECEIPTS);
306         SpringContext.getBean(CashManagementService.class).createNewCashDetails(cmDoc, OLEConstants.CurrencyCoinSources.CASH_MANAGEMENT_IN);
307         SpringContext.getBean(CashManagementService.class).createNewCashDetails(cmDoc, OLEConstants.CurrencyCoinSources.CASH_MANAGEMENT_OUT);
308         try {
309             SpringContext.getBean(DocumentService.class).saveDocument(cmDoc);
310         }
311         catch (WorkflowException e) {
312             // force it closed if workflow proves recalcitrant
313             cds.closeCashDrawer(cmDoc.getCashDrawer());
314             throw e;
315         }
316 
317         // update the CashDrawerSummary to reflect the change
318         cmForm.populateCashDrawerSummary();
319 
320         return mapping.findForward(OLEConstants.MAPPING_BASIC);
321     }
322 
323     /**
324      * This action makes the last interim deposit a final deposit
325      * 
326      * @param mapping the mapping of the actions
327      * @param form the Struts form populated on the post
328      * @param request the servlet request
329      * @param response the servlet response
330      * @return a forward to the same page we were on
331      * @throws Exception because you never know when something just might go wrong
332      */
333     public ActionForward finalizeLastInterimDeposit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
334         CashManagementDocument cmDoc = ((CashManagementForm) form).getCashManagementDocument();
335         CashManagementService cms = SpringContext.getBean(CashManagementService.class);
336 
337         if (cmDoc.hasFinalDeposit()) {
338             GlobalVariables.getMessageMap().putError(OLEConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS, CashManagement.ERROR_DOCUMENT_ALREADY_HAS_FINAL_DEPOSIT, new String[] {});
339         }
340         else if (cmDoc.getDeposits().size() == 0) {
341             GlobalVariables.getMessageMap().putError(OLEConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS, CashManagement.ERROR_DOCUMENT_NO_DEPOSITS_TO_MAKE_FINAL, new String[] {});
342         }
343         else if (!cms.allVerifiedCashReceiptsAreDeposited(cmDoc)) {
344             GlobalVariables.getMessageMap().putError(OLEConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS, CashManagement.ERROR_NON_DEPOSITED_VERIFIED_CASH_RECEIPTS, new String[] {});
345         }
346 
347         cms.finalizeLastInterimDeposit(cmDoc);
348 
349         ((CashManagementForm) form).getCashDrawerSummary().resummarize(cmDoc);
350 
351         return mapping.findForward(OLEConstants.MAPPING_BASIC);
352     }
353 
354     /**
355      * This action applies the current cashiering transaction to the cash drawer
356      * 
357      * @param mapping
358      * @param form
359      * @param request
360      * @param response
361      * @return
362      * @throws Exception
363      */
364     public ActionForward applyCashieringTransaction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
365         CashManagementDocument cmDoc = ((CashManagementForm) form).getCashManagementDocument();
366         CashManagementService cmService = SpringContext.getBean(CashManagementService.class);
367         
368         final boolean valid = SpringContext.getBean(KualiRuleService.class).applyRules(new CashieringTransactionApplicationEventBase("Cashiering Transaction Application Event", "", cmDoc, SpringContext.getBean(CashDrawerService.class).getByCampusCode(cmDoc.getCampusCode()), cmDoc.getCurrentTransaction()));
369 
370         if (valid) {
371             cmService.applyCashieringTransaction(cmDoc);
372 
373             ((CashManagementForm) form).getCashDrawerSummary().resummarize(cmDoc);
374         }
375 
376         return mapping.findForward(OLEConstants.MAPPING_BASIC);
377     }
378 
379     /**
380      * This action allows the user to go to the cash drawer correction screen
381      * 
382      * @param mapping
383      * @param form
384      * @param request
385      * @param response
386      * @return
387      * @throws Exception
388      */
389     public ActionForward correctCashDrawer(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
390         return new ActionForward("CashDrawerCorrectionForm", buildCashDrawerCorrectionUrl(((CashManagementForm) form).getCashManagementDocument()), true);
391     }
392 
393     /**
394      * @param cmDoc
395      * @param depositTypeCode
396      * @return URL for passing control to the DepositWizard
397      */
398     protected String buildCashDrawerCorrectionUrl(CashManagementDocument cmDoc) {
399         Properties params = new Properties();
400         params.setProperty("methodToCall", "startCorrections");
401         params.setProperty("campusCode", cmDoc.getCampusCode());
402 
403         return UrlFactory.parameterizeUrl("cashDrawerCorrection.do", params);
404     }
405 
406     /**
407      * Adds Check instance created from the current "new check" line to the document
408      * 
409      * @param mapping
410      * @param form
411      * @param request
412      * @param response
413      * @return ActionForward
414      * @throws Exception
415      */
416     public ActionForward addCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
417         CashManagementDocument cmDoc = ((CashManagementForm) form).getCashManagementDocument();
418 
419         Check newCheck = cmDoc.getCurrentTransaction().getNewCheck();
420         newCheck.setDocumentNumber(cmDoc.getDocumentNumber());
421 
422         // check business rules
423         boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AddCheckEvent(OLEConstants.NEW_CHECK_PROPERTY_NAME, cmDoc, newCheck));
424         if (rulePassed) {
425             // add check
426             cmDoc.getCurrentTransaction().addCheck(newCheck);
427 
428             // clear the used newCheck
429             cmDoc.getCurrentTransaction().setNewCheck(cmDoc.getCurrentTransaction().createNewCheck());
430 
431         }
432 
433         return mapping.findForward(OLEConstants.MAPPING_BASIC);
434     }
435 
436     /**
437      * Deletes the selected check (line) from the document
438      * 
439      * @param mapping
440      * @param form
441      * @param request
442      * @param response
443      * @return ActionForward
444      * @throws Exception
445      */
446     public ActionForward deleteCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
447         CashManagementDocument cmDoc = ((CashManagementForm) form).getCashManagementDocument();
448 
449         int deleteIndex = getLineToDelete(request);
450         Check oldCheck = cmDoc.getCurrentTransaction().getCheck(deleteIndex);
451 
452 
453         boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteCheckEvent(OLEConstants.EXISTING_CHECK_PROPERTY_NAME, cmDoc, oldCheck));
454 
455         if (rulePassed) {
456             // delete check
457             cmDoc.getCurrentTransaction().removeCheck(deleteIndex);
458 
459             // delete baseline check, if any
460             if (cmDoc.getCurrentTransaction().hasBaselineCheck(deleteIndex)) {
461                 cmDoc.getCurrentTransaction().getBaselineChecks().remove(deleteIndex);
462             }
463 
464         }
465         else {
466             GlobalVariables.getMessageMap().putError("document.currentTransaction.check[" + deleteIndex + "]", OLEKeyConstants.Check.ERROR_CHECK_DELETERULE, Integer.toString(deleteIndex));
467         }
468 
469         return mapping.findForward(OLEConstants.MAPPING_BASIC);
470     }
471 
472     /**
473      * Overridden to clear the CashDrawerSummary info
474      * 
475      * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#route(org.apache.struts.action.ActionMapping,
476      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
477      */
478     @Override
479     public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
480         CashManagementForm cmForm = (CashManagementForm) form;
481         CashManagementDocument cmDoc = cmForm.getCashManagementDocument();
482 
483         ActionForward dest = super.route(mapping, form, request, response);
484 
485         // clear the CashDrawerSummary
486         cmForm.setCashDrawerSummary(null);
487 
488         return dest;
489     }
490 }
491