/*
* 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.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.kuali.kfs.fp.businessobject.CashDrawer;
import org.kuali.kfs.fp.businessobject.CashieringTransaction;
import org.kuali.kfs.fp.businessobject.Check;
import org.kuali.kfs.fp.businessobject.CoinDetail;
import org.kuali.kfs.fp.businessobject.CurrencyDetail;
import org.kuali.kfs.fp.businessobject.Deposit;
import org.kuali.kfs.fp.businessobject.DepositWizardCashieringCheckHelper;
import org.kuali.kfs.fp.businessobject.DepositWizardHelper;
import org.kuali.kfs.fp.businessobject.format.CashDrawerStatusCodeFormatter;
import org.kuali.kfs.fp.document.CashManagementDocument;
import org.kuali.kfs.fp.document.CashReceiptDocument;
import org.kuali.kfs.fp.document.service.CashManagementService;
import org.kuali.kfs.fp.document.service.CashReceiptService;
import org.kuali.kfs.fp.exception.CashDrawerStateException;
import org.kuali.kfs.fp.service.CashDrawerService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSConstants.CashDrawerConstants;
import org.kuali.kfs.sys.KFSConstants.DepositConstants;
import org.kuali.kfs.sys.KFSConstants.DocumentStatusCodes.CashReceipt;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.businessobject.Bank;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.document.datadictionary.FinancialSystemTransactionalDocumentEntry;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.core.web.format.CurrencyFormatter;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer;
import org.kuali.rice.kns.document.authorization.TransactionalDocumentPresentationController;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.kns.service.DocumentHelperService;
import org.kuali.rice.kns.web.struts.action.KualiAction;
import org.kuali.rice.krad.exception.InfrastructureException;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.UrlFactory;
/**
* This class handles actions for the deposit wizard, which is used to create deposits that bundle groupings of Cash Receipt
* documents.
*/
public class DepositWizardAction extends KualiAction {
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DepositWizardAction.class);
private static final String CASH_MANAGEMENT_STATUS_PAGE = "/cashManagementStatus.do";
/**
* Overrides the parent to validate the document state of the cashManagementDocument which will be updated and redisplayed after
* the DepositWizard builds and attaches the new Deposit.
*
* @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 {
DepositWizardForm dwForm = (DepositWizardForm) form;
ActionForward dest = super.execute(mapping, form, request, response);
// check authorization manually, since the auth-check isn't inherited by this class
DocumentAuthorizer cmDocAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(KFSConstants.FinancialDocumentTypeCodes.CASH_MANAGEMENT);
Person luser = GlobalVariables.getUserSession().getPerson();
cmDocAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.CASH_MANAGEMENT, luser);
// populate the outgoing form used by the JSP if it seems empty
String cmDocId = dwForm.getCashManagementDocId();
if (StringUtils.isBlank(cmDocId)) {
cmDocId = request.getParameter("cmDocId");
String depositTypeCode = request.getParameter("depositTypeCode");
CashManagementDocument cmDoc = (CashManagementDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(cmDocId);
try {
initializeForm(dwForm, cmDoc, depositTypeCode);
}
catch (CashDrawerStateException cdse) {
dest = new ActionForward(UrlFactory.parameterizeUrl(CASH_MANAGEMENT_STATUS_PAGE, cdse.toProperties()), true);
}
} else { // for recalculation
loadCashReceipts(dwForm);
loadUndepositedCashieringChecks(dwForm);
if (dwForm.getTargetDepositAmount() == null) {
calculateTargetFinalDepositAmount(dwForm);
}
loadEditModesAndDocumentActions(dwForm);
}
return dest;
}
/**
* Initializes the given form using the given values
*
* @param dform
* @param cmDoc
* @param depositTypeCode
*/
private void initializeForm(DepositWizardForm dform, CashManagementDocument cmDoc, String depositTypeCode) {
CashDrawer cd = SpringContext.getBean(CashDrawerService.class).getByCampusCode(cmDoc.getCampusCode());
if (cd == null) {
throw new RuntimeException("No cash drawer exists for campus code " + cmDoc.getCampusCode() + "; please create on via the Cash Drawer Maintenance Document before attemping to create a CashManagementDocument for campus " + cmDoc.getCampusCode());
}
if (!cd.isOpen()) {
CashDrawerStatusCodeFormatter f = new CashDrawerStatusCodeFormatter();
String cmDocId = cmDoc.getDocumentNumber();
String currentState = cd.getStatusCode();
throw new CashDrawerStateException(cmDoc.getCampusCode(), cmDocId, (String) f.format(CashDrawerConstants.STATUS_OPEN), (String) f.format(cd.getStatusCode()));
}
dform.setCashManagementDocId(cmDoc.getDocumentNumber());
dform.setCashDrawerCampusCode(cmDoc.getCampusCode());
dform.setDepositTypeCode(depositTypeCode);
if (depositTypeCode.equals(DepositConstants.DEPOSIT_TYPE_FINAL)) {
// hey, we're the magical final deposit. We get currency and coin details!
CurrencyDetail currencyDetail = new CurrencyDetail();
currencyDetail.setDocumentNumber(cmDoc.getDocumentNumber());
currencyDetail.setCashieringStatus(KFSConstants.CurrencyCoinSources.DEPOSITS);
currencyDetail.setFinancialDocumentTypeCode(CashieringTransaction.DETAIL_DOCUMENT_TYPE);
dform.setCurrencyDetail(currencyDetail);
CoinDetail coinDetail = new CoinDetail();
coinDetail.setDocumentNumber(cmDoc.getDocumentNumber());
coinDetail.setCashieringStatus(KFSConstants.CurrencyCoinSources.DEPOSITS);
coinDetail.setFinancialDocumentTypeCode(CashieringTransaction.DETAIL_DOCUMENT_TYPE);
dform.setCoinDetail(coinDetail);
}
loadCashReceipts(dform);
loadUndepositedCashieringChecks(dform);
if (dform.isDepositFinal() && dform.getTargetDepositAmount() == null) {
calculateTargetFinalDepositAmount(dform);
}
loadEditModesAndDocumentActions(dform);
}
/**
* Loads the CashReceipt information, re/setting the related form fields
*
* @param dform
*/
private void loadCashReceipts(DepositWizardForm dform) {
List<CashReceiptDocument> verifiedReceipts = SpringContext.getBean(CashReceiptService.class).getCashReceipts(dform.getCashDrawerCampusCode(), new String[] { CashReceipt.VERIFIED, CashReceipt.INTERIM });
dform.setDepositableCashReceipts(new ArrayList());
dform.setCheckFreeCashReceipts(new ArrayList<CashReceiptDocument>());
dform.resetCurrentCheckTotal();
// prepopulate DepositWizardHelpers
int index = 0;
for (Iterator i = verifiedReceipts.iterator(); i.hasNext();) {
CashReceiptDocument receipt = (CashReceiptDocument) i.next();
receipt.processAfterRetrieve(); // To populate Currency and Coin details
String docStatus = receipt.getFinancialSystemDocumentHeader().getFinancialDocumentStatusCode();
if (docStatus.equalsIgnoreCase(CashReceipt.VERIFIED)) { // for interim or final deposit
if (receipt.getCheckCount() == 0 && receipt.getTotalConfirmedCheckAmount().equals(KualiDecimal.ZERO)) {
dform.getCheckFreeCashReceipts().add(receipt);
}
else {
dform.getDepositableCashReceipts().add(receipt);
DepositWizardHelper d = dform.getDepositWizardHelper(index++);
// KFSMI-5232 Jira fix. Convert the time stamp to SQL date format
Timestamp ts = new Timestamp(receipt.getDocumentHeader().getWorkflowDocument().getDateCreated().getMillis());
try {
d.setCashReceiptCreateDate(SpringContext.getBean(DateTimeService.class).convertToSqlDate(ts));
}
catch (Exception e) {
}
}
}
else if (docStatus.equalsIgnoreCase(CashReceipt.INTERIM)) { // for final deposit
// checks are already deposited but there are cash to be deposited
/* We should check whether the net cash total, i.e. (currency + coin) - (change currency + change coin)
* is greater than 0; and if so, there's cash to deposit.
*/
if (receipt.getTotalConfirmedNetCashAmount().isGreaterThan(KualiDecimal.ZERO)) {
dform.getCheckFreeCashReceipts().add(receipt);
}
}
dform.addCashReceiptToChecks(receipt);
}
}
/**
* Loads cashiering transactions for final deposit target amount
* @param dwform
*/
private void calculateTargetFinalDepositAmount(DepositWizardForm dwform) {
final CashReceiptService cashReceiptService = SpringContext.getBean(CashReceiptService.class);
final List<CashReceiptDocument> interestingReceipts =
cashReceiptService.getCashReceipts(dwform.getCashDrawerCampusCode(), new String[] { CashReceipt.VERIFIED, CashReceipt.INTERIM, CashReceipt.FINAL });
for (CashReceiptDocument crDoc : interestingReceipts) {
crDoc.refreshCashDetails();
dwform.addCashReceiptToTargetTotal(crDoc);
}
final CashManagementService cashManagementService = SpringContext.getBean(CashManagementService.class);
KualiDecimal toBeDepositedChecksTotal = KualiDecimal.ZERO;
for (Check check : cashManagementService.selectUndepositedCashieringChecks(dwform.getCashManagementDocId())) {
toBeDepositedChecksTotal = toBeDepositedChecksTotal.add(check.getAmount());
}
// since final, include deposited checks as well (see KFSCNTRB-160)
for (Check check : cashManagementService.selectDepositedCashieringChecks(dwform.getCashManagementDocId())) {
toBeDepositedChecksTotal = toBeDepositedChecksTotal.add(check.getAmount());
}
dwform.addCashieringTransactionToTargetTotal(toBeDepositedChecksTotal);
}
/**
* This loads any cashiering checks which have not yet been deposited into the DepositWizardForm
*
* @param dform a form to load undeposited checks into
*/
private void loadUndepositedCashieringChecks(DepositWizardForm dform) {
List<Check> cashieringChecks = SpringContext.getBean(CashManagementService.class).selectUndepositedCashieringChecks(dform.getCashManagementDocId());
dform.setDepositableCashieringChecks(cashieringChecks);
dform.addCashieringReceiptToChecks();
}
private void loadEditModesAndDocumentActions(DepositWizardForm dform) {
final FinancialSystemTransactionalDocumentEntry ddEntry = getCashManagementDataDictionaryEntry();
final TransactionalDocumentPresentationController presentationController = getCashManagementPresentationController(ddEntry);
final TransactionalDocumentAuthorizer docAuthorizer = getCashManagementDocumentAuthorizer(ddEntry);
dform.setEditingMode(retrieveEditingModes(dform.getCashManagementDocId(), presentationController, docAuthorizer));
dform.setDocumentActions(retrieveDocumentActions(dform.getCashManagementDocId(), presentationController, docAuthorizer));
}
/**
* @return the class of the cash management document
*/
protected String getCashManagementDocumentTypeName() {
return "CMD";
}
/**
* @return the data dictionary entry for the cash management class
*/
private FinancialSystemTransactionalDocumentEntry getCashManagementDataDictionaryEntry() {
final DataDictionaryService ddService = SpringContext.getBean(DataDictionaryService.class);
return (FinancialSystemTransactionalDocumentEntry)ddService.getDataDictionary().getDocumentEntry(getCashManagementDocumentTypeName());
}
/**
* Returns an instance of the document presentation controller for the cash management class
* @param cashManagementEntry the data dictionary entry for the cash management document
* @return an instance of the proper document presentation controller
*/
private TransactionalDocumentPresentationController getCashManagementPresentationController(FinancialSystemTransactionalDocumentEntry cashManagementEntry) {
final Class presentationControllerClass = cashManagementEntry.getDocumentPresentationControllerClass();
TransactionalDocumentPresentationController presentationController = null;
try {
presentationController = (TransactionalDocumentPresentationController)presentationControllerClass.newInstance();
}
catch (InstantiationException ie) {
throw new RuntimeException("Could not instantiate cash management presentation controller of class " + presentationControllerClass.getName(), ie);
}
catch (IllegalAccessException iae) {
throw new RuntimeException("Could not instantiate cash management presentation controller of class " + presentationControllerClass.getName(), iae);
}
return presentationController;
}
/**
* Returns an instance of the document authorizer for the cash management class
* @param cashManagementEntry the data dictionary entry for the cash management document
* @return an instance of the proper document authorizer
*/
private TransactionalDocumentAuthorizer getCashManagementDocumentAuthorizer(FinancialSystemTransactionalDocumentEntry cashManagementEntry) {
final Class docAuthorizerClass = cashManagementEntry.getDocumentAuthorizerClass();
TransactionalDocumentAuthorizer docAuthorizer = null;
try {
docAuthorizer = (TransactionalDocumentAuthorizer)docAuthorizerClass.newInstance();
}
catch (InstantiationException ie) {
throw new RuntimeException("Could not instantiate cash management document authorizer of class " + docAuthorizerClass.getName(), ie);
}
catch (IllegalAccessException iae) {
throw new RuntimeException("Could not instantiate cash management document authorizer of class " + docAuthorizerClass.getName(), iae);
}
return docAuthorizer;
}
/**
* Retrieves the edit modes for the given cash management document
* @param cashManagementDocId the id of the cash management document to check
* @param presentationController the presentation controller of the cash management document
* @param docAuthorizer the cash management document authorizer
* @return a Map of edit modes
*/
private Map retrieveEditingModes(String cashManagementDocId, TransactionalDocumentPresentationController presentationController, TransactionalDocumentAuthorizer docAuthorizer) {
Map editModeMap = null;
try {
final CashManagementDocument cmDoc = (CashManagementDocument)SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(cashManagementDocId);
Set<String> editModes = presentationController.getEditModes(cmDoc);
editModes = docAuthorizer.getEditModes(cmDoc, GlobalVariables.getUserSession().getPerson(), editModes);
editModeMap = convertSetToMap(editModes);
}
catch (WorkflowException we) {
throw new RuntimeException("Workflow exception while retrieving document " + cashManagementDocId, we);
}
return editModeMap;
}
/**
* Retrieves the document actions for the given cash management document
* @param cashManagementDocId the id of the cash management document to check
* @param presentationController the presentation controller of the cash management document
* @param docAuthorizer the cash management document authorizer
* @return a Map of document actions
*/
private Map retrieveDocumentActions(String cashManagementDocId, TransactionalDocumentPresentationController presentationController, TransactionalDocumentAuthorizer docAuthorizer) {
Map documentActionsMap = null;
try {
final CashManagementDocument cmDoc = (CashManagementDocument)SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(cashManagementDocId);
Set<String> documentActions = presentationController.getDocumentActions(cmDoc);
documentActions = docAuthorizer.getEditModes(cmDoc, GlobalVariables.getUserSession().getPerson(), documentActions);
documentActionsMap = convertSetToMap(documentActions);
}
catch (WorkflowException we) {
throw new RuntimeException("Workflow exception while retrieving document " + cashManagementDocId, we);
}
return documentActionsMap;
}
/**
* Converts a set into a map, where each value in the set becomes a key and each value becomes KNSConstants.KUALI_DEFAULT_TRUE_VALUE
* @param s a set
* @return a map
*/
protected Map convertSetToMap(Set s){
Map map = new HashMap();
Iterator i = s.iterator();
while(i.hasNext()) {
Object key = i.next();
map.put(key, KRADConstants.KUALI_DEFAULT_TRUE_VALUE);
}
return map;
}
/**
* Reloads the CashReceipts, leaving everything else unchanged
*
* @see org.kuali.rice.kns.web.struts.action.KualiAction#refresh(org.apache.struts.action.ActionMapping,
* org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
loadCashReceipts((DepositWizardForm) form);
loadUndepositedCashieringChecks((DepositWizardForm) form);
if (((DepositWizardForm) form).isDepositFinal() && ((DepositWizardForm)form).getTargetDepositAmount() == null) {
calculateTargetFinalDepositAmount((DepositWizardForm) form);
}
loadEditModesAndDocumentActions((DepositWizardForm) form);
return super.refresh(mapping, form, request, response);
}
/**
* This method is the starting point for the deposit document wizard.
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward startWizard(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
return mapping.findForward(KFSConstants.MAPPING_BASIC);
}
/**
* This method is the action method for creating the new deposit document from the information chosen by the user in the UI.
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward createDeposit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
ActionForward dest = mapping.findForward(KFSConstants.MAPPING_BASIC);
DepositWizardForm dform = (DepositWizardForm) form;
final BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class);
final CashReceiptService cashReceiptService = SpringContext.getBean(CashReceiptService.class);
final DocumentService documentService = SpringContext.getBean(DocumentService.class);
final CashManagementService cashManagementService = SpringContext.getBean(CashManagementService.class);
CurrencyFormatter formatter = new CurrencyFormatter();
// reload edit modes and summary totals - just in case we have to return to the deposit wizard page
loadCashReceipts((DepositWizardForm) form);
if (((DepositWizardForm) form).isDepositFinal() && ((DepositWizardForm)form).getTargetDepositAmount() == null) {
calculateTargetFinalDepositAmount((DepositWizardForm) form);
}
loadEditModesAndDocumentActions(dform);
// validate Bank
String bankCode = dform.getBankCode();
if (StringUtils.isBlank(bankCode)) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_MISSING_BANK);
}
else {
Map keyMap = new HashMap();
keyMap.put(KFSPropertyConstants.BANK_CODE, bankCode);
Bank bank = boService.findByPrimaryKey(Bank.class, keyMap);
if (bank == null) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_UNKNOWN_BANK, bankCode);
}
else {
dform.setBank(bank);
}
}
boolean depositIsFinal = (StringUtils.equals(dform.getDepositTypeCode(), KFSConstants.DepositConstants.DEPOSIT_TYPE_FINAL));
// validate cashReceipt selection
List selectedIds = new ArrayList();
for (Iterator i = dform.getDepositWizardHelpers().iterator(); i.hasNext();) {
String checkValue = ((DepositWizardHelper) i.next()).getSelectedValue();
if (StringUtils.isNotBlank(checkValue) && !checkValue.equals(KFSConstants.ParameterValues.NO)) {
// removed apparently-unnecessary test for !checkValue.equals(KFSConstants.ParameterValues.YES)
selectedIds.add(checkValue);
}
}
if (depositIsFinal) {
// add check free cash receipts to the selected receipts so they are automatically deposited
dform.setCheckFreeCashReceipts(new ArrayList<CashReceiptDocument>());
List<CashReceiptDocument> cashReceipts = cashReceiptService.getCashReceipts(dform.getCashDrawerCampusCode(), new String[] {CashReceipt.VERIFIED, CashReceipt.INTERIM});
for (Object crDocObj : cashReceipts) {
CashReceiptDocument crDoc = (CashReceiptDocument) crDocObj;
crDoc.refreshCashDetails();
if (crDoc.getFinancialSystemDocumentHeader().getFinancialDocumentStatusCode().equals(CashReceipt.VERIFIED) && crDoc.getCheckCount() == 0) {
// it's check free; it is automatically deposited as part of the final deposit
selectedIds.add(crDoc.getDocumentNumber());
dform.getCheckFreeCashReceipts().add(crDoc);
}
else if (crDoc.getFinancialSystemDocumentHeader().getFinancialDocumentStatusCode().equals(CashReceipt.INTERIM) &&
crDoc.getTotalConfirmedNetAmount().isGreaterThan(KualiDecimal.ZERO)) {
selectedIds.add(crDoc.getDocumentNumber());
dform.getCheckFreeCashReceipts().add(crDoc);
}
}
}
// make a list of cashiering checks to deposit
List<Integer> selectedCashieringChecks = new ArrayList<Integer>();
for (DepositWizardCashieringCheckHelper helper : dform.getDepositWizardCashieringCheckHelpers()) {
if (helper.getSequenceId() != null && !helper.getSequenceId().equals(new Integer(-1))) {
selectedCashieringChecks.add(helper.getSequenceId());
}
}
if (selectedIds.isEmpty() && selectedCashieringChecks.isEmpty()) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_CASHRECEIPT_ERROR, KFSKeyConstants.Deposit.ERROR_NO_CASH_RECEIPTS_SELECTED);
}
//
// proceed, if possible
if (GlobalVariables.getMessageMap().hasNoErrors()) {
try {
// retrieve selected receipts
List selectedReceipts = new ArrayList();
if (selectedIds != null && !selectedIds.isEmpty()) {
selectedReceipts = documentService.getDocumentsByListOfDocumentHeaderIds(CashReceiptDocument.class, selectedIds);
}
if (depositIsFinal) {
// have all verified CRs been deposited? If not, that's an error
// List verifiedReceipts = cashReceiptService.getCashReceipts(dform.getCashDrawerCampusCode(), new String[] {CashReceipt.VERIFIED, CashReceipt.INTERIM});
// for (Object o : verifiedReceipts) {
// CashReceiptDocument crDoc = (CashReceiptDocument) o;
// if (!selectedReceipts.contains(crDoc)) {
// GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NON_DEPOSITED_VERIFIED_CASH_RECEIPT, new String[] { crDoc.getDocumentNumber() });
// }
// }
KualiDecimal toBeDepositedChecksTotal = KualiDecimal.ZERO;
// have we selected the rest of the undeposited checks?
for (Check check : cashManagementService.selectUndepositedCashieringChecks(dform.getCashManagementDocId())) {
if (!selectedCashieringChecks.contains(check.getSequenceId())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_CASHIERING_CHECK_MUST_BE_DEPOSITED, new String[] { check.getCheckNumber() });
}
else {
toBeDepositedChecksTotal = toBeDepositedChecksTotal.add(check.getAmount());
}
}
// add the rest of the deposited cashiering checks to the toBeDepositedChecksTotal
for (Check check : cashManagementService.selectDepositedCashieringChecks(dform.getCashManagementDocId())) {
toBeDepositedChecksTotal = toBeDepositedChecksTotal.add(check.getAmount());
}
// does the cash drawer have enough currency and coin to fulfill the requested deposit?
checkEnoughCurrencyForDeposit(dform);
checkEnoughCoinForDeposit(dform);
// does this deposit have currency and coin to match all currency and coin from CRs?
List<CashReceiptDocument> interestingReceipts = cashReceiptService.getCashReceipts(dform.getCashDrawerCampusCode(), new String[] { CashReceipt.VERIFIED, CashReceipt.INTERIM, CashReceipt.FINAL });
CurrencyDetail currencyTotal = new CurrencyDetail();
CoinDetail coinTotal = new CoinDetail();
for (CashReceiptDocument receipt : interestingReceipts) {
receipt.refreshCashDetails();
/* We should check on confirmed details instead of original ones;
* we don't really need to check null here, since these details won't be null after refreshCashDetails.
*/
currencyTotal.add(receipt.getConfirmedCurrencyDetail());
currencyTotal.subtract(receipt.getConfirmedChangeCurrencyDetail());
coinTotal.add(receipt.getConfirmedCoinDetail());
coinTotal.subtract(receipt.getConfirmedChangeCoinDetail());
}
KualiDecimal cashReceiptCashTotal = currencyTotal.getTotalAmount().add(coinTotal.getTotalAmount());
// remove the cashiering checks amounts from the cash receipts total; cashiering checks act as if they were CR
// currency/coin that gets deposited
cashReceiptCashTotal = cashReceiptCashTotal.subtract(toBeDepositedChecksTotal);
KualiDecimal depositedCashTotal = dform.getCurrencyDetail().getTotalAmount().add(dform.getCoinDetail().getTotalAmount());
if (!cashReceiptCashTotal.equals(depositedCashTotal)) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_CASH_DEPOSIT_DID_NOT_BALANCE, new String[] { formatter.format(depositedCashTotal).toString(), formatter.format(cashReceiptCashTotal).toString() });
}
}
// proceed again...if possible
if (GlobalVariables.getMessageMap().hasNoErrors()) {
// retrieve CashManagementDocument
String cashManagementDocId = dform.getCashManagementDocId();
CashManagementDocument cashManagementDoc = null;
try {
cashManagementDoc = (CashManagementDocument) documentService.getByDocumentHeaderId(cashManagementDocId);
if (cashManagementDoc == null) {
throw new IllegalStateException("unable to find cashManagementDocument with id " + cashManagementDocId);
}
}
catch (WorkflowException e) {
throw new IllegalStateException("unable to retrieve cashManagementDocument with id " + cashManagementDocId, e);
}
// create deposit
String cmDocId = dform.getCashManagementDocId();
cashManagementService.addDeposit(cashManagementDoc, dform.getDepositTicketNumber(), dform.getBank(), selectedReceipts, selectedCashieringChecks, depositIsFinal);
if (depositIsFinal) {
// find the final deposit
Deposit finalDeposit = findFinalDeposit(cashManagementDoc);
// if the currency and coin details aren't empty, save them and remove them from the cash drawer
if (dform.getCurrencyDetail() != null) {
// do we have enough currency to allow the deposit to leave the drawer?
boService.save(dform.getCurrencyDetail());
cashManagementDoc.getCashDrawer().removeCurrency(dform.getCurrencyDetail());
finalDeposit.setDepositAmount(finalDeposit.getDepositAmount().add(dform.getCurrencyDetail().getTotalAmount()));
}
if (dform.getCoinDetail() != null) {
// do we have enough coin to allow the deposit to leave the drawer?
boService.save(dform.getCoinDetail());
cashManagementDoc.getCashDrawer().removeCoin(dform.getCoinDetail());
finalDeposit.setDepositAmount(finalDeposit.getDepositAmount().add(dform.getCoinDetail().getTotalAmount()));
}
boService.save(cashManagementDoc.getCashDrawer());
boService.save(finalDeposit);
}
// redirect to controlling CashManagementDocument
dest = returnToSender(cashManagementDocId);
}
}
catch (WorkflowException e) {
throw new InfrastructureException("unable to retrieve cashReceipts by documentId", e);
}
}
return dest;
}
private Deposit findFinalDeposit(CashManagementDocument cmDoc) {
Deposit finalDeposit = null;
for (Deposit deposit : cmDoc.getDeposits()) {
if (deposit.getDepositTypeCode().equals(KFSConstants.DepositConstants.DEPOSIT_TYPE_FINAL)) {
finalDeposit = deposit;
break;
}
}
return finalDeposit;
}
/**
* Checks that the currency amount requested to be part of a deposit can be fulfilled by the amount of currency in the cash
* drawer
*
* @param depositForm the deposit form we are checking against
* @param detail the currency detail to check against the drawer
* @return true if enough currency, false if otherwise
*/
private boolean checkEnoughCurrencyForDeposit(DepositWizardForm depositForm) {
boolean success = true;
CurrencyDetail detail = depositForm.getCurrencyDetail();
if (detail != null) {
// 1. get the cash drawer
CashDrawer drawer = SpringContext.getBean(CashDrawerService.class).getByCampusCode(depositForm.getCashDrawerCampusCode());
// assumptions at this point:
// 1. a cash drawer does exist for the unit
// 2. we can ignore negative amounts, because if we have negative amounts, we're actually gaining money (and that will
// happen with cashiering checks)
CurrencyFormatter formatter = new CurrencyFormatter();
if (detail.getFinancialDocumentHundredDollarAmount() != null && detail.getFinancialDocumentHundredDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentHundredDollarAmount() == null || drawer.getFinancialDocumentHundredDollarAmount().isLessThan(detail.getFinancialDocumentHundredDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "hundred dollar amount", formatter.format(detail.getFinancialDocumentHundredDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentHundredDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentFiftyDollarAmount() != null && detail.getFinancialDocumentFiftyDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentFiftyDollarAmount() == null || drawer.getFinancialDocumentFiftyDollarAmount().isLessThan(detail.getFinancialDocumentFiftyDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "fifty dollar amount", formatter.format(detail.getFinancialDocumentFiftyDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentFiftyDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentTwentyDollarAmount() != null && detail.getFinancialDocumentTwentyDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentTwentyDollarAmount() == null || drawer.getFinancialDocumentTwentyDollarAmount().isLessThan(detail.getFinancialDocumentTwentyDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "twenty dollar amount", formatter.format(detail.getFinancialDocumentTwentyDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentTwentyDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentTenDollarAmount() != null && detail.getFinancialDocumentTenDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentTenDollarAmount() == null || drawer.getFinancialDocumentTenDollarAmount().isLessThan(detail.getFinancialDocumentTenDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "ten dollar amount", formatter.format(detail.getFinancialDocumentTenDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentTenDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentFiveDollarAmount() != null && detail.getFinancialDocumentFiveDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentFiveDollarAmount() == null || drawer.getFinancialDocumentFiveDollarAmount().isLessThan(detail.getFinancialDocumentFiveDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "five dollar amount", formatter.format(detail.getFinancialDocumentFiveDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentFiveDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentTwoDollarAmount() != null && detail.getFinancialDocumentTwoDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentTwoDollarAmount() == null || drawer.getFinancialDocumentTwoDollarAmount().isLessThan(detail.getFinancialDocumentTwoDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "two dollar amount", formatter.format(detail.getFinancialDocumentTwoDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentTwoDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentOneDollarAmount() != null && detail.getFinancialDocumentOneDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentOneDollarAmount() == null || drawer.getFinancialDocumentOneDollarAmount().isLessThan(detail.getFinancialDocumentOneDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "one dollar amount", formatter.format(detail.getFinancialDocumentOneDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentOneDollarAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentOtherDollarAmount() != null && detail.getFinancialDocumentOtherDollarAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentOtherDollarAmount() == null || drawer.getFinancialDocumentOtherDollarAmount().isLessThan(detail.getFinancialDocumentOtherDollarAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "other dollar amount", formatter.format(detail.getFinancialDocumentOtherDollarAmount()).toString(), formatter.format(drawer.getFinancialDocumentOtherDollarAmount()).toString() });
success = false;
}
}
}
return success;
}
/**
* Checks that the coin amount requested by the deposit does not exceed the amount actually in the drawer
*
* @param depositForm the deposit form we are checking against
* @param detail the coin detail to check against the drawer
* @return true if there is enough coin, false if otherwise
*/
public boolean checkEnoughCoinForDeposit(DepositWizardForm depositForm) {
boolean success = true;
CoinDetail detail = depositForm.getCoinDetail();
if (detail != null) {
// 1. get the cash drawer
CashDrawer drawer = SpringContext.getBean(CashDrawerService.class).getByCampusCode(depositForm.getCashDrawerCampusCode());
// assumptions at this point:
// 1. a cash drawer does exist for the unit
// 2. we can ignore negative amounts, because if we have negative amounts, we're actually gaining money (and that will
// happen with cashiering checks)
CurrencyFormatter formatter = new CurrencyFormatter();
if (detail.getFinancialDocumentHundredCentAmount() != null && detail.getFinancialDocumentHundredCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentHundredCentAmount() == null || drawer.getFinancialDocumentHundredCentAmount().isLessThan(detail.getFinancialDocumentHundredCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "hundred cent amount", formatter.format(detail.getFinancialDocumentHundredCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentHundredCentAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentFiftyCentAmount() != null && detail.getFinancialDocumentFiftyCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentFiftyCentAmount() == null || drawer.getFinancialDocumentFiftyCentAmount().isLessThan(detail.getFinancialDocumentFiftyCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "fifty cent amount", formatter.format(detail.getFinancialDocumentFiftyCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentFiftyCentAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentTwentyFiveCentAmount() != null && detail.getFinancialDocumentTwentyFiveCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentTwentyFiveCentAmount() == null || drawer.getFinancialDocumentTwentyFiveCentAmount().isLessThan(detail.getFinancialDocumentTwentyFiveCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "twenty five cent amount", formatter.format(detail.getFinancialDocumentTwentyFiveCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentTwentyFiveCentAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentTenCentAmount() != null && detail.getFinancialDocumentTenCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentTenCentAmount() == null || drawer.getFinancialDocumentTenCentAmount().isLessThan(detail.getFinancialDocumentTenCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "ten cent amount", formatter.format(detail.getFinancialDocumentTenCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentTenCentAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentFiveCentAmount() != null && detail.getFinancialDocumentFiveCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentFiveCentAmount() == null || drawer.getFinancialDocumentFiveCentAmount().isLessThan(detail.getFinancialDocumentFiveCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "five cent amount", formatter.format(detail.getFinancialDocumentFiveCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentFiveCentAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentOneCentAmount() != null && detail.getFinancialDocumentOneCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentOneCentAmount() == null || drawer.getFinancialDocumentOneCentAmount().isLessThan(detail.getFinancialDocumentOneCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "one cent amount", formatter.format(detail.getFinancialDocumentOneCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentOneCentAmount()).toString() });
success = false;
}
}
if (detail.getFinancialDocumentOtherCentAmount() != null && detail.getFinancialDocumentOtherCentAmount().isGreaterThan(KualiDecimal.ZERO)) {
if (drawer.getFinancialDocumentOtherCentAmount() == null || drawer.getFinancialDocumentOtherCentAmount().isLessThan(detail.getFinancialDocumentOtherCentAmount())) {
GlobalVariables.getMessageMap().putError(KFSConstants.DepositConstants.DEPOSIT_WIZARD_DEPOSITHEADER_ERROR, KFSKeyConstants.Deposit.ERROR_NOT_ENOUGH_CASH_TO_COMPLETE_DEPOSIT, new String[] { "other cent amount", formatter.format(detail.getFinancialDocumentOtherCentAmount()).toString(), formatter.format(drawer.getFinancialDocumentOtherCentAmount()).toString() });
success = false;
}
}
}
return success;
}
/**
* This method handles canceling (closing) the deposit wizard.
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @throws Exception
*/
public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
DepositWizardForm dform = (DepositWizardForm) form;
ActionForward dest = returnToSender(dform.getCashManagementDocId());
return dest;
}
/**
* @param cmDocId
* @return ActionForward which will redirect the user to the docSearchDisplay for the CashManagementDocument with the given
* documentId
*/
private ActionForward returnToSender(String cmDocId) {
Properties params = new Properties();
params.setProperty("methodToCall", "docHandler");
params.setProperty("command", "displayDocSearchView");
params.setProperty("docId", cmDocId);
String cmActionUrl = UrlFactory.parameterizeUrl(KFSConstants.CASH_MANAGEMENT_DOCUMENT_ACTION, params);
return new ActionForward(cmActionUrl, true);
}
}