001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.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/ecl2.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.kfs.fp.document.web.struts; 017 018 import java.io.ByteArrayOutputStream; 019 import java.util.Iterator; 020 import java.util.List; 021 022 import javax.servlet.http.HttpServletRequest; 023 import javax.servlet.http.HttpServletResponse; 024 025 import org.apache.struts.action.ActionForm; 026 import org.apache.struts.action.ActionForward; 027 import org.apache.struts.action.ActionMapping; 028 import org.kuali.kfs.fp.businessobject.Check; 029 import org.kuali.kfs.fp.businessobject.CoinDetail; 030 import org.kuali.kfs.fp.businessobject.CurrencyDetail; 031 import org.kuali.kfs.fp.document.CashReceiptDocument; 032 import org.kuali.kfs.fp.document.service.CashReceiptCoverSheetService; 033 import org.kuali.kfs.fp.document.service.CashReceiptService; 034 import org.kuali.kfs.fp.document.validation.event.AddCheckEvent; 035 import org.kuali.kfs.fp.document.validation.event.DeleteCheckEvent; 036 import org.kuali.kfs.fp.document.validation.event.UpdateCheckEvent; 037 import org.kuali.kfs.sys.KFSConstants; 038 import org.kuali.kfs.sys.KFSKeyConstants; 039 import org.kuali.kfs.sys.KFSPropertyConstants; 040 import org.kuali.kfs.sys.context.SpringContext; 041 import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase; 042 import org.kuali.rice.kew.exception.WorkflowException; 043 import org.kuali.rice.kns.service.DocumentService; 044 import org.kuali.rice.kns.service.KualiConfigurationService; 045 import org.kuali.rice.kns.service.KualiRuleService; 046 import org.kuali.rice.kns.util.GlobalVariables; 047 import org.kuali.rice.kns.util.Timer; 048 import org.kuali.rice.kns.util.WebUtils; 049 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 050 051 /** 052 * 053 */ 054 public class CashReceiptAction extends KualiAccountingDocumentActionBase { 055 /** 056 * Adds handling for check updates 057 * 058 * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, 059 * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 060 */ 061 @Override 062 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 063 Timer t0 = new Timer("execute"); 064 CashReceiptForm cform = (CashReceiptForm) form; 065 066 if (cform.hasDocumentId()) { 067 CashReceiptDocument cdoc = cform.getCashReceiptDocument(); 068 069 // handle change of checkEntryMode 070 processCheckEntryMode(cform, cdoc); 071 072 // handle changes to checks (but only if current checkEntryMode is 'detail') 073 if (CashReceiptDocument.CHECK_ENTRY_DETAIL.equals(cdoc.getCheckEntryMode())) { 074 cdoc.setTotalCheckAmount(cdoc.calculateCheckTotal()); // recalc b/c changes to the amounts could have happened 075 processChecks(cdoc, cform); 076 } 077 078 // generate errors for negative cash totals (especially for the recalculate button) 079 SpringContext.getBean(CashReceiptService.class).areCashTotalsInvalid(cdoc); 080 } 081 082 // proceed as usual 083 ActionForward result = super.execute(mapping, form, request, response); 084 t0.log(); 085 return result; 086 087 } 088 089 /** 090 * Prepares and streams CR PDF Cover Sheet 091 * 092 * @param mapping 093 * @param form 094 * @param request 095 * @param response 096 * @return ActionForward 097 * @throws Exception 098 */ 099 public ActionForward printCoverSheet(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 100 CashReceiptForm crForm = (CashReceiptForm) form; 101 102 // get directory of tempate 103 String directory = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.EXTERNALIZABLE_HELP_URL_KEY); 104 105 // retrieve document 106 String documentNumber = request.getParameter(KFSPropertyConstants.DOCUMENT_NUMBER); 107 108 CashReceiptDocument document = (CashReceiptDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(documentNumber); 109 110 // since this action isn't triggered by a post, we don't have the normal document data 111 // so we have to set the document into the form manually so that later authz processing 112 // has a document object instance to work with 113 crForm.setDocument(document); 114 115 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 116 CashReceiptCoverSheetService coverSheetService = SpringContext.getBean(CashReceiptCoverSheetService.class); 117 coverSheetService.generateCoverSheet(document, directory, baos); 118 String fileName = documentNumber + "_cover_sheet.pdf"; 119 WebUtils.saveMimeOutputStreamAsFile(response, "application/pdf", baos, fileName); 120 121 return null; 122 } 123 124 /** 125 * This method processes the check entry mode to determine if the user is entering checks or if they are just entering the 126 * total. 127 * 128 * @param crForm 129 * @param crDoc 130 */ 131 protected void processCheckEntryMode(CashReceiptForm crForm, CashReceiptDocument crDoc) { 132 String formMode = crForm.getCheckEntryMode(); 133 String docMode = crDoc.getCheckEntryMode(); 134 135 if (CashReceiptDocument.CHECK_ENTRY_DETAIL.equals(formMode) || CashReceiptDocument.CHECK_ENTRY_TOTAL.equals(formMode)) { 136 if (!formMode.equals(docMode)) { 137 if (formMode.equals(CashReceiptDocument.CHECK_ENTRY_DETAIL)) { 138 // save current checkTotal, for future restoration 139 crForm.setCheckTotal(crDoc.getTotalCheckAmount()); 140 141 // change mode 142 crDoc.setCheckEntryMode(formMode); 143 crDoc.setTotalCheckAmount(crDoc.calculateCheckTotal()); 144 145 // notify user 146 GlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_INDIVIDUAL); 147 } 148 else { 149 // restore saved checkTotal 150 crDoc.setTotalCheckAmount(crForm.getCheckTotal()); 151 152 // change mode 153 crDoc.setCheckEntryMode(formMode); 154 155 // notify user 156 GlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_TOTAL); 157 } 158 } 159 } 160 } 161 162 /** 163 * This method handles iterating over the check list and generating check events to apply rules to. 164 * 165 * @param cdoc 166 * @param cform 167 */ 168 protected void processChecks(CashReceiptDocument cdoc, CashReceiptForm cform) { 169 List formChecks = cdoc.getChecks(); 170 171 int index = 0; 172 Iterator i = formChecks.iterator(); 173 while (i.hasNext()) { 174 Check formCheck = (Check) i.next(); 175 176 // only generate update events for specific action methods 177 String methodToCall = cform.getMethodToCall(); 178 if (UPDATE_EVENT_ACTIONS.contains(methodToCall)) { 179 SpringContext.getBean(KualiRuleService.class).applyRules(new UpdateCheckEvent(KFSPropertyConstants.DOCUMENT + "." + KFSPropertyConstants.CHECK + "[" + index + "]", cdoc, formCheck)); 180 } 181 index++; 182 } 183 } 184 185 /** 186 * Adds Check instance created from the current "new check" line to the document 187 * 188 * @param mapping 189 * @param form 190 * @param request 191 * @param response 192 * @return ActionForward 193 * @throws Exception 194 */ 195 public ActionForward addCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 196 CashReceiptForm crForm = (CashReceiptForm) form; 197 CashReceiptDocument crDoc = crForm.getCashReceiptDocument(); 198 199 Check newCheck = crForm.getNewCheck(); 200 newCheck.setDocumentNumber(crDoc.getDocumentNumber()); 201 202 // check business rules 203 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AddCheckEvent(KFSConstants.NEW_CHECK_PROPERTY_NAME, crDoc, newCheck)); 204 if (rulePassed) { 205 // add check 206 crDoc.addCheck(newCheck); 207 208 // clear the used newCheck 209 crForm.setNewCheck(crDoc.createNewCheck()); 210 } 211 212 return mapping.findForward(KFSConstants.MAPPING_BASIC); 213 } 214 215 /** 216 * Deletes the selected check (line) from the document 217 * 218 * @param mapping 219 * @param form 220 * @param request 221 * @param response 222 * @return ActionForward 223 * @throws Exception 224 */ 225 public ActionForward deleteCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 226 CashReceiptForm crForm = (CashReceiptForm) form; 227 CashReceiptDocument crDoc = crForm.getCashReceiptDocument(); 228 229 int deleteIndex = getLineToDelete(request); 230 Check oldCheck = crDoc.getCheck(deleteIndex); 231 232 233 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteCheckEvent(KFSConstants.EXISTING_CHECK_PROPERTY_NAME, crDoc, oldCheck)); 234 235 if (rulePassed) { 236 // delete check 237 crDoc.removeCheck(deleteIndex); 238 239 // delete baseline check, if any 240 if (crForm.hasBaselineCheck(deleteIndex)) { 241 crForm.getBaselineChecks().remove(deleteIndex); 242 } 243 } 244 else { 245 GlobalVariables.getMessageMap().putError("document.check[" + deleteIndex + "]", KFSKeyConstants.Check.ERROR_CHECK_DELETERULE, Integer.toString(deleteIndex)); 246 } 247 248 return mapping.findForward(KFSConstants.MAPPING_BASIC); 249 } 250 251 252 /** 253 * Changes the current check-entry mode, if necessary 254 * 255 * @param mapping 256 * @param form 257 * @param request 258 * @param response 259 * @return ActionForward 260 * @throws Exception 261 */ 262 public ActionForward changeCheckEntryMode(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 263 264 CashReceiptForm crForm = (CashReceiptForm) form; 265 CashReceiptDocument crDoc = crForm.getCashReceiptDocument(); 266 267 String formMode = crForm.getCheckEntryMode(); 268 String docMode = crDoc.getCheckEntryMode(); 269 270 if (CashReceiptDocument.CHECK_ENTRY_DETAIL.equals(formMode) || CashReceiptDocument.CHECK_ENTRY_TOTAL.equals(formMode)) { 271 if (!formMode.equals(docMode)) { 272 273 if (formMode.equals(CashReceiptDocument.CHECK_ENTRY_DETAIL)) { 274 // save current checkTotal, for future restoration 275 crForm.setCheckTotal(crDoc.getTotalCheckAmount()); 276 277 // change mode 278 crDoc.setCheckEntryMode(formMode); 279 crDoc.setTotalCheckAmount(crDoc.calculateCheckTotal()); 280 281 // notify user 282 GlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_INDIVIDUAL); 283 } 284 else { 285 // restore saved checkTotal 286 crDoc.setTotalCheckAmount(crForm.getCheckTotal()); 287 288 // change mode 289 crDoc.setCheckEntryMode(formMode); 290 291 // notify user 292 GlobalVariables.getMessageList().add(KFSKeyConstants.CashReceipt.MSG_CHECK_ENTRY_TOTAL); 293 } 294 } 295 } 296 297 return mapping.findForward(KFSConstants.MAPPING_BASIC); 298 } 299 300 301 /** 302 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 303 */ 304 @Override 305 protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 306 super.createDocument(kualiDocumentFormBase); 307 308 CashReceiptForm crForm = (CashReceiptForm) kualiDocumentFormBase; 309 CashReceiptDocument crDoc = crForm.getCashReceiptDocument(); 310 311 CashReceiptService crs = SpringContext.getBean(CashReceiptService.class); 312 crDoc.initializeCampusLocationCode(); 313 314 /* initialize currency and coin detail */ 315 CurrencyDetail currencyDetail = new CurrencyDetail(); 316 currencyDetail.setCashieringRecordSource(KFSConstants.CurrencyCoinSources.CASH_RECEIPTS); 317 currencyDetail.setFinancialDocumentTypeCode(CashReceiptDocument.DOCUMENT_TYPE); 318 currencyDetail.setDocumentNumber(crDoc.getDocumentNumber()); 319 crDoc.setCurrencyDetail(currencyDetail); 320 321 CoinDetail coinDetail = new CoinDetail(); 322 coinDetail.setCashieringRecordSource(KFSConstants.CurrencyCoinSources.CASH_RECEIPTS); 323 coinDetail.setFinancialDocumentTypeCode(CashReceiptDocument.DOCUMENT_TYPE); 324 coinDetail.setDocumentNumber(crDoc.getDocumentNumber()); 325 crDoc.setCoinDetail(coinDetail); 326 327 initDerivedCheckValues(crForm); 328 } 329 330 /** 331 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 332 */ 333 @Override 334 protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 335 super.loadDocument(kualiDocumentFormBase); 336 337 initDerivedCheckValues((CashReceiptForm) kualiDocumentFormBase); 338 } 339 340 /** 341 * Initializes form values which must be derived form document contents (i.e. those which aren't directly available from the 342 * document) 343 * 344 * @param cform 345 */ 346 protected void initDerivedCheckValues(CashReceiptForm cform) { 347 CashReceiptDocument cdoc = cform.getCashReceiptDocument(); 348 349 cform.setCheckEntryMode(cdoc.getCheckEntryMode()); 350 cform.setCheckTotal(cdoc.getTotalCheckAmount()); 351 352 cform.getBaselineChecks().clear(); 353 cform.getBaselineChecks().addAll(cform.getCashReceiptDocument().getChecks()); 354 } 355 356 /** 357 * Overridden to guarantee that form of copied document is set to whatever the entry mode of the document is 358 * @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) 359 */ 360 @Override 361 public ActionForward copy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 362 ActionForward forward = super.copy(mapping, form, request, response); 363 initDerivedCheckValues((CashReceiptForm)form); 364 return forward; 365 } 366 } 367