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.util.Map;
019: import java.util.Properties;
020:
021: import javax.servlet.http.HttpServletRequest;
022: import javax.servlet.http.HttpServletResponse;
023:
024: import org.apache.commons.lang.StringUtils;
025: import org.apache.log4j.Logger;
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.authorization.AuthorizationConstants;
030: import org.kuali.core.bo.user.UniversalUser;
031: import org.kuali.core.document.authorization.DocumentAuthorizer;
032: import org.kuali.core.service.DataDictionaryService;
033: import org.kuali.core.service.DocumentAuthorizationService;
034: import org.kuali.core.service.DocumentService;
035: import org.kuali.core.service.KualiConfigurationService;
036: import org.kuali.core.service.KualiRuleService;
037: import org.kuali.core.util.GlobalVariables;
038: import org.kuali.core.util.UrlFactory;
039: import org.kuali.core.web.struts.action.KualiDocumentActionBase;
040: import org.kuali.core.web.struts.form.KualiDocumentFormBase;
041: import org.kuali.core.workflow.service.KualiWorkflowDocument;
042: import org.kuali.kfs.KFSConstants;
043: import org.kuali.kfs.KFSKeyConstants;
044: import org.kuali.kfs.KFSConstants.CashDrawerConstants;
045: import org.kuali.kfs.KFSConstants.DepositConstants;
046: import org.kuali.kfs.KFSKeyConstants.CashManagement;
047: import org.kuali.kfs.context.SpringContext;
048: import org.kuali.module.financial.bo.Check;
049: import org.kuali.module.financial.bo.Deposit;
050: import org.kuali.module.financial.document.CashManagementDocument;
051: import org.kuali.module.financial.document.authorization.CashManagementDocumentAuthorizer;
052: import org.kuali.module.financial.rule.event.AddCheckEvent;
053: import org.kuali.module.financial.rule.event.DeleteCheckEvent;
054: import org.kuali.module.financial.service.CashDrawerService;
055: import org.kuali.module.financial.service.CashManagementService;
056: import org.kuali.module.financial.service.CashReceiptService;
057: import org.kuali.module.financial.web.struts.form.CashManagementForm;
058: import org.kuali.module.financial.web.struts.form.CashManagementForm.CashDrawerSummary;
059:
060: import edu.iu.uis.eden.exception.WorkflowException;
061:
062: /**
063: * Action class for CashManagementForm
064: */
065: public class CashManagementAction extends KualiDocumentActionBase {
066: private static Logger LOG = Logger
067: .getLogger(CashManagementAction.class);
068:
069: /**
070: * Default constructor
071: */
072: public CashManagementAction() {
073: }
074:
075: /**
076: * Overrides to call super, but also make sure the helpers are populated.
077: *
078: * @see org.kuali.core.web.struts.action.KualiDocumentActionBase#execute(org.apache.struts.action.ActionMapping,
079: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
080: */
081: @Override
082: public ActionForward execute(ActionMapping mapping,
083: ActionForm form, HttpServletRequest request,
084: HttpServletResponse response) throws Exception {
085: ActionForward dest = super .execute(mapping, form, request,
086: response);
087:
088: CashManagementForm cmf = (CashManagementForm) form;
089: cmf.populateDepositHelpers();
090: KualiWorkflowDocument kwd = cmf.getDocument()
091: .getDocumentHeader().getWorkflowDocument();
092: if (kwd.stateIsEnroute() || kwd.stateIsFinal()) {
093: cmf.setCashDrawerSummary(null);
094: } else {
095: if (cmf.getCashDrawerSummary() == null) {
096: cmf.populateCashDrawerSummary();
097: }
098: }
099: // put any recently closed items in process in the form
100: cmf.setRecentlyClosedItemsInProcess(SpringContext.getBean(
101: CashManagementService.class)
102: .getRecentlyClosedItemsInProcess(
103: cmf.getCashManagementDocument()));
104:
105: return dest;
106: }
107:
108: /**
109: * Overrides the default document-creation code to auto-save new documents upon creation: since creating a CMDoc changes the
110: * CashDrawer's state as a side-effect, we need all CMDocs to be docsearchable so that someone can relocate and use or cancel
111: * whatever the current CMDoc is.
112: *
113: * @param kualiDocumentFormBase
114: * @throws WorkflowException
115: */
116: @Override
117: protected void createDocument(
118: KualiDocumentFormBase kualiDocumentFormBase)
119: throws WorkflowException {
120: UniversalUser user = GlobalVariables.getUserSession()
121: .getUniversalUser();
122: String workgroupName = SpringContext.getBean(
123: CashReceiptService.class)
124: .getCashReceiptVerificationUnitForUser(user);
125:
126: String defaultDescription = SpringContext.getBean(
127: KualiConfigurationService.class).getPropertyString(
128: CashManagement.DEFAULT_DOCUMENT_DESCRIPTION);
129: defaultDescription = StringUtils.replace(defaultDescription,
130: "{0}", workgroupName);
131: defaultDescription = StringUtils.substring(defaultDescription,
132: 0, 39);
133:
134: // create doc
135: CashManagementDocument cmDoc = SpringContext.getBean(
136: CashManagementService.class)
137: .createCashManagementDocument(workgroupName,
138: defaultDescription, null);
139:
140: // update form
141: kualiDocumentFormBase.setDocument(cmDoc);
142: kualiDocumentFormBase.setDocTypeName(cmDoc.getDocumentHeader()
143: .getWorkflowDocument().getDocumentType());
144: }
145:
146: private CashManagementDocumentAuthorizer getDocumentAuthorizer() {
147: String documentTypeName = SpringContext.getBean(
148: DataDictionaryService.class)
149: .getDocumentTypeNameByClass(
150: CashManagementDocument.class);
151: DocumentAuthorizer documentAuthorizer = SpringContext.getBean(
152: DocumentAuthorizationService.class)
153: .getDocumentAuthorizer(documentTypeName);
154:
155: return (CashManagementDocumentAuthorizer) documentAuthorizer;
156: }
157:
158: /**
159: * @param mapping
160: * @param form
161: * @param request
162: * @param response
163: * @return ActionForward
164: * @throws Exception
165: */
166: public ActionForward addInterimDeposit(ActionMapping mapping,
167: ActionForm form, HttpServletRequest request,
168: HttpServletResponse response) throws Exception {
169: CashManagementForm cmForm = (CashManagementForm) form;
170: CashManagementDocument cmDoc = cmForm
171: .getCashManagementDocument();
172:
173: checkDepositAuthorization(cmDoc,
174: DepositConstants.DEPOSIT_TYPE_INTERIM);
175:
176: String wizardUrl = buildDepositWizardUrl(cmDoc,
177: DepositConstants.DEPOSIT_TYPE_INTERIM);
178: return new ActionForward(wizardUrl, true);
179: }
180:
181: /**
182: * @param mapping
183: * @param form
184: * @param request
185: * @param response
186: * @return ActionForward
187: * @throws Exception
188: */
189: public ActionForward addFinalDeposit(ActionMapping mapping,
190: ActionForm form, HttpServletRequest request,
191: HttpServletResponse response) throws Exception {
192: CashManagementForm cmForm = (CashManagementForm) form;
193: CashManagementDocument cmDoc = cmForm
194: .getCashManagementDocument();
195:
196: checkDepositAuthorization(cmDoc,
197: DepositConstants.DEPOSIT_TYPE_FINAL);
198:
199: String wizardUrl = buildDepositWizardUrl(cmDoc,
200: DepositConstants.DEPOSIT_TYPE_FINAL);
201: return new ActionForward(wizardUrl, true);
202: }
203:
204: /**
205: * Throws a DocumentAuthorizationException if the current user is not authorized to add a deposit of the given type to the given
206: * document.
207: *
208: * @param cmDoc
209: * @param depositTypeCode
210: */
211: private void checkDepositAuthorization(
212: CashManagementDocument cmDoc, String depositTypeCode) {
213: // deposits can only be added if the CashDrawer is open
214: if (!cmDoc.getCashDrawerStatus().equals(
215: CashDrawerConstants.STATUS_OPEN)) {
216: throw new IllegalStateException("CashDrawer '"
217: + cmDoc.getWorkgroupName()
218: + "' must be open for deposits to be made");
219: }
220:
221: // verify user's ability to add a deposit
222: UniversalUser user = GlobalVariables.getUserSession()
223: .getUniversalUser();
224: Map editModes = getDocumentAuthorizer()
225: .getEditMode(cmDoc, user);
226: if (!editModes
227: .containsKey(AuthorizationConstants.CashManagementEditMode.ALLOW_ADDITIONAL_DEPOSITS)) {
228: throw buildAuthorizationException("add a deposit", cmDoc);
229: }
230: }
231:
232: /**
233: * @param cmDoc
234: * @param depositTypeCode
235: * @return URL for passing control to the DepositWizard
236: */
237: private String buildDepositWizardUrl(CashManagementDocument cmDoc,
238: String depositTypeCode) {
239: Properties params = new Properties();
240: params.setProperty("methodToCall", "startWizard");
241: params.setProperty("cmDocId", cmDoc.getDocumentNumber());
242: params.setProperty("depositTypeCode", depositTypeCode);
243:
244: String wizardActionUrl = UrlFactory.parameterizeUrl(
245: "depositWizard.do", params);
246: return wizardActionUrl;
247: }
248:
249: /**
250: * @param mapping
251: * @param form
252: * @param request
253: * @param response
254: * @return ActionForward
255: * @throws Exception
256: */
257: public ActionForward cancelDeposit(ActionMapping mapping,
258: ActionForm form, HttpServletRequest request,
259: HttpServletResponse response) throws Exception {
260: CashManagementForm cmForm = (CashManagementForm) form;
261: CashManagementDocument cmDoc = cmForm
262: .getCashManagementDocument();
263:
264: // validate cancelability
265: int depositIndex = getSelectedLine(request);
266: Deposit deposit = cmDoc.getDeposit(depositIndex);
267: if (StringUtils.equals(deposit.getDepositTypeCode(),
268: DepositConstants.DEPOSIT_TYPE_INTERIM)
269: && cmDoc.hasFinalDeposit()) {
270: throw new IllegalStateException(
271: "interim deposits cannot be canceled if the document already has a final deposit");
272: }
273:
274: // cancel the deposit
275: deposit = cmDoc.removeDeposit(depositIndex);
276: SpringContext.getBean(CashManagementService.class)
277: .cancelDeposit(deposit);
278:
279: // update the form
280: cmForm.removeDepositHelper(depositIndex);
281:
282: // open the CashDrawer so that user can add new deposits
283: cmDoc.getCashDrawer().setStatusCode(
284: KFSConstants.CashDrawerConstants.STATUS_OPEN);
285:
286: // display status message
287: GlobalVariables.getMessageList().add(
288: CashManagement.STATUS_DEPOSIT_CANCELED);
289:
290: return mapping.findForward(KFSConstants.MAPPING_BASIC);
291: }
292:
293: /**
294: * @see org.kuali.core.web.struts.action.KualiDocumentActionBase#reload(org.apache.struts.action.ActionMapping,
295: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
296: */
297: @Override
298: public ActionForward reload(ActionMapping mapping, ActionForm form,
299: HttpServletRequest request, HttpServletResponse response)
300: throws Exception {
301: ActionForward dest = super .reload(mapping, form, request,
302: response);
303:
304: // refresh the CashDrawerSummary, just in case
305: CashManagementForm cmForm = (CashManagementForm) form;
306: CashManagementDocument cmDoc = cmForm
307: .getCashManagementDocument();
308:
309: CashDrawerSummary cms = cmForm.getCashDrawerSummary();
310: if (cms != null) {
311: cms.resummarize(cmDoc);
312: }
313:
314: return dest;
315: }
316:
317: /**
318: * @param mapping
319: * @param form
320: * @param request
321: * @param response
322: * @return ActionForward
323: * @throws Exception
324: */
325: public ActionForward refreshSummary(ActionMapping mapping,
326: ActionForm form, HttpServletRequest request,
327: HttpServletResponse response) throws Exception {
328: CashManagementForm cmForm = (CashManagementForm) form;
329: CashManagementDocument cmDoc = cmForm
330: .getCashManagementDocument();
331:
332: cmForm.getCashDrawerSummary().resummarize(cmDoc);
333:
334: return mapping.findForward(KFSConstants.MAPPING_BASIC);
335: }
336:
337: /**
338: * Saves the document, then opens the cash drawer
339: *
340: * @param mapping
341: * @param form
342: * @param request
343: * @param response
344: * @return
345: * @throws Exception
346: */
347: public ActionForward openCashDrawer(ActionMapping mapping,
348: ActionForm form, HttpServletRequest request,
349: HttpServletResponse response) throws Exception {
350: CashManagementForm cmForm = (CashManagementForm) form;
351: CashManagementDocument cmDoc = cmForm
352: .getCashManagementDocument();
353:
354: if (!cmDoc.getDocumentHeader().getWorkflowDocument()
355: .stateIsInitiated()) {
356: throw new IllegalStateException(
357: "openCashDrawer should only be called on documents which haven't yet been saved");
358: }
359:
360: // open the CashDrawer
361: CashDrawerService cds = SpringContext
362: .getBean(CashDrawerService.class);
363: cds.openCashDrawer(cmDoc.getCashDrawer(), cmDoc
364: .getDocumentNumber());
365: // now that the cash drawer is open, let's create currency/coin detail records for this document
366: // create and save the cumulative cash receipt, deposit, money in and money out curr/coin details
367: SpringContext.getBean(CashManagementService.class)
368: .createNewCashDetails(cmDoc,
369: KFSConstants.CurrencyCoinSources.CASH_RECEIPTS);
370: SpringContext
371: .getBean(CashManagementService.class)
372: .createNewCashDetails(
373: cmDoc,
374: KFSConstants.CurrencyCoinSources.CASH_MANAGEMENT_IN);
375: SpringContext
376: .getBean(CashManagementService.class)
377: .createNewCashDetails(
378: cmDoc,
379: KFSConstants.CurrencyCoinSources.CASH_MANAGEMENT_OUT);
380: try {
381: SpringContext.getBean(DocumentService.class).saveDocument(
382: cmDoc);
383: } catch (WorkflowException e) {
384: // force it closed if workflow proves recalcitrant
385: cds.closeCashDrawer(cmDoc.getCashDrawer());
386: throw e;
387: }
388:
389: // update the CashDrawerSummary to reflect the change
390: cmForm.populateCashDrawerSummary();
391:
392: return mapping.findForward(KFSConstants.MAPPING_BASIC);
393: }
394:
395: /**
396: * This action makes the last interim deposit a final deposit
397: *
398: * @param mapping the mapping of the actions
399: * @param form the Struts form populated on the post
400: * @param request the servlet request
401: * @param response the servlet response
402: * @return a forward to the same page we were on
403: * @throws Exception because you never know when something just might go wrong
404: */
405: public ActionForward finalizeLastInterimDeposit(
406: ActionMapping mapping, ActionForm form,
407: HttpServletRequest request, HttpServletResponse response)
408: throws Exception {
409: CashManagementDocument cmDoc = ((CashManagementForm) form)
410: .getCashManagementDocument();
411: CashManagementService cms = SpringContext
412: .getBean(CashManagementService.class);
413:
414: if (cmDoc.hasFinalDeposit()) {
415: GlobalVariables
416: .getErrorMap()
417: .putError(
418: KFSConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS,
419: CashManagement.ERROR_DOCUMENT_ALREADY_HAS_FINAL_DEPOSIT,
420: new String[] {});
421: } else if (cmDoc.getDeposits().size() == 0) {
422: GlobalVariables
423: .getErrorMap()
424: .putError(
425: KFSConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS,
426: CashManagement.ERROR_DOCUMENT_NO_DEPOSITS_TO_MAKE_FINAL,
427: new String[] {});
428: } else if (!cms.allVerifiedCashReceiptsAreDeposited(cmDoc)) {
429: GlobalVariables
430: .getErrorMap()
431: .putError(
432: KFSConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS,
433: CashManagement.ERROR_NON_DEPOSITED_VERIFIED_CASH_RECEIPTS,
434: new String[] {});
435: }
436:
437: cms.finalizeLastInterimDeposit(cmDoc);
438:
439: ((CashManagementForm) form).getCashDrawerSummary().resummarize(
440: cmDoc);
441:
442: return mapping.findForward(KFSConstants.MAPPING_BASIC);
443: }
444:
445: /**
446: * This action applies the current cashiering transaction to the cash drawer
447: *
448: * @param mapping
449: * @param form
450: * @param request
451: * @param response
452: * @return
453: * @throws Exception
454: */
455: public ActionForward applyCashieringTransaction(
456: ActionMapping mapping, ActionForm form,
457: HttpServletRequest request, HttpServletResponse response)
458: throws Exception {
459: CashManagementDocument cmDoc = ((CashManagementForm) form)
460: .getCashManagementDocument();
461: CashManagementService cmService = SpringContext
462: .getBean(CashManagementService.class);
463:
464: cmService.applyCashieringTransaction(cmDoc);
465:
466: ((CashManagementForm) form).getCashDrawerSummary().resummarize(
467: cmDoc);
468:
469: return mapping.findForward(KFSConstants.MAPPING_BASIC);
470: }
471:
472: /**
473: * This action allows the user to go to the cash drawer correction screen
474: *
475: * @param mapping
476: * @param form
477: * @param request
478: * @param response
479: * @return
480: * @throws Exception
481: */
482: public ActionForward correctCashDrawer(ActionMapping mapping,
483: ActionForm form, HttpServletRequest request,
484: HttpServletResponse response) throws Exception {
485: return new ActionForward(
486: "CashDrawerCorrectionForm",
487: buildCashDrawerCorrectionUrl(((CashManagementForm) form)
488: .getCashManagementDocument()), true);
489: }
490:
491: /**
492: * @param cmDoc
493: * @param depositTypeCode
494: * @return URL for passing control to the DepositWizard
495: */
496: private String buildCashDrawerCorrectionUrl(
497: CashManagementDocument cmDoc) {
498: Properties params = new Properties();
499: params.setProperty("methodToCall", "startCorrections");
500: params.setProperty("wrkgrpNm", cmDoc.getWorkgroupName());
501:
502: return UrlFactory.parameterizeUrl("cashDrawerCorrection.do",
503: params);
504: }
505:
506: /**
507: * Adds Check instance created from the current "new check" line to the document
508: *
509: * @param mapping
510: * @param form
511: * @param request
512: * @param response
513: * @return ActionForward
514: * @throws Exception
515: */
516: public ActionForward addCheck(ActionMapping mapping,
517: ActionForm form, HttpServletRequest request,
518: HttpServletResponse response) throws Exception {
519: CashManagementDocument cmDoc = ((CashManagementForm) form)
520: .getCashManagementDocument();
521:
522: Check newCheck = cmDoc.getCurrentTransaction().getNewCheck();
523: newCheck.setDocumentNumber(cmDoc.getDocumentNumber());
524:
525: // check business rules
526: boolean rulePassed = SpringContext.getBean(
527: KualiRuleService.class).applyRules(
528: new AddCheckEvent(KFSConstants.NEW_CHECK_PROPERTY_NAME,
529: cmDoc, newCheck));
530: if (rulePassed) {
531: // add check
532: cmDoc.getCurrentTransaction().addCheck(newCheck);
533:
534: // clear the used newCheck
535: cmDoc.getCurrentTransaction().setNewCheck(
536: cmDoc.getCurrentTransaction().createNewCheck());
537:
538: }
539:
540: return mapping.findForward(KFSConstants.MAPPING_BASIC);
541: }
542:
543: /**
544: * Deletes the selected check (line) from the document
545: *
546: * @param mapping
547: * @param form
548: * @param request
549: * @param response
550: * @return ActionForward
551: * @throws Exception
552: */
553: public ActionForward deleteCheck(ActionMapping mapping,
554: ActionForm form, HttpServletRequest request,
555: HttpServletResponse response) throws Exception {
556: CashManagementDocument cmDoc = ((CashManagementForm) form)
557: .getCashManagementDocument();
558:
559: int deleteIndex = getLineToDelete(request);
560: Check oldCheck = cmDoc.getCurrentTransaction().getCheck(
561: deleteIndex);
562:
563: boolean rulePassed = SpringContext.getBean(
564: KualiRuleService.class).applyRules(
565: new DeleteCheckEvent(
566: KFSConstants.EXISTING_CHECK_PROPERTY_NAME,
567: cmDoc, oldCheck));
568:
569: if (rulePassed) {
570: // delete check
571: cmDoc.getCurrentTransaction().removeCheck(deleteIndex);
572:
573: // delete baseline check, if any
574: if (cmDoc.getCurrentTransaction().hasBaselineCheck(
575: deleteIndex)) {
576: cmDoc.getCurrentTransaction().getBaselineChecks()
577: .remove(deleteIndex);
578: }
579:
580: } else {
581: GlobalVariables.getErrorMap().putError(
582: "document.currentTransaction.check[" + deleteIndex
583: + "]",
584: KFSKeyConstants.Check.ERROR_CHECK_DELETERULE,
585: Integer.toString(deleteIndex));
586: }
587:
588: return mapping.findForward(KFSConstants.MAPPING_BASIC);
589: }
590:
591: /**
592: * Overridden to clear the CashDrawerSummary info
593: *
594: * @see org.kuali.core.web.struts.action.KualiDocumentActionBase#route(org.apache.struts.action.ActionMapping,
595: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
596: */
597: @Override
598: public ActionForward route(ActionMapping mapping, ActionForm form,
599: HttpServletRequest request, HttpServletResponse response)
600: throws Exception {
601: CashManagementForm cmForm = (CashManagementForm) form;
602: CashManagementDocument cmDoc = cmForm
603: .getCashManagementDocument();
604:
605: ActionForward dest = super .route(mapping, form, request,
606: response);
607:
608: // clear the CashDrawerSummary
609: cmForm.setCashDrawerSummary(null);
610:
611: return dest;
612: }
613: }
|