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.List;
022    
023    import javax.servlet.ServletOutputStream;
024    import javax.servlet.http.HttpServletRequest;
025    import javax.servlet.http.HttpServletResponse;
026    
027    import org.apache.commons.lang.StringUtils;
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.coa.service.AccountService;
032    import org.kuali.kfs.module.ar.ArConstants;
033    import org.kuali.kfs.module.ar.businessobject.CustomerAddress;
034    import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
035    import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument;
036    import org.kuali.kfs.module.ar.document.service.CustomerAddressService;
037    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDetailService;
038    import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService;
039    import org.kuali.kfs.module.ar.document.validation.event.DiscountCustomerInvoiceDetailEvent;
040    import org.kuali.kfs.module.ar.document.validation.event.RecalculateCustomerInvoiceDetailEvent;
041    import org.kuali.kfs.module.ar.report.service.AccountsReceivableReportService;
042    import org.kuali.kfs.sys.KFSConstants;
043    import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader;
044    import org.kuali.kfs.sys.context.SpringContext;
045    import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent;
046    import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase;
047    import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentFormBase;
048    import org.kuali.rice.kew.exception.WorkflowException;
049    import org.kuali.rice.kns.question.ConfirmationQuestion;
050    import org.kuali.rice.kns.service.DataDictionaryService;
051    import org.kuali.rice.kns.service.DocumentService;
052    import org.kuali.rice.kns.service.KualiRuleService;
053    import org.kuali.rice.kns.util.ObjectUtils;
054    import org.kuali.rice.kns.util.WebUtils;
055    import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
056    import org.kuali.rice.kns.web.struts.form.KualiForm;
057    
058    import com.lowagie.text.Document;
059    import com.lowagie.text.pdf.PdfCopy;
060    import com.lowagie.text.pdf.PdfImportedPage;
061    import com.lowagie.text.pdf.PdfReader;
062    import com.lowagie.text.pdf.SimpleBookmark;
063    
064    public class CustomerInvoiceDocumentAction extends KualiAccountingDocumentActionBase {
065    
066    
067        /**
068         * Overriding to make it easier to distinguish discount lines and lines that are associated to discounts
069         * 
070         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#execute(org.apache.struts.action.ActionMapping,
071         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
072         */
073        @Override
074        public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
075            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) form;
076            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
077            if(StringUtils.isBlank(customerInvoiceDocument.getDocumentNumber())) {
078                String docId = request.getParameter(KFSConstants.PARAMETER_DOC_ID);
079                customerInvoiceDocument.setDocumentNumber(docId);
080                customerInvoiceDocument.refresh();
081            }
082            customerInvoiceDocument.updateAccountReceivableObjectCodes();
083            try {
084                // proceed as usual
085                customerInvoiceDocumentForm.getCustomerInvoiceDocument().updateDiscountAndParentLineReferences();
086                ActionForward result = super.execute(mapping, form, request, response);
087                return result;
088            }
089            finally {
090                // update it again for display purposes
091                customerInvoiceDocumentForm.getCustomerInvoiceDocument().updateDiscountAndParentLineReferences();
092            }
093        }
094    
095        /**
096         * Called when customer invoice document is initiated.
097         * 
098         * Makes a call to parent's createDocument method, but also defaults values for customer invoice document. Line which inserts
099         * Customer Invoice Detail (i.e. insertSourceLine) has its values defaulted by
100         * CustomerInvoiceDocumentForm.createNewSourceAccountingLine()
101         * 
102         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
103         */
104        @Override
105        protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
106            super.createDocument(kualiDocumentFormBase);
107    
108            // set up the default values for customer invoice document
109            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) kualiDocumentFormBase;
110            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
111            SpringContext.getBean(CustomerInvoiceDocumentService.class).setupDefaultValuesForNewCustomerInvoiceDocument(customerInvoiceDocument);
112        }
113    
114        /**
115         * All document-load operations get routed through here
116         * 
117         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
118         */
119        @Override
120        protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
121            super.loadDocument(kualiDocumentFormBase);
122    
123            CustomerInvoiceDocumentForm form = (CustomerInvoiceDocumentForm) kualiDocumentFormBase;
124            form.getCustomerInvoiceDocument().updateDiscountAndParentLineReferences();
125    
126        }
127    
128        /**
129         * Method that will take the current document, copy it, replace all references to doc header id with a new one, clear pending
130         * entries, clear notes, and reset version numbers
131         * 
132         * @param mapping
133         * @param form
134         * @param request
135         * @param response
136         * @return
137         * @throws Exception
138         */
139        public ActionForward copy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
140    
141            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) form;
142            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
143            
144            // perform discount check
145            ActionForward forward = performInvoiceWithDiscountsCheck(mapping, form, request, response, customerInvoiceDocument);
146            if (forward != null) {
147                return forward;
148            }
149    
150            return super.copy(mapping, form, request, response);
151        }
152    
153    
154        /**
155         * This method checks if the user wants to copy a document that contains a discount line.  If yes, this method returns null. If no,
156         * this method returns the "basic" forward. 
157         * 
158         * @param mapping
159         * @param form
160         * @param request
161         * @param response
162         * @param customerInvoiceDocument
163         * @return
164         * @throws Exception
165         */
166        protected ActionForward performInvoiceWithDiscountsCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, CustomerInvoiceDocument customerInvoiceDocument) throws Exception {
167            ActionForward forward = null;
168    
169            if( customerInvoiceDocument.hasAtLeastOneDiscount() ){
170                
171                Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
172                if (question == null) {
173                    return this.performQuestionWithoutInput(mapping, form, request, response, ArConstants.COPY_CUSTOMER_INVOICE_DOCUMENT_WITH_DISCOUNTS_QUESTION, 
174                            "This document contains a discount line.  Are you sure you want to copy this document?", KFSConstants.CONFIRMATION_QUESTION,
175                            KFSConstants.ROUTE_METHOD, "");
176                }
177        
178                Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
179                if (ArConstants.COPY_CUSTOMER_INVOICE_DOCUMENT_WITH_DISCOUNTS_QUESTION.equals(question) && ConfirmationQuestion.NO.equals(buttonClicked)) {
180                    forward = mapping.findForward(KFSConstants.MAPPING_BASIC);
181                }
182            }
183    
184            return forward;
185        }
186    
187        /**
188         * This method is the action for refreshing the added source line (or customer invoice detail) based off a provided invoice item
189         * code.
190         * 
191         * @param mapping
192         * @param form
193         * @param request
194         * @param response
195         * @return
196         * @throws Exception
197         */
198        public ActionForward refreshNewSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
199    
200            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) form;
201            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
202            CustomerInvoiceDetail newCustomerInvoiceDetail = (CustomerInvoiceDetail) customerInvoiceDocumentForm.getNewSourceLine();
203    
204            CustomerInvoiceDetailService customerInvoiceDetailService = SpringContext.getBean(CustomerInvoiceDetailService.class);
205            CustomerInvoiceDetail loadedCustomerInvoiceDetail = customerInvoiceDetailService.getCustomerInvoiceDetailFromCustomerInvoiceItemCode(newCustomerInvoiceDetail.getInvoiceItemCode(), customerInvoiceDocument.getBillByChartOfAccountCode(), customerInvoiceDocument.getBilledByOrganizationCode());
206            if (loadedCustomerInvoiceDetail == null) {
207                loadedCustomerInvoiceDetail = (CustomerInvoiceDetail) customerInvoiceDocumentForm.getNewSourceLine();
208            }
209    
210            customerInvoiceDocumentForm.setNewSourceLine(loadedCustomerInvoiceDetail);
211    
212            return mapping.findForward(KFSConstants.MAPPING_BASIC);
213        }
214    
215    
216        /**
217         * This method is the action for recalculating the amount added line assuming that the unit price or quantity has changed
218         * 
219         * @param mapping
220         * @param form
221         * @param request
222         * @param response
223         * @return
224         * @throws Exception
225         */
226        public ActionForward recalculateSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
227    
228            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) form;
229            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
230    
231            int index = getSelectedLine(request);
232            CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) customerInvoiceDocument.getSourceAccountingLine(index);
233    
234            String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + KFSConstants.EXISTING_SOURCE_ACCT_LINE_PROPERTY_NAME + "[" + index + "]";
235    
236            boolean rulePassed = true;
237            rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new RecalculateCustomerInvoiceDetailEvent(errorPath, customerInvoiceDocumentForm.getDocument(), customerInvoiceDetail));
238            if (rulePassed) {
239    
240                CustomerInvoiceDetailService customerInvoiceDetailService = SpringContext.getBean(CustomerInvoiceDetailService.class);
241                customerInvoiceDetailService.recalculateCustomerInvoiceDetail(customerInvoiceDocument, customerInvoiceDetail);
242                customerInvoiceDetailService.updateAccountsForCorrespondingDiscount(customerInvoiceDetail);
243            }
244    
245            // Update the doc total
246            ((FinancialSystemDocumentHeader) customerInvoiceDocumentForm.getDocument().getDocumentHeader()).setFinancialDocumentTotalAmount(customerInvoiceDocument.getTotalDollarAmount());
247            
248            return mapping.findForward(KFSConstants.MAPPING_BASIC);
249        }
250    
251    
252        /**
253         * This method is used for inserting a discount line based on a selected source line.
254         * 
255         * @param mapping
256         * @param form
257         * @param request
258         * @param response
259         * @return
260         * @throws Exception
261         */
262        public ActionForward discountSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
263    
264            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) form;
265            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
266    
267            int index = getSelectedLine(request);
268            CustomerInvoiceDetail parentCustomerInvoiceDetail = (CustomerInvoiceDetail) customerInvoiceDocument.getSourceAccountingLine(index);
269    
270            // document.sourceAccountingLine[0].invoiceItemUnitPrice
271            String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + KFSConstants.EXISTING_SOURCE_ACCT_LINE_PROPERTY_NAME + "[" + index + "]";
272    
273            boolean rulePassed = true;
274            rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new DiscountCustomerInvoiceDetailEvent(errorPath, customerInvoiceDocumentForm.getDocument(), parentCustomerInvoiceDetail));
275            if (rulePassed) {
276    
277                CustomerInvoiceDetail discountCustomerInvoiceDetail = SpringContext.getBean(CustomerInvoiceDetailService.class).getDiscountCustomerInvoiceDetailForCurrentYear(parentCustomerInvoiceDetail, customerInvoiceDocument);
278                discountCustomerInvoiceDetail.refreshNonUpdateableReferences();
279                insertAccountingLine(true, customerInvoiceDocumentForm, discountCustomerInvoiceDetail);
280    
281                // also set parent customer invoice detail line to have discount line seq number
282                parentCustomerInvoiceDetail.setInvoiceItemDiscountLineNumber(discountCustomerInvoiceDetail.getSequenceNumber());
283            }
284    
285            return mapping.findForward(KFSConstants.MAPPING_BASIC);
286        }
287    
288    
289        /**
290         * Removed salesTax checking. Need to verify if this check has be moved out later of the KualiAccountingDocumentActionBase
291         * class. If so just use the parent class' insertSourceLine method.
292         * 
293         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#insertSourceLine(org.apache.struts.action.ActionMapping,
294         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
295         */
296        @Override
297        public ActionForward insertSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
298    
299            CustomerInvoiceDocumentForm customerInvoiceDocumentForm = (CustomerInvoiceDocumentForm) form;
300            CustomerInvoiceDocument customerInvoiceDocument = customerInvoiceDocumentForm.getCustomerInvoiceDocument();
301            CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) customerInvoiceDocumentForm.getNewSourceLine();
302    
303            // populate chartOfAccountsCode from account number if accounts cant cross chart and Javascript is turned off
304            //SpringContext.getBean(AccountService.class).populateAccountingLineChartIfNeeded(customerInvoiceDetail);
305            
306            // make sure amount is up to date before rules
307            CustomerInvoiceDetailService service = SpringContext.getBean(CustomerInvoiceDetailService.class);
308            service.recalculateCustomerInvoiceDetail(customerInvoiceDocument, customerInvoiceDetail);
309    
310            boolean rulePassed = true;
311            // check any business rules
312            rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddAccountingLineEvent(KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME, customerInvoiceDocumentForm.getDocument(), customerInvoiceDetail));
313    
314            if (rulePassed) {
315    
316                // add accountingLine
317                customerInvoiceDetail.refreshNonUpdateableReferences();
318                service.prepareCustomerInvoiceDetailForAdd(customerInvoiceDetail, customerInvoiceDocument);
319                insertAccountingLine(true, customerInvoiceDocumentForm, customerInvoiceDetail);
320    
321                // clear the used newTargetLine
322                customerInvoiceDocumentForm.setNewSourceLine(null);
323            }
324    
325            return mapping.findForward(KFSConstants.MAPPING_BASIC);
326        }
327    
328    
329        /**
330         * Overrides method to delete accounting line. If line to be deleted has a corresponding discount line, the corresponding
331         * discount line is also deleted. If the line to be delete is a discount line, set the reference for the parent to null
332         * 
333         * @param isSource
334         * @param financialDocumentForm
335         * @param deleteIndex
336         */
337        @Override
338        protected void deleteAccountingLine(boolean isSource, KualiAccountingDocumentFormBase financialDocumentForm, int deleteIndex) {
339    
340            CustomerInvoiceDocument customerInvoiceDocument = ((CustomerInvoiceDocumentForm) financialDocumentForm).getCustomerInvoiceDocument();
341    
342            // if line to delete is a discount parent discountLine, remove discount line too
343            CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) customerInvoiceDocument.getSourceAccountingLine(deleteIndex);
344            if (customerInvoiceDetail.isDiscountLineParent()) {
345                customerInvoiceDocument.removeDiscountLineBasedOnParentLineIndex(deleteIndex);
346            }
347            else if (customerInvoiceDocument.isDiscountLineBasedOnSequenceNumber(customerInvoiceDetail.getSequenceNumber())) {
348    
349                // if line to delete is a discount line, set discount line reference for parent to null
350                CustomerInvoiceDetail parentCustomerInvoiceDetail = customerInvoiceDetail.getParentDiscountCustomerInvoiceDetail();
351                if (ObjectUtils.isNotNull(parentCustomerInvoiceDetail)) {
352                    parentCustomerInvoiceDetail.setInvoiceItemDiscountLineNumber(null);
353                }
354            }
355    
356            // delete line like normal
357            super.deleteAccountingLine(isSource, financialDocumentForm, deleteIndex);
358        }
359    
360        @Override
361        public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
362            super.refresh(mapping, form, request, response);
363            refreshBillToAddress(mapping, form, request, response);
364            refreshShipToAddress(mapping, form, request, response);
365            return mapping.findForward(KFSConstants.MAPPING_BASIC);
366        }
367    
368        /**
369         * This method refresh the ShipToAddress CustomerAddress object
370         * @param mapping
371         * @param form
372         * @param request
373         * @param response
374         * @return
375         * @throws Exception
376         */
377        public ActionForward refreshBillToAddress(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
378            
379            CustomerInvoiceDocument customerInvoiceDocument = ((CustomerInvoiceDocumentForm) form).getCustomerInvoiceDocument();
380            
381            CustomerAddress customerBillToAddress = null;
382            if (ObjectUtils.isNotNull(customerInvoiceDocument.getCustomerBillToAddressIdentifier())) {
383                int customerBillToAddressIdentifier = customerInvoiceDocument.getCustomerBillToAddressIdentifier();
384               
385                customerBillToAddress = SpringContext.getBean(CustomerAddressService.class).getByPrimaryKey(customerInvoiceDocument.getAccountsReceivableDocumentHeader().getCustomerNumber(), customerBillToAddressIdentifier);
386                if (ObjectUtils.isNotNull(customerBillToAddress)) {
387                    customerInvoiceDocument.setCustomerBillToAddress(customerBillToAddress);
388                    customerInvoiceDocument.setCustomerBillToAddressOnInvoice(customerBillToAddress);
389                    customerInvoiceDocument.setCustomerBillToAddressIdentifier(customerBillToAddressIdentifier);
390                } else {
391                    customerBillToAddress = SpringContext.getBean(CustomerAddressService.class).getPrimaryAddress(customerInvoiceDocument.getAccountsReceivableDocumentHeader().getCustomerNumber());
392    
393                    if (ObjectUtils.isNotNull(customerBillToAddress)) {
394                        customerInvoiceDocument.setCustomerBillToAddress(customerBillToAddress);
395                        customerInvoiceDocument.setCustomerBillToAddressOnInvoice(customerBillToAddress);
396                        customerInvoiceDocument.setCustomerBillToAddressIdentifier(customerBillToAddress.getCustomerAddressIdentifier());
397                    } else {
398                        customerInvoiceDocument.setCustomerBillToAddress(null);
399                        customerInvoiceDocument.setCustomerBillToAddressOnInvoice(null);
400                        customerInvoiceDocument.setCustomerBillToAddressIdentifier(null);
401                    }
402                }
403                
404            } else {
405                customerBillToAddress = SpringContext.getBean(CustomerAddressService.class).getPrimaryAddress(customerInvoiceDocument.getAccountsReceivableDocumentHeader().getCustomerNumber());
406    
407                if (ObjectUtils.isNotNull(customerBillToAddress)) {
408                    customerInvoiceDocument.setCustomerBillToAddress(customerBillToAddress);
409                    customerInvoiceDocument.setCustomerBillToAddressOnInvoice(customerBillToAddress);
410                    customerInvoiceDocument.setCustomerBillToAddressIdentifier(customerBillToAddress.getCustomerAddressIdentifier());
411                } else {
412                    customerInvoiceDocument.setCustomerBillToAddress(null);
413                    customerInvoiceDocument.setCustomerBillToAddressOnInvoice(null);
414                    customerInvoiceDocument.setCustomerBillToAddressIdentifier(null);
415                }
416            }
417            
418            return mapping.findForward(KFSConstants.MAPPING_BASIC);
419        }
420        
421        /**
422         * This method refresh the ShipToAddress CustomerAddress object
423         * @param mapping
424         * @param form
425         * @param request
426         * @param response
427         * @return
428         * @throws Exception
429         */
430        public ActionForward refreshShipToAddress(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
431            CustomerInvoiceDocument customerInvoiceDocument = ((CustomerInvoiceDocumentForm) form).getCustomerInvoiceDocument();
432            
433            CustomerAddress customerShipToAddress = null;
434            if (ObjectUtils.isNotNull(customerInvoiceDocument.getCustomerShipToAddressIdentifier())) {
435                int customerShipToAddressIdentifier = customerInvoiceDocument.getCustomerShipToAddressIdentifier();
436                
437                customerShipToAddress = SpringContext.getBean(CustomerAddressService.class).getByPrimaryKey(customerInvoiceDocument.getAccountsReceivableDocumentHeader().getCustomerNumber(), customerShipToAddressIdentifier);
438                if (ObjectUtils.isNotNull(customerShipToAddress)) {
439                    customerInvoiceDocument.setCustomerShipToAddress(customerShipToAddress);
440                    customerInvoiceDocument.setCustomerShipToAddressOnInvoice(customerShipToAddress);
441                    customerInvoiceDocument.setCustomerShipToAddressIdentifier(customerShipToAddressIdentifier);
442                }
443            }
444            if (ObjectUtils.isNull(customerInvoiceDocument.getCustomerShipToAddressIdentifier()) | ObjectUtils.isNull(customerShipToAddress)) {
445                customerInvoiceDocument.setCustomerShipToAddress(null);
446                customerInvoiceDocument.setCustomerShipToAddressOnInvoice(null);
447                customerInvoiceDocument.setCustomerShipToAddressIdentifier(null);
448            }
449            
450    
451            return mapping.findForward(KFSConstants.MAPPING_BASIC);
452        }    
453    
454        /**
455         * 
456         * This method...
457         * @param mapping
458         * @param form
459         * @param request
460         * @param response
461         * @return
462         * @throws Exception
463         */
464        public ActionForward print(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
465            String basePath = getBasePath(request);
466            String docId = ((CustomerInvoiceDocumentForm) form).getCustomerInvoiceDocument().getDocumentNumber();
467            String methodToCallPrintInvoicePDF = "printInvoicePDF";
468            String methodToCallDocHandler = "docHandler";
469            String printInvoicePDFUrl = getUrlForPrintInvoice(basePath, docId, methodToCallPrintInvoicePDF);
470            String displayInvoiceTabbedPageUrl = getUrlForPrintInvoice(basePath, docId, methodToCallDocHandler);
471            
472            request.setAttribute("printPDFUrl", printInvoicePDFUrl);
473            request.setAttribute("displayTabbedPageUrl", displayInvoiceTabbedPageUrl);
474            request.setAttribute(KFSConstants.PARAMETER_DOC_ID, docId);
475            String label = SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(KFSConstants.FinancialDocumentTypeCodes.CUSTOMER_INVOICE);
476            request.setAttribute("printLabel", label);
477            return mapping.findForward("arPrintPDF");
478            
479        }
480        
481        /**
482         * 
483         * This method...
484         * @param mapping
485         * @param form
486         * @param request
487         * @param response
488         * @return
489         * @throws Exception
490         */
491        public ActionForward printInvoicePDF(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
492            String invoiceDocId = request.getParameter(KFSConstants.PARAMETER_DOC_ID);
493            CustomerInvoiceDocument customerInvoiceDocument = (CustomerInvoiceDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(invoiceDocId);
494            
495            AccountsReceivableReportService reportService = SpringContext.getBean(AccountsReceivableReportService.class);
496            File report = reportService.generateInvoice(customerInvoiceDocument);
497            
498            StringBuilder fileName = new StringBuilder();
499            fileName.append(customerInvoiceDocument.getOrganizationInvoiceNumber());
500            fileName.append("-");
501            fileName.append(customerInvoiceDocument.getDocumentNumber());
502            fileName.append(".pdf");
503            
504            if (report.length() == 0) {
505                //csForm.setMessage("No Report Generated");
506                return mapping.findForward(KFSConstants.MAPPING_BASIC);
507            }
508                
509            ByteArrayOutputStream baos = new ByteArrayOutputStream();
510            String contentDisposition = "";
511            try {
512                ArrayList master = new ArrayList();
513                PdfCopy writer = null;
514    
515                // create a reader for the document
516                String reportName = report.getAbsolutePath();
517                PdfReader reader = new PdfReader(reportName);
518                reader.consolidateNamedDestinations();
519                
520                // retrieve the total number of pages
521                int n = reader.getNumberOfPages();
522                List bookmarks = SimpleBookmark.getBookmark(reader);
523                if (bookmarks != null) {
524                    master.addAll(bookmarks);
525                }
526    
527                // step 1: create a document-object
528                Document document = new Document(reader.getPageSizeWithRotation(1));
529                // step 2: create a writer that listens to the document
530                writer = new PdfCopy(document, baos);
531                // step 3: open the document
532                document.open();
533                // step 4: add content
534                PdfImportedPage page;
535                for (int i = 0; i < n; ) {
536                    ++i;
537                    page = writer.getImportedPage(reader, i);
538                    writer.addPage(page);
539                }
540                writer.freeReader(reader);
541                if (!master.isEmpty()) {
542                    writer.setOutlines(master);
543                }
544                // step 5: we close the document
545                document.close();
546    
547                StringBuffer sbContentDispValue = new StringBuffer();
548                String useJavascript = request.getParameter("useJavascript");
549                if (useJavascript == null || useJavascript.equalsIgnoreCase("false")) {
550                    sbContentDispValue.append("attachment");
551                }
552                else {
553                    sbContentDispValue.append("inline");
554                }
555                sbContentDispValue.append("; filename=");
556                sbContentDispValue.append(fileName);
557                
558                contentDisposition = sbContentDispValue.toString();
559                
560            }
561            catch(Exception e) {
562                e.printStackTrace();
563            } 
564            
565            response.setContentType("application/pdf");
566            response.setHeader("Content-Disposition", contentDisposition);
567            response.setHeader("Expires", "0");
568            response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
569            response.setHeader("Pragma", "public");
570            response.setContentLength(baos.size());
571    
572            // write to output
573            ServletOutputStream sos;
574            sos = response.getOutputStream();
575            baos.writeTo(sos);
576            sos.flush();
577            sos.close();
578            
579            return null;
580        }
581        
582        /**
583         * Creates a URL to be used in printing the customer invoice document.
584         * 
585         * @param basePath String: The base path of the current URL
586         * @param docId String: The document ID of the document to be printed
587         * @param methodToCall String: The name of the method that will be invoked to do this particular print
588         * @return The URL
589         */
590        protected String getUrlForPrintInvoice(String basePath, String docId, String methodToCall) {
591            StringBuffer result = new StringBuffer(basePath);
592            result.append("/arCustomerInvoiceDocument.do?methodToCall=");
593            result.append(methodToCall);
594            result.append("&docId=");
595            result.append(docId);
596            result.append("&command=displayDocSearchView");
597    
598            return result.toString();
599        }
600    
601        
602        
603    }