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.module.ar.document.web.struts;
017    
018    import java.io.ByteArrayOutputStream;
019    import java.io.File;
020    import java.util.ArrayList;
021    import java.util.Iterator;
022    import java.util.List;
023    
024    import javax.servlet.ServletOutputStream;
025    import javax.servlet.http.HttpServletRequest;
026    import javax.servlet.http.HttpServletResponse;
027    
028    import org.apache.struts.action.ActionForm;
029    import org.apache.struts.action.ActionForward;
030    import org.apache.struts.action.ActionMapping;
031    import org.kuali.kfs.module.ar.businessobject.CustomerCreditMemoDetail;
032    import org.kuali.kfs.module.ar.document.CustomerCreditMemoDocument;
033    import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
034    import org.kuali.kfs.module.ar.document.service.CustomerCreditMemoDetailService;
035    import org.kuali.kfs.module.ar.document.service.CustomerCreditMemoDocumentService;
036    import org.kuali.kfs.module.ar.document.validation.event.ContinueCustomerCreditMemoDocumentEvent;
037    import org.kuali.kfs.module.ar.document.validation.event.RecalculateCustomerCreditMemoDetailEvent;
038    import org.kuali.kfs.module.ar.document.validation.event.RecalculateCustomerCreditMemoDocumentEvent;
039    import org.kuali.kfs.module.ar.report.service.AccountsReceivableReportService;
040    import org.kuali.kfs.module.ar.web.struts.CustomerStatementForm;
041    import org.kuali.kfs.sys.KFSConstants;
042    import org.kuali.kfs.sys.context.SpringContext;
043    import org.kuali.rice.kew.exception.WorkflowException;
044    import org.kuali.rice.kns.service.DataDictionaryService;
045    import org.kuali.rice.kns.service.DocumentService;
046    import org.kuali.rice.kns.service.KualiRuleService;
047    import org.kuali.rice.kns.util.KualiDecimal;
048    import org.kuali.rice.kns.util.WebUtils;
049    import org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase;
050    import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
051    
052    import com.lowagie.text.Document;
053    import com.lowagie.text.pdf.PdfCopy;
054    import com.lowagie.text.pdf.PdfImportedPage;
055    import com.lowagie.text.pdf.PdfReader;
056    import com.lowagie.text.pdf.SimpleBookmark;
057    
058    public class CustomerCreditMemoDocumentAction extends KualiTransactionalDocumentActionBase {
059        
060        public CustomerCreditMemoDocumentAction() {
061            super();
062        }
063        
064        /**
065         * Do initialization for a new customer credit memo.
066         * 
067         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
068         */
069        @Override
070        protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
071            super.createDocument(kualiDocumentFormBase);
072            ((CustomerCreditMemoDocument) kualiDocumentFormBase.getDocument()).initiateDocument();
073        }
074        
075        /**
076         * This method loads the document by its provided document header id. This has been abstracted out so that it can be overridden
077         * in children if the need arises.
078         *
079         * @param kualiDocumentFormBase
080         * @throws WorkflowException
081         */
082        @Override
083        protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
084           super.loadDocument(kualiDocumentFormBase);
085           ((CustomerCreditMemoDocument)kualiDocumentFormBase.getDocument()).populateCustomerCreditMemoDetailsAfterLoad();
086        }
087        
088        /**
089         * Clears out init tab.
090         * 
091         * @param mapping An ActionMapping
092         * @param form An ActionForm
093         * @param request The HttpServletRequest
094         * @param response The HttpServletResponse
095         * @throws Exception
096         * @return An ActionForward
097         */
098        public ActionForward clearInitTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
099            
100            CustomerCreditMemoDocumentForm customerCreditMemoDocumentForm = (CustomerCreditMemoDocumentForm) form;
101            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument) customerCreditMemoDocumentForm.getDocument();
102            customerCreditMemoDocument.clearInitFields();
103            
104            return super.refresh(mapping, form, request, response);
105        }   
106        
107        /**
108         * Handles continue request. This request comes from the initial screen which gives ref. invoice number.
109         * Based on that, the customer credit memo is initially populated.
110         * 
111         * @param mapping An ActionMapping
112         * @param form An ActionForm
113         * @param request The HttpServletRequest
114         * @param response The HttpServletResponse
115         * @throws Exception
116         * @return An ActionForward
117         */
118        public ActionForward continueCreditMemo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
119    
120            CustomerCreditMemoDocumentForm customerCreditMemoDocumentForm = (CustomerCreditMemoDocumentForm) form;
121            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument) customerCreditMemoDocumentForm.getDocument();
122            
123            String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME;
124            boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new ContinueCustomerCreditMemoDocumentEvent(errorPath,customerCreditMemoDocument));
125            if (rulePassed)
126                customerCreditMemoDocument.populateCustomerCreditMemoDetails();
127    
128            return mapping.findForward(KFSConstants.MAPPING_BASIC);
129        }
130    
131        /**
132         * Based on user input this method recalculates a customer credit memo detail
133         * 
134         * @param mapping action mapping
135         * @param form action form
136         * @param request
137         * @param response
138         * @return action forward
139         * @throws Exception
140         */
141        public ActionForward recalculateCustomerCreditMemoDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
142    
143            CustomerCreditMemoDocumentForm customerCreditMemoDocumentForm = (CustomerCreditMemoDocumentForm) form;
144            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument)customerCreditMemoDocumentForm.getDocument();
145            
146            int indexOfLineToRecalculate = getSelectedLine(request);
147            CustomerCreditMemoDetail customerCreditMemoDetail = customerCreditMemoDocument.getCreditMemoDetails().get(indexOfLineToRecalculate);
148         
149            String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + KFSConstants.CUSTOMER_CREDIT_MEMO_DETAIL_PROPERTY_NAME + "[" + indexOfLineToRecalculate + "]";
150    
151            boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new RecalculateCustomerCreditMemoDetailEvent(errorPath, customerCreditMemoDocument, customerCreditMemoDetail));
152            if (rulePassed) {
153                CustomerCreditMemoDetailService customerCreditMemoDetailService = SpringContext.getBean(CustomerCreditMemoDetailService.class);
154                customerCreditMemoDetailService.recalculateCustomerCreditMemoDetail(customerCreditMemoDetail,customerCreditMemoDocument);
155            } else {
156                customerCreditMemoDocument.recalculateTotals(customerCreditMemoDetail);
157            }
158            return mapping.findForward(KFSConstants.MAPPING_BASIC);
159        }
160        
161        /**
162         * This method refreshes a customer credit memo detail
163         * 
164         * @param mapping action mapping
165         * @param form action form
166         * @param request
167         * @param response
168         * @return action forward
169         * @throws Exception
170         */
171        public ActionForward refreshCustomerCreditMemoDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
172            
173            CustomerCreditMemoDocumentForm customerCreditMemoDocForm = (CustomerCreditMemoDocumentForm) form;
174            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument)customerCreditMemoDocForm.getDocument();
175            int indexOfLineToRefresh = getSelectedLine(request);
176            
177            CustomerCreditMemoDetail customerCreditMemoDetail = customerCreditMemoDocument.getCreditMemoDetails().get(indexOfLineToRefresh);
178            
179            customerCreditMemoDetail.setCreditMemoItemQuantity(null);
180            customerCreditMemoDetail.setCreditMemoItemTotalAmount(null);
181            customerCreditMemoDetail.setCreditMemoItemTaxAmount(KualiDecimal.ZERO);
182            customerCreditMemoDetail.setCreditMemoLineTotalAmount(KualiDecimal.ZERO);
183            
184            customerCreditMemoDocument.recalculateTotals(customerCreditMemoDetail);
185            
186            return mapping.findForward(KFSConstants.MAPPING_BASIC);
187        }
188     
189        /**
190         * This method refreshes customer credit memo details and line with totals
191         * 
192         * @param mapping action mapping
193         * @param form action form
194         * @param request
195         * @param response
196         * @return action forward
197         * @throws Exception
198         */
199        public ActionForward refreshCustomerCreditMemoDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
200            CustomerCreditMemoDocumentForm customerCreditMemoDocForm = (CustomerCreditMemoDocumentForm) form;
201            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument)customerCreditMemoDocForm.getDocument();
202        
203            List<CustomerCreditMemoDetail> customerCreditMemoDetails = customerCreditMemoDocument.getCreditMemoDetails();
204            for( CustomerCreditMemoDetail customerCreditMemoDetail : customerCreditMemoDetails ){
205                customerCreditMemoDetail.setCreditMemoItemQuantity(null);
206                customerCreditMemoDetail.setCreditMemoItemTotalAmount(null);
207                customerCreditMemoDetail.setCreditMemoItemTaxAmount(KualiDecimal.ZERO);
208                customerCreditMemoDetail.setCreditMemoLineTotalAmount(KualiDecimal.ZERO);
209                customerCreditMemoDetail.setDuplicateCreditMemoItemTotalAmount(null);
210            }
211            customerCreditMemoDocument.setCrmTotalItemAmount(KualiDecimal.ZERO);
212            customerCreditMemoDocument.setCrmTotalTaxAmount(KualiDecimal.ZERO);
213            customerCreditMemoDocument.setCrmTotalAmount(KualiDecimal.ZERO);
214            
215            return mapping.findForward(KFSConstants.MAPPING_BASIC);
216        }
217        
218        /**
219         * Based on user input this method recalculates customer credit memo document <=> all customer credit memo details
220         * 
221         * @param mapping action mapping
222         * @param form action form
223         * @param request
224         * @param response
225         * @return action forward
226         * @throws Exception
227         */
228        public ActionForward recalculateCustomerCreditMemoDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
229    
230            CustomerCreditMemoDocumentForm customerCreditMemoDocumentForm = (CustomerCreditMemoDocumentForm) form;
231            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument)customerCreditMemoDocumentForm.getDocument();
232    
233            String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME;
234            boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new RecalculateCustomerCreditMemoDocumentEvent(errorPath,customerCreditMemoDocument,false));
235            if (rulePassed) {
236                CustomerCreditMemoDocumentService customerCreditMemoDocumentService = SpringContext.getBean(CustomerCreditMemoDocumentService.class);
237                customerCreditMemoDocumentService.recalculateCustomerCreditMemoDocument(customerCreditMemoDocument,false);
238            }
239            return mapping.findForward(KFSConstants.MAPPING_BASIC);
240        }
241        
242        /**
243         * 
244         * This method...
245         * @param mapping
246         * @param form
247         * @param request
248         * @param response
249         * @return
250         * @throws Exception
251         */
252        public ActionForward print(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
253            String basePath = getBasePath(request);
254            String docId = ((CustomerCreditMemoDocumentForm) form).getDocument().getDocumentNumber();
255            String methodToCallPrintCreditMemoPDF = "printCreditMemoPDF";
256            String methodToCallDocHandler = "docHandler";
257            String printCreditMemoPDFUrl = getUrlForPrintCreditMemo(basePath, docId, methodToCallPrintCreditMemoPDF);
258            String displayInvoiceTabbedPageUrl = getUrlForPrintCreditMemo(basePath, docId, methodToCallDocHandler);
259            
260            request.setAttribute("printPDFUrl", printCreditMemoPDFUrl);
261            request.setAttribute("displayTabbedPageUrl", displayInvoiceTabbedPageUrl);
262            request.setAttribute("docId", docId);
263            String label = SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(KFSConstants.FinancialDocumentTypeCodes.CUSTOMER_CREDIT_MEMO);
264            request.setAttribute("printLabel", label);
265            return mapping.findForward("arPrintPDF");
266            
267        }
268            
269        /**
270         * 
271         * This method...
272         * @param mapping
273         * @param form
274         * @param request
275         * @param response
276         * @return
277         * @throws Exception
278         */
279        public ActionForward printCreditMemoPDF(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
280            String creditMemoDocId = request.getParameter(KFSConstants.PARAMETER_DOC_ID);
281            CustomerCreditMemoDocument customerCreditMemoDocument = (CustomerCreditMemoDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(creditMemoDocId);
282            
283            AccountsReceivableReportService reportService = SpringContext.getBean(AccountsReceivableReportService.class);
284            File report = reportService.generateCreditMemo(customerCreditMemoDocument);
285            
286            StringBuilder fileName = new StringBuilder();
287            fileName.append(customerCreditMemoDocument.getFinancialDocumentReferenceInvoiceNumber());
288            fileName.append("-");
289            fileName.append(customerCreditMemoDocument.getDocumentNumber());
290            fileName.append(".pdf");
291            
292            if (report.length() == 0) {
293                //csForm.setMessage("No Report Generated");
294                return mapping.findForward(KFSConstants.MAPPING_BASIC);
295            }
296                
297            ByteArrayOutputStream baos = new ByteArrayOutputStream();
298            String contentDisposition = "";
299            try {
300                ArrayList master = new ArrayList();
301                PdfCopy  writer = null;
302                        
303                // create a reader for the document
304                String reportName = report.getAbsolutePath();
305                PdfReader reader = new PdfReader(reportName);
306                reader.consolidateNamedDestinations();
307                
308                // retrieve the total number of pages
309                int n = reader.getNumberOfPages();
310                List bookmarks = SimpleBookmark.getBookmark(reader);
311                if (bookmarks != null)
312                    master.addAll(bookmarks);
313    
314                // step 1: create a document-object
315                Document document = new Document(reader.getPageSizeWithRotation(1));
316                // step 2: create a writer that listens to the document
317                writer = new PdfCopy(document, baos);
318                // step 3: open the document
319                document.open();
320                // step 4: add content
321                PdfImportedPage page;
322                for (int i = 0; i < n; ) {
323                    ++i;
324                    page = writer.getImportedPage(reader, i);
325                    writer.addPage(page);
326                }
327                writer.freeReader(reader);
328                if (!master.isEmpty())
329                    writer.setOutlines(master);
330                // step 5: we close the document
331                document.close();
332    
333                StringBuffer sbContentDispValue = new StringBuffer();
334                String useJavascript = request.getParameter("useJavascript");
335                if (useJavascript == null || useJavascript.equalsIgnoreCase("false")) {
336                    sbContentDispValue.append("attachment");
337                }
338                else {
339                    sbContentDispValue.append("inline");
340                }
341                sbContentDispValue.append("; filename=");
342                sbContentDispValue.append(fileName);
343                
344                contentDisposition = sbContentDispValue.toString();
345            }
346            catch(Exception e) {
347                e.printStackTrace();
348            } 
349    
350            response.setContentType("application/pdf");
351            response.setHeader("Content-Disposition", contentDisposition);
352            response.setHeader("Expires", "0");
353            response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
354            response.setHeader("Pragma", "public");
355            response.setContentLength(baos.size());
356    
357            // write to output
358            ServletOutputStream sos;
359            sos = response.getOutputStream();
360            baos.writeTo(sos);
361            sos.flush();
362            sos.close();
363    
364            return null;
365        }
366        
367        /**
368         * Creates a URL to be used in printing the customer credit memo.
369         * 
370         * @param basePath String: The base path of the current URL
371         * @param docId String: The document ID of the document to be printed
372         * @param methodToCall String: The name of the method that will be invoked to do this particular print
373         * @return The URL
374         */
375        protected String getUrlForPrintCreditMemo(String basePath, String docId, String methodToCall) {
376            StringBuffer result = new StringBuffer(basePath);
377            result.append("/arCustomerCreditMemoDocument.do?methodToCall=");
378            result.append(methodToCall);
379            result.append("&docId=");
380            result.append(docId);
381            result.append("&command=displayDocSearchView");
382    
383            return result.toString();
384        }
385    
386        
387    }