Subversion Repositories SmartDukaan

Rev

Rev 36111 | Rev 36119 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 36111 Rev 36116
Line 444... Line 444...
444
                document.add(declarationParagraph);
444
                document.add(declarationParagraph);
445
            }
445
            }
446
        }
446
        }
447
    }
447
    }
448
 
448
 
-
 
449
    // ── Margin Scheme Invoice Helpers ──────────────────────────────────────
-
 
450
    private static final BaseColor MS_BORDER   = new BaseColor(204, 204, 204);
-
 
451
    private static final BaseColor MS_HEADER_BG = new BaseColor(242, 242, 242);
-
 
452
    private static final BaseColor MS_TOTAL_BG  = new BaseColor(249, 249, 249);
-
 
453
    private static final BaseColor MS_SUMM_BG   = new BaseColor(242, 242, 242);
-
 
454
 
-
 
455
    private static final Font MS_TITLE      = new Font(Font.FontFamily.HELVETICA, 13, Font.BOLD);
-
 
456
    private static final Font MS_SUBTITLE   = new Font(Font.FontFamily.HELVETICA, 7.5f, Font.ITALIC, new BaseColor(51, 51, 51));
-
 
457
    private static final Font MS_SECTION    = new Font(Font.FontFamily.HELVETICA, 6.5f, Font.BOLD, new BaseColor(85, 85, 85));
-
 
458
    private static final Font MS_NORMAL     = new Font(Font.FontFamily.HELVETICA, 8, Font.NORMAL);
-
 
459
    private static final Font MS_BOLD       = new Font(Font.FontFamily.HELVETICA, 8, Font.BOLD);
-
 
460
    private static final Font MS_SMALL      = new Font(Font.FontFamily.HELVETICA, 7, Font.NORMAL, new BaseColor(68, 68, 68));
-
 
461
    private static final Font MS_SMALL_BOLD = new Font(Font.FontFamily.HELVETICA, 7, Font.BOLD);
-
 
462
    private static final Font MS_ITALIC     = new Font(Font.FontFamily.HELVETICA, 7.5f, Font.ITALIC);
-
 
463
    private static final Font MS_TBL_HDR    = new Font(Font.FontFamily.HELVETICA, 7, Font.BOLD);
-
 
464
 
-
 
465
    private static Paragraph msSpacer(float spacing) {
-
 
466
        Paragraph p = new Paragraph(" ");
-
 
467
        p.setSpacingAfter(spacing);
-
 
468
        p.setLeading(0f);
-
 
469
        return p;
-
 
470
    }
-
 
471
 
-
 
472
    private static Paragraph msRightPara(String text, Font font) {
-
 
473
        Paragraph p = new Paragraph(text, font);
-
 
474
        p.setAlignment(Element.ALIGN_RIGHT);
-
 
475
        return p;
-
 
476
    }
-
 
477
 
-
 
478
    private static void msAddHeader(PdfPTable table, String text, int align) {
-
 
479
        PdfPCell cell = new PdfPCell(new Phrase(text, MS_TBL_HDR));
-
 
480
        cell.setHorizontalAlignment(align);
-
 
481
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
482
        cell.setBackgroundColor(MS_HEADER_BG);
-
 
483
        cell.setBorderColor(MS_BORDER);
-
 
484
        cell.setPadding(4f);
-
 
485
        table.addCell(cell);
-
 
486
    }
-
 
487
 
-
 
488
    private static void msAddDataCell(PdfPTable table, String text, int align, boolean bold, boolean totalRow) {
-
 
489
        Font font = bold ? MS_BOLD : MS_NORMAL;
-
 
490
        PdfPCell cell = new PdfPCell();
-
 
491
        cell.setHorizontalAlignment(align);
-
 
492
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
493
        cell.setBorderColor(MS_BORDER);
-
 
494
        if (totalRow) cell.setBackgroundColor(MS_TOTAL_BG);
-
 
495
        cell.setPadding(4f);
-
 
496
        String[] lines = text.split("\n");
-
 
497
        for (String line : lines) {
-
 
498
            Paragraph p = new Paragraph(line, font);
-
 
499
            p.setAlignment(align);
-
 
500
            p.setLeading(11f);
-
 
501
            cell.addElement(p);
-
 
502
        }
-
 
503
        table.addCell(cell);
-
 
504
    }
-
 
505
 
-
 
506
    private static void msAddSummaryRow(PdfPTable table, String label, String value, boolean highlight) {
-
 
507
        Font lf = highlight ? MS_BOLD : MS_NORMAL;
-
 
508
        Font vf = highlight ? MS_BOLD : MS_NORMAL;
-
 
509
        BaseColor bg = highlight ? MS_SUMM_BG : BaseColor.WHITE;
-
 
510
        PdfPCell lc = new PdfPCell(new Phrase(label, lf));
-
 
511
        lc.setBorderColor(MS_BORDER);
-
 
512
        lc.setPadding(5f);
-
 
513
        lc.setBackgroundColor(bg);
-
 
514
        table.addCell(lc);
-
 
515
        PdfPCell vc = new PdfPCell(new Phrase(value, vf));
-
 
516
        vc.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
517
        vc.setBorderColor(MS_BORDER);
-
 
518
        vc.setPadding(5f);
-
 
519
        vc.setBackgroundColor(bg);
-
 
520
        table.addCell(vc);
-
 
521
    }
-
 
522
 
449
    public static void generateMarginSchemeInvoice(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
523
    public static void generateMarginSchemeInvoice(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
-
 
524
        generateInvoiceV2(pdfModels, outputStream);
-
 
525
    }
-
 
526
 
-
 
527
    public static void generateInvoiceV2(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
450
        try {
528
        try {
451
            boolean cancelledPages = false;
529
            boolean cancelledPages = false;
452
            List<Integer> cancelledPageList = new ArrayList<>();
530
            List<Integer> cancelledPageList = new ArrayList<>();
453
            Document document = new Document();
531
            Document document = new Document(PageSize.A4, 28, 28, 34, 34);
454
            document.setMargins(0, 0, 25, 0);
-
 
455
            PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream);
532
            PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream);
456
            document.open();
533
            document.open();
457
 
534
 
458
            // 8 columns: S.No | Description | HSN | Qty | Gross Sale Value | Taxable Value (Margin) | Tax Rate | Tax Amount
-
 
459
            float[] marginSchemeWidths = new float[]{0.3f, 2.4f, 0.6f, 0.3f, 0.9f, 0.9f, 0.9f, 0.7f};
-
 
460
 
-
 
461
            for (InvoicePdfModel pdfModel : pdfModels) {
535
            for (InvoicePdfModel pdfModel : pdfModels) {
462
                CustomCustomer customer = pdfModel.getCustomer();
536
                CustomCustomer customer = pdfModel.getCustomer();
463
                CustomRetailer retailer = pdfModel.getRetailer();
537
                CustomRetailer retailer = pdfModel.getRetailer();
464
                boolean stateGst = customer.getAddress().getState().equals(retailer.getAddress().getState());
538
                boolean stateGst = customer.getAddress().getState().equals(retailer.getAddress().getState());
465
 
-
 
-
 
539
                String stateCode = stateGst ? pdfModel.getCustomerAddressStateCode() : pdfModel.getPartnerAddressStateCode();
466
                List<CustomOrderItem> orderItems = pdfModel.getOrderItems();
540
                List<CustomOrderItem> orderItems = pdfModel.getOrderItems();
-
 
541
                boolean isMargin = pdfModel.isHasMarginSchemeItems();
-
 
542
 
467
                if (pdfModel.isCancelled()) {
543
                if (pdfModel.isCancelled()) {
468
                    cancelledPageList.add(1);
544
                    cancelledPageList.add(1);
469
                    cancelledPages = true;
545
                    cancelledPages = true;
470
                } else {
546
                } else {
471
                    cancelledPageList.add(0);
547
                    cancelledPageList.add(0);
472
                }
548
                }
473
 
549
 
-
 
550
                // ── Header: Logo (left) + Title (center) + QR (right) ─────
-
 
551
                Rectangle rectangle = document.getPageSize();
-
 
552
                String titleText = pdfModel.getTitle() != null ? pdfModel.getTitle().toUpperCase() : "TAX INVOICE";
-
 
553
 
-
 
554
                PdfPTable headerBanner = new PdfPTable(3);
-
 
555
                headerBanner.setWidthPercentage(100);
-
 
556
                headerBanner.setWidths(new float[]{1.2f, 4f, 1.2f});
-
 
557
                headerBanner.setSpacingAfter(4f);
-
 
558
 
-
 
559
                // Left: Logo
-
 
560
                PdfPCell logoCell = new PdfPCell();
-
 
561
                logoCell.setBorder(Rectangle.NO_BORDER);
-
 
562
                logoCell.setPadding(4f);
-
 
563
                logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
564
                Image logoImg = Image.getInstance(iconImg);
-
 
565
                logoImg.scalePercent(25);
474
                document.addTitle("TAX INVOICE");
566
                logoCell.addElement(logoImg);
-
 
567
                headerBanner.addCell(logoCell);
-
 
568
 
-
 
569
                // Center: Title + subtitle
-
 
570
                PdfPCell titleCell = new PdfPCell();
-
 
571
                titleCell.setBorder(Rectangle.NO_BORDER);
-
 
572
                titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
573
                titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
-
 
574
                Paragraph title = new Paragraph(titleText, MS_TITLE);
-
 
575
                title.setAlignment(Element.ALIGN_CENTER);
-
 
576
                titleCell.addElement(title);
-
 
577
                if (isMargin) {
-
 
578
                    Paragraph subtitle = new Paragraph(
-
 
579
                            "(GST Payable on Margin Scheme Basis \u2014 ITC not admissible to buyer)", MS_SUBTITLE);
-
 
580
                    subtitle.setAlignment(Element.ALIGN_CENTER);
-
 
581
                    titleCell.addElement(subtitle);
-
 
582
                }
475
                document.addAuthor(pdfModel.getAuther());
583
                headerBanner.addCell(titleCell);
476
 
584
 
-
 
585
                // Right: QR code (or empty)
477
                Paragraph paragraphTitle = new Paragraph("TAX INVOICE", FONT_TITLE);
586
                PdfPCell qrCell = new PdfPCell();
-
 
587
                qrCell.setBorder(Rectangle.NO_BORDER);
478
                paragraphTitle.setAlignment(Element.ALIGN_CENTER);
588
                qrCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
479
                document.add(paragraphTitle);
589
                qrCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
480
 
-
 
481
                Font subtitleFont = new Font(Font.FontFamily.HELVETICA, 9, Font.ITALIC);
590
                if (pdfModel.getIrnModel() != null && pdfModel.getIrnModel().getQrCode() != null) {
482
                Paragraph subtitle = new Paragraph("(GST Payable on Margin Scheme Basis \u2014 ITC not admissible to buyer)", subtitleFont);
591
                    Image qrImg = Image.getInstance(pdfModel.getIrnModel().getQrCode().toURI().toURL());
-
 
592
                    qrImg.scaleAbsolute(80, 80);
483
                subtitle.setAlignment(Element.ALIGN_CENTER);
593
                    qrCell.addElement(qrImg);
-
 
594
                }
484
                document.add(subtitle);
595
                headerBanner.addCell(qrCell);
485
 
596
 
486
                Rectangle rectangle = document.getPageSize();
597
                document.add(headerBanner);
487
 
598
 
-
 
599
                // ── IRN Details (full width below header) ──────────────────
488
                if (pdfModel.getIrnModel() != null) {
600
                if (pdfModel.getIrnModel() != null) {
-
 
601
                    PdfPTable irnTable = new PdfPTable(1);
-
 
602
                    irnTable.setWidthPercentage(100);
-
 
603
                    irnTable.setSpacingAfter(8f);
-
 
604
 
-
 
605
                    PdfPCell irnCell = new PdfPCell();
489
                    addIrnDetails(pdfModel.getIrnModel(), rectangle, document);
606
                    irnCell.setBorder(Rectangle.BOTTOM);
-
 
607
                    irnCell.setBorderColor(MS_BORDER);
-
 
608
                    irnCell.setPadding(3f);
-
 
609
                    irnCell.addElement(new Paragraph("IRN: " + pdfModel.getIrnModel().getIrnNumber(), MS_SMALL));
-
 
610
                    irnCell.addElement(new Paragraph("Ack No: " + pdfModel.getIrnModel().getAcknowledgeNumber(), MS_SMALL));
-
 
611
                    irnCell.addElement(new Paragraph("Ack Date: " + FormattingUtils.format(pdfModel.getIrnModel().getAcknowledgeDate()), MS_SMALL));
-
 
612
                    irnTable.addCell(irnCell);
-
 
613
 
-
 
614
                    document.add(irnTable);
490
                }
615
                }
491
 
616
 
492
                // Customer and Retailer details (same as regular invoice)
617
                // ── Supplier (left) + Invoice Details (right) ──────────────
493
                PdfPTable tableCustomerRetailer = new PdfPTable(2);
618
                PdfPTable headerTable = new PdfPTable(2);
494
                tableCustomerRetailer.setWidthPercentage(90);
619
                headerTable.setWidthPercentage(100);
495
                tableCustomerRetailer.getDefaultCell().setBorder(Rectangle.NO_BORDER);
620
                headerTable.setWidths(new float[]{1f, 1f});
-
 
621
                headerTable.setSpacingAfter(8f);
496
 
622
 
497
                PdfPCell columnCustomerInfo = new PdfPCell();
623
                PdfPCell supplierCell = new PdfPCell();
-
 
624
                supplierCell.setBorder(Rectangle.NO_BORDER);
-
 
625
                supplierCell.setPadding(4f);
-
 
626
                supplierCell.setPaddingLeft(0f);
498
                columnCustomerInfo.addElement(new Paragraph("Buyer Details", FONT_BOLD));
627
                supplierCell.addElement(new Paragraph("SUPPLIER DETAILS", MS_SECTION));
-
 
628
                supplierCell.addElement(msSpacer(2f));
-
 
629
                supplierCell.addElement(new Paragraph(StringUtils.capitalize(retailer.getAddress().getName()), MS_BOLD));
499
                columnCustomerInfo.addElement(new Paragraph(
630
                supplierCell.addElement(new Paragraph(
-
 
631
                        StringUtils.capitalize(retailer.getAddress().getLine1()) + ", "
-
 
632
                        + StringUtils.capitalize(retailer.getAddress().getLine2()) + ", "
-
 
633
                        + StringUtils.capitalize(retailer.getAddress().getCity()) + " - "
-
 
634
                        + retailer.getAddress().getPinCode(), MS_NORMAL));
-
 
635
                supplierCell.addElement(new Paragraph("GSTIN: " + retailer.getGstNumber(), MS_NORMAL));
-
 
636
                supplierCell.addElement(new Paragraph("State: " + retailer.getAddress().getState()
-
 
637
                        + "  |  Code: " + stateCode, MS_NORMAL));
-
 
638
                headerTable.addCell(supplierCell);
-
 
639
 
-
 
640
                String invoiceLabel = (titleText.contains("CHALLAN")) ? "DC No:" : "Invoice No:";
-
 
641
                PdfPCell invoiceCell = new PdfPCell();
-
 
642
                invoiceCell.setBorder(Rectangle.NO_BORDER);
-
 
643
                invoiceCell.setPadding(4f);
-
 
644
                invoiceCell.setPaddingRight(0f);
-
 
645
                invoiceCell.addElement(msRightPara("INVOICE DETAILS", MS_SECTION));
-
 
646
                invoiceCell.addElement(msSpacer(2f));
-
 
647
                invoiceCell.addElement(msRightPara(invoiceLabel + " " + pdfModel.getInvoiceNumber(), MS_BOLD));
-
 
648
                invoiceCell.addElement(msRightPara("Date: " + pdfModel.getInvoiceDate(), MS_NORMAL));
-
 
649
                String supplyType = stateGst ? "Intra-state" : "Inter-state";
500
                        StringUtils.capitalize(customer.getAddress().getName() + (customer.getAddress().getLastName() == null ? "" : " " + customer.getAddress().getLastName())), FONT_NORMAL));
650
                invoiceCell.addElement(msRightPara("Place of supply: " + customer.getAddress().getState()
-
 
651
                        + " (" + pdfModel.getCustomerAddressStateCode() + ")", MS_NORMAL));
-
 
652
                invoiceCell.addElement(msRightPara("Supply type: " + supplyType, MS_NORMAL));
501
                if (customer.getAddress() != null) {
653
                headerTable.addCell(invoiceCell);
-
 
654
 
-
 
655
                document.add(headerTable);
-
 
656
 
-
 
657
                // ── Buyer Details ──────────────────────────────────────────
-
 
658
                PdfPTable buyerTable = new PdfPTable(1);
-
 
659
                buyerTable.setWidthPercentage(100);
-
 
660
                buyerTable.setSpacingAfter(8f);
-
 
661
 
-
 
662
                PdfPCell buyerCell = new PdfPCell();
-
 
663
                buyerCell.setBorder(Rectangle.BOX);
-
 
664
                buyerCell.setBorderColor(MS_BORDER);
-
 
665
                buyerCell.setPadding(5f);
-
 
666
                buyerCell.addElement(new Paragraph("BUYER DETAILS", MS_SECTION));
-
 
667
                buyerCell.addElement(msSpacer(2f));
-
 
668
                String buyerName = StringUtils.capitalize(customer.getAddress().getName()
502
                    if ((customer.getAddress().getLine1() != null && !customer.getAddress().getLine1().trim().isEmpty()) || (customer.getAddress().getLine2() != null && !customer.getAddress().getLine2().trim().isEmpty())) {
669
                        + (customer.getAddress().getLastName() == null ? "" : " " + customer.getAddress().getLastName()));
-
 
670
                buyerCell.addElement(new Paragraph(buyerName, MS_BOLD));
503
                        columnCustomerInfo.addElement(new Paragraph(StringUtils.capitalize(customer.getAddress().getLine1()) + ", " + StringUtils.capitalize(customer.getAddress().getLine2()), FONT_NORMAL));
671
                if (customer.getAddress().getLine1() != null || customer.getAddress().getLine2() != null) {
504
                    }
672
                    String addr = "";
505
                    if ((customer.getAddress().getCity() != null && !customer.getAddress().getCity().trim().isEmpty()) || (customer.getAddress().getState() != null && !customer.getAddress().getState().trim().isEmpty())) {
673
                    if (customer.getAddress().getLine1() != null) addr += StringUtils.capitalize(customer.getAddress().getLine1());
506
                        columnCustomerInfo.addElement(new Paragraph(StringUtils.capitalize(customer.getAddress().getCity()) + ", " + StringUtils.capitalize(customer.getAddress().getState()) + "(" + pdfModel.getCustomerAddressStateCode() + ")" + "\n" + customer.getAddress().getPinCode(), FONT_NORMAL));
674
                    if (customer.getAddress().getLine2() != null) addr += ", " + StringUtils.capitalize(customer.getAddress().getLine2());
507
                    }
675
                    buyerCell.addElement(new Paragraph(addr, MS_NORMAL));
508
                }
676
                }
-
 
677
                String buyerLocation = StringUtils.capitalize(customer.getAddress().getCity()) + ", "
509
                columnCustomerInfo.addElement(new Paragraph("Mobile - " + customer.getAddress().getPhoneNumber(), FONT_NORMAL));
678
                        + customer.getAddress().getState() + " - " + customer.getAddress().getPinCode();
-
 
679
                buyerCell.addElement(new Paragraph(buyerLocation, MS_NORMAL));
-
 
680
                String buyerGstLine = "";
510
                if (customer.getGstNumber() != null && !customer.getGstNumber().isEmpty()) {
681
                if (customer.getGstNumber() != null && !customer.getGstNumber().isEmpty()) {
-
 
682
                    buyerGstLine += "GSTIN: " + customer.getGstNumber() + "  |  ";
-
 
683
                }
-
 
684
                buyerGstLine += "State: " + customer.getAddress().getState()
-
 
685
                        + " (Code: " + pdfModel.getCustomerAddressStateCode() + ")";
-
 
686
                buyerCell.addElement(new Paragraph(buyerGstLine, MS_NORMAL));
-
 
687
                if (customer.getAddress().getPhoneNumber() != null) {
511
                    columnCustomerInfo.addElement(new Paragraph("GST Number - " + customer.getGstNumber(), FONT_NORMAL));
688
                    buyerCell.addElement(new Paragraph("Mobile: " + customer.getAddress().getPhoneNumber(), MS_NORMAL));
512
                }
689
                }
-
 
690
                buyerTable.addCell(buyerCell);
513
                columnCustomerInfo.setBorder(Rectangle.NO_BORDER);
691
                document.add(buyerTable);
514
 
692
 
515
                PdfPCell columnRetailerInfo = new PdfPCell();
-
 
516
                columnRetailerInfo.addElement(new Paragraph("Supplier Details", FONT_BOLD));
-
 
517
                columnRetailerInfo.addElement(new Paragraph(StringUtils.capitalize(retailer.getAddress().getName()), FONT_BOLD));
-
 
518
                columnRetailerInfo.addElement(new Paragraph(StringUtils.capitalize(retailer.getAddress().getLine1()) + ", " + StringUtils.capitalize(retailer.getAddress().getLine2()) + ", " + StringUtils.capitalize(retailer.getAddress().getCity()) + "-" + retailer.getAddress().getPinCode() + ", " + retailer.getAddress().getState() + "(" + (stateGst ? pdfModel.getCustomerAddressStateCode() : pdfModel.getPartnerAddressStateCode()) + ")", FONT_BOLD));
693
                // ── Item Table ─────────────────────────────────────────────
519
                columnRetailerInfo.addElement(new Paragraph("Contact No.- " + retailer.getAddress().getPhoneNumber(), FONT_BOLD));
-
 
520
                columnRetailerInfo.addElement(new Paragraph("GST NO. " + retailer.getGstNumber(), FONT_BOLD));
-
 
521
                columnRetailerInfo.setBorder(Rectangle.NO_BORDER);
-
 
522
 
-
 
523
                PdfPTable tableInvoiceDateRetailer = new PdfPTable(1);
-
 
524
                tableInvoiceDateRetailer.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
525
 
-
 
526
                PdfPTable tableInvoiceDate = new PdfPTable(2);
694
                PdfPTable itemTable;
527
                tableInvoiceDate.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
528
 
-
 
529
                PdfPCell invoiceNumberKey = new PdfPCell(new Paragraph("Invoice No:", FONT_NORMAL));
-
 
530
                invoiceNumberKey.setBorder(Rectangle.NO_BORDER);
695
                // 10 columns for both margin and regular
531
                PdfPCell invoiceNumberValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceNumber(), FONT_NORMAL));
-
 
532
                invoiceNumberValue.setBorder(Rectangle.NO_BORDER);
-
 
533
                PdfPCell dateKey = new PdfPCell(new Paragraph("Date:", FONT_NORMAL));
-
 
534
                dateKey.setBorder(Rectangle.NO_BORDER);
696
                itemTable = new PdfPTable(10);
535
                PdfPCell dateValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceDate(), FONT_NORMAL));
697
                itemTable.setWidths(new float[]{0.8f, 1.0f, 3.8f, 1.2f, 0.7f, 2.0f, 2.0f, 2.4f, 1.6f, 1.6f});
536
                dateValue.setBorder(Rectangle.NO_BORDER);
698
                itemTable.setWidthPercentage(100);
537
 
-
 
538
                tableInvoiceDate.addCell(invoiceNumberKey);
-
 
539
                tableInvoiceDate.addCell(invoiceNumberValue);
-
 
540
                tableInvoiceDate.addCell(dateKey);
699
                itemTable.setSpacingAfter(0f);
541
                tableInvoiceDate.addCell(dateValue);
700
                itemTable.setHeaderRows(1);
542
                tableInvoiceDateRetailer.addCell(tableInvoiceDate);
-
 
543
                tableInvoiceDateRetailer.addCell(columnRetailerInfo);
-
 
544
 
701
 
545
                tableCustomerRetailer.addCell(columnCustomerInfo);
702
                msAddHeader(itemTable, "S.No.",      Element.ALIGN_CENTER);
546
                tableCustomerRetailer.addCell(tableInvoiceDateRetailer);
703
                msAddHeader(itemTable, "Order Id",   Element.ALIGN_CENTER);
547
 
-
 
548
                // Item table — margin scheme columns (no purchase price disclosed)
704
                msAddHeader(itemTable, "Description of Goods", Element.ALIGN_LEFT);
549
                PdfPTable orders = new PdfPTable(marginSchemeWidths.length);
705
                msAddHeader(itemTable, "HSN\nCode",  Element.ALIGN_CENTER);
550
                orders.setWidths(marginSchemeWidths);
706
                msAddHeader(itemTable, "Qty",        Element.ALIGN_CENTER);
551
                orders.setWidthPercentage(90);
-
 
552
 
707
 
553
                orders.addCell(new Paragraph("S.No", FONT_BOLD));
-
 
554
                orders.addCell(new Paragraph("Description of Goods", FONT_BOLD));
-
 
555
                orders.addCell(new Paragraph("HSN\nCode", FONT_BOLD));
708
                msAddHeader(itemTable, "Rate\n(Rs.)", Element.ALIGN_RIGHT);
556
                orders.addCell(new Paragraph("Qty", FONT_BOLD));
-
 
557
                orders.addCell(new Paragraph("Gross Sale\nValue (Rs.)", FONT_BOLD));
-
 
558
                orders.addCell(new Paragraph("Taxable Value\n- Margin (Rs.)", FONT_BOLD));
709
                msAddHeader(itemTable, isMargin ? "Taxable Value\n- Margin (Rs.)" : "Taxable\nValue (Rs.)", Element.ALIGN_RIGHT);
559
                String taxRateHeader = stateGst ? "CGST+SGST\nRate" : "IGST\nRate";
710
                msAddHeader(itemTable, "Tax\nRate",             Element.ALIGN_CENTER);
560
                orders.addCell(new Paragraph(taxRateHeader, FONT_BOLD));
711
                msAddHeader(itemTable, "Tax\n(Rs.)",         Element.ALIGN_RIGHT);
561
                orders.addCell(new Paragraph("Tax Amount\n(Rs.)", FONT_BOLD));
712
                msAddHeader(itemTable, "Total\n(Rs.)",       Element.ALIGN_RIGHT);
562
                orders.setHeaderRows(1);
-
 
563
 
713
 
-
 
714
                float totalGrossSale = 0, totalTaxable = 0, totalTaxAmount = 0, totalNetAmount = 0;
564
                float totalGrossSale = 0, totalMargin = 0, totalTaxAmount = 0;
715
                float totalCgst = 0, totalSgst = 0, totalIgst = 0;
565
                int index = 1;
716
                int index = 1;
566
                for (CustomOrderItem orderItem : orderItems) {
717
                for (CustomOrderItem orderItem : orderItems) {
567
                    float taxAmount = orderItem.getCgstAmount() + orderItem.getSgstAmount() + orderItem.getIgstAmount();
718
                    float taxAmount = orderItem.getCgstAmount() + orderItem.getSgstAmount() + orderItem.getIgstAmount();
568
 
719
 
569
                    orders.addCell(new Paragraph(String.valueOf(index++), FONT_NORMAL));
720
                    msAddDataCell(itemTable, String.valueOf(index++),                    Element.ALIGN_CENTER, false, false);
570
                    orders.addCell(new Paragraph(orderItem.getDescription(), FONT_NORMAL));
-
 
571
                    orders.addCell(new Paragraph(orderItem.getHsnCode(), FONT_NORMAL));
721
                    msAddDataCell(itemTable, String.valueOf(orderItem.getOrderId()),     Element.ALIGN_CENTER, false, false);
572
                    orders.addCell(new Paragraph(String.valueOf(orderItem.getQuantity()), FONT_NORMAL));
722
                    msAddDataCell(itemTable, orderItem.getDescription(),                 Element.ALIGN_LEFT,   false, false);
573
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getNetAmount()), FONT_NORMAL));
723
                    msAddDataCell(itemTable, orderItem.getHsnCode(),                     Element.ALIGN_CENTER, false, false);
574
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getAmount()), FONT_NORMAL));
724
                    msAddDataCell(itemTable, String.valueOf(orderItem.getQuantity()),     Element.ALIGN_CENTER, false, false);
575
 
725
 
-
 
726
                    if (isMargin) {
-
 
727
                        float grossSaleValue = orderItem.getNetAmount() - taxAmount;
-
 
728
                        msAddDataCell(itemTable, String.format("%.2f", grossSaleValue),          Element.ALIGN_RIGHT, false, false);
-
 
729
                        totalGrossSale += grossSaleValue;
-
 
730
                    } else {
-
 
731
                        msAddDataCell(itemTable, String.format("%.2f", orderItem.getRate()),      Element.ALIGN_RIGHT, false, false);
-
 
732
                    }
-
 
733
                    totalNetAmount += orderItem.getNetAmount();
-
 
734
                    msAddDataCell(itemTable, String.format("%.2f", orderItem.getAmount()),        Element.ALIGN_RIGHT, false, false);
576
                    String taxRateText;
735
                    String rateText;
577
                    if (stateGst) {
736
                    if (stateGst) {
578
                        taxRateText = String.format("CGST %.1f%%\n+ SGST %.1f%%", orderItem.getCgstRate(), orderItem.getSgstRate());
737
                        rateText = String.format("CGST %.1f%%\n+ SGST %.1f%%", orderItem.getCgstRate(), orderItem.getSgstRate());
579
                    } else {
738
                    } else {
580
                        taxRateText = String.format("IGST %.1f%%", orderItem.getIgstRate());
739
                        rateText = String.format("IGST %.1f%%", orderItem.getIgstRate());
581
                    }
740
                    }
-
 
741
                    msAddDataCell(itemTable, rateText,                                            Element.ALIGN_CENTER, false, false);
582
                    orders.addCell(new Paragraph(taxRateText, FONT_NORMAL));
742
                    msAddDataCell(itemTable, String.format("%.2f", taxAmount), Element.ALIGN_RIGHT, false, false);
583
                    orders.addCell(new Paragraph(String.format("%.2f", taxAmount), FONT_NORMAL));
743
                    msAddDataCell(itemTable, String.format("%.0f", orderItem.getNetAmount()), Element.ALIGN_RIGHT, false, false);
584
 
744
 
585
                    totalGrossSale += orderItem.getNetAmount();
-
 
586
                    totalMargin += orderItem.getAmount();
745
                    totalTaxable += orderItem.getAmount();
587
                    totalTaxAmount += taxAmount;
746
                    totalTaxAmount += taxAmount;
-
 
747
                    totalCgst += orderItem.getCgstAmount();
-
 
748
                    totalSgst += orderItem.getSgstAmount();
-
 
749
                    totalIgst += orderItem.getIgstAmount();
588
                }
750
                }
589
 
751
 
590
                // Total row
752
                // Total row
-
 
753
                int totalPcs = 0;
591
                PdfPCell totalLabelCell = new PdfPCell(new Paragraph("Total", FONT_BOLD));
754
                for (CustomOrderItem oi : orderItems) totalPcs += oi.getQuantity();
592
                totalLabelCell.setColspan(4);
755
                int totalColSpan = 5;
593
                orders.addCell(totalLabelCell);
756
                PdfPCell totalSpan = new PdfPCell(new Phrase("Total " + totalPcs + " pc(s)", MS_BOLD));
594
                orders.addCell(new Paragraph(String.format("%.2f", totalGrossSale), FONT_BOLD));
757
                totalSpan.setColspan(totalColSpan);
595
                orders.addCell(new Paragraph(String.format("%.2f", totalMargin), FONT_BOLD));
758
                totalSpan.setHorizontalAlignment(Element.ALIGN_RIGHT);
596
                PdfPCell dashCell = new PdfPCell(new Paragraph("\u2014", FONT_BOLD));
759
                totalSpan.setBorderColor(MS_BORDER);
597
                dashCell.setHorizontalAlignment(Element.ALIGN_CENTER);
760
                totalSpan.setBackgroundColor(MS_TOTAL_BG);
598
                orders.addCell(dashCell);
761
                totalSpan.setPadding(4f);
599
                orders.addCell(new Paragraph(String.format("%.2f", totalTaxAmount), FONT_BOLD));
762
                itemTable.addCell(totalSpan);
600
 
763
 
601
                // Logo and layout
-
 
602
                iconImg.setAbsolutePosition(25, rectangle.getHeight() - 100);
764
                msAddDataCell(itemTable, isMargin ? String.format("%.2f", totalGrossSale) : "", Element.ALIGN_RIGHT, true, true);
603
                iconImg.scalePercent(30);
-
 
604
                document.add(iconImg);
-
 
605
                document.add(Chunk.NEWLINE);
765
                msAddDataCell(itemTable, String.format("%.2f", totalTaxable),     Element.ALIGN_RIGHT, true, true);
606
                document.add(Chunk.NEWLINE);
766
                msAddDataCell(itemTable, "\u2014",                                Element.ALIGN_CENTER, false, true);
607
                document.add(tableCustomerRetailer);
767
                msAddDataCell(itemTable, String.format("%.2f", totalTaxAmount), Element.ALIGN_RIGHT, true, true);
608
                document.add(Chunk.NEWLINE);
768
                msAddDataCell(itemTable, String.format("%.0f", totalNetAmount), Element.ALIGN_RIGHT, true, true);
-
 
769
 
609
                document.add(orders);
770
                document.add(itemTable);
610
 
771
 
611
                // Declaration box
772
                // ── Bottom: Info (left) + Summary (right) + Amount in words ──
612
                document.add(Chunk.NEWLINE);
773
                float totalInvoiceValue = isMargin ? (totalGrossSale + totalTaxAmount) : totalNetAmount;
-
 
774
 
613
                PdfPTable declarationTable = new PdfPTable(1);
775
                PdfPTable bottomTable = new PdfPTable(2);
614
                declarationTable.setWidthPercentage(90);
776
                bottomTable.setWidthPercentage(100);
615
                Font declarationFont = new Font(Font.FontFamily.HELVETICA, 9, Font.BOLD);
777
                bottomTable.setWidths(new float[]{1.15f, 1f});
616
                PdfPCell declarationCell = new PdfPCell();
778
                bottomTable.setSpacingBefore(0f);
617
                declarationCell.addElement(new Paragraph("Declaration", declarationFont));
779
                bottomTable.setSpacingAfter(0f);
-
 
780
 
618
                Font declarationBodyFont = new Font(Font.FontFamily.TIMES_ROMAN, 9, Font.NORMAL);
781
                // Left: Declaration (margin) or Tax Summary (regular)
619
                declarationCell.addElement(new Paragraph(
782
                PdfPCell leftCell = new PdfPCell();
620
                        "GST is payable on margin scheme basis under Section 2(27) read with Rule 32(5) of CGST Rules, 2017. " +
-
 
621
                        "The buyer is NOT eligible to claim Input Tax Credit on this invoice.", declarationBodyFont));
-
 
622
                declarationCell.setPadding(8);
783
                leftCell.setBorder(Rectangle.BOX);
623
                declarationCell.setBackgroundColor(new BaseColor(245, 245, 245));
784
                leftCell.setBorderColor(MS_BORDER);
624
                declarationTable.addCell(declarationCell);
785
                leftCell.setPadding(6f);
625
                document.add(declarationTable);
786
                leftCell.setPaddingRight(8f);
626
 
787
 
627
                // Summary table: Total Selling Price, GST on Margin, Total Invoice Value
-
 
628
                document.add(Chunk.NEWLINE);
788
                if (isMargin) {
629
                PdfPTable summaryTable = new PdfPTable(2);
789
                    leftCell.addElement(new Paragraph("Declaration", MS_SMALL_BOLD));
630
                summaryTable.setWidthPercentage(50);
790
                    leftCell.addElement(msSpacer(3f));
631
                summaryTable.setHorizontalAlignment(Element.ALIGN_RIGHT);
791
                    leftCell.addElement(new Paragraph(
632
                summaryTable.setWidths(new float[]{3f, 2f});
792
                            "GST is payable on margin scheme basis under Section 2(27) read with "
633
 
-
 
634
                PdfPCell slCell = new PdfPCell(new Paragraph("Total Selling Price", FONT_BOLD));
793
                            + "Rule 32(5) of CGST Rules, 2017.", MS_SMALL));
635
                slCell.setPadding(4);
794
                    leftCell.addElement(msSpacer(4f));
636
                summaryTable.addCell(slCell);
795
                    leftCell.addElement(new Paragraph(
637
                PdfPCell slValCell = new PdfPCell(new Paragraph(String.format("Rs. %.2f", totalGrossSale), FONT_NORMAL));
796
                            "The buyer is NOT eligible to claim Input Tax Credit on this invoice.", MS_SMALL_BOLD));
638
                slValCell.setPadding(4);
797
                }
639
                summaryTable.addCell(slValCell);
798
                bottomTable.addCell(leftCell);
640
 
799
 
-
 
800
                // Right: Summary totals
641
                PdfPCell gstCell = new PdfPCell(new Paragraph("GST on Margin", FONT_BOLD));
801
                PdfPCell summaryCell = new PdfPCell();
642
                gstCell.setPadding(4);
802
                summaryCell.setBorder(Rectangle.BOX);
-
 
803
                summaryCell.setBorderColor(MS_BORDER);
643
                summaryTable.addCell(gstCell);
804
                summaryCell.setPadding(0f);
644
                PdfPCell gstValCell = new PdfPCell(new Paragraph(String.format("Rs. %.2f", totalTaxAmount), FONT_NORMAL));
805
                PdfPTable sumTable = new PdfPTable(2);
645
                gstValCell.setPadding(4);
806
                sumTable.setWidthPercentage(100);
646
                summaryTable.addCell(gstValCell);
807
                sumTable.setWidths(new float[]{1.4f, 1f});
647
 
808
 
-
 
809
                if (isMargin) {
648
                Font grandTotalFont = new Font(Font.FontFamily.HELVETICA, 11, Font.BOLD);
810
                    msAddSummaryRow(sumTable, "Total Selling Price", String.format("Rs. %.2f", totalGrossSale), false);
649
                PdfPCell gtCell = new PdfPCell(new Paragraph("Total Invoice Value", grandTotalFont));
811
                    msAddSummaryRow(sumTable, "GST on Margin", String.format("Rs. %.2f", totalTaxAmount), false);
650
                gtCell.setPadding(5);
812
                } else {
651
                gtCell.setBackgroundColor(new BaseColor(230, 230, 230));
813
                    msAddSummaryRow(sumTable, "Total Taxable Value", String.format("Rs. %.2f", totalTaxable), false);
652
                summaryTable.addCell(gtCell);
-
 
653
                PdfPCell gtValCell = new PdfPCell(new Paragraph(String.format("Rs. %.2f", pdfModel.getTotalAmount()), grandTotalFont));
814
                    msAddSummaryRow(sumTable, "Total GST", String.format("Rs. %.2f", totalTaxAmount), false);
654
                gtValCell.setPadding(5);
815
                }
655
                gtValCell.setBackgroundColor(new BaseColor(230, 230, 230));
816
                msAddSummaryRow(sumTable, "Total Invoice Value", String.format("Rs. %.2f", totalInvoiceValue), true);
656
                summaryTable.addCell(gtValCell);
817
                summaryCell.addElement(sumTable);
657
 
-
 
658
                document.add(summaryTable);
818
                bottomTable.addCell(summaryCell);
659
 
819
 
660
                // Amount in words
820
                // Row 2: empty (left) + Amount in words (right)
661
                PdfPTable amountInWordsTable = new PdfPTable(1);
821
                PdfPCell emptyLeft = new PdfPCell(new Phrase("", MS_NORMAL));
662
                amountInWordsTable.setWidthPercentage(90);
822
                emptyLeft.setBorder(Rectangle.NO_BORDER);
663
                String amountInWords = toAmountInWords(pdfModel.getTotalAmount());
823
                bottomTable.addCell(emptyLeft);
664
                PdfPCell wordsCell = new PdfPCell(new Paragraph(amountInWords, FONT_BOLD));
824
                PdfPCell wordsCell = new PdfPCell(new Phrase(toAmountInWords(totalInvoiceValue), MS_ITALIC));
-
 
825
                wordsCell.setBorder(Rectangle.BOX);
-
 
826
                wordsCell.setBorderColor(MS_BORDER);
665
                wordsCell.setPadding(5);
827
                wordsCell.setPadding(5f);
666
                amountInWordsTable.addCell(wordsCell);
828
                wordsCell.setBackgroundColor(MS_TOTAL_BG);
667
                document.add(amountInWordsTable);
829
                bottomTable.addCell(wordsCell);
668
 
830
 
669
                // Payment options
831
                document.add(bottomTable);
-
 
832
 
-
 
833
                // ── Payment Options ────────────────────────────────────────
670
                if (pdfModel.getPaymentOptions() != null) {
834
                if (pdfModel.getPaymentOptions() != null) {
671
                    PdfPTable paidAmountTable = new PdfPTable(2);
835
                    PdfPTable paidTable = new PdfPTable(2);
672
                    paidAmountTable.setWidthPercentage(90);
836
                    paidTable.setWidthPercentage(100);
673
                    paidAmountTable.setWidths(new float[]{7.1f, 0.9f});
837
                    paidTable.setWidths(new float[]{7f, 1f});
674
                    float totalPaidValue = 0;
838
                    float totalPaidValue = 0;
675
                    for (CustomPaymentOption paymentOption : pdfModel.getPaymentOptions()) {
839
                    for (CustomPaymentOption po : pdfModel.getPaymentOptions()) {
676
                        if (!"CASH DISCOUNT".equals(paymentOption.getPaymentOption())) {
840
                        if (!"CASH DISCOUNT".equals(po.getPaymentOption())) {
677
                            PdfPCell cell = new PdfPCell(new Paragraph(10, "Paid Through " + paymentOption.getPaymentOption(), FONT_BOLD));
841
                            PdfPCell lbl = new PdfPCell(new Phrase("Paid Through " + po.getPaymentOption(), MS_BOLD));
678
                            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
842
                            lbl.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
843
                            lbl.setBorderColor(MS_BORDER);
679
                            cell.setPadding(5);
844
                            lbl.setPadding(4f);
680
                            paidAmountTable.addCell(cell);
845
                            paidTable.addCell(lbl);
681
 
-
 
682
                            PdfPCell cell1 = new PdfPCell(new Paragraph(10, FormattingUtils.formatDecimal(paymentOption.getAmount()), FONT_BOLD));
846
                            PdfPCell val = new PdfPCell(new Phrase(FormattingUtils.formatDecimal(po.getAmount()), MS_BOLD));
-
 
847
                            val.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
848
                            val.setBorderColor(MS_BORDER);
683
                            cell1.setPadding(5);
849
                            val.setPadding(4f);
684
                            paidAmountTable.addCell(cell1);
850
                            paidTable.addCell(val);
685
                            totalPaidValue += paymentOption.getAmount();
851
                            totalPaidValue += po.getAmount();
686
                        }
852
                        }
687
                    }
853
                    }
688
                    PdfPCell totalPaidCell = new PdfPCell(new Paragraph(10, "Total Paid", FONT_BOLD));
854
                    PdfPCell tpLbl = new PdfPCell(new Phrase("Total Paid", MS_BOLD));
689
                    totalPaidCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
855
                    tpLbl.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
856
                    tpLbl.setBorderColor(MS_BORDER);
690
                    totalPaidCell.setPadding(5);
857
                    tpLbl.setPadding(4f);
691
                    paidAmountTable.addCell(totalPaidCell);
858
                    paidTable.addCell(tpLbl);
692
 
-
 
693
                    PdfPCell totalPaidValueCell = new PdfPCell(new Paragraph(10, FormattingUtils.formatDecimal(totalPaidValue), FONT_BOLD));
859
                    PdfPCell tpVal = new PdfPCell(new Phrase(FormattingUtils.formatDecimal(totalPaidValue), MS_BOLD));
-
 
860
                    tpVal.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
861
                    tpVal.setBorderColor(MS_BORDER);
694
                    totalPaidValueCell.setPadding(5);
862
                    tpVal.setPadding(4f);
695
                    paidAmountTable.addCell(totalPaidValueCell);
863
                    paidTable.addCell(tpVal);
696
                    document.add(paidAmountTable);
864
                    document.add(paidTable);
697
                }
865
                }
698
 
-
 
699
                // Computer generated note
-
 
700
                Paragraph autoGenerateParagraph = new Paragraph("Note - This is computer generated Invoice, no signature is required", FONT_NORMAL);
-
 
701
                autoGenerateParagraph.setAlignment(Element.ALIGN_CENTER);
-
 
702
                document.add(autoGenerateParagraph);
-
 
703
 
866
 
704
                // Credit terms
867
                // ── Note + Credit Terms ────────────────────────────────────
705
                if (pdfModel.getCreditTerms() != null) {
868
                Paragraph note = new Paragraph("This is a computer-generated invoice and does not require a physical signature.", MS_SMALL);
706
                    Paragraph title = new Paragraph("Credit terms :-\n", FONT_BOLD);
869
                note.setAlignment(Element.ALIGN_CENTER);
707
                    title.setIndentationLeft(25);
870
                note.setSpacingBefore(8f);
708
                    title.setIndentationRight(25);
871
                note.setSpacingAfter(4f);
709
                    document.add(title);
872
                document.add(note);
710
 
873
 
-
 
874
                if (pdfModel.getCreditTerms() != null) {
-
 
875
                    Paragraph ctTitle = new Paragraph("Credit terms:", MS_SMALL_BOLD);
711
                    StringBuffer termsBuffer = new StringBuffer();
876
                    ctTitle.setIndentationLeft(25);
-
 
877
                    document.add(ctTitle);
712
                    int count = 0;
878
                    int count = 0;
713
                    for (String creditTerm : pdfModel.getCreditTerms()) {
879
                    for (String ct : pdfModel.getCreditTerms()) {
714
                        count++;
880
                        count++;
715
                        termsBuffer.append(count).append(". ").append(creditTerm).append(".\n");
881
                        Paragraph line = new Paragraph(count + ". " + ct + ".", MS_SMALL);
-
 
882
                        line.setIndentationLeft(25);
-
 
883
                        line.setIndentationRight(25);
-
 
884
                        document.add(line);
716
                    }
885
                    }
717
                    Paragraph body = new Paragraph(termsBuffer.toString(), FONT_NORMAL);
-
 
718
                    body.setIndentationLeft(25);
-
 
719
                    body.setIndentationRight(25);
-
 
720
                    document.add(body);
-
 
721
                }
886
                }
722
 
887
 
723
                document.newPage();
888
                document.newPage();
724
 
889
 
725
                // E-Way Bill support
890
                // ── E-Way Bill ─────────────────────────────────────────────
726
                if (pdfModel.geteWayBillPdfModel() != null) {
891
                if (pdfModel.geteWayBillPdfModel() != null) {
727
                    EWayBillPDF.generateDocument(document, pdfWriter, pdfModel.geteWayBillPdfModel());
892
                    EWayBillPDF.generateDocument(document, pdfWriter, pdfModel.geteWayBillPdfModel());
728
                }
893
                }
729
            }
894
            }
730
 
895
 
731
            document.close();
896
            document.close();
732
            if (cancelledPages) {
897
            if (cancelledPages) {
733
                stampCancelled(outputStream, cancelledPageList);
898
                stampCancelled(outputStream, cancelledPageList);
734
            }
899
            }
735
        } catch (DocumentException e) {
900
        } catch (DocumentException e) {
736
            LOGGER.error("Unable to write data to margin scheme pdf file : ", e);
901
            LOGGER.error("Unable to write data to pdf file : ", e);
737
        } catch (Exception e) {
902
        } catch (Exception e) {
738
            e.printStackTrace();
903
            e.printStackTrace();
739
        }
904
        }
740
    }
905
    }
741
 
906