Subversion Repositories SmartDukaan

Rev

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

Rev 36674 Rev 37052
Line 1... Line 1...
1
package com.spice.profitmandi.common.util;
1
package com.spice.profitmandi.common.util;
2
 
2
 
3
import com.ibm.icu.text.RuleBasedNumberFormat;
3
import com.itextpdf.text.Document;
4
import com.itextpdf.text.*;
4
import com.itextpdf.text.DocumentException;
5
import com.itextpdf.text.Font.FontFamily;
5
import com.itextpdf.text.pdf.PdfCopy;
6
import com.itextpdf.text.pdf.*;
6
import com.itextpdf.text.pdf.PdfReader;
-
 
7
import com.spice.profitmandi.common.document.DocumentData;
-
 
8
import com.spice.profitmandi.common.document.DocumentDataAdapter;
-
 
9
import com.spice.profitmandi.common.document.DocumentRenderer;
7
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
10
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
8
import com.spice.profitmandi.common.model.*;
11
import com.spice.profitmandi.common.model.CreditNotePdfModel;
9
import org.apache.logging.log4j.LogManager;
12
import com.spice.profitmandi.common.model.DebitNotePdfModel;
10
import org.apache.logging.log4j.Logger;
-
 
11
import org.springframework.util.StringUtils;
13
import com.spice.profitmandi.common.model.InvoicePdfModel;
12
 
14
 
13
import java.io.ByteArrayInputStream;
15
import java.io.ByteArrayInputStream;
14
import java.io.ByteArrayOutputStream;
16
import java.io.ByteArrayOutputStream;
15
import java.io.IOException;
17
import java.io.IOException;
16
import java.io.OutputStream;
18
import java.io.OutputStream;
17
import java.net.URL;
-
 
18
import java.util.ArrayList;
19
import java.util.ArrayList;
19
import java.util.List;
20
import java.util.List;
20
import java.util.Locale;
-
 
21
 
21
 
-
 
22
/**
-
 
23
 * Entry points for invoice/note PDF generation. All A4 document rendering is delegated to
-
 
24
 * {@link DocumentRenderer} (package {@code com.spice.profitmandi.common.document}); these methods
-
 
25
 * are thin adapters kept for their existing callers. Thermal (58/80mm) printing still goes through
-
 
26
 * {@link InvoiceFormatter}.
-
 
27
 */
22
public class PdfUtils {
28
public class PdfUtils {
23
 
29
 
24
    private static final Font FONT_TITLE = new Font(Font.FontFamily.HELVETICA, 18, Font.BOLD);
-
 
25
    private static Font FONT_NORMAL = new Font(Font.FontFamily.TIMES_ROMAN, 10, Font.NORMAL);
-
 
26
    private static Font FONT_BOLD = new Font(Font.FontFamily.TIMES_ROMAN, 10, Font.BOLD);
-
 
27
    private static Font FONT_MARGIN_HEADER = new Font(Font.FontFamily.HELVETICA, 9, Font.BOLDITALIC);
-
 
28
    public static final String INVOICE_TITLE = "TAX INVOICE";
30
    public static final String INVOICE_TITLE = "TAX INVOICE";
29
    public static final String DEBIT_NOTE_TITLE = "DEBIT NOTE";
31
    public static final String DEBIT_NOTE_TITLE = "DEBIT NOTE";
30
    public static final String SECURITY_DEPOSIT = "SECURITY DEPOSIT RECEIPT";
32
    public static final String SECURITY_DEPOSIT = "SECURITY DEPOSIT RECEIPT";
31
 
33
 
32
    private static float[] igstWidthsWithDiscount = new float[]{.2f, 2.6f, 0.7f, .4f, 0.7f, 0.6f, .7f, .6f, 0.7f};
-
 
33
    private static float[] stateWidthsWithDiscount = new float[]{.2f, 2.1f, 0.7f, .3f, 0.6f, 0.5f, .7f, .6f, .6f, .7f};
-
 
34
 
-
 
35
    // Column widths without discount column (for Transaction.Order invoices)
-
 
36
    private static float[] igstWidthsNoDiscount = new float[]{.2f, 2.8f, 0.7f, .4f, 0.8f, .7f, .6f, 0.8f};
-
 
37
    private static float[] stateWidthsNoDiscount = new float[]{.2f, 2.3f, 0.7f, .4f, 0.7f, .7f, .6f, .6f, .8f};
-
 
38
 
-
 
39
    private static float[] igstWidths = new float[]{.6f, 2.6f, 0.7f, .4f, 0.7f, .7f, .6f, 0.6f, 0.9f};
-
 
40
    private static float[] stateWidths = new float[]{.6f, 2.1f, 0.7f, .3f, 0.6f, .7f, .5f, .6f, .5f, .6f, .8f};
-
 
41
 
-
 
42
    private static float[] igstWidthsCrNote = new float[]{2.6f, 0.7f, .4f, 0.7f, .7f, .6f, 0.6f, 0.9f};
-
 
43
    private static float[] stateWidthsCrNote = new float[]{2.1f, 0.7f, .3f, 0.6f, .7f, .5f, .6f, .5f, .6f, .8f};
-
 
44
 
-
 
45
    private static final Locale indianLocale = new Locale("en", "IN");
-
 
46
    private static final java.text.NumberFormat indianCurrencyFormat = java.text.NumberFormat.getCurrencyInstance(new Locale("en", "IN"));
-
 
47
 
-
 
48
    private static final Logger LOGGER = LogManager.getLogger(PdfUtils.class);
-
 
49
 
-
 
50
    private static final URL iconUrl = PdfUtils.class.getClassLoader().getResource("sdlogo.png");
-
 
51
    private static Image iconImg = null;
-
 
52
 
-
 
53
    static {
-
 
54
        try {
-
 
55
            iconImg = Image.getInstance(iconUrl);
-
 
56
        } catch (Exception e) {
-
 
57
            e.printStackTrace();
-
 
58
        }
-
 
59
    }
-
 
60
 
-
 
61
    //Debit Note generation logic has been changed
-
 
62
    //Debit Note considers price drops so amount in debit note is current price of item.
-
 
63
    //From 16Nov 2019 onwards all debit notes will be as per actuall billing value, all pricedrops
-
 
64
    //shall be rolledback or cancelled once the debit note is generated.
34
    /** A4 → full document renderer; 58/80mm → thermal formatter. */
65
 
-
 
66
    public static void generateAndWrite(List<InvoicePdfModel> pdfModels, PrinterType printerType, ByteArrayOutputStream outputStream) throws ProfitMandiBusinessException {
35
    public static void generateAndWrite(List<InvoicePdfModel> pdfModels, PrinterType printerType, ByteArrayOutputStream outputStream) throws ProfitMandiBusinessException {
67
        if (PrinterType.A4.equals(printerType)) {
36
        if (PrinterType.A4.equals(printerType)) {
68
            generateAndWrite(pdfModels, outputStream);
37
            generateAndWrite(pdfModels, outputStream);
69
        } else {
38
        } else {
70
            if (pdfModels.size() > 1) {
-
 
71
            }
-
 
72
            if (PrinterType.W80.equals(printerType)) {
39
            if (PrinterType.W80.equals(printerType)) {
73
                InvoiceFormatter.getInvoice(pdfModels.get(0), outputStream, InvoiceFormatter.WIDTH_80MM);
40
                InvoiceFormatter.getInvoice(pdfModels.get(0), outputStream, InvoiceFormatter.WIDTH_80MM);
74
            } else if (PrinterType.W58.equals(printerType)) {
41
            } else if (PrinterType.W58.equals(printerType)) {
75
                InvoiceFormatter.getInvoice(pdfModels.get(0), outputStream, InvoiceFormatter.WIDTH_58MM);
42
                InvoiceFormatter.getInvoice(pdfModels.get(0), outputStream, InvoiceFormatter.WIDTH_58MM);
76
 
-
 
77
            }
43
            }
78
        }
44
        }
79
    }
45
    }
80
 
46
 
81
 
-
 
82
    //Standard
-
 
83
    public static void generateAndWrite(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
47
    public static void generateAndWrite(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
84
        try {
-
 
85
            boolean cancelledPages = false;
-
 
86
            List<Integer> caneclledPageList = new ArrayList<>();
48
        List<DocumentData> docs = new ArrayList<>();
87
            Document document = new Document();
-
 
88
            document.setMargins(0, 0, 25, 0);
-
 
89
            PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream);
-
 
90
            document.open();
-
 
91
            for (InvoicePdfModel pdfModel : pdfModels) {
-
 
92
                CustomCustomer customer = pdfModel.getCustomer();
-
 
93
                CustomRetailer retailer = pdfModel.getRetailer();
-
 
94
                boolean stateGst = false;
-
 
95
                if (customer.getAddress().getState().equals(retailer.getAddress().getState())) {
-
 
96
                    stateGst = true;
-
 
97
                }
-
 
98
                List<CustomOrderItem> orderItems = pdfModel.getOrderItems();
-
 
99
                if (pdfModel.isCancelled()) {
-
 
100
                    caneclledPageList.add(1);
-
 
101
                    cancelledPages = true;
-
 
102
                } else {
-
 
103
                    caneclledPageList.add(0);
-
 
104
                }
-
 
105
                document.addTitle(pdfModel.getTitle());
-
 
106
                document.addAuthor(pdfModel.getAuther());
-
 
107
 
-
 
108
                String titleText = pdfModel.getTitle() != null ? pdfModel.getTitle().toUpperCase() : INVOICE_TITLE;
-
 
109
                Paragraph paragraphTitle = new Paragraph(titleText, FONT_TITLE);
-
 
110
                paragraphTitle.setAlignment(Element.ALIGN_CENTER);
-
 
111
 
-
 
112
                document.add(paragraphTitle);
-
 
113
 
-
 
114
                Rectangle rectangle = document.getPageSize();
-
 
115
 
-
 
116
                if (pdfModel.getIrnModel() != null) {
-
 
117
                    addIrnDetails(pdfModel.getIrnModel(), rectangle, document);
-
 
118
                }
-
 
119
 
-
 
120
 
-
 
121
                PdfPTable tableCustomerRetailer = new PdfPTable(2);
-
 
122
                tableCustomerRetailer.setWidthPercentage(90);
-
 
123
                tableCustomerRetailer.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
124
                PdfPCell columnCustomerInfo = new PdfPCell();
-
 
125
                columnCustomerInfo.addElement(new Paragraph("Customer Details", FONT_BOLD));
-
 
126
                columnCustomerInfo.addElement(new Paragraph(
-
 
127
                        StringUtils.capitalize(customer.getAddress().getName() + (customer.getAddress().getLastName() == null ? "" : " " + customer.getAddress().getLastName())), FONT_NORMAL));
-
 
128
                if (customer.getAddress() != null) {
-
 
129
                    if ((customer.getAddress().getLine1() != null && !customer.getAddress().getLine1().trim().isEmpty()) || (customer.getAddress().getLine2() != null && !customer.getAddress().getLine2().trim().isEmpty())) {
-
 
130
                        columnCustomerInfo.addElement(new Paragraph(StringUtils.capitalize(customer.getAddress().getLine1()) + ", " + StringUtils.capitalize(customer.getAddress().getLine2()), FONT_NORMAL));
-
 
131
                    }
-
 
132
                    if ((customer.getAddress().getCity() != null && !customer.getAddress().getCity().trim().isEmpty()) || (customer.getAddress().getState() != null && !customer.getAddress().getState().trim().isEmpty())) {
-
 
133
                        columnCustomerInfo.addElement(new Paragraph(StringUtils.capitalize(customer.getAddress().getCity()) + ", " + StringUtils.capitalize(customer.getAddress().getState()) + "(" + pdfModel.getCustomerAddressStateCode() + ")" + "\n" + customer.getAddress().getPinCode(), FONT_NORMAL));
49
        for (InvoicePdfModel m : pdfModels) docs.add(DocumentDataAdapter.from(m));
134
                    }
-
 
135
                }
-
 
136
 
-
 
137
                columnCustomerInfo.addElement(new Paragraph("Mobile - " + customer.getAddress().getPhoneNumber(), FONT_NORMAL));
-
 
138
                if (customer.getGstNumber() != null && !customer.getGstNumber().isEmpty()) {
-
 
139
                    columnCustomerInfo.addElement(new Paragraph("GST Number - " + customer.getGstNumber(), FONT_NORMAL));
-
 
140
                }
-
 
141
                columnCustomerInfo.setBorder(Rectangle.NO_BORDER);
-
 
142
                PdfPCell columnRetailerInfo = new PdfPCell();
-
 
143
                columnRetailerInfo.addElement(new Paragraph(StringUtils.capitalize(retailer.getAddress().getName()), FONT_BOLD));
-
 
144
                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));
50
        new DocumentRenderer().render(docs, outputStream);
145
                columnRetailerInfo.addElement(new Paragraph("Contact No.- " + retailer.getAddress().getPhoneNumber(), FONT_BOLD));
-
 
146
                columnRetailerInfo.addElement(new Paragraph("GST NO. " + retailer.getGstNumber(), FONT_BOLD));
-
 
147
                columnRetailerInfo.setBorder(Rectangle.NO_BORDER);
-
 
148
 
-
 
149
                PdfPTable tableInvoiceDateRetailer = new PdfPTable(1);
-
 
150
                tableInvoiceDateRetailer.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
151
 
-
 
152
                PdfPTable tableInvoiceDate = new PdfPTable(2);
-
 
153
                tableInvoiceDate.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
154
 
-
 
155
                String invoiceLabel = pdfModel.getTitle() != null && pdfModel.getTitle().toLowerCase().contains("challan") ? "DC No:" : "Invoice No:";
-
 
156
                PdfPCell invoiceNumberKey = new PdfPCell(new Paragraph(invoiceLabel, FONT_NORMAL));
-
 
157
                invoiceNumberKey.setBorder(Rectangle.NO_BORDER);
-
 
158
 
-
 
159
                PdfPCell invoiceNumberValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceNumber(), FONT_NORMAL));
-
 
160
                invoiceNumberValue.setBorder(Rectangle.NO_BORDER);
-
 
161
 
-
 
162
                PdfPCell dateKey = new PdfPCell(new Paragraph("Date:", FONT_NORMAL));
-
 
163
                dateKey.setBorder(Rectangle.NO_BORDER);
-
 
164
 
-
 
165
                PdfPCell dateValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceDate(), FONT_NORMAL));
-
 
166
                dateValue.setBorder(Rectangle.NO_BORDER);
-
 
167
                tableInvoiceDate.addCell(invoiceNumberKey);
-
 
168
                tableInvoiceDate.addCell(invoiceNumberValue);
-
 
169
                tableInvoiceDate.addCell(dateKey);
-
 
170
                tableInvoiceDate.addCell(dateValue);
-
 
171
                tableInvoiceDateRetailer.addCell(tableInvoiceDate);
-
 
172
                tableInvoiceDateRetailer.addCell(columnRetailerInfo);
-
 
173
 
-
 
174
                tableCustomerRetailer.addCell(columnCustomerInfo);
-
 
175
                tableCustomerRetailer.addCell(tableInvoiceDateRetailer);
-
 
176
 
-
 
177
                boolean showDiscount = pdfModel.isShowDiscountColumn();
-
 
178
                PdfPTable orders = null;
-
 
179
                if (stateGst) {
-
 
180
                    if (showDiscount) {
-
 
181
                        orders = new PdfPTable(stateWidthsWithDiscount.length);
-
 
182
                        orders.setWidths(stateWidthsWithDiscount);
-
 
183
                    } else {
-
 
184
                        orders = new PdfPTable(stateWidthsNoDiscount.length);
-
 
185
                        orders.setWidths(stateWidthsNoDiscount);
-
 
186
                    }
-
 
187
                } else {
-
 
188
                    if (showDiscount) {
-
 
189
                        orders = new PdfPTable(igstWidthsWithDiscount.length);
-
 
190
                        orders.setWidths(igstWidthsWithDiscount);
-
 
191
                    } else {
-
 
192
                        orders = new PdfPTable(igstWidthsNoDiscount.length);
-
 
193
                        orders.setWidths(igstWidthsNoDiscount);
-
 
194
                    }
-
 
195
                }
-
 
196
                orders.setWidthPercentage(90);
-
 
197
                orders.addCell(new Paragraph("Sl", FONT_BOLD));
-
 
198
                orders.addCell(new Paragraph("Description", FONT_BOLD));
-
 
199
                orders.addCell(new Paragraph("HSN", FONT_BOLD));
-
 
200
                orders.addCell(new Paragraph("Qty", FONT_BOLD));
-
 
201
                orders.addCell(new Paragraph("Rate\n(Per pc)", FONT_BOLD));
-
 
202
                if (showDiscount) {
-
 
203
                    orders.addCell(new Paragraph("Discount", FONT_BOLD));
-
 
204
                }
-
 
205
                orders.addCell(new Paragraph("Total\nTaxable", FONT_BOLD));
-
 
206
                if (!stateGst) {
-
 
207
                    orders.addCell(new Paragraph("IGST", FONT_BOLD));
-
 
208
                } else {
-
 
209
                    orders.addCell(new Paragraph("CGST", FONT_BOLD));
-
 
210
                    orders.addCell(new Paragraph("SGST", FONT_BOLD));
-
 
211
                }
-
 
212
                orders.addCell(new Paragraph("Total", FONT_BOLD));
-
 
213
 
-
 
214
                orders.setHeaderRows(1);
-
 
215
 
-
 
216
                float igstTotalAmount = 0, cgstTotalAmount = 0, sgstTotalAmount = 0;
-
 
217
                int index = 1;
-
 
218
                for (CustomOrderItem orderItem : orderItems) {
-
 
219
                    orders.addCell(new Paragraph(String.valueOf(index++), FONT_NORMAL));
-
 
220
                    orders.addCell(new Paragraph(orderItem.getDescription(), FONT_NORMAL));
-
 
221
                    orders.addCell(new Paragraph(orderItem.getHsnCode(), FONT_NORMAL));
-
 
222
                    orders.addCell(new Paragraph(String.valueOf(orderItem.getQuantity()), FONT_NORMAL));
-
 
223
 
-
 
224
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getRate()), FONT_NORMAL));
-
 
225
                    if (showDiscount) {
-
 
226
                        String discountText = orderItem.getDiscount() == 0 ? "-" : String.format("%.2f", orderItem.getDiscount());
-
 
227
                        orders.addCell(new Paragraph(discountText, FONT_NORMAL));
-
 
228
                    }
-
 
229
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getAmount()), FONT_NORMAL));
-
 
230
                    if (!stateGst) {
-
 
231
                        orders.addCell(new Paragraph(String.format("%.2f%n(@%.0f%%)", orderItem.getIgstAmount(), orderItem.getIgstRate()), FONT_NORMAL));
-
 
232
                        igstTotalAmount = igstTotalAmount + orderItem.getIgstAmount();
-
 
233
                    } else {
-
 
234
                        orders.addCell(new Paragraph(String.format("%.2f%n(@%.0f%%)", orderItem.getCgstAmount(), orderItem.getCgstRate()), FONT_NORMAL));
-
 
235
                        orders.addCell(new Paragraph(String.format("%.2f%n(@%.0f%%)", orderItem.getSgstAmount(), orderItem.getSgstRate()), FONT_NORMAL));
-
 
236
                        cgstTotalAmount = cgstTotalAmount + orderItem.getCgstAmount();
-
 
237
                        sgstTotalAmount = sgstTotalAmount + orderItem.getSgstAmount();
-
 
238
                    }
-
 
239
                    orders.addCell(new Paragraph(String.format("%.0f", orderItem.getNetAmount()), FONT_NORMAL));
-
 
240
                }
-
 
241
                if (pdfModel.getInsurancePolicies() != null) {
-
 
242
                    for (CustomInsurancePolicy insurancePolicy : pdfModel.getInsurancePolicies()) {
-
 
243
                        orders.addCell(new Paragraph(String.valueOf(index++), FONT_NORMAL));
-
 
244
                        orders.addCell(new Paragraph(insurancePolicy.getDescription(), FONT_NORMAL));
-
 
245
                        orders.addCell(new Paragraph(insurancePolicy.getHsnCode(), FONT_NORMAL));
-
 
246
                        orders.addCell(new Paragraph("1", FONT_NORMAL));
-
 
247
                        orders.addCell(new Paragraph(String.format("%.2f", insurancePolicy.getRate()), FONT_NORMAL));
-
 
248
                        if (showDiscount) {
-
 
249
                            orders.addCell(new Paragraph("-", FONT_NORMAL));
-
 
250
                        }
-
 
251
                        orders.addCell(new Paragraph(String.format("%.2f", insurancePolicy.getRate()), FONT_NORMAL));
-
 
252
                        if (!stateGst) {
-
 
253
                            orders.addCell(new Paragraph(String.format("%.2f%n(@%.0f%%)", insurancePolicy.getIgstAmount(), insurancePolicy.getIgstRate()), FONT_NORMAL));
-
 
254
                            igstTotalAmount = igstTotalAmount + insurancePolicy.getIgstAmount();
-
 
255
                        } else {
-
 
256
                            orders.addCell(new Paragraph(String.format("%.2f%n(@%.0f%%)", insurancePolicy.getCgstAmount(), insurancePolicy.getCgstRate()), FONT_NORMAL));
-
 
257
                            orders.addCell(new Paragraph(String.format("%.2f%n(@%.0f%%)", insurancePolicy.getSgstAmount(), insurancePolicy.getSgstRate()), FONT_NORMAL));
-
 
258
                            cgstTotalAmount = cgstTotalAmount + insurancePolicy.getCgstAmount();
-
 
259
                            sgstTotalAmount = sgstTotalAmount + insurancePolicy.getSgstAmount();
-
 
260
                        }
-
 
261
                        orders.addCell(new Paragraph(String.format("%.0f", insurancePolicy.getNetAmount()), FONT_NORMAL));
-
 
262
                    }
-
 
263
                }
-
 
264
 
-
 
265
                iconImg.setAbsolutePosition(25, rectangle.getHeight() - 100);
-
 
266
                iconImg.scalePercent(30);
-
 
267
 
-
 
268
                document.add(iconImg);
-
 
269
                document.add(Chunk.NEWLINE);
-
 
270
                document.add(Chunk.NEWLINE);
-
 
271
                document.add(tableCustomerRetailer);
-
 
272
 
-
 
273
                document.add(Chunk.NEWLINE);
-
 
274
                document.add(orders);
-
 
275
 
-
 
276
                PdfPTable grandTotalTable = new PdfPTable(3);
-
 
277
                PdfPTable paymentsTable = new PdfPTable(2);
-
 
278
                paymentsTable.setWidthPercentage(95);
-
 
279
                paymentsTable.setWidths(new float[]{8f, 2f});
-
 
280
 
-
 
281
                if (stateGst) {
-
 
282
                    grandTotalTable.setWidths(new float[]{6.6f, .6f, .8f});
-
 
283
                } else {
-
 
284
                    grandTotalTable.setWidths(new float[]{6.5f, .6f, .9f});
-
 
285
                }
-
 
286
                grandTotalTable.setWidthPercentage(90);
-
 
287
 
-
 
288
                Paragraph grandTotalParagraph = new Paragraph("Grand total", FONT_BOLD);
-
 
289
                grandTotalParagraph.setIndentationRight(20);
-
 
290
                grandTotalTable.addCell(grandTotalParagraph);
-
 
291
                Paragraph rsParagraph = new Paragraph("Rs.", FONT_BOLD);
-
 
292
                grandTotalTable.addCell(rsParagraph);
-
 
293
                Paragraph amountParagraph = new Paragraph(String.format("%.2f", pdfModel.getTotalAmount()), FONT_BOLD);
-
 
294
                grandTotalTable.addCell(amountParagraph);
-
 
295
 
-
 
296
                document.add(grandTotalTable);
-
 
297
 
-
 
298
                PdfPTable amountInWordsTable = new PdfPTable(3);
-
 
299
                amountInWordsTable.setWidthPercentage(90);
-
 
300
                amountInWordsTable.addCell(new Paragraph("Amount in Words:", FONT_BOLD));
-
 
301
                if (!stateGst) {
-
 
302
                    amountInWordsTable.setWidths(new float[]{2, 5.1f, 0.9f});
-
 
303
                } else {
-
 
304
                    amountInWordsTable.setWidths(new float[]{2, 5.2f, 0.8f});
-
 
305
                }
-
 
306
 
-
 
307
                String amountInWords = toAmountInWords(pdfModel.getTotalAmount());
-
 
308
                amountInWordsTable.addCell(new Paragraph(amountInWords.toString(), FONT_BOLD));
-
 
309
                amountInWordsTable.addCell(new Paragraph("E & O.E", FONT_NORMAL));
-
 
310
                document.add(amountInWordsTable);
-
 
311
 
-
 
312
                if (pdfModel.getPaymentOptions() != null) {
-
 
313
                    PdfPTable paidAmountTable = new PdfPTable(2);
-
 
314
                    paidAmountTable.setWidthPercentage(90);
-
 
315
                    if (!stateGst) {
-
 
316
                        paidAmountTable.setWidths(new float[]{7.1f, 0.9f});
-
 
317
                    } else {
-
 
318
                        paidAmountTable.setWidths(new float[]{7.2f, 0.8f});
-
 
319
                    }
-
 
320
                    float totalPaidValue = 0;
-
 
321
                    for (CustomPaymentOption paymentOption : pdfModel.getPaymentOptions()) {
-
 
322
                        LOGGER.info("paymentOption - {}", paymentOption);
-
 
323
                        if (!"CASH DISCOUNT".equals(paymentOption.getPaymentOption())) {
-
 
324
                            PdfPCell cell = new PdfPCell(
-
 
325
                                    new Paragraph(10, "Paid Through " + paymentOption.getPaymentOption(), FONT_BOLD));
-
 
326
                            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
327
                            cell.setPadding(5);
-
 
328
                            paidAmountTable.addCell(cell);
-
 
329
 
-
 
330
                            PdfPCell cell1 = new PdfPCell(new Paragraph(10, FormattingUtils.formatDecimal(paymentOption.getAmount()), FONT_BOLD));
-
 
331
                            cell1.setPadding(5);
-
 
332
                            paidAmountTable.addCell(cell1);
-
 
333
                            totalPaidValue += paymentOption.getAmount();
-
 
334
                        }
-
 
335
                    }
-
 
336
                    PdfPCell totalPaidCell = new PdfPCell(new Paragraph(10, "Total Paid", FONT_BOLD));
-
 
337
                    totalPaidCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
338
                    totalPaidCell.setPadding(5);
-
 
339
                    paidAmountTable.addCell(totalPaidCell);
-
 
340
 
-
 
341
                    PdfPCell totalPaidValueCell = new PdfPCell(
-
 
342
                            new Paragraph(10, FormattingUtils.formatDecimal(totalPaidValue), FONT_BOLD));
-
 
343
                    totalPaidValueCell.setPadding(5);
-
 
344
                    paidAmountTable.addCell(totalPaidValueCell);
-
 
345
 
-
 
346
                    document.add(paidAmountTable);
-
 
347
                }
-
 
348
                String docType = pdfModel.getTitle() != null && pdfModel.getTitle().toLowerCase().contains("challan") ? "Delivery Challan" : "Invoice";
-
 
349
                Paragraph autoGenerateParagraph = new Paragraph("Note - This is computer generated " + docType + ", no signature is required", FONT_NORMAL);
-
 
350
                autoGenerateParagraph.setAlignment(Element.ALIGN_CENTER);
-
 
351
                document.add(autoGenerateParagraph);
-
 
352
 
-
 
353
                if(pdfModel.getCreditTerms()!=null) {
-
 
354
                    Paragraph title = new Paragraph("Credit terms :-\n", FONT_BOLD);
-
 
355
                    title.setIndentationLeft(25);
-
 
356
                    title.setIndentationRight(25);
-
 
357
                    document.add(title);
-
 
358
 
-
 
359
                    StringBuffer termsBuffer = new StringBuffer();
-
 
360
                    int count = 0;
-
 
361
                    for (String creditTerm : pdfModel.getCreditTerms()) {
-
 
362
                        count++;
-
 
363
                        termsBuffer.append(count).append(". ").append(creditTerm).append(".\n");
-
 
364
                    }
-
 
365
 
-
 
366
                    Paragraph body = new Paragraph(termsBuffer.toString(), FONT_NORMAL);
-
 
367
                    body.setIndentationLeft(25);
-
 
368
                    body.setIndentationRight(25);
-
 
369
                    document.add(body);
-
 
370
 
-
 
371
                }
-
 
372
 
-
 
373
                if (pdfModel.getTncs() != null) {
-
 
374
                    StringBuffer sb = new StringBuffer();
-
 
375
                    for (String tnc : pdfModel.getTncs()) {
-
 
376
                        sb.append(tnc).append("\n");
-
 
377
                    }
-
 
378
                    Paragraph warningParagraph = new Paragraph(sb.toString(), FONT_NORMAL);
-
 
379
                    warningParagraph.setIndentationLeft(40);
-
 
380
                    document.add(Chunk.NEWLINE);
-
 
381
                    document.add(warningParagraph);
-
 
382
                }
-
 
383
 
-
 
384
                document.newPage();
-
 
385
                if (pdfModel.geteWayBillPdfModel() != null) {
-
 
386
 
-
 
387
                    EWayBillPDF.generateDocument(document, pdfWriter, pdfModel.geteWayBillPdfModel());
-
 
388
                }
-
 
389
            }
-
 
390
            document.close(); // no need to close PDFwriter?
-
 
391
            if (cancelledPages) {
-
 
392
                stampCancelled(outputStream, caneclledPageList);
-
 
393
            }
-
 
394
 
-
 
395
        } catch (DocumentException e) {
-
 
396
            LOGGER.error("Unable to write data to pdf file : ", e);
-
 
397
        } catch (Exception e) {
-
 
398
            // TODO Auto-generated catch block
-
 
399
            e.printStackTrace();
-
 
400
        }
-
 
401
 
-
 
402
    }
-
 
403
 
-
 
404
    private static void addIrnDetails(IrnModel irnModel, Rectangle rectangle, Document document) throws IOException, DocumentException {
-
 
405
        PdfPTable taxTable = new PdfPTable(1);
-
 
406
        taxTable.setWidthPercentage(45);
-
 
407
        PdfPCell pdfCell = new PdfPCell();
-
 
408
        pdfCell.setBorder(Rectangle.NO_BORDER);
-
 
409
        Image img = Image.getInstance(irnModel.getQrCode().toURI().toURL());
-
 
410
        img.setAbsolutePosition(450f, rectangle.getHeight() - 140);
-
 
411
        document.add(img);
-
 
412
        Paragraph irnParagraph = new Paragraph("IRN No - " + irnModel.getIrnNumber(), FONT_NORMAL);
-
 
413
        irnParagraph.setAlignment(Element.ALIGN_LEFT);
-
 
414
        pdfCell.addElement(irnParagraph);
-
 
415
 
-
 
416
        Paragraph ackParagraph = new Paragraph("Ack No - " + irnModel.getAcknowledgeNumber(), FONT_NORMAL);
-
 
417
        ackParagraph.setAlignment(Element.ALIGN_LEFT);
-
 
418
        pdfCell.addElement(ackParagraph);
-
 
419
 
-
 
420
        Paragraph ackDateParagraph = new Paragraph("Ack Date - " + FormattingUtils.format(irnModel.getAcknowledgeDate()), FONT_NORMAL);
-
 
421
        ackDateParagraph.setAlignment(Element.ALIGN_LEFT);
-
 
422
        pdfCell.addElement(ackDateParagraph);
-
 
423
        taxTable.addCell(pdfCell);
-
 
424
        document.add(taxTable);
-
 
425
    }
-
 
426
 
-
 
427
    private static void addMarginSchemeSeparator(PdfPTable table, int numColumns) {
-
 
428
        PdfPCell separatorCell = new PdfPCell(new Paragraph("Items under Margin Scheme \u2013 Rule 32(5) of CGST Rules, 2017", FONT_MARGIN_HEADER));
-
 
429
        separatorCell.setColspan(numColumns);
-
 
430
        separatorCell.setBackgroundColor(new BaseColor(240, 240, 240));
-
 
431
        separatorCell.setPadding(5);
-
 
432
        separatorCell.setHorizontalAlignment(Element.ALIGN_CENTER);
-
 
433
        table.addCell(separatorCell);
-
 
434
    }
-
 
435
 
-
 
436
    private static void addMarginSchemeDeclaration(Document document, InvoicePdfModel pdfModel) throws DocumentException {
-
 
437
        if (pdfModel.getMarginSchemeDeclarations() != null && !pdfModel.getMarginSchemeDeclarations().isEmpty()) {
-
 
438
            document.add(Chunk.NEWLINE);
-
 
439
            Paragraph declarationTitle = new Paragraph("Margin Scheme Declaration:", FONT_BOLD);
-
 
440
            declarationTitle.setIndentationLeft(25);
-
 
441
            document.add(declarationTitle);
-
 
442
            for (String declaration : pdfModel.getMarginSchemeDeclarations()) {
-
 
443
                Paragraph declarationParagraph = new Paragraph("- " + declaration, FONT_NORMAL);
-
 
444
                declarationParagraph.setIndentationLeft(30);
-
 
445
                document.add(declarationParagraph);
-
 
446
            }
-
 
447
        }
-
 
448
    }
-
 
449
 
-
 
450
    // ── Margin Scheme Invoice Helpers ──────────────────────────────────────
-
 
451
    private static final BaseColor MS_BORDER   = new BaseColor(204, 204, 204);
-
 
452
    private static final BaseColor MS_HEADER_BG = new BaseColor(242, 242, 242);
-
 
453
    private static final BaseColor MS_TOTAL_BG  = new BaseColor(249, 249, 249);
-
 
454
    private static final BaseColor MS_SUMM_BG   = new BaseColor(242, 242, 242);
-
 
455
 
-
 
456
    private static final Font MS_TITLE      = new Font(Font.FontFamily.HELVETICA, 13, Font.BOLD);
-
 
457
    private static final Font MS_SUBTITLE   = new Font(Font.FontFamily.HELVETICA, 7.5f, Font.ITALIC, new BaseColor(51, 51, 51));
-
 
458
    private static final Font MS_SECTION    = new Font(Font.FontFamily.HELVETICA, 6.5f, Font.BOLD, new BaseColor(85, 85, 85));
-
 
459
    private static final Font MS_NORMAL     = new Font(Font.FontFamily.HELVETICA, 8, Font.NORMAL);
-
 
460
    private static final Font MS_BOLD       = new Font(Font.FontFamily.HELVETICA, 8, Font.BOLD);
-
 
461
    private static final Font MS_SMALL      = new Font(Font.FontFamily.HELVETICA, 7, Font.NORMAL, new BaseColor(68, 68, 68));
-
 
462
    private static final Font MS_SMALL_BOLD = new Font(Font.FontFamily.HELVETICA, 7, Font.BOLD);
-
 
463
    private static final Font MS_ITALIC     = new Font(Font.FontFamily.HELVETICA, 7.5f, Font.ITALIC);
-
 
464
    private static final Font MS_TBL_HDR    = new Font(Font.FontFamily.HELVETICA, 7, Font.BOLD);
-
 
465
 
-
 
466
    private static Paragraph msSpacer(float spacing) {
-
 
467
        Paragraph p = new Paragraph(" ");
-
 
468
        p.setSpacingAfter(spacing);
-
 
469
        p.setLeading(0f);
-
 
470
        return p;
-
 
471
    }
-
 
472
 
-
 
473
    private static Paragraph msRightPara(String text, Font font) {
-
 
474
        Paragraph p = new Paragraph(text, font);
-
 
475
        p.setAlignment(Element.ALIGN_RIGHT);
-
 
476
        return p;
-
 
477
    }
-
 
478
 
-
 
479
    private static void msAddHeader(PdfPTable table, String text, int align) {
-
 
480
        PdfPCell cell = new PdfPCell(new Phrase(text, MS_TBL_HDR));
-
 
481
        cell.setHorizontalAlignment(align);
-
 
482
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
483
        cell.setBackgroundColor(MS_HEADER_BG);
-
 
484
        cell.setBorderColor(MS_BORDER);
-
 
485
        cell.setPadding(4f);
-
 
486
        table.addCell(cell);
-
 
487
    }
-
 
488
 
-
 
489
    private static void msAddDataCell(PdfPTable table, String text, int align, boolean bold, boolean totalRow) {
-
 
490
        if (text == null) text = "";
-
 
491
        Font font = bold ? MS_BOLD : MS_NORMAL;
-
 
492
        PdfPCell cell = new PdfPCell();
-
 
493
        cell.setHorizontalAlignment(align);
-
 
494
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
495
        cell.setBorderColor(MS_BORDER);
-
 
496
        if (totalRow) cell.setBackgroundColor(MS_TOTAL_BG);
-
 
497
        cell.setPadding(4f);
-
 
498
        String[] lines = text.split("\n");
-
 
499
        for (String line : lines) {
-
 
500
            Paragraph p = new Paragraph(line, font);
-
 
501
            p.setAlignment(align);
-
 
502
            p.setLeading(11f);
-
 
503
            cell.addElement(p);
-
 
504
        }
-
 
505
        table.addCell(cell);
-
 
506
    }
-
 
507
 
-
 
508
    private static void msAddSummaryRow(PdfPTable table, String label, String value, boolean highlight) {
-
 
509
        Font lf = highlight ? MS_BOLD : MS_NORMAL;
-
 
510
        Font vf = highlight ? MS_BOLD : MS_NORMAL;
-
 
511
        BaseColor bg = highlight ? MS_SUMM_BG : BaseColor.WHITE;
-
 
512
        PdfPCell lc = new PdfPCell(new Phrase(label, lf));
-
 
513
        lc.setBorderColor(MS_BORDER);
-
 
514
        lc.setPadding(5f);
-
 
515
        lc.setBackgroundColor(bg);
-
 
516
        table.addCell(lc);
-
 
517
        PdfPCell vc = new PdfPCell(new Phrase(value, vf));
-
 
518
        vc.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
519
        vc.setBorderColor(MS_BORDER);
-
 
520
        vc.setPadding(5f);
-
 
521
        vc.setBackgroundColor(bg);
-
 
522
        table.addCell(vc);
-
 
523
    }
51
    }
524
 
52
 
525
    public static void generateMarginSchemeInvoice(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
53
    public static void generateMarginSchemeInvoice(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
526
        generateInvoiceV2(pdfModels, outputStream);
54
        generateInvoiceV2(pdfModels, outputStream);
527
    }
55
    }
528
 
56
 
529
    public static void generateInvoiceV2(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
57
    public static void generateInvoiceV2(List<InvoicePdfModel> pdfModels, ByteArrayOutputStream outputStream) {
530
        try {
-
 
531
            boolean cancelledPages = false;
-
 
532
            List<Integer> cancelledPageList = new ArrayList<>();
58
        List<DocumentData> docs = new ArrayList<>();
533
            Document document = new Document(PageSize.A4, 28, 28, 34, 34);
-
 
534
            PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream);
-
 
535
            document.open();
-
 
536
 
-
 
537
            for (InvoicePdfModel pdfModel : pdfModels) {
59
        for (InvoicePdfModel m : pdfModels) docs.add(DocumentDataAdapter.from(m));
538
                CustomCustomer customer = pdfModel.getCustomer();
-
 
539
                CustomRetailer retailer = pdfModel.getRetailer();
-
 
540
                boolean stateGst = customer.getAddress().getState().equals(retailer.getAddress().getState());
-
 
541
                String stateCode = stateGst ? pdfModel.getCustomerAddressStateCode() : pdfModel.getPartnerAddressStateCode();
-
 
542
                List<CustomOrderItem> orderItems = pdfModel.getOrderItems();
-
 
543
                boolean isMargin = pdfModel.isHasMarginSchemeItems();
-
 
544
 
-
 
545
                if (pdfModel.isCancelled()) {
-
 
546
                    cancelledPageList.add(1);
-
 
547
                    cancelledPages = true;
-
 
548
                } else {
-
 
549
                    cancelledPageList.add(0);
-
 
550
                }
-
 
551
 
-
 
552
                // ── Header: Logo (left) + Title (center) + QR (right) ─────
-
 
553
                Rectangle rectangle = document.getPageSize();
-
 
554
                String titleText = pdfModel.getTitle() != null ? pdfModel.getTitle().toUpperCase() : "TAX INVOICE";
-
 
555
 
-
 
556
                PdfPTable headerBanner = new PdfPTable(3);
-
 
557
                headerBanner.setWidthPercentage(100);
-
 
558
                headerBanner.setWidths(new float[]{1.2f, 4f, 1.2f});
-
 
559
                headerBanner.setSpacingAfter(4f);
-
 
560
 
-
 
561
                // Left: Logo
-
 
562
                PdfPCell logoCell = new PdfPCell();
-
 
563
                logoCell.setBorder(Rectangle.NO_BORDER);
-
 
564
                logoCell.setPadding(4f);
-
 
565
                logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
566
                Image logoImg = Image.getInstance(iconImg);
-
 
567
                logoImg.scalePercent(25);
-
 
568
                logoCell.addElement(logoImg);
-
 
569
                headerBanner.addCell(logoCell);
-
 
570
 
-
 
571
                // Center: Title + subtitle
-
 
572
                PdfPCell titleCell = new PdfPCell();
-
 
573
                titleCell.setBorder(Rectangle.NO_BORDER);
-
 
574
                titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
575
                titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
-
 
576
                Paragraph title = new Paragraph(titleText, MS_TITLE);
-
 
577
                title.setAlignment(Element.ALIGN_CENTER);
-
 
578
                titleCell.addElement(title);
-
 
579
                if (isMargin) {
-
 
580
                    Paragraph subtitle = new Paragraph(
-
 
581
                            "(GST Payable on Margin Scheme Basis \u2014 ITC not admissible to buyer)", MS_SUBTITLE);
-
 
582
                    subtitle.setAlignment(Element.ALIGN_CENTER);
-
 
583
                    titleCell.addElement(subtitle);
-
 
584
                }
-
 
585
                headerBanner.addCell(titleCell);
-
 
586
 
-
 
587
                // Right: QR code (or empty)
-
 
588
                PdfPCell qrCell = new PdfPCell();
-
 
589
                qrCell.setBorder(Rectangle.NO_BORDER);
-
 
590
                qrCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
-
 
591
                qrCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
592
                if (pdfModel.getIrnModel() != null && pdfModel.getIrnModel().getQrCode() != null) {
-
 
593
                    Image qrImg = Image.getInstance(pdfModel.getIrnModel().getQrCode().toURI().toURL());
-
 
594
                    qrImg.scaleAbsolute(80, 80);
-
 
595
                    qrCell.addElement(qrImg);
-
 
596
                }
-
 
597
                headerBanner.addCell(qrCell);
-
 
598
 
-
 
599
                document.add(headerBanner);
-
 
600
 
-
 
601
                // ── IRN Details (full width below header) ──────────────────
-
 
602
                if (pdfModel.getIrnModel() != null) {
-
 
603
                    PdfPTable irnTable = new PdfPTable(1);
-
 
604
                    irnTable.setWidthPercentage(100);
-
 
605
                    irnTable.setSpacingAfter(8f);
-
 
606
 
-
 
607
                    PdfPCell irnCell = new PdfPCell();
-
 
608
                    irnCell.setBorder(Rectangle.BOTTOM);
-
 
609
                    irnCell.setBorderColor(MS_BORDER);
-
 
610
                    irnCell.setPadding(3f);
-
 
611
                    irnCell.addElement(new Paragraph("IRN: " + pdfModel.getIrnModel().getIrnNumber(), MS_SMALL));
-
 
612
                    irnCell.addElement(new Paragraph("Ack No: " + pdfModel.getIrnModel().getAcknowledgeNumber(), MS_SMALL));
-
 
613
                    irnCell.addElement(new Paragraph("Ack Date: " + FormattingUtils.format(pdfModel.getIrnModel().getAcknowledgeDate()), MS_SMALL));
-
 
614
                    irnTable.addCell(irnCell);
-
 
615
 
-
 
616
                    document.add(irnTable);
-
 
617
                } else if (pdfModel.getIrnErrorMessage() != null) {
-
 
618
                    PdfPTable irnTable = new PdfPTable(1);
-
 
619
                    irnTable.setWidthPercentage(100);
-
 
620
                    irnTable.setSpacingAfter(8f);
-
 
621
 
-
 
622
                    Font errorFont = new Font(Font.FontFamily.HELVETICA, 7, Font.BOLD, new BaseColor(204, 0, 0));
-
 
623
                    PdfPCell irnCell = new PdfPCell();
-
 
624
                    irnCell.setBorder(Rectangle.BOTTOM);
-
 
625
                    irnCell.setBorderColor(MS_BORDER);
-
 
626
                    irnCell.setPadding(3f);
-
 
627
                    irnCell.addElement(new Paragraph("IRN: " + pdfModel.getIrnErrorMessage(), errorFont));
-
 
628
                    irnTable.addCell(irnCell);
-
 
629
 
-
 
630
                    document.add(irnTable);
-
 
631
                }
-
 
632
 
-
 
633
                // ── Supplier (left) + Invoice Details (right) ──────────────
-
 
634
                PdfPTable headerTable = new PdfPTable(2);
-
 
635
                headerTable.setWidthPercentage(100);
-
 
636
                headerTable.setWidths(new float[]{1f, 1f});
-
 
637
                headerTable.setSpacingAfter(8f);
-
 
638
 
-
 
639
                PdfPCell supplierCell = new PdfPCell();
-
 
640
                supplierCell.setBorder(Rectangle.NO_BORDER);
-
 
641
                supplierCell.setPadding(4f);
-
 
642
                supplierCell.setPaddingLeft(0f);
-
 
643
                supplierCell.addElement(new Paragraph("SUPPLIER DETAILS", MS_SECTION));
-
 
644
                supplierCell.addElement(msSpacer(2f));
-
 
645
                supplierCell.addElement(new Paragraph(StringUtils.capitalize(retailer.getAddress().getName()), MS_BOLD));
-
 
646
                supplierCell.addElement(new Paragraph(
-
 
647
                        StringUtils.capitalize(retailer.getAddress().getLine1()) + ", "
-
 
648
                        + StringUtils.capitalize(retailer.getAddress().getLine2()) + ", "
-
 
649
                        + StringUtils.capitalize(retailer.getAddress().getCity()) + " - "
-
 
650
                        + retailer.getAddress().getPinCode(), MS_NORMAL));
-
 
651
                supplierCell.addElement(new Paragraph("GSTIN: " + retailer.getGstNumber(), MS_NORMAL));
-
 
652
                supplierCell.addElement(new Paragraph("State: " + retailer.getAddress().getState()
-
 
653
                        + "  |  Code: " + stateCode, MS_NORMAL));
-
 
654
                headerTable.addCell(supplierCell);
-
 
655
 
-
 
656
                boolean isChallan = titleText.contains("CHALLAN");
-
 
657
                boolean isCreditNote = titleText.contains("CREDIT");
-
 
658
                boolean isDebitNote = titleText.contains("DEBIT");
-
 
659
                String docName = isCreditNote ? "credit note" : (isDebitNote ? "debit note" : (isChallan ? "delivery challan" : "invoice"));
-
 
660
                String docLabel = isCreditNote ? "CN No:" : (isDebitNote ? "DN No:" : (isChallan ? "Challan No:" : "Invoice No:"));
-
 
661
                String sectionLabel = isCreditNote ? "CREDIT NOTE DETAILS" : (isDebitNote ? "DEBIT NOTE DETAILS" : (isChallan ? "CHALLAN DETAILS" : "INVOICE DETAILS"));
-
 
662
                PdfPCell invoiceCell = new PdfPCell();
-
 
663
                invoiceCell.setBorder(Rectangle.NO_BORDER);
-
 
664
                invoiceCell.setPadding(4f);
-
 
665
                invoiceCell.setPaddingRight(0f);
-
 
666
                invoiceCell.addElement(msRightPara(sectionLabel, MS_SECTION));
-
 
667
                invoiceCell.addElement(msSpacer(2f));
-
 
668
                invoiceCell.addElement(msRightPara(docLabel + " " + pdfModel.getInvoiceNumber(), MS_BOLD));
-
 
669
                invoiceCell.addElement(msRightPara("Date: " + pdfModel.getInvoiceDate(), MS_NORMAL));
-
 
670
                String supplyType = stateGst ? "Intra-state" : "Inter-state";
-
 
671
                invoiceCell.addElement(msRightPara("Place of supply: " + customer.getAddress().getState()
-
 
672
                        + " (" + pdfModel.getCustomerAddressStateCode() + ")", MS_NORMAL));
-
 
673
                invoiceCell.addElement(msRightPara("Supply type: " + supplyType, MS_NORMAL));
-
 
674
                headerTable.addCell(invoiceCell);
-
 
675
 
-
 
676
                document.add(headerTable);
-
 
677
 
-
 
678
                // ── Buyer Details ──────────────────────────────────────────
-
 
679
                PdfPTable buyerTable = new PdfPTable(1);
-
 
680
                buyerTable.setWidthPercentage(100);
-
 
681
                buyerTable.setSpacingAfter(8f);
-
 
682
 
-
 
683
                PdfPCell buyerCell = new PdfPCell();
-
 
684
                buyerCell.setBorder(Rectangle.BOX);
-
 
685
                buyerCell.setBorderColor(MS_BORDER);
-
 
686
                buyerCell.setPadding(5f);
-
 
687
                buyerCell.addElement(new Paragraph("BUYER DETAILS", MS_SECTION));
-
 
688
                buyerCell.addElement(msSpacer(2f));
-
 
689
                String buyerName = StringUtils.capitalize(customer.getAddress().getName()
-
 
690
                        + (customer.getAddress().getLastName() == null ? "" : " " + customer.getAddress().getLastName()));
-
 
691
                buyerCell.addElement(new Paragraph(buyerName, MS_BOLD));
-
 
692
                if (customer.getAddress().getLine1() != null || customer.getAddress().getLine2() != null) {
-
 
693
                    String addr = "";
-
 
694
                    if (customer.getAddress().getLine1() != null) addr += StringUtils.capitalize(customer.getAddress().getLine1());
-
 
695
                    if (customer.getAddress().getLine2() != null) addr += ", " + StringUtils.capitalize(customer.getAddress().getLine2());
-
 
696
                    buyerCell.addElement(new Paragraph(addr, MS_NORMAL));
-
 
697
                }
-
 
698
                String buyerLocation = StringUtils.capitalize(customer.getAddress().getCity()) + ", "
-
 
699
                        + customer.getAddress().getState() + " - " + customer.getAddress().getPinCode();
-
 
700
                buyerCell.addElement(new Paragraph(buyerLocation, MS_NORMAL));
-
 
701
                String buyerGstLine = "";
-
 
702
                if (customer.getGstNumber() != null && !customer.getGstNumber().isEmpty()) {
-
 
703
                    buyerGstLine += "GSTIN: " + customer.getGstNumber() + "  |  ";
-
 
704
                }
-
 
705
                buyerGstLine += "State: " + customer.getAddress().getState()
-
 
706
                        + " (Code: " + pdfModel.getCustomerAddressStateCode() + ")";
-
 
707
                buyerCell.addElement(new Paragraph(buyerGstLine, MS_NORMAL));
-
 
708
                if (customer.getAddress().getPhoneNumber() != null) {
-
 
709
                    buyerCell.addElement(new Paragraph("Mobile: " + customer.getAddress().getPhoneNumber(), MS_NORMAL));
-
 
710
                }
-
 
711
                buyerTable.addCell(buyerCell);
-
 
712
                document.add(buyerTable);
-
 
713
 
-
 
714
                // ── Item Table ─────────────────────────────────────────────
-
 
715
                boolean showOrderId = orderItems.stream().anyMatch(oi -> oi.getOrderId() != 0);
-
 
716
                PdfPTable itemTable;
-
 
717
                if (showOrderId) {
-
 
718
                    itemTable = new PdfPTable(10);
-
 
719
                    itemTable.setWidths(new float[]{0.7f, 1.4f, 3.5f, 1.2f, 0.6f, 1.8f, 1.8f, 2.4f, 1.6f, 1.6f});
-
 
720
                } else {
-
 
721
                    itemTable = new PdfPTable(9);
-
 
722
                    itemTable.setWidths(new float[]{0.7f, 4.9f, 1.2f, 0.6f, 1.8f, 1.8f, 2.4f, 1.6f, 1.6f});
-
 
723
                }
-
 
724
                itemTable.setWidthPercentage(100);
-
 
725
                itemTable.setSpacingAfter(0f);
-
 
726
                itemTable.setHeaderRows(1);
-
 
727
 
-
 
728
                msAddHeader(itemTable, "S.No.",      Element.ALIGN_CENTER);
-
 
729
                if (showOrderId) msAddHeader(itemTable, "Order Id", Element.ALIGN_CENTER);
-
 
730
                msAddHeader(itemTable, "Description of Goods", Element.ALIGN_LEFT);
-
 
731
                msAddHeader(itemTable, "HSN\nCode",  Element.ALIGN_CENTER);
-
 
732
                msAddHeader(itemTable, "Qty",        Element.ALIGN_CENTER);
-
 
733
 
-
 
734
                msAddHeader(itemTable, "Rate\n(Rs.)", Element.ALIGN_RIGHT);
-
 
735
                msAddHeader(itemTable, isMargin ? "Taxable Value\n- Margin (Rs.)" : "Taxable\nValue (Rs.)", Element.ALIGN_RIGHT);
-
 
736
                msAddHeader(itemTable, "Tax\nRate",             Element.ALIGN_CENTER);
-
 
737
                msAddHeader(itemTable, "Tax\n(Rs.)",         Element.ALIGN_RIGHT);
-
 
738
                msAddHeader(itemTable, "Total\n(Rs.)",       Element.ALIGN_RIGHT);
-
 
739
 
-
 
740
                float totalGrossSale = 0, totalTaxable = 0, totalTaxAmount = 0, totalNetAmount = 0;
-
 
741
                float totalCgst = 0, totalSgst = 0, totalIgst = 0;
-
 
742
                int index = 1;
-
 
743
                for (CustomOrderItem orderItem : orderItems) {
-
 
744
                    float taxAmount = orderItem.getCgstAmount() + orderItem.getSgstAmount() + orderItem.getIgstAmount();
-
 
745
 
-
 
746
                    msAddDataCell(itemTable, String.valueOf(index++),                    Element.ALIGN_CENTER, false, false);
-
 
747
                    if (showOrderId) msAddDataCell(itemTable, String.valueOf(orderItem.getOrderId()), Element.ALIGN_CENTER, false, false);
-
 
748
                    msAddDataCell(itemTable, orderItem.getDescription(),                 Element.ALIGN_LEFT,   false, false);
-
 
749
                    msAddDataCell(itemTable, orderItem.getHsnCode(),                     Element.ALIGN_CENTER, false, false);
-
 
750
                    msAddDataCell(itemTable, String.valueOf(orderItem.getQuantity()),     Element.ALIGN_CENTER, false, false);
-
 
751
 
-
 
752
                    if (isMargin) {
-
 
753
                        float grossSaleTotal = orderItem.getNetAmount() - taxAmount;
-
 
754
                        float grossSalePerUnit = grossSaleTotal / orderItem.getQuantity();
-
 
755
                        msAddDataCell(itemTable, formatIndianCurrency(grossSalePerUnit),          Element.ALIGN_RIGHT, false, false);
-
 
756
                        totalGrossSale += grossSaleTotal;
-
 
757
                    } else {
-
 
758
                        msAddDataCell(itemTable, formatIndianCurrency(orderItem.getRate()),       Element.ALIGN_RIGHT, false, false);
-
 
759
                    }
-
 
760
                    totalNetAmount += orderItem.getNetAmount();
-
 
761
                    msAddDataCell(itemTable, formatIndianCurrency(orderItem.getAmount()),         Element.ALIGN_RIGHT, false, false);
-
 
762
                    String rateText;
-
 
763
                    if (stateGst) {
-
 
764
                        rateText = String.format("CGST %.1f%%\n+ SGST %.1f%%", orderItem.getCgstRate(), orderItem.getSgstRate());
-
 
765
                    } else {
-
 
766
                        rateText = String.format("IGST %.1f%%", orderItem.getIgstRate());
-
 
767
                    }
-
 
768
                    msAddDataCell(itemTable, rateText,                                            Element.ALIGN_CENTER, false, false);
-
 
769
                    msAddDataCell(itemTable, formatIndianCurrency(taxAmount),                     Element.ALIGN_RIGHT, false, false);
-
 
770
                    msAddDataCell(itemTable, formatIndianCurrency(orderItem.getNetAmount()),      Element.ALIGN_RIGHT, false, false);
-
 
771
 
-
 
772
                    totalTaxable += orderItem.getAmount();
-
 
773
                    totalTaxAmount += taxAmount;
-
 
774
                    totalCgst += orderItem.getCgstAmount();
-
 
775
                    totalSgst += orderItem.getSgstAmount();
-
 
776
                    totalIgst += orderItem.getIgstAmount();
-
 
777
                }
-
 
778
 
-
 
779
                // Total row
-
 
780
                int totalPcs = 0;
-
 
781
                for (CustomOrderItem oi : orderItems) totalPcs += oi.getQuantity();
-
 
782
                int totalColSpan = showOrderId ? 5 : 4;
-
 
783
                PdfPCell totalSpan = new PdfPCell(new Phrase("Total " + totalPcs + " pc(s)", MS_BOLD));
-
 
784
                totalSpan.setColspan(totalColSpan);
-
 
785
                totalSpan.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
786
                totalSpan.setBorderColor(MS_BORDER);
-
 
787
                totalSpan.setBackgroundColor(MS_TOTAL_BG);
-
 
788
                totalSpan.setPadding(4f);
-
 
789
                itemTable.addCell(totalSpan);
-
 
790
 
-
 
791
                msAddDataCell(itemTable, isMargin ? formatIndianCurrency(totalGrossSale) : "", Element.ALIGN_RIGHT, true, true);
-
 
792
                msAddDataCell(itemTable, formatIndianCurrency(totalTaxable),      Element.ALIGN_RIGHT, true, true);
-
 
793
                msAddDataCell(itemTable, "\u2014",                                Element.ALIGN_CENTER, false, true);
-
 
794
                msAddDataCell(itemTable, formatIndianCurrency(totalTaxAmount),    Element.ALIGN_RIGHT, true, true);
-
 
795
                msAddDataCell(itemTable, formatIndianCurrency(totalNetAmount),    Element.ALIGN_RIGHT, true, true);
-
 
796
 
-
 
797
                document.add(itemTable);
-
 
798
 
-
 
799
                // ── Bottom: Info (left) + Summary (right) + Amount in words ──
-
 
800
                float totalInvoiceValue = isMargin ? (totalGrossSale + totalTaxAmount) : totalNetAmount;
-
 
801
 
-
 
802
                PdfPTable bottomTable = new PdfPTable(2);
-
 
803
                bottomTable.setWidthPercentage(100);
-
 
804
                bottomTable.setWidths(new float[]{1.15f, 1f});
-
 
805
                bottomTable.setSpacingBefore(0f);
-
 
806
                bottomTable.setSpacingAfter(0f);
-
 
807
 
-
 
808
                // Left: Declaration (margin) or Tax Summary (regular)
-
 
809
                PdfPCell leftCell = new PdfPCell();
-
 
810
                leftCell.setBorder(Rectangle.BOX);
-
 
811
                leftCell.setBorderColor(MS_BORDER);
-
 
812
                leftCell.setPadding(6f);
-
 
813
                leftCell.setPaddingRight(8f);
-
 
814
 
-
 
815
                if (isMargin) {
-
 
816
                    leftCell.addElement(new Paragraph("Declaration", MS_SMALL_BOLD));
-
 
817
                    leftCell.addElement(msSpacer(3f));
-
 
818
                    leftCell.addElement(new Paragraph(
-
 
819
                            "GST is payable on margin scheme basis under Section 2(27) read with "
-
 
820
                            + "Rule 32(5) of CGST Rules, 2017.", MS_SMALL));
-
 
821
                    leftCell.addElement(msSpacer(4f));
-
 
822
                    leftCell.addElement(new Paragraph(
-
 
823
                            "The buyer is NOT eligible to claim Input Tax Credit on this invoice.", MS_SMALL_BOLD));
-
 
824
                }
-
 
825
                bottomTable.addCell(leftCell);
-
 
826
 
-
 
827
                // Right: Summary totals
-
 
828
                PdfPCell summaryCell = new PdfPCell();
-
 
829
                summaryCell.setBorder(Rectangle.BOX);
-
 
830
                summaryCell.setBorderColor(MS_BORDER);
-
 
831
                summaryCell.setPadding(0f);
-
 
832
                PdfPTable sumTable = new PdfPTable(2);
-
 
833
                sumTable.setWidthPercentage(100);
-
 
834
                sumTable.setWidths(new float[]{1.4f, 1f});
-
 
835
 
-
 
836
                if (isMargin) {
-
 
837
                    msAddSummaryRow(sumTable, "Total Selling Price", "Rs. " + formatIndianCurrency(totalGrossSale), false);
-
 
838
                    msAddSummaryRow(sumTable, "GST on Margin", "Rs. " + formatIndianCurrency(totalTaxAmount), false);
-
 
839
                } else {
-
 
840
                    msAddSummaryRow(sumTable, "Total Taxable Value", "Rs. " + formatIndianCurrency(totalTaxable), false);
-
 
841
                    msAddSummaryRow(sumTable, "Total GST", "Rs. " + formatIndianCurrency(totalTaxAmount), false);
-
 
842
                }
-
 
843
                String totalValueLabel = isCreditNote ? "Total Credit Note Value" : (isDebitNote ? "Total Debit Note Value" : (isChallan ? "Total Challan Value" : "Total Invoice Value"));
-
 
844
                msAddSummaryRow(sumTable, totalValueLabel, "Rs. " + formatIndianCurrency(totalInvoiceValue), true);
-
 
845
                summaryCell.addElement(sumTable);
-
 
846
                bottomTable.addCell(summaryCell);
-
 
847
 
-
 
848
                // Row 2: empty (left) + Amount in words (right) — no gap
-
 
849
                PdfPCell emptyLeft = new PdfPCell(new Phrase("", MS_NORMAL));
-
 
850
                emptyLeft.setBorder(Rectangle.NO_BORDER);
-
 
851
                emptyLeft.setPadding(0f);
-
 
852
                emptyLeft.setFixedHeight(0.1f);
-
 
853
                bottomTable.addCell(emptyLeft);
-
 
854
                PdfPCell wordsCell = new PdfPCell(new Phrase(toAmountInWords(totalInvoiceValue), MS_ITALIC));
-
 
855
                wordsCell.setBorder(Rectangle.BOX);
-
 
856
                wordsCell.setBorderColor(MS_BORDER);
-
 
857
                wordsCell.setPadding(4f);
-
 
858
                wordsCell.setBackgroundColor(MS_TOTAL_BG);
-
 
859
                bottomTable.addCell(wordsCell);
-
 
860
 
-
 
861
                document.add(bottomTable);
-
 
862
 
-
 
863
                // ── Payment Options ────────────────────────────────────────
-
 
864
                if (pdfModel.getPaymentOptions() != null) {
-
 
865
                    PdfPTable paidTable = new PdfPTable(2);
-
 
866
                    paidTable.setWidthPercentage(100);
-
 
867
                    paidTable.setWidths(new float[]{7f, 1f});
-
 
868
                    float totalPaidValue = 0;
-
 
869
                    for (CustomPaymentOption po : pdfModel.getPaymentOptions()) {
-
 
870
                        if (!"CASH DISCOUNT".equals(po.getPaymentOption())) {
-
 
871
                            PdfPCell lbl = new PdfPCell(new Phrase("Paid Through " + po.getPaymentOption(), MS_BOLD));
-
 
872
                            lbl.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
873
                            lbl.setBorderColor(MS_BORDER);
-
 
874
                            lbl.setPadding(4f);
-
 
875
                            paidTable.addCell(lbl);
-
 
876
                            PdfPCell val = new PdfPCell(new Phrase(FormattingUtils.formatDecimal(po.getAmount()), MS_BOLD));
-
 
877
                            val.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
878
                            val.setBorderColor(MS_BORDER);
-
 
879
                            val.setPadding(4f);
-
 
880
                            paidTable.addCell(val);
-
 
881
                            totalPaidValue += po.getAmount();
-
 
882
                        }
-
 
883
                    }
-
 
884
                    PdfPCell tpLbl = new PdfPCell(new Phrase("Total Paid", MS_BOLD));
-
 
885
                    tpLbl.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
886
                    tpLbl.setBorderColor(MS_BORDER);
-
 
887
                    tpLbl.setPadding(4f);
-
 
888
                    paidTable.addCell(tpLbl);
-
 
889
                    PdfPCell tpVal = new PdfPCell(new Phrase(FormattingUtils.formatDecimal(totalPaidValue), MS_BOLD));
-
 
890
                    tpVal.setHorizontalAlignment(Element.ALIGN_RIGHT);
-
 
891
                    tpVal.setBorderColor(MS_BORDER);
-
 
892
                    tpVal.setPadding(4f);
-
 
893
                    paidTable.addCell(tpVal);
-
 
894
                    document.add(paidTable);
-
 
895
                }
-
 
896
 
-
 
897
                // ── Note + Credit Terms ────────────────────────────────────
-
 
898
                Paragraph note = new Paragraph("This is a computer-generated " + docName + " and does not require a physical signature.", MS_SMALL);
-
 
899
                note.setAlignment(Element.ALIGN_CENTER);
-
 
900
                note.setSpacingBefore(8f);
-
 
901
                note.setSpacingAfter(4f);
-
 
902
                document.add(note);
-
 
903
 
-
 
904
                if (pdfModel.getCreditTerms() != null) {
-
 
905
                    Paragraph ctTitle = new Paragraph("Credit terms:", MS_SMALL_BOLD);
-
 
906
                    ctTitle.setIndentationLeft(25);
-
 
907
                    document.add(ctTitle);
-
 
908
                    int count = 0;
-
 
909
                    for (String ct : pdfModel.getCreditTerms()) {
-
 
910
                        count++;
-
 
911
                        Paragraph line = new Paragraph(count + ". " + ct + ".", MS_SMALL);
-
 
912
                        line.setIndentationLeft(25);
-
 
913
                        line.setIndentationRight(25);
-
 
914
                        document.add(line);
-
 
915
                    }
-
 
916
                }
-
 
917
 
-
 
918
                document.newPage();
-
 
919
 
-
 
920
                // ── E-Way Bill ─────────────────────────────────────────────
-
 
921
                if (pdfModel.geteWayBillPdfModel() != null) {
-
 
922
                    EWayBillPDF.generateDocument(document, pdfWriter, pdfModel.geteWayBillPdfModel());
-
 
923
                }
-
 
924
            }
-
 
925
 
-
 
926
            document.close();
-
 
927
            if (cancelledPages) {
-
 
928
                stampCancelled(outputStream, cancelledPageList);
-
 
929
            }
-
 
930
        } catch (DocumentException e) {
-
 
931
            LOGGER.error("Unable to write data to pdf file : ", e);
-
 
932
        } catch (Exception e) {
-
 
933
            e.printStackTrace();
-
 
934
        }
-
 
935
    }
-
 
936
 
-
 
937
    private static void stampCancelled(ByteArrayOutputStream byteStream, List<Integer> cancelledPage) throws IOException, DocumentException {
-
 
938
        ByteArrayInputStream bais = new ByteArrayInputStream(byteStream.toByteArray());
-
 
939
        PdfReader pdfReader = new PdfReader(bais);
-
 
940
        int n = pdfReader.getNumberOfPages();
-
 
941
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
60
        new DocumentRenderer().render(docs, outputStream);
942
        PdfStamper pdfStamper = new PdfStamper(pdfReader, baos);
-
 
943
        pdfStamper.setRotateContents(false);
-
 
944
        // text watermark
-
 
945
        Font f = new Font(FontFamily.HELVETICA, 30);
-
 
946
        Phrase p = new Phrase("My watermark (text)", f);
-
 
947
        URL cancelledImgUrl = PdfUtils.class.getClassLoader().getResource("cancelled.png");
-
 
948
        URL waterMarkImgUrl = PdfUtils.class.getClassLoader().getResource("sd1.jpg");
-
 
949
        Image imgCancelled = Image.getInstance(cancelledImgUrl);
-
 
950
        Image imgWatermark = Image.getInstance(waterMarkImgUrl);
-
 
951
        imgWatermark.scaleAbsolute(imgWatermark.getScaledWidth() * 2.5f, imgWatermark.getScaledHeight() * 2.5f);
-
 
952
        float w = imgCancelled.getScaledWidth() / 2;
-
 
953
        float h = imgCancelled.getScaledHeight() / 2;
-
 
954
        float wWaterMark = imgWatermark.getScaledWidth() / 2;
-
 
955
        float hWatermark = imgWatermark.getScaledHeight() / 2;
-
 
956
        // transparency
-
 
957
        PdfGState gs1 = new PdfGState();
-
 
958
        gs1.setFillOpacity(0.4f);
-
 
959
        PdfGState gs2 = new PdfGState();
-
 
960
        gs2.setFillOpacity(0.05f);
-
 
961
        // properties
-
 
962
        PdfContentByte over;
-
 
963
        Rectangle pagesize;
-
 
964
        float x, y;
-
 
965
 
-
 
966
        // loop over every page
-
 
967
        for (int i = 1; i <= n; i++) {
-
 
968
            pagesize = pdfReader.getPageSize(i);
-
 
969
            x = (pagesize.getLeft() + pagesize.getRight()) / 2;
-
 
970
            y = (pagesize.getTop() + pagesize.getBottom()) / 2;
-
 
971
            over = pdfStamper.getOverContent(i);
-
 
972
            over.saveState();
-
 
973
            if (cancelledPage.get(i - 1) == 1) {
-
 
974
                over.setGState(gs1);
-
 
975
                over.addImage(imgCancelled, w, 0, 0, h, x - (w / 2), y - (h / 2));
-
 
976
                over.restoreState();
-
 
977
            } else {
-
 
978
                over.setGState(gs2);
-
 
979
                over.addImage(imgWatermark, wWaterMark, 0, 0, hWatermark, x - (wWaterMark / 2), y - (hWatermark / 2));
-
 
980
                over.restoreState();
-
 
981
            }
-
 
982
        }
-
 
983
        pdfStamper.close();
-
 
984
        pdfReader.close();
-
 
985
        baos.writeTo(byteStream);
-
 
986
 
-
 
987
    }
61
    }
988
 
62
 
989
    public static void generateAndWriteDebitNote(List<DebitNotePdfModel> debitNotePdfModels, OutputStream outputStream) {
63
    public static void generateAndWriteDebitNote(List<DebitNotePdfModel> debitNotePdfModels, OutputStream outputStream) {
990
        Document document = new Document();
64
        List<DocumentData> docs = new ArrayList<>();
991
        document.setMargins(0, 0, 25, 0);
-
 
992
        try {
-
 
993
            for (DebitNotePdfModel debitNotePdfModel : debitNotePdfModels) {
-
 
994
 
-
 
995
                InvoicePdfModel pdfModel = debitNotePdfModel.getPdfModel();
-
 
996
                CustomCustomer customer = pdfModel.getCustomer();
-
 
997
                CustomRetailer retailer = pdfModel.getRetailer();
-
 
998
                boolean stateGst = false;
-
 
999
 
-
 
1000
                LOGGER.info("Customer - {}", customer.getAddress().getState());
-
 
1001
                LOGGER.info("retailer - {}", retailer.getAddress().getState());
-
 
1002
 
-
 
1003
 
-
 
1004
                if (customer.getAddress().getState().equals(retailer.getAddress().getState())) {
-
 
1005
                    stateGst = true;
-
 
1006
                }
-
 
1007
                List<CustomOrderItem> orderItems = pdfModel.getOrderItems();
-
 
1008
 
-
 
1009
                PdfWriter.getInstance(document, outputStream);
-
 
1010
 
-
 
1011
                document.open();
-
 
1012
                document.addTitle(pdfModel.getTitle());
-
 
1013
                document.addAuthor(pdfModel.getAuther());
-
 
1014
 
-
 
1015
                Paragraph paragraphTitle = new Paragraph(pdfModel.getTitle(), FONT_TITLE);
-
 
1016
                paragraphTitle.setAlignment(Element.ALIGN_CENTER);
-
 
1017
 
-
 
1018
                PdfPCell blankCell = new PdfPCell();
-
 
1019
                blankCell.setBorder(Rectangle.NO_BORDER);
-
 
1020
                PdfPTable tableCustomerRetailer = new PdfPTable(3);
-
 
1021
                tableCustomerRetailer.setWidthPercentage(95);
-
 
1022
                PdfPCell partnerInfo = new PdfPCell();
-
 
1023
                partnerInfo.addElement(new Paragraph("From Party:", FONT_BOLD));
-
 
1024
                partnerInfo.addElement(
-
 
1025
                        new Paragraph(StringUtils.capitalize(customer.getAddress().getName()), FONT_NORMAL));
-
 
1026
                partnerInfo.addElement(new Paragraph(
-
 
1027
                        (customer.getAddress().getLine1() == null ? "" : StringUtils.capitalize(customer.getAddress().getLine1()) + ", ") + (customer.getAddress().getLine2() == null ? "" : StringUtils.capitalize(customer.getAddress().getLine2()) + ", ") + (customer.getAddress().getCity() == null ? "" : StringUtils.capitalize(customer.getAddress().getCity()) + " - ") + (customer.getAddress().getPinCode() == null ? "" : StringUtils.capitalize(customer.getAddress().getPinCode())), FONT_NORMAL));
65
        for (DebitNotePdfModel m : debitNotePdfModels) docs.add(DocumentDataAdapter.from(m));
1028
 
-
 
1029
                partnerInfo.addElement(new Paragraph(
-
 
1030
                        StringUtils.capitalize(customer.getAddress().getState()) + "(" + pdfModel.getCustomerAddressStateCode() + ")", FONT_NORMAL));
-
 
1031
                partnerInfo.addElement(new Paragraph("Mobile - " + customer.getMobileNumber(), FONT_NORMAL));
-
 
1032
                if (customer.getGstNumber() != null && !customer.getGstNumber().isEmpty()) {
-
 
1033
                    partnerInfo.addElement(new Paragraph("GST No - " + customer.getGstNumber(), FONT_BOLD));
-
 
1034
                }
-
 
1035
 
-
 
1036
                PdfPCell sellerParty = new PdfPCell();
-
 
1037
                sellerParty.addElement(new Paragraph("To Party:", FONT_BOLD));
-
 
1038
                sellerParty.addElement(
-
 
1039
                        new Paragraph(StringUtils.capitalize(retailer.getAddress().getName()), FONT_NORMAL));
-
 
1040
                sellerParty.addElement(new Paragraph((retailer.getAddress().getLine1() == null ? "" : StringUtils.capitalize(retailer.getAddress().getLine1()) + ", ") + (retailer.getAddress().getLine2() == null ? "" : StringUtils.capitalize(retailer.getAddress().getLine2()) + ", ") + (retailer.getAddress().getCity() == null ? "" : StringUtils.capitalize(retailer.getAddress().getCity()) + "-") + (retailer.getAddress().getPinCode() == null ? "" : StringUtils.capitalize(retailer.getAddress().getPinCode())), FONT_NORMAL));
66
        new DocumentRenderer().render(docs, outputStream);
1041
                sellerParty.addElement(new Paragraph(
-
 
1042
                        retailer.getAddress().getState() + "(" + pdfModel.getPartnerAddressStateCode() + ")", FONT_NORMAL));
-
 
1043
                sellerParty.addElement(new Paragraph("Mobile - " + retailer.getAddress().getPhoneNumber(), FONT_NORMAL));
-
 
1044
                sellerParty.addElement(new Paragraph("GST No - " + retailer.getGstNumber(), FONT_BOLD));
-
 
1045
 
-
 
1046
                PdfPTable tableInvoiceDateRetailer = new PdfPTable(1);
-
 
1047
                tableInvoiceDateRetailer.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
1048
 
-
 
1049
                PdfPTable tableInvoiceDate = new PdfPTable(2);
-
 
1050
                tableInvoiceDate.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
1051
                tableInvoiceDate.setWidthPercentage(90);
-
 
1052
 
-
 
1053
                PdfPCell debitNoteDetails = new PdfPCell(new Paragraph("Debit Note Details", FONT_BOLD));
-
 
1054
                debitNoteDetails.setColspan(2);
-
 
1055
                debitNoteDetails.setBorder(Rectangle.NO_BORDER);
-
 
1056
 
-
 
1057
                PdfPCell debitNoteNumberKey = new PdfPCell(new Paragraph("Debit Note No:", FONT_NORMAL));
-
 
1058
                debitNoteNumberKey.setBorder(Rectangle.NO_BORDER);
-
 
1059
                PdfPCell debitNoteNumberValue = new PdfPCell(
-
 
1060
                        new Paragraph(debitNotePdfModel.getDebitNoteNumber(), FONT_NORMAL));
-
 
1061
                debitNoteNumberValue.setBorder(Rectangle.NO_BORDER);
-
 
1062
 
-
 
1063
                PdfPCell debitNoteDateKey = new PdfPCell(new Paragraph("Debit Note Dt:", FONT_NORMAL));
-
 
1064
                debitNoteDateKey.setBorder(Rectangle.NO_BORDER);
-
 
1065
 
-
 
1066
                PdfPCell debitNoteDateValue = new PdfPCell(
-
 
1067
                        new Paragraph(debitNotePdfModel.getDebitNoteDate(), FONT_NORMAL));
-
 
1068
                debitNoteDateValue.setBorder(Rectangle.NO_BORDER);
-
 
1069
 
-
 
1070
                PdfPCell invoiceNumberKey = new PdfPCell(new Paragraph("Invoice Ref No:", FONT_NORMAL));
-
 
1071
                invoiceNumberKey.setBorder(Rectangle.NO_BORDER);
-
 
1072
                PdfPCell invoiceNumberValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceNumber(), FONT_NORMAL));
-
 
1073
                invoiceNumberValue.setBorder(Rectangle.NO_BORDER);
-
 
1074
 
-
 
1075
                PdfPCell dateKey = new PdfPCell(new Paragraph("Invoice Dt:", FONT_NORMAL));
-
 
1076
                dateKey.setBorder(Rectangle.NO_BORDER);
-
 
1077
                PdfPCell dateValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceDate(), FONT_NORMAL));
-
 
1078
                dateValue.setBorder(Rectangle.NO_BORDER);
-
 
1079
 
-
 
1080
                tableInvoiceDate.addCell(debitNoteDetails);
-
 
1081
                tableInvoiceDate.addCell(debitNoteNumberKey);
-
 
1082
                tableInvoiceDate.addCell(debitNoteNumberValue);
-
 
1083
                tableInvoiceDate.addCell(debitNoteDateKey);
-
 
1084
                tableInvoiceDate.addCell(debitNoteDateValue);
-
 
1085
                tableInvoiceDate.addCell(invoiceNumberKey);
-
 
1086
                tableInvoiceDate.addCell(invoiceNumberValue);
-
 
1087
                tableInvoiceDate.addCell(dateKey);
-
 
1088
                tableInvoiceDate.addCell(dateValue);
-
 
1089
 
-
 
1090
                tableCustomerRetailer.addCell(partnerInfo);
-
 
1091
                tableCustomerRetailer.addCell(tableInvoiceDate);
-
 
1092
                tableCustomerRetailer.addCell(sellerParty);
-
 
1093
 
-
 
1094
                PdfPTable orders = null;
-
 
1095
                if (stateGst) {
-
 
1096
                    orders = new PdfPTable(stateWidths.length);
-
 
1097
                    orders.setWidths(stateWidths);
-
 
1098
                } else {
-
 
1099
                    orders = new PdfPTable(igstWidths.length);
-
 
1100
                    orders.setWidths(igstWidths);
-
 
1101
                }
-
 
1102
                orders.setWidthPercentage(95);
-
 
1103
                orders.addCell(new Paragraph("Order Id", FONT_BOLD));
-
 
1104
                orders.addCell(new Paragraph("Description", FONT_BOLD));
-
 
1105
                orders.addCell(new Paragraph("HSN", FONT_BOLD));
-
 
1106
                orders.addCell(new Paragraph("Qty", FONT_BOLD));
-
 
1107
                orders.addCell(new Paragraph("Rate\n(Per pc)", FONT_BOLD));
-
 
1108
                orders.addCell(new Paragraph("Total\nTaxable", FONT_BOLD));
-
 
1109
                if (!stateGst) {
-
 
1110
                    orders.addCell(new Paragraph("IGST\n%", FONT_BOLD));
-
 
1111
                    orders.addCell(new Paragraph("IGST", FONT_BOLD));
-
 
1112
                } else {
-
 
1113
                    orders.addCell(new Paragraph("CGST %", FONT_BOLD));
-
 
1114
                    orders.addCell(new Paragraph("CGST", FONT_BOLD));
-
 
1115
                    orders.addCell(new Paragraph("SGST %", FONT_BOLD));
-
 
1116
                    orders.addCell(new Paragraph("SGST", FONT_BOLD));
-
 
1117
                }
-
 
1118
                orders.addCell(new Paragraph("Total", FONT_BOLD));
-
 
1119
 
-
 
1120
                orders.setHeaderRows(1);
-
 
1121
 
-
 
1122
                float igstTotalAmount = 0, cgstTotalAmount = 0, sgstTotalAmount = 0;
-
 
1123
                boolean marginSeparatorAdded = false;
-
 
1124
                for (CustomOrderItem orderItem : orderItems) {
-
 
1125
                    if (orderItem.isMarginScheme() && !marginSeparatorAdded) {
-
 
1126
                        addMarginSchemeSeparator(orders, stateGst ? stateWidths.length : igstWidths.length);
-
 
1127
                        marginSeparatorAdded = true;
-
 
1128
                    }
-
 
1129
 
-
 
1130
                    orders.addCell(new Paragraph(String.valueOf(orderItem.getOrderId()), FONT_NORMAL));
-
 
1131
                    orders.addCell(new Paragraph(orderItem.getDescription(), FONT_NORMAL));
-
 
1132
                    orders.addCell(new Paragraph(orderItem.getHsnCode(), FONT_NORMAL));
-
 
1133
                    orders.addCell(new Paragraph(String.valueOf(orderItem.getQuantity()), FONT_NORMAL));
-
 
1134
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getRate()), FONT_NORMAL));
-
 
1135
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getAmount()), FONT_NORMAL));
-
 
1136
                    if (!stateGst) {
-
 
1137
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getIgstRate()), FONT_NORMAL));
-
 
1138
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getIgstAmount()), FONT_NORMAL));
-
 
1139
                        igstTotalAmount = igstTotalAmount + orderItem.getIgstAmount();
-
 
1140
                    } else {
-
 
1141
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getCgstRate()), FONT_NORMAL));
-
 
1142
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getCgstAmount()), FONT_NORMAL));
-
 
1143
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getSgstRate()), FONT_NORMAL));
-
 
1144
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getSgstAmount()), FONT_NORMAL));
-
 
1145
                        cgstTotalAmount = cgstTotalAmount + orderItem.getCgstAmount();
-
 
1146
                        sgstTotalAmount = sgstTotalAmount + orderItem.getSgstAmount();
-
 
1147
                    }
-
 
1148
                    orders.addCell(new Paragraph(String.format("%.0f", orderItem.getNetAmount()), FONT_NORMAL));
-
 
1149
                    LOGGER.info("IN FOR LOOP");
-
 
1150
                }
-
 
1151
 
-
 
1152
                document.add(paragraphTitle);
-
 
1153
 
-
 
1154
                document.add(Chunk.NEWLINE);
-
 
1155
                document.add(tableCustomerRetailer);
-
 
1156
 
-
 
1157
                document.add(Chunk.NEWLINE);
-
 
1158
                document.add(orders);
-
 
1159
 
-
 
1160
                PdfPTable grandTotalTable = new PdfPTable(3);
-
 
1161
                if (stateGst) {
-
 
1162
                    grandTotalTable.setWidths(new float[]{6.6f, .6f, .8f});
-
 
1163
                } else {
-
 
1164
                    grandTotalTable.setWidths(new float[]{6.5f, .6f, .9f});
-
 
1165
                }
-
 
1166
                grandTotalTable.setWidthPercentage(95);
-
 
1167
 
-
 
1168
                Paragraph grandTotalParagraph = new Paragraph("Grand total", FONT_BOLD);
-
 
1169
                grandTotalParagraph.setIndentationRight(20);
-
 
1170
                grandTotalTable.addCell(grandTotalParagraph);
-
 
1171
                Paragraph rsParagraph = new Paragraph("Rs.", FONT_BOLD);
-
 
1172
                grandTotalTable.addCell(rsParagraph);
-
 
1173
                Paragraph amountParagraph = new Paragraph(String.format("%.2f", pdfModel.getTotalAmount()), FONT_BOLD);
-
 
1174
                grandTotalTable.addCell(amountParagraph);
-
 
1175
 
-
 
1176
                document.add(grandTotalTable);
-
 
1177
 
-
 
1178
                PdfPTable amountInWordsTable = new PdfPTable(3);
-
 
1179
                if (!stateGst) {
-
 
1180
                    amountInWordsTable.setWidths(new float[]{2, 5.1f, 0.9f});
-
 
1181
                } else {
-
 
1182
                    amountInWordsTable.setWidths(new float[]{2, 5.2f, 0.8f});
-
 
1183
                }
-
 
1184
                amountInWordsTable.setWidthPercentage(95);
-
 
1185
                amountInWordsTable.addCell(new Paragraph("Amount in Words:", FONT_BOLD));
-
 
1186
 
-
 
1187
                String amountInWords = toAmountInWords(pdfModel.getTotalAmount());
-
 
1188
                amountInWordsTable.addCell(new Paragraph(amountInWords.toString(), FONT_BOLD));
-
 
1189
                amountInWordsTable.addCell(new Paragraph("E & O.E", FONT_NORMAL));
-
 
1190
                document.add(amountInWordsTable);
-
 
1191
 
-
 
1192
                // Margin scheme declaration for debit notes
-
 
1193
                addMarginSchemeDeclaration(document, pdfModel);
-
 
1194
 
-
 
1195
                document.newPage();
-
 
1196
            }
-
 
1197
            document.close(); // no need to close PDFwriter?
-
 
1198
 
-
 
1199
        } catch (DocumentException e) {
-
 
1200
            LOGGER.error("Unable to write data to pdf file : ", e);
-
 
1201
        } catch (Exception e) {
-
 
1202
            // TODO Auto-generated catch block
-
 
1203
            e.printStackTrace();
-
 
1204
        }
-
 
1205
    }
-
 
1206
 
-
 
1207
    private static String toAmountInWords(float amount) {
-
 
1208
        int rupees = (int) amount;
-
 
1209
        int paise = Math.round((amount - rupees) * 100);
-
 
1210
        StringBuilder sb = new StringBuilder("Rs. ");
-
 
1211
        sb.append(StringUtils.capitalize(indianNumberToWords(rupees)));
-
 
1212
        if (paise > 0) {
-
 
1213
            sb.append(" and ");
-
 
1214
            RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(indianLocale, RuleBasedNumberFormat.SPELLOUT);
-
 
1215
            sb.append(StringUtils.capitalize(fmt.format(paise)));
-
 
1216
            sb.append(" Paise");
-
 
1217
        } else {
-
 
1218
            sb.append(" Only");
-
 
1219
        }
-
 
1220
        return sb.toString();
-
 
1221
    }
-
 
1222
 
-
 
1223
    /**
-
 
1224
     * Convert number to Indian English words (lakh, crore system).
-
 
1225
     */
-
 
1226
    private static String indianNumberToWords(int number) {
-
 
1227
        if (number == 0) return "zero";
-
 
1228
        String[] ones = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
-
 
1229
                "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
-
 
1230
                "eighteen", "nineteen"};
-
 
1231
        String[] tens = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
-
 
1232
 
-
 
1233
        if (number < 0) return "minus " + indianNumberToWords(-number);
-
 
1234
 
-
 
1235
        StringBuilder words = new StringBuilder();
-
 
1236
        if (number / 10000000 > 0) {
-
 
1237
            words.append(indianNumberToWords(number / 10000000)).append(" crore ");
-
 
1238
            number %= 10000000;
-
 
1239
        }
-
 
1240
        if (number / 100000 > 0) {
-
 
1241
            words.append(indianNumberToWords(number / 100000)).append(" lakh ");
-
 
1242
            number %= 100000;
-
 
1243
        }
-
 
1244
        if (number / 1000 > 0) {
-
 
1245
            words.append(indianNumberToWords(number / 1000)).append(" thousand ");
-
 
1246
            number %= 1000;
-
 
1247
        }
-
 
1248
        if (number / 100 > 0) {
-
 
1249
            words.append(ones[number / 100]).append(" hundred ");
-
 
1250
            number %= 100;
-
 
1251
        }
-
 
1252
        if (number > 0) {
-
 
1253
            if (words.length() > 0) words.append("and ");
-
 
1254
            if (number < 20) {
-
 
1255
                words.append(ones[number]);
-
 
1256
            } else {
-
 
1257
                words.append(tens[number / 10]);
-
 
1258
                if (number % 10 > 0) words.append("-").append(ones[number % 10]);
-
 
1259
            }
-
 
1260
        }
-
 
1261
        return words.toString().trim();
-
 
1262
    }
-
 
1263
 
-
 
1264
    /**
-
 
1265
     * Format amount in Indian comma style: 1,25,129.00
-
 
1266
     */
-
 
1267
    static String formatIndianCurrency(double amount) {
-
 
1268
        String formatted = indianCurrencyFormat.format(amount);
-
 
1269
        // Java 8 en_IN produces "Rs." prefix (e.g. "Rs.17,618.00", "-Rs.500.50")
-
 
1270
        return formatted.replace("Rs.", "").replace("\u20B9", "").trim();
-
 
1271
    }
67
    }
1272
 
68
 
1273
    public static void generateAndWriteCustomerCreditNotes(List<CreditNotePdfModel> creditNotes, OutputStream outputStream) {
69
    public static void generateAndWriteCustomerCreditNotes(List<CreditNotePdfModel> creditNotes, OutputStream outputStream) {
1274
        Document document = new Document();
70
        List<DocumentData> docs = new ArrayList<>();
1275
        document.setMargins(0, 0, 25, 0);
-
 
1276
        try {
-
 
1277
            PdfWriter.getInstance(document, outputStream);
-
 
1278
 
-
 
1279
            document.open();
-
 
1280
            document.addTitle(creditNotes.get(0).getPdfModel().getTitle());
-
 
1281
            document.addAuthor(creditNotes.get(0).getPdfModel().getAuther());
-
 
1282
            for (CreditNotePdfModel creditNotePdfModel : creditNotes) {
-
 
1283
                InvoicePdfModel pdfModel = creditNotePdfModel.getPdfModel();
-
 
1284
                CustomCustomer customer = pdfModel.getCustomer();
-
 
1285
                CustomRetailer retailer = pdfModel.getRetailer();
-
 
1286
                boolean stateGst = false;
-
 
1287
 
-
 
1288
                if (customer.getAddress().getState().equals(retailer.getAddress().getState())) {
-
 
1289
                    stateGst = true;
-
 
1290
                }
-
 
1291
                List<CustomOrderItem> orderItems = pdfModel.getOrderItems();
-
 
1292
 
-
 
1293
                Paragraph paragraphTitle = new Paragraph(pdfModel.getTitle(), FONT_TITLE);
-
 
1294
                paragraphTitle.setAlignment(Element.ALIGN_CENTER);
-
 
1295
 
-
 
1296
                PdfPCell blankCell = new PdfPCell();
-
 
1297
                blankCell.setBorder(Rectangle.NO_BORDER);
-
 
1298
                PdfPTable tableCustomerRetailer = new PdfPTable(3);
-
 
1299
                tableCustomerRetailer.setWidthPercentage(95);
-
 
1300
                PdfPCell partnerInfo = new PdfPCell();
-
 
1301
                partnerInfo.addElement(new Paragraph("To Party:", FONT_BOLD));
-
 
1302
                partnerInfo.addElement(
-
 
1303
                        new Paragraph(StringUtils.capitalize(customer.getAddress().getName()), FONT_NORMAL));
-
 
1304
                partnerInfo.addElement(new Paragraph(
-
 
1305
                        StringUtils.capitalize(customer.getAddress().getLine1()) + ", " + (customer.getAddress().getLine2() == null ? "" : StringUtils.capitalize(customer.getAddress().getLine2())) + ", " + customer.getAddress().getCity() + " - " + customer.getAddress().getPinCode(), FONT_NORMAL));
71
        for (CreditNotePdfModel m : creditNotes) docs.add(DocumentDataAdapter.from(m));
1306
 
-
 
1307
                partnerInfo.addElement(new Paragraph(
-
 
1308
                        StringUtils.capitalize(customer.getAddress().getState()) + "(" + pdfModel.getCustomerAddressStateCode() + ")", FONT_NORMAL));
-
 
1309
                partnerInfo.addElement(new Paragraph("Mobile - " + customer.getMobileNumber(), FONT_NORMAL));
-
 
1310
                if (customer.getGstNumber() != null && !customer.getGstNumber().isEmpty()) {
-
 
1311
                    partnerInfo.addElement(new Paragraph("GST No - " + customer.getGstNumber(), FONT_BOLD));
-
 
1312
                }
-
 
1313
 
-
 
1314
                PdfPCell sellerParty = new PdfPCell();
-
 
1315
                sellerParty.addElement(new Paragraph("From Party:", FONT_BOLD));
-
 
1316
                sellerParty.addElement(
-
 
1317
                        new Paragraph(StringUtils.capitalize(retailer.getAddress().getName()), FONT_NORMAL));
-
 
1318
                sellerParty.addElement(new Paragraph((retailer.getAddress().getLine1() == null ? "" : StringUtils.capitalize(retailer.getAddress().getLine1()) + ", ") + (retailer.getAddress().getLine2() == null ? "" : StringUtils.capitalize(retailer.getAddress().getLine2()) + ", ") + StringUtils.capitalize(retailer.getAddress().getCity()) + "-" + retailer.getAddress().getPinCode() + ", ", FONT_NORMAL));
72
        new DocumentRenderer().render(docs, outputStream);
1319
                sellerParty.addElement(new Paragraph(
-
 
1320
                        retailer.getAddress().getState() + "(" + pdfModel.getPartnerAddressStateCode() + ")", FONT_NORMAL));
-
 
1321
                sellerParty.addElement(new Paragraph("Mobile - " + retailer.getAddress().getPhoneNumber(), FONT_NORMAL));
-
 
1322
                sellerParty.addElement(new Paragraph("GST No - " + retailer.getGstNumber(), FONT_BOLD));
-
 
1323
 
-
 
1324
                PdfPTable tableInvoiceDateRetailer = new PdfPTable(1);
-
 
1325
                tableInvoiceDateRetailer.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
1326
 
-
 
1327
                PdfPTable tableInvoiceDate = new PdfPTable(2);
-
 
1328
                tableInvoiceDate.getDefaultCell().setBorder(Rectangle.NO_BORDER);
-
 
1329
                tableInvoiceDate.setWidthPercentage(90);
-
 
1330
 
-
 
1331
                PdfPCell debitNoteDetails = new PdfPCell(new Paragraph("Credit Note Details", FONT_BOLD));
-
 
1332
                debitNoteDetails.setColspan(2);
-
 
1333
                debitNoteDetails.setBorder(Rectangle.NO_BORDER);
-
 
1334
 
-
 
1335
                PdfPCell debitNoteNumberKey = new PdfPCell(new Paragraph("Credit Note No:", FONT_NORMAL));
-
 
1336
                debitNoteNumberKey.setBorder(Rectangle.NO_BORDER);
-
 
1337
                PdfPCell debitNoteNumberValue = new PdfPCell(
-
 
1338
                        new Paragraph(creditNotePdfModel.getCreditNoteNumber(), FONT_NORMAL));
-
 
1339
                debitNoteNumberValue.setBorder(Rectangle.NO_BORDER);
-
 
1340
 
-
 
1341
                PdfPCell debitNoteDateKey = new PdfPCell(new Paragraph("Credit Note Dt:", FONT_NORMAL));
-
 
1342
                debitNoteDateKey.setBorder(Rectangle.NO_BORDER);
-
 
1343
 
-
 
1344
                PdfPCell debitNoteDateValue = new PdfPCell(
-
 
1345
                        new Paragraph(creditNotePdfModel.getCreditNoteDate(), FONT_NORMAL));
-
 
1346
                debitNoteDateValue.setBorder(Rectangle.NO_BORDER);
-
 
1347
                tableInvoiceDate.addCell(debitNoteDetails);
-
 
1348
                tableInvoiceDate.addCell(debitNoteNumberKey);
-
 
1349
                tableInvoiceDate.addCell(debitNoteNumberValue);
-
 
1350
                tableInvoiceDate.addCell(debitNoteDateKey);
-
 
1351
                tableInvoiceDate.addCell(debitNoteDateValue);
-
 
1352
                if (pdfModel.getInvoiceNumber() != null) {
-
 
1353
                    PdfPCell dateKey = new PdfPCell(new Paragraph("Invoice Dt:", FONT_NORMAL));
-
 
1354
                    dateKey.setBorder(Rectangle.NO_BORDER);
-
 
1355
                    PdfPCell dateValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceDate(), FONT_NORMAL));
-
 
1356
                    dateValue.setBorder(Rectangle.NO_BORDER);
-
 
1357
 
-
 
1358
                    PdfPCell invoiceNumberKey = new PdfPCell(new Paragraph("Invoice Ref No:", FONT_NORMAL));
-
 
1359
                    invoiceNumberKey.setBorder(Rectangle.NO_BORDER);
-
 
1360
                    PdfPCell invoiceNumberValue = new PdfPCell(new Paragraph(pdfModel.getInvoiceNumber(), FONT_NORMAL));
-
 
1361
                    invoiceNumberValue.setBorder(Rectangle.NO_BORDER);
-
 
1362
                    tableInvoiceDate.addCell(invoiceNumberKey);
-
 
1363
                    tableInvoiceDate.addCell(invoiceNumberValue);
-
 
1364
                    tableInvoiceDate.addCell(dateKey);
-
 
1365
                    tableInvoiceDate.addCell(dateValue);
-
 
1366
                }
-
 
1367
 
-
 
1368
                tableCustomerRetailer.addCell(partnerInfo);
-
 
1369
                tableCustomerRetailer.addCell(tableInvoiceDate);
-
 
1370
                tableCustomerRetailer.addCell(sellerParty);
-
 
1371
 
-
 
1372
                PdfPTable orders = null;
-
 
1373
                if (stateGst) {
-
 
1374
                    orders = new PdfPTable(stateWidthsCrNote.length);
-
 
1375
                    orders.setWidths(stateWidthsCrNote);
-
 
1376
                } else {
-
 
1377
                    orders = new PdfPTable(igstWidthsCrNote.length);
-
 
1378
                    orders.setWidths(igstWidthsCrNote);
-
 
1379
                }
-
 
1380
                orders.setWidthPercentage(95);
-
 
1381
                orders.addCell(new Paragraph("Description", FONT_BOLD));
-
 
1382
                orders.addCell(new Paragraph("HSN", FONT_BOLD));
-
 
1383
                orders.addCell(new Paragraph("Qty", FONT_BOLD));
-
 
1384
                orders.addCell(new Paragraph("Rate\n(Per pc)", FONT_BOLD));
-
 
1385
                orders.addCell(new Paragraph("Total\nTaxable", FONT_BOLD));
-
 
1386
                if (!stateGst) {
-
 
1387
                    orders.addCell(new Paragraph("IGST%", FONT_BOLD));
-
 
1388
                    orders.addCell(new Paragraph("IGST", FONT_BOLD));
-
 
1389
                } else {
-
 
1390
                    orders.addCell(new Paragraph("CGST %", FONT_BOLD));
-
 
1391
                    orders.addCell(new Paragraph("CGST", FONT_BOLD));
-
 
1392
                    orders.addCell(new Paragraph("SGST %", FONT_BOLD));
-
 
1393
                    orders.addCell(new Paragraph("SGST", FONT_BOLD));
-
 
1394
                }
-
 
1395
                orders.addCell(new Paragraph("Total", FONT_BOLD));
-
 
1396
 
-
 
1397
                orders.setHeaderRows(1);
-
 
1398
 
-
 
1399
                float igstTotalAmount = 0, cgstTotalAmount = 0, sgstTotalAmount = 0;
-
 
1400
                boolean marginSeparatorAdded = false;
-
 
1401
                for (CustomOrderItem orderItem : orderItems) {
-
 
1402
                    if (orderItem.isMarginScheme() && !marginSeparatorAdded) {
-
 
1403
                        addMarginSchemeSeparator(orders, stateGst ? stateWidthsCrNote.length : igstWidthsCrNote.length);
-
 
1404
                        marginSeparatorAdded = true;
-
 
1405
                    }
-
 
1406
 
-
 
1407
                    LOGGER.info("Custom Order Item - {}", orderItem);
-
 
1408
                    orders.addCell(new Paragraph(orderItem.getDescription(), FONT_NORMAL));
-
 
1409
                    orders.addCell(new Paragraph(orderItem.getHsnCode(), FONT_NORMAL));
-
 
1410
                    orders.addCell(new Paragraph(String.valueOf(orderItem.getQuantity()), FONT_NORMAL));
-
 
1411
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getRate()), FONT_NORMAL));
-
 
1412
                    orders.addCell(new Paragraph(String.format("%.2f", orderItem.getAmount()), FONT_NORMAL));
-
 
1413
                    if (!stateGst) {
-
 
1414
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getIgstRate()), FONT_NORMAL));
-
 
1415
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getIgstAmount()), FONT_NORMAL));
-
 
1416
                        igstTotalAmount = igstTotalAmount + orderItem.getIgstAmount();
-
 
1417
                    } else {
-
 
1418
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getCgstRate()), FONT_NORMAL));
-
 
1419
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getCgstAmount()), FONT_NORMAL));
-
 
1420
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getSgstRate()), FONT_NORMAL));
-
 
1421
                        orders.addCell(new Paragraph(String.format("%.2f", orderItem.getSgstAmount()), FONT_NORMAL));
-
 
1422
                        cgstTotalAmount = cgstTotalAmount + orderItem.getCgstAmount();
-
 
1423
                        sgstTotalAmount = sgstTotalAmount + orderItem.getSgstAmount();
-
 
1424
                    }
-
 
1425
                    orders.addCell(new Paragraph(String.format("%.0f", orderItem.getNetAmount()), FONT_NORMAL));
-
 
1426
                    LOGGER.info("IN FOR LOOP");
-
 
1427
                }
-
 
1428
 
-
 
1429
                document.add(paragraphTitle);
-
 
1430
 
-
 
1431
                document.add(Chunk.NEWLINE);
-
 
1432
                document.add(tableCustomerRetailer);
-
 
1433
 
-
 
1434
                document.add(Chunk.NEWLINE);
-
 
1435
                document.add(orders);
-
 
1436
 
-
 
1437
                PdfPTable grandTotalTable = new PdfPTable(3);
-
 
1438
                if (stateGst) {
-
 
1439
                    grandTotalTable.setWidths(new float[]{6.6f, .6f, .8f});
-
 
1440
                } else {
-
 
1441
                    grandTotalTable.setWidths(new float[]{6.5f, .6f, .9f});
-
 
1442
                }
-
 
1443
                grandTotalTable.setWidthPercentage(95);
-
 
1444
 
-
 
1445
                Paragraph grandTotalParagraph = new Paragraph("Grand total", FONT_BOLD);
-
 
1446
                grandTotalParagraph.setIndentationRight(20);
-
 
1447
                grandTotalTable.addCell(grandTotalParagraph);
-
 
1448
                Paragraph rsParagraph = new Paragraph("Rs.", FONT_BOLD);
-
 
1449
                grandTotalTable.addCell(rsParagraph);
-
 
1450
                Paragraph amountParagraph = new Paragraph(String.format("%.2f", pdfModel.getTotalAmount()), FONT_BOLD);
-
 
1451
                grandTotalTable.addCell(amountParagraph);
-
 
1452
 
-
 
1453
                document.add(grandTotalTable);
-
 
1454
 
-
 
1455
                PdfPTable amountInWordsTable = new PdfPTable(3);
-
 
1456
                if (!stateGst) {
-
 
1457
                    amountInWordsTable.setWidths(new float[]{2, 5.1f, 0.9f});
-
 
1458
                } else {
-
 
1459
                    amountInWordsTable.setWidths(new float[]{2, 5.2f, 0.8f});
-
 
1460
                }
-
 
1461
                amountInWordsTable.setWidthPercentage(95);
-
 
1462
                amountInWordsTable.addCell(new Paragraph("Amount in Words:", FONT_BOLD));
-
 
1463
 
-
 
1464
                String amountInWords = toAmountInWords(pdfModel.getTotalAmount());
-
 
1465
                amountInWordsTable.addCell(new Paragraph(amountInWords.toString(), FONT_BOLD));
-
 
1466
                amountInWordsTable.addCell(new Paragraph("E & O.E", FONT_NORMAL));
-
 
1467
                document.add(amountInWordsTable);
-
 
1468
 
-
 
1469
                // Margin scheme declaration for credit notes
-
 
1470
                addMarginSchemeDeclaration(document, pdfModel);
-
 
1471
 
-
 
1472
                document.newPage();
-
 
1473
            }
-
 
1474
            document.close(); // no need to close PDFwriter?
-
 
1475
        } catch (DocumentException e) {
-
 
1476
            LOGGER.error("Unable to write data to pdf file : ", e);
-
 
1477
        } catch (Exception e) {
-
 
1478
            // TODO Auto-generated catch block
-
 
1479
            e.printStackTrace();
-
 
1480
        }
-
 
1481
 
-
 
1482
    }
73
    }
1483
 
74
 
1484
    public static byte[] mergePdfFiles(List<byte[]> pdfFiles) throws IOException, DocumentException {
75
    public static byte[] mergePdfFiles(List<byte[]> pdfFiles) throws IOException, DocumentException {
1485
        ByteArrayOutputStream mergedOutputStream = new ByteArrayOutputStream();
76
        ByteArrayOutputStream mergedOutputStream = new ByteArrayOutputStream();
1486
        Document document = new Document();
77
        Document document = new Document();
Line 1498... Line 89...
1498
        }
89
        }
1499
 
90
 
1500
        document.close();
91
        document.close();
1501
        return mergedOutputStream.toByteArray();
92
        return mergedOutputStream.toByteArray();
1502
    }
93
    }
1503
 
-
 
1504
}
94
}