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