/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.fp.document.web.struts;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.kuali.kfs.fp.businessobject.Check;
import org.kuali.kfs.fp.document.CashReceiptDocument;
import org.kuali.kfs.fp.document.service.CashReceiptCoverSheetService;
import org.kuali.kfs.fp.document.service.CashReceiptService;
import org.kuali.kfs.fp.document.validation.event.AddCheckEvent;
import org.kuali.kfs.fp.document.validation.event.DeleteCheckEvent;
import org.kuali.kfs.fp.document.validation.event.UpdateCheckEvent;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.config.property.ConfigurationService;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kns.util.KNSGlobalVariables;
import org.kuali.rice.kns.util.WebUtils;
import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.service.KualiRuleService;
import org.kuali.rice.krad.util.GlobalVariables;
/**
*
*/
public class CashReceiptAction extends CapitalAccountingLinesActionBase {
/**
* Adds handling for check updates
*
* @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm,
* javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm cform = (CashReceiptForm) form;
if (cform.hasDocumentId()) {
CashReceiptDocument cdoc = cform.getCashReceiptDocument();
// handle change of checkEntryMode
processCheckEntryMode(cform, cdoc);
// handle changes to checks (but only if current checkEntryMode is 'detail')
if (CashReceiptDocument.CHECK_ENTRY_DETAIL.equals(cdoc.getCheckEntryMode())) {
cdoc.setTotalCheckAmount(cdoc.calculateCheckTotal()); // recalc b/c changes to the amounts could have happened
cdoc.setTotalConfirmedCheckAmount(cdoc.calculateConfirmedCheckTotal());
processChecks(cdoc, cform);
}
// generate errors for negative cash detail and total amounts (especially for the recalculate button)
SpringContext.getBean(CashReceiptService.class).areCashAmountsInvalid(cdoc);
}
// proceed as usual
ActionForward result = super.execute(mapping, form, request, response);
return result;
}
/**
* Prepares and streams CR PDF Cover Sheet
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward printCoverSheet(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
// get directory of tempate
String directory = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(KFSConstants.EXTERNALIZABLE_HELP_URL_KEY);
// retrieve document
String documentNumber = request.getParameter(KFSPropertyConstants.DOCUMENT_NUMBER);
CashReceiptDocument document = (CashReceiptDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(documentNumber);
// since this action isn't triggered by a post, we don't have the normal document data
// so we have to set the document into the form manually so that later authz processing
// has a document object instance to work with
crForm.setDocument(document);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CashReceiptCoverSheetService coverSheetService = SpringContext.getBean(CashReceiptCoverSheetService.class);
coverSheetService.generateCoverSheet(document, directory, baos);
String fileName = documentNumber + "_cover_sheet.pdf";
WebUtils.saveMimeOutputStreamAsFile(response, "application/pdf", baos, fileName);
return null;
}
/**
* This method processes the check entry mode to determine if the user is entering checks or if they are just entering the
* total.
*
* @param crForm
* @param crDoc
*/
protected void processCheckEntryMode(CashReceiptForm crForm, CashReceiptDocument crDoc) {
String formMode = crForm.getCheckEntryMode();
String docMode = crDoc.getCheckEntryMode();
if (CashReceiptDocument.CHECK_ENTRY_DETAIL.equals(formMode) || CashReceiptDocument.CHECK_ENTRY_TOTAL.equals(formMode)) {
if (!formMode.equals(docMode)) {
if (formMode.equals(CashReceiptDocument.CHECK_ENTRY_DETAIL)) {
// save current checkTotal, for future restoration
crForm.setCheckTotal(crDoc.getTotalCheckAmount());
// change mode
crDoc.setCheckEntryMode(formMode);
crDoc.setTotalCheckAmount(crDoc.calculateCheckTotal());
// notify user
KNSGlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_INDIVIDUAL);
}
else {
// restore saved checkTotal
crDoc.setTotalCheckAmount(crForm.getCheckTotal());
// change mode
crDoc.setCheckEntryMode(formMode);
// notify user
KNSGlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_TOTAL);
}
}
}
}
/**
* This method handles iterating over the check list and generating check events to apply rules to.
*
* @param cdoc
* @param cform
*/
protected void processChecks(CashReceiptDocument cdoc, CashReceiptForm cform) {
List formChecks = cdoc.getChecks();
int index = 0;
Iterator i = formChecks.iterator();
while (i.hasNext()) {
Check formCheck = (Check) i.next();
// only generate update events for specific action methods
String methodToCall = cform.getMethodToCall();
if (UPDATE_EVENT_ACTIONS.contains(methodToCall)) {
SpringContext.getBean(KualiRuleService.class).applyRules(new UpdateCheckEvent(KFSPropertyConstants.DOCUMENT + "." + KFSPropertyConstants.CHECK + "[" + index + "]", cdoc, formCheck));
}
index++;
}
}
/**
* Adds Check instance created from the current "new check" line to the document
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward addCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
Check newCheck = crForm.getNewCheck();
newCheck.setDocumentNumber(crDoc.getDocumentNumber());
// check business rules
boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AddCheckEvent(KFSConstants.NEW_CHECK_PROPERTY_NAME, crDoc, newCheck));
if (rulePassed) {
// add check
crDoc.addCheck(newCheck);
// clear the used newCheck
crForm.setNewCheck(crDoc.createNewCheck());
}
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Adds confirmed Check instance created from the current "new check" line to the document
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward addConfirmedCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
Check newCheck = crForm.getNewConfirmedCheck();
newCheck.setDocumentNumber(crDoc.getDocumentNumber());
// check business rules
boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AddCheckEvent(KFSConstants.NEW_CHECK_PROPERTY_NAME, crDoc, newCheck));
if (rulePassed) {
// add check
crDoc.addConfirmedCheck(newCheck);
// clear the used newCheck
crForm.setNewConfirmedCheck(crDoc.createNewConfirmedCheck());
}
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Deletes the selected check (line) from the document
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward deleteCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
int deleteIndex = getLineToDelete(request);
Check oldCheck = crDoc.getCheck(deleteIndex);
boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteCheckEvent(KFSConstants.EXISTING_CHECK_PROPERTY_NAME, crDoc, oldCheck));
if (rulePassed) {
// delete check
crDoc.removeCheck(deleteIndex);
// delete baseline check, if any
if (crForm.hasBaselineCheck(deleteIndex)) {
crForm.getBaselineChecks().remove(deleteIndex);
}
}
else {
GlobalVariables.getMessageMap().putError("document.check[" + deleteIndex + "]", KFSKeyConstants.Check.ERROR_CHECK_DELETERULE, Integer.toString(deleteIndex));
}
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Deletes the selected check (line) from the document
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward deleteConfirmedCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
int deleteIndex = getLineToDelete(request);
Check oldCheck = crDoc.getConfirmedCheck(deleteIndex);
boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteCheckEvent(KFSConstants.EXISTING_CHECK_PROPERTY_NAME, crDoc, oldCheck));
if (rulePassed) {
// delete check
crDoc.removeConfirmedCheck(deleteIndex);
// delete baseline check, if any
if (crForm.hasBaselineCheck(deleteIndex)) {
crForm.getBaselineChecks().remove(deleteIndex);
}
}
else {
GlobalVariables.getMessageMap().putError("document.confirmedCheck[" + deleteIndex + "]", KFSKeyConstants.Check.ERROR_CHECK_DELETERULE, Integer.toString(deleteIndex));
}
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Changes the current check-entry mode, if necessary
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward changeCheckEntryMode(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
String formMode = crForm.getCheckEntryMode();
String docMode = crDoc.getCheckEntryMode();
if (CashReceiptDocument.CHECK_ENTRY_DETAIL.equals(formMode) || CashReceiptDocument.CHECK_ENTRY_TOTAL.equals(formMode)) {
if (!formMode.equals(docMode)) {
if (formMode.equals(CashReceiptDocument.CHECK_ENTRY_DETAIL)) {
// save current checkTotal, for future restoration
crForm.setCheckTotal(crDoc.getTotalCheckAmount());
// change mode
crDoc.setCheckEntryMode(formMode);
crDoc.setTotalCheckAmount(crDoc.calculateCheckTotal());
// notify user
KNSGlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_INDIVIDUAL);
}
else {
// restore saved checkTotal
crDoc.setTotalCheckAmount(crForm.getCheckTotal());
// change mode
crDoc.setCheckEntryMode(formMode);
// notify user
KNSGlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_TOTAL);
}
}
}
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
*/
@Override
protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
super.createDocument(kualiDocumentFormBase);
CashReceiptForm crForm = (CashReceiptForm) kualiDocumentFormBase;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
// We don't need to call initializeCampusLocationCode or initializeCashChangeDetails anymore,
// because they are called in CashReceiptDocument().
initDerivedCheckValues(crForm);
}
/**
* @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
*/
@Override
protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
super.loadDocument(kualiDocumentFormBase);
initDerivedCheckValues((CashReceiptForm) kualiDocumentFormBase);
}
/**
* Copy all original checks to cash manager confirmed checks
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward copyAllChecks(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
Check c, confirmedCheck;
for (Iterator<Check> i = crDoc.getChecks().iterator(); i.hasNext();) {
c = i.next();
confirmedCheck = crForm.getNewConfirmedCheck();
confirmedCheck.setDocumentNumber(c.getDocumentNumber());
confirmedCheck.setCheckDate(c.getCheckDate());
confirmedCheck.setCheckNumber(c.getCheckNumber());
confirmedCheck.setAmount(c.getAmount());
confirmedCheck.setDescription(c.getDescription());
crDoc.addConfirmedCheck(confirmedCheck);
// clear the used newCheck
crForm.setNewConfirmedCheck(crDoc.createNewConfirmedCheck());
}
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Copies all original currency and coin amounts to cash manager confirmed currency and coin amounts.
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward copyAllCurrencyAndCoin(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
crDoc.getConfirmedCurrencyDetail().copyAmounts(crDoc.getCurrencyDetail());
crDoc.getConfirmedCoinDetail().copyAmounts(crDoc.getCoinDetail());
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Copies all original change currency and coin amounts to cash manager confirmed change currency and coin amounts.
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward copyAllChangeCurrencyAndCoin(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
CashReceiptForm crForm = (CashReceiptForm) form;
CashReceiptDocument crDoc = crForm.getCashReceiptDocument();
crDoc.getConfirmedChangeCurrencyDetail().copyAmounts(crDoc.getChangeCurrencyDetail());
crDoc.getConfirmedChangeCoinDetail().copyAmounts(crDoc.getChangeCoinDetail());
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* Initializes form values which must be derived form document contents (i.e. those which aren't directly available from the
* document)
*
* @param cform
*/
protected void initDerivedCheckValues(CashReceiptForm cform) {
CashReceiptDocument cdoc = cform.getCashReceiptDocument();
cform.setCheckEntryMode(cdoc.getCheckEntryMode());
cform.setCheckTotal(cdoc.getTotalCheckAmount());
cform.getBaselineChecks().clear();
cform.getBaselineChecks().addAll(cform.getCashReceiptDocument().getChecks());
}
/**
* Overridden to guarantee that form of copied document is set to whatever the entry mode of the document is
* @see org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase#copy(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
public ActionForward copy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
ActionForward forward = super.copy(mapping, form, request, response);
initDerivedCheckValues((CashReceiptForm)form);
return forward;
}
}