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.purap.pdf;
017    
018    import java.io.ByteArrayOutputStream;
019    
020    import org.apache.commons.lang.StringUtils;
021    import org.apache.commons.logging.Log;
022    import org.apache.commons.logging.LogFactory;
023    import org.kuali.kfs.module.purap.document.BulkReceivingDocument;
024    import org.kuali.kfs.sys.KFSConstants;
025    
026    import com.lowagie.text.Chunk;
027    import com.lowagie.text.Document;
028    import com.lowagie.text.Element;
029    import com.lowagie.text.ExceptionConverter;
030    import com.lowagie.text.Image;
031    import com.lowagie.text.Paragraph;
032    import com.lowagie.text.Phrase;
033    import com.lowagie.text.pdf.BaseFont;
034    import com.lowagie.text.pdf.PdfPCell;
035    import com.lowagie.text.pdf.PdfPTable;
036    import com.lowagie.text.pdf.PdfWriter;
037    
038    /**
039     * Base class to handle pdf for bulk receiving ticket.
040     */
041    public class BulkReceivingPdf extends PurapPdf {
042        
043        private static Log LOG = LogFactory.getLog(BulkReceivingPdf.class);
044        private BulkReceivingDocument blkRecDoc;
045    
046        public BulkReceivingPdf() {
047            super();
048        }
049    
050        /**
051         * Overrides the method in PdfPageEventHelper from itext to create and set the headerTable and set its logo image if 
052         * there is a logoImage to be used, creates and sets the nestedHeaderTable and its content.
053         * 
054         * @param writer    The PdfWriter for this document.
055         * @param document  The document.
056         * @see com.lowagie.text.pdf.PdfPageEventHelper#onOpenDocument(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document)
057         */
058        public void onOpenDocument(PdfWriter writer, Document document) {
059            try {
060                
061                loadHeaderTable();
062                
063                // initialization of the template
064                tpl = writer.getDirectContent().createTemplate(100, 100);
065                
066                // initialization of the font
067                helv = BaseFont.createFont("Helvetica", BaseFont.WINANSI, false);
068                
069            }catch (Exception e) {
070                throw new ExceptionConverter(e);
071            }
072        }
073    
074        private void loadHeaderTable()
075        throws Exception {
076            
077            float[] headerWidths = { 0.20f, 0.80f };
078            
079            headerTable = new PdfPTable(headerWidths);
080            headerTable.setWidthPercentage(100);
081            headerTable.setHorizontalAlignment(Element.ALIGN_CENTER);
082            headerTable.setSplitLate(false);
083            headerTable.getDefaultCell().setBorderWidth(0);
084            headerTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
085            headerTable.getDefaultCell().setVerticalAlignment(Element.ALIGN_CENTER);
086            
087            /**
088             * Logo display
089             */
090            if (StringUtils.isNotBlank(logoImage)) {
091                logo = Image.getInstance(logoImage);
092                logo.scalePercent(3, 3);
093                headerTable.addCell(new Phrase(new Chunk(logo, 0, 0)));
094            }
095            else {
096                headerTable.addCell(new Phrase(new Chunk("")));
097            }
098            
099            /**
100             * Nested table in tableHeader to display title and doc number
101             */
102            float[] nestedHeaderWidths = { 0.70f, 0.30f };
103            nestedHeaderTable = new PdfPTable(nestedHeaderWidths);
104            nestedHeaderTable.setSplitLate(false);
105            PdfPCell cell;
106    
107            /**
108             * Title
109             */
110            cell = new PdfPCell(new Paragraph("RECEIVING TICKET", ver_15_normal));
111            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
112            cell.setBorderWidth(0);
113            nestedHeaderTable.addCell(cell);
114            
115            /**
116             * Doc Number
117             */
118            Paragraph p = new Paragraph();
119            p.add(new Chunk("Doc Number: ", ver_11_normal));
120            p.add(new Chunk(blkRecDoc.getDocumentNumber().toString(), cour_10_normal));
121            cell = new PdfPCell(p);
122            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
123            cell.setBorderWidth(0);
124            nestedHeaderTable.addCell(cell);
125            
126            // Add the nestedHeaderTable to the headerTable
127            cell = new PdfPCell(nestedHeaderTable);
128            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
129            cell.setBorderWidth(0);
130            headerTable.addCell(cell);
131        }
132        
133        /**
134         * Gets a PageEvents object.
135         * 
136         * @return a new PageEvents object
137         */
138        public BulkReceivingPdf getPageEvents() {
139            LOG.debug("getPageEvents() started.");
140            return new BulkReceivingPdf();
141        }
142    
143        /**
144         * Generates the pdf document based on the data in the given BulkReceivingDocument
145         * 
146         * @param blkRecDoc   The BulkReceivingDocument to be used to generate the pdf.
147         * @param byteStream  The ByteArrayOutputStream where the pdf document will be written to.
148         */
149        public void generatePdf(BulkReceivingDocument blkRecDoc, 
150                                ByteArrayOutputStream byteStream,
151                                String logoImage,
152                                String environment) {
153            
154            LOG.debug("generatePdf() started for bulk receiving - " + blkRecDoc.getDocumentNumber());
155    
156            Document document = null;
157            
158            try {
159                
160                document = this.getDocument(9, 9, 70, 36);
161                PdfWriter writer = PdfWriter.getInstance(document, byteStream);
162    
163                //These have to be set because they are used by the onOpenDocument() and onStartPage() methods.
164                this.logoImage = logoImage;
165                this.blkRecDoc = blkRecDoc;
166                this.environment = environment;
167                
168                // This turns on the page events that handle the header and page numbers.
169                BulkReceivingPdf events = new BulkReceivingPdf().getPageEvents();
170                writer.setPageEvent(this); 
171    
172                document.open();
173                
174                document.add(createVendorAndDeliveryDetailsTable());
175                document.add(new Paragraph("\nAdditional Details\n  ", ver_8_bold));
176                document.add(createAdditionalDetailsTable());
177                
178                document.close();
179                
180            }catch (Exception de) {
181                throw new RuntimeException("Document Exception when trying to save a Bulk Receiving PDF", de);
182            }finally{
183                if (document != null && document.isOpen()){
184                    document.close();
185                }
186            }
187            LOG.debug("generatePdf() completed for bulk receiving - " + blkRecDoc.getDocumentNumber());
188        }
189        
190        private PdfPTable createVendorAndDeliveryDetailsTable(){
191            
192            PdfPCell cell;
193            Paragraph p = new Paragraph();
194    
195            float[] infoWidths = { 0.50f, 0.50f };
196            PdfPTable infoTable = new PdfPTable(infoWidths);
197    
198            infoTable.setWidthPercentage(100);
199            infoTable.setHorizontalAlignment(Element.ALIGN_CENTER);
200            infoTable.setSplitLate(false);
201            
202            infoTable.addCell(getPDFCell("Vendor", getFormattedVendorAddress()));
203            infoTable.addCell(getPDFCell("Delivery", getFormattedDeliveryAddress()));
204            infoTable.addCell(getPDFCell("Reference Number\n", blkRecDoc.getShipmentReferenceNumber()));
205            
206            if (blkRecDoc.getCarrier() != null){
207                infoTable.addCell(getPDFCell("Carrier\n", blkRecDoc.getCarrier().getCarrierDescription()));
208            }else{
209                infoTable.addCell(getPDFCell("Carrier\n", StringUtils.EMPTY));
210            }
211            
212            infoTable.addCell(getPDFCell("Tracking/Pro Number\n", blkRecDoc.getTrackingNumber()));
213            
214            if (blkRecDoc.getPurchaseOrderIdentifier() != null){
215                infoTable.addCell(getPDFCell("PO\n", blkRecDoc.getPurchaseOrderIdentifier().toString()));
216            }else{
217                infoTable.addCell(getPDFCell("PO\n", StringUtils.EMPTY));
218            }
219            
220            infoTable.addCell(getPDFCell("# of Pieces\n", "" + blkRecDoc.getNoOfCartons()));
221            infoTable.addCell(getPDFCell("Shipment Received Date\n", blkRecDoc.getShipmentReceivedDate().toString()));
222    
223            if (blkRecDoc.getShipmentWeight() != null){
224                infoTable.addCell(getPDFCell("Weight\n", blkRecDoc.getShipmentWeight().toString()));
225            }else{
226                infoTable.addCell(getPDFCell("Weight\n", StringUtils.EMPTY));
227            }
228            
229            infoTable.addCell(getPDFCell("\n", StringUtils.EMPTY));
230    
231            return infoTable;
232        }
233        
234        private PdfPCell getPDFCell(String fieldTitle,
235                                    String fieldValue){
236            
237            Paragraph p = new Paragraph();
238            p.add(new Chunk("  " + fieldTitle, ver_5_normal));
239            
240            if (StringUtils.isNotEmpty(fieldValue)){
241                p.add(new Chunk("     " + fieldValue, cour_10_normal));
242            }else{
243                p.add(new Chunk("  "));
244            }
245            
246            PdfPCell cell = new PdfPCell(p);
247            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
248            
249            return cell;
250        }
251        
252        private String getFormattedVendorAddress(){
253    
254            StringBuffer vendorInfo = new StringBuffer();
255            vendorInfo.append("\n");
256            
257            /**
258             * GoodsDeliveredVendorNumber will be null if it the doc is not for a specific PO 
259             */
260            if (blkRecDoc.getGoodsDeliveredVendorNumber() == null ||
261                blkRecDoc.getGoodsDeliveredVendorNumber().equals(blkRecDoc.getVendorNumber())){
262                
263                if (StringUtils.isNotBlank(blkRecDoc.getVendorName())) {
264                    vendorInfo.append("     " + blkRecDoc.getVendorName() + "\n");
265                }
266                
267                if (StringUtils.isNotBlank(blkRecDoc.getVendorLine1Address())) {
268                    vendorInfo.append("     " + blkRecDoc.getVendorLine1Address() + "\n");
269                }
270                
271                if (StringUtils.isNotBlank(blkRecDoc.getVendorLine2Address())) {
272                    vendorInfo.append("     " + blkRecDoc.getVendorLine2Address() + "\n");
273                }
274                
275                if (StringUtils.isNotBlank(blkRecDoc.getVendorCityName())) {
276                    vendorInfo.append("     " + blkRecDoc.getVendorCityName());
277                }
278                
279                if (StringUtils.isNotBlank(blkRecDoc.getVendorStateCode())) {
280                    vendorInfo.append(", " + blkRecDoc.getVendorStateCode());
281                }
282                
283                if (StringUtils.isNotBlank(blkRecDoc.getVendorAddressInternationalProvinceName())) {
284                    vendorInfo.append(", " + blkRecDoc.getVendorAddressInternationalProvinceName());
285                }
286                
287                if (StringUtils.isNotBlank(blkRecDoc.getVendorPostalCode())) {
288                    vendorInfo.append(" " + blkRecDoc.getVendorPostalCode() + "\n");
289                }else {
290                    vendorInfo.append("\n");
291                }
292                
293                if (!KFSConstants.COUNTRY_CODE_UNITED_STATES.equalsIgnoreCase(blkRecDoc.getVendorCountryCode()) && blkRecDoc.getVendorCountry() != null) {
294                    vendorInfo.append("     " + blkRecDoc.getVendorCountry().getPostalCountryName() + "\n\n");
295                }else {
296                    vendorInfo.append("\n\n");
297                }
298                
299            }else{
300                
301                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getVendorName())) {
302                    vendorInfo.append("     " + blkRecDoc.getAlternateVendorDetail().getVendorName() + "\n");
303                }
304                
305                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getDefaultAddressLine1())) {
306                    vendorInfo.append("     " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressLine1() + "\n");
307                }
308                
309                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getDefaultAddressLine2())) {
310                    vendorInfo.append("     " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressLine2() + "\n");
311                }
312                
313                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getDefaultAddressCity())) {
314                    vendorInfo.append("     " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressCity());
315                }
316                
317                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getDefaultAddressStateCode())) {
318                    vendorInfo.append(", " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressStateCode());
319                }
320                
321                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getDefaultAddressInternationalProvince())) {
322                    vendorInfo.append(", " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressInternationalProvince());
323                }
324                
325                if (StringUtils.isNotBlank(blkRecDoc.getAlternateVendorDetail().getDefaultAddressPostalCode())) {
326                    vendorInfo.append(" " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressPostalCode() + "\n");
327                }else {
328                    vendorInfo.append("\n");
329                }
330                
331                if (!KFSConstants.COUNTRY_CODE_UNITED_STATES.equalsIgnoreCase(blkRecDoc.getAlternateVendorDetail().getDefaultAddressCountryCode()) && blkRecDoc.getAlternateVendorDetail().getDefaultAddressCountryCode() != null) {
332                    vendorInfo.append("     " + blkRecDoc.getAlternateVendorDetail().getDefaultAddressCountryCode() + "\n\n");
333                }else {
334                    vendorInfo.append("\n\n");
335                }
336            }
337            
338            return vendorInfo.toString();
339        }
340    
341        private String getFormattedDeliveryAddress(){
342            
343            StringBuffer shipToInfo = new StringBuffer();
344            
345            shipToInfo.append("\n");
346            
347            if (StringUtils.isNotBlank(blkRecDoc.getDeliveryToName())){
348                shipToInfo.append("     " + StringUtils.defaultString(blkRecDoc.getDeliveryToName()) + "\n");    
349            }
350            
351            String deliveryBuildingName = blkRecDoc.getDeliveryBuildingName();
352    
353            if(StringUtils.isNotBlank(blkRecDoc.getDeliveryBuildingRoomNumber())){
354                if (StringUtils.isBlank(deliveryBuildingName)){
355                    shipToInfo.append("     Room #" + blkRecDoc.getDeliveryBuildingRoomNumber() + "\n");
356                }else{
357                    shipToInfo.append("     " + deliveryBuildingName + " Room #" + blkRecDoc.getDeliveryBuildingRoomNumber() + "\n");    
358                }
359            }else{
360                if (StringUtils.isNotBlank(deliveryBuildingName)){
361                    shipToInfo.append("     " + deliveryBuildingName + "\n");
362                }
363            }
364            
365            shipToInfo.append("     " + blkRecDoc.getDeliveryBuildingLine1Address() + "\n");
366            
367            if (StringUtils.isNotBlank(blkRecDoc.getDeliveryBuildingLine2Address())) {
368                shipToInfo.append("     " + blkRecDoc.getDeliveryBuildingLine2Address() + "\n");
369            }
370            
371            shipToInfo.append("     " + blkRecDoc.getDeliveryCityName() + ", " + 
372                                        blkRecDoc.getDeliveryStateCode() + " " + 
373                                        blkRecDoc.getDeliveryPostalCode() + "\n\n");
374            
375            return shipToInfo.toString();
376        }
377        
378        private PdfPTable createAdditionalDetailsTable(){
379            
380            float[] additionalInfoWidths = { 0.25f, 0.75f };
381            PdfPTable additionalInfoTable = new PdfPTable(additionalInfoWidths);
382            additionalInfoTable.setWidthPercentage(100);
383            additionalInfoTable.setSplitLate(false);
384            
385            Paragraph p = new Paragraph();
386            PdfPCell cell;
387            
388            /**
389             * Notes to vendor
390             */
391            p.add(new Chunk("  Notes to Vendor  ", ver_5_normal));
392            cell = new PdfPCell(p);
393            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
394            additionalInfoTable.addCell(cell);
395            
396            p = new Paragraph();
397            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getVendorNoteText()), cour_10_normal));
398            
399            cell = new PdfPCell(p);
400            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
401            additionalInfoTable.addCell(cell);
402            
403            /**
404             * Delivery instructions
405             */
406            p = new Paragraph();
407            p.add(new Chunk("  Delivery instructions  ", ver_5_normal));
408            cell = new PdfPCell(p);
409            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
410            additionalInfoTable.addCell(cell);
411            
412            p = new Paragraph();
413            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getDeliveryInstructionText()), cour_10_normal));
414            
415            cell = new PdfPCell(p);
416            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
417            additionalInfoTable.addCell(cell);
418            
419            /**
420             * Additional Delivery instructions
421             */
422            p = new Paragraph();
423            p.add(new Chunk("  Additional Delivery instructions  ", ver_5_normal));
424            cell = new PdfPCell(p);
425            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
426            additionalInfoTable.addCell(cell);
427            
428            p = new Paragraph();
429            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getDeliveryAdditionalInstructionText()), cour_10_normal));
430            
431            cell = new PdfPCell(p);
432            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
433            additionalInfoTable.addCell(cell);
434            
435            updateRequestorInfo(blkRecDoc,additionalInfoTable);
436            
437            String campusCode = blkRecDoc.getDeliveryCampusCode();
438            
439            /**
440             * Dept Contact 
441             */
442            p = new Paragraph();
443            p.add(new Chunk("   Contact Name ", ver_5_normal));
444            cell = new PdfPCell(p);
445            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
446            additionalInfoTable.addCell(cell);
447            
448            p = new Paragraph();
449            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getInstitutionContactName()), cour_10_normal));
450            
451            cell = new PdfPCell(p);
452            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
453            additionalInfoTable.addCell(cell);
454            
455            /**
456             * Dept Contact Phone 
457             */
458            p = new Paragraph();
459            p.add(new Chunk("  Contact Phone  ", ver_5_normal));
460            cell = new PdfPCell(p);
461            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
462            additionalInfoTable.addCell(cell);
463            
464            p = new Paragraph();
465            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getInstitutionContactPhoneNumber()), cour_10_normal));
466            
467            cell = new PdfPCell(p);
468            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
469            additionalInfoTable.addCell(cell);
470            
471            /**
472             * Dept Contact email 
473             */
474            p = new Paragraph();
475            p.add(new Chunk("  Contact Email  ", ver_5_normal));
476            cell = new PdfPCell(p);
477            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
478            additionalInfoTable.addCell(cell);
479            
480            p = new Paragraph();
481            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getInstitutionContactEmailAddress()), cour_10_normal));
482            
483            cell = new PdfPCell(p);
484            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
485            additionalInfoTable.addCell(cell);
486            
487            
488            /**
489             * Signature
490             */
491            p = new Paragraph();
492            p.add(new Chunk("  " + " Signature  ", ver_5_normal));
493            cell = new PdfPCell(p);
494            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
495            additionalInfoTable.addCell(cell);
496            
497            p = new Paragraph();
498            p.add(new Chunk("\n\n\n\n"));
499            
500            cell = new PdfPCell(p);
501            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
502            additionalInfoTable.addCell(cell);
503            
504            /**
505             * Date
506             */
507            p = new Paragraph();
508            p.add(new Chunk("  " + " Date  ", ver_5_normal));
509            cell = new PdfPCell(p);
510            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
511            additionalInfoTable.addCell(cell);
512            
513            p = new Paragraph();
514            p.add(new Chunk("\n\n\n\n"));
515            
516            cell = new PdfPCell(p);
517            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
518            additionalInfoTable.addCell(cell);
519            
520            return additionalInfoTable;
521        }
522        
523        private void updateRequestorInfo(BulkReceivingDocument blkRecDoc,
524                                         PdfPTable additionalInfoTable){
525            /**
526             * Requestor Name
527             */
528            Paragraph p = new Paragraph();
529            p.add(new Chunk("  Requestor Name  ", ver_5_normal));
530            PdfPCell cell = new PdfPCell(p);
531            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
532            additionalInfoTable.addCell(cell);
533            
534            p = new Paragraph();
535            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getRequestorPersonName()), cour_10_normal));
536            
537            cell = new PdfPCell(p);
538            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
539            additionalInfoTable.addCell(cell);
540            
541            /**
542             * Requestor Phone
543             */
544            p = new Paragraph();
545            p.add(new Chunk("  Requestor Phone  ", ver_5_normal));
546            cell = new PdfPCell(p);
547            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
548            additionalInfoTable.addCell(cell);
549            
550            p = new Paragraph();
551            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getRequestorPersonPhoneNumber()), cour_10_normal));
552            
553            cell = new PdfPCell(p);
554            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
555            additionalInfoTable.addCell(cell);
556            
557            /**
558             * Requestor Email
559             */
560            p = new Paragraph();
561            p.add(new Chunk("  Requestor Email  ", ver_5_normal));
562            cell = new PdfPCell(p);
563            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
564            additionalInfoTable.addCell(cell);
565            
566            p = new Paragraph();
567            p.add(new Chunk("  " + StringUtils.defaultString(blkRecDoc.getRequestorPersonEmailAddress()), cour_10_normal));
568            cell = new PdfPCell(p);
569            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
570            additionalInfoTable.addCell(cell);
571        }
572    }