Custom Button Action for Generating Deposit Summary Client and Suitelet Scripts

The Client Script used for generating the PDF:

/**
 * @NApiVersion 2.1
 * @NScriptType ClientScript
 * @NModuleScope SameAccount
 */
/***********************************************************************************************************
 * Chesapeake Coffee Roasters-USA-NS/SCA
 * CCRUN-8 Custom Print Button for Bank Deposit Summary with Advanced PDF/HTML Template
 *****************************************************************************************
 * Author : Jobin & Jismi
 * Date Created : 15-October-2024
 * Description : This Client script is for PDF customization of Bank deposit
 * 
 * REVISION HISTORY
 * 
 * Version 1.0 : 15-October-2024 : Created the initial build by JJ0325
 * 
 ************************************************************************************/
define(['N/record', 'N/currentRecord','N/url'],
    /**
     * @param{record} record
     * @param{currentRecord} currentRecord
     */
    function (record, currentRecord,url) {

        /**
         * Function to be executed after page is initialized.
         *
         * @param {Object} scriptContext
         * @param {Record} scriptContext.currentRecord - Current form record
         * @param {string} scriptContext.mode - The mode in which the record is being accessed (create, copy, or edit)
         *
         * @since 2015.2
         */
        function pageInit(scriptContext) {
            try {
                return true;
            } catch (e) {
                console.error('error in Pageinit', e);
            }


        }
/**
 * To generate the Print 
 */
        function printDeposit() {
            try {
                let recId = currentRecord.get().id;
                let recType = currentRecord.get().type;

                console.log("internalId of the Deposit record is ", recId);

                let currenturl = url.resolveScript({
                    scriptId: "customscript_jj_sl_btn_pdf_depo_ccrun_8",
                    deploymentId: "customdeploy_jj_sl_btn_pdf_depo_ccrun_8",
                    params:
                    {
                        "recId": recId, "recType": recType
                    },
                    returnExternalUrl: false
                })
                window.open(currenturl)
            }
            catch (e) {
                console.error({ title: "error@customerPaymentReceipt", details: e });
            }
        }
        return {
            pageInit: pageInit,
            printDeposit: printDeposit
        };

    });

The Suitelet used for generating the PDF:

/**
 * @NApiVersion 2.1
 * @NScriptType Suitelet
 */
/***********************************************************************************************************
 * Chesapeake Coffee Roasters-USA-NS/SCA
 * CCRUN-8 Custom Print Button for Bank Deposit Summary with Advanced PDF/HTML Template
 *****************************************************************************************
 * Author : Jobin & Jismi
 * Date Created : 15-October-2024
 * Description : This suitelet script is for PDF customization of Bank deposit
 *
 * REVISION HISTORY
 * 
 * Version 1.0: 19-October-2024 : Created the initial build by JJ0325
 * 
 ************************************************************************************/
define(['N/record', 'N/render', 'N/file', 'N/format'],
    /**
     * @param{record} record
     */
    (record, render, file, format1) => {
        /**
         * Defines the Suitelet script trigger point.
         * @param {Object} scriptContext
         * @param {ServerRequest} scriptContext.request - Incoming request
         * @param {ServerResponse} scriptContext.response - Suitelet response
         * @since 2015.2
         */
        const onRequest = (scriptContext) => {
            try {
                if (scriptContext.request.method === 'GET') {
                    let depRecID = scriptContext.request.parameters.recId
                    let depositType = scriptContext.request.parameters.recType;
                   // log.debug('Deposit record Id', depRecID, 'type is', depositType);
                    let currentDeposit = record.load({
                        type: depositType,
                        id: depRecID,
                        isDynamic: true,
                    });
                   // log.debug('Loaded record', currentDeposit);
                    let lineCount = currentDeposit.getLineCount({ sublistId: 'payment' });
                    let lineCountOther = currentDeposit.getLineCount({ sublistId: 'other' });
                    let lineCountCash = currentDeposit.getLineCount({ sublistId: 'cashback' });
                    if (lineCount > 0 || lineCountOther > 0 || lineCountCash > 0) {


                        let generatedContents = generateContents(depRecID, depositType);
                        log.debug('the lines are', generatedContents.lines);
                        if (!generatedContents.lines[0]) {
                            log.debug("lines Doesn't exists");
                            scriptContext.response.write('Invalid request method');
                        } else {

                     let generatedPdf = generatePrint(118, depRecID, generatedContents); // 118 is the internal ID of the PDF Template.

                            scriptContext.response.writeFile({ file: generatedPdf, isInline: true });
                        }
                    } else {
                        scriptContext.response.write('Invalid request method');
                    }
                }
            } catch (e) {
                log.error({ title: "error@onRequest", details: e });
            }
        }

        /**
         * Generate contents by loading the deposit record and its sublist data.
         * @param {number} internalId - The internal ID of the deposit record.
         * @param {string} depositType - The record type of the deposit.
         * @returns {Array} - Array of objects containing deposit details and line data.
         */
        function generateContents(internalId, depositType) {
            try {
                let currentDeposit = record.load({
                    type: depositType,
                    id: internalId,
                    isDynamic: true,
                });
                log.debug('Loaded record', currentDeposit);
                let lineCountPayment = currentDeposit.getLineCount({ sublistId: 'payment' });
                let lineCountOther = currentDeposit.getLineCount({ sublistId: 'other' });
            

             // Create an object to hold the deposit header information and an array for line items
                let contents = {
                    trandate: escapeSpecialChar(currentDeposit.getText({ fieldId: 'trandate' })),
                    account: escapeSpecialChar(currentDeposit.getText({ fieldId: 'account' })),
                    totalAmount: formatNumberIndianStyle(currentDeposit.getValue({ fieldId: 'total' })),
                    tranid: escapeSpecialChar(currentDeposit.getValue({ fieldId: 'transactionnumber' })),
                    lines: [], // Array to hold line items
                };

                for (let i = 0; i < lineCountPayment; i++) {
            // for generating contets from 'Payments' sublist
                        let deposit = currentDeposit.getSublistValue({
                            sublistId: 'payment',
                            fieldId: "deposit",
                            line: i
                        })
                        log.debug('deposit value', deposit)
                        if (deposit == 'T' || deposit == true) {
    
                            let lineDetails = {
                                customer: escapeSpecialChar(currentDeposit.getSublistText({
                                    sublistId: 'payment',
                                    fieldId: "entity",
                                    line: i
                                })),
                                amount: formatNumberIndianStyle(currentDeposit.getSublistValue({
                                    sublistId: 'payment',
                                    fieldId: "paymentamount",
                                    line: i
                                })),
                                method: escapeSpecialChar(currentDeposit.getSublistText({
                                    sublistId: 'payment',
                                    fieldId: "paymentmethod",
                                    line: i
                                })),
                                memo: escapeSpecialChar(currentDeposit.getSublistValue({
                                    sublistId: 'payment',
                                    fieldId: "memo",
                                    line: i
                                })),
                                checkNo: currentDeposit.getSublistValue({
                                    sublistId: 'payment',
                                    fieldId: "refnum",
                                    line: i
                                })
                            };
    
                            contents.lines.push(lineDetails);
                        }
                    }
                    log.debug('Content generated is', contents);
             // for generating contets from 'others' sublist
                    for (let i = 0; i < lineCountOther; i++) {
                        let lineDetailsOther = {
                            customer: escapeSpecialChar(currentDeposit.getSublistText({
                                sublistId: 'other',
                                fieldId: "entity",
                                line: i
                            })),
                            amount: formatNumberIndianStyle(currentDeposit.getSublistValue({
                                sublistId: 'other',
                              fieldId: "amount",
                              line: i
                        })),
                        method: escapeSpecialChar(currentDeposit.getSublistText({
                            sublistId: 'other',
                            fieldId: "paymentmethod",
                            line: i
                        })),
                        memo: escapeSpecialChar(currentDeposit.getSublistValue({
                            sublistId: 'other',
                            fieldId: "memo",
                            line: i
                        })),
                        checkNo: currentDeposit.getSublistValue({
                            sublistId: 'other',
                            fieldId: "refnum",
                            line: i
                        })
                    };
                    contents.lines.push(lineDetailsOther);
                }
                
                return contents;
            } catch (e) {
                log.error('Error in generateContents', e);
            }
        }

        /**
         * Generates and renders the PDF with the provided template and content.
         * @param {number} tempId - The internal ID of the PDF template file.
         * @param {number} cpRecID - The internal ID of the deposit record.
         * @param {Object} generateContents - The content object generated from the record.
         * @returns {file.File} - The generated PDF file.
         */
        function generatePrint(tempId, cpRecID, generateContents) {
            try {
                let renderer = render.create();
                let templateFile = file.load({ id: tempId });
                log.debug('Loaded template', templateFile);

                renderer.setTemplateById(tempId);

                // Add the entire contents array as a custom data source
                renderer.addCustomDataSource({
                    format: render.DataSource.OBJECT,
                    alias: "contents",
                    data: { contents: generateContents }
                });

                let pdfFile = renderer.renderAsPdf();
                log.debug('Generated PDF Output', pdfFile);
                return pdfFile;
            } catch (e) {
                log.error('Error in generatePrint function', e);
            }
        }

        /**
         * Escapes special characters to avoid breaking the template rendering.
         * @param {string} textvalue - The string to escape special characters.
         * @returns {string} - The escaped string.
         */
        function escapeSpecialChar(textvalue) {
            try {
                if (textvalue) {
                    textvalue = textvalue.replace(/&/g, '&amp;');
                    textvalue = textvalue.replace(/</g, '&lt;');
                    textvalue = textvalue.replace(/>/g, '&gt;');
                    textvalue = textvalue.replace(/"/g, '&quot;');
                    textvalue = textvalue.replace(/'/g, '&apos;');
                    textvalue = textvalue.replace(/u00A0/g, ' '); // Non-breaking space
                    textvalue = textvalue.replace(/$/g, ""); // Remove dollar sign
                }
                return textvalue;
            } catch (e) {
                log.error('error in escape special Char ', e);
                return null;
            }
        }

  /**
 * For Formating the number for amounts
 * @param {*} value 
 * @returns 
 */
        function formatNumberIndianStyle(value) {
            try {
                if (value !== null && value !== undefined) {
                    let formattedValue = format1.format({
                        value: value,
                        type: format1.Type.CURRENCY // This will format it with commas and two decimals
                    });

                    // If you need a specific custom logic for Indian formatting, you can apply it here 
                    formattedValue = formattedValue.replace(/(d)(?=(dd)+db)/g, "$1,");
                    return formattedValue;
                }
                return value;
            } catch (e) {
                log.debug('error in formating', e)
            }
        }

        return { onRequest };
    }
);

Template Code:

<?xml version="1.0"?>
<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<head>
	<link name="NotoSans" type="font" subtype="truetype" src="${nsfont.NotoSans_Regular}" src-bold="${nsfont.NotoSans_Bold}" src-italic="${nsfont.NotoSans_Italic}" src-bolditalic="${nsfont.NotoSans_BoldItalic}" bytes="2" />
	<#if .locale == "zh_CN">
		<link name="NotoSansCJKsc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKsc_Regular}" src-bold="${nsfont.NotoSansCJKsc_Bold}" bytes="2" />
	<#elseif .locale == "zh_TW">
		<link name="NotoSansCJKtc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKtc_Regular}" src-bold="${nsfont.NotoSansCJKtc_Bold}" bytes="2" />
	<#elseif .locale == "ja_JP">
		<link name="NotoSansCJKjp" type="font" subtype="opentype" src="${nsfont.NotoSansCJKjp_Regular}" src-bold="${nsfont.NotoSansCJKjp_Bold}" bytes="2" />
	<#elseif .locale == "ko_KR">
		<link name="NotoSansCJKkr" type="font" subtype="opentype" src="${nsfont.NotoSansCJKkr_Regular}" src-bold="${nsfont.NotoSansCJKkr_Bold}" bytes="2" />
	<#elseif .locale == "th_TH">
		<link name="NotoSansThai" type="font" subtype="opentype" src="${nsfont.NotoSansThai_Regular}" src-bold="${nsfont.NotoSansThai_Bold}" bytes="2" />
	</#if>
    <macrolist>
        <macro id="footer">
<table class="footer" style="width: 100%;"><tr>
<td align="center" font-size="11px">Page <pagenumber/> </td>
</tr></table>
        </macro>
    </macrolist>
    <style>
			* {
			<#if .locale == "zh_CN">
				font-family: NotoSans, NotoSansCJKsc, sans-serif;
			<#elseif .locale == "zh_TW">
				font-family: NotoSans, NotoSansCJKtc, sans-serif;
			<#elseif .locale == "ja_JP">
				font-family: NotoSans, NotoSansCJKjp, sans-serif;
			<#elseif .locale == "ko_KR">
				font-family: NotoSans, NotoSansCJKkr, sans-serif;
			<#elseif .locale == "th_TH">
				font-family: NotoSans, NotoSansThai, sans-serif;
			<#else>
				font-family: NotoSans, sans-serif;
			</#if>
			}
              {
              font-family: TimesNewRoman, serif;
                  font-size: 11x;
                }
              table {
			font-size: 11px;
			table-layout: fixed;
		}
               td {
            padding: 8px 3px 6px;
        }
            span.title {
                font-size: 16px;
            }
            span.number {
                font-size: 11px;
            }
             table.itemtable th {
            padding-bottom: 12px;
            padding-top: 8px;
        }
          table.footer td {
            padding: 0;
            font-size: 8px;
        }
            td.empty {
                border: none;
               background-color: #e3e3e3;
            }
            th {
                font-weight: bold;
                vertical-align: middle;
                padding: 5px 6px 3px;
                background-color: #e3e3e3;
                color: #333333;
            }
               tr.totalrow {
            background-color: #e3e3e3;
            line-height: 200%;
        }
			td p { align:left }
        </style>
</head>
<body footer="footer" footer-height="0.25in" padding="0.5in 0.5in 0.5in 0.5in" size="Letter">
    <table class="header" style="width: 100%; height: 23.5833px;"><tr style="height: 23.5833px;">
<td style="height: 23.5833px;" colspan="7">&nbsp;</td>
<td style="height: 23.5833px;" colspan="4" align="center"><span class="title">Deposit Summary </span></td>
<td style="height: 23.5833px;" colspan="4" align="right" font-size="11px">${.now?string('MM/dd/yyyy')} ${.now?string("hh:mm a")}</td>
</tr></table>
<table class="header" style="width: 100%;"><tr style="height: 22px;">
<td style="height: 22px;" align="center" font-size="11px"><span class="number"> CBRC LLC</span></td>
</tr>
<tr>
<td align="center">Summary of Deposits to ${contents.contents.account} on ${contents.contents.trandate}</td>
</tr></table>
<table class="itemtable" table-layout= "fixed" style="width: 100%; margin-top: 10px;">
<thead font-size="11px">
<tr border-bottom="2px solid" >
<th colspan="2" align="left">&nsbp;<strong>Check No</strong></th>
<th colspan="2" align="left">&nsbp;<strong>Pmt Method</strong></th>
<th colspan="4" align="left">&nsbp;<strong>Received From</strong></th>
<th colspan="4" align="left"><strong>Memo</strong></th>
<th colspan="2" align="right"><strong>Amount</strong></th>
</tr>
</thead>
<#list contents.contents.lines as item><tr>
<td font-size="11px" colspan="2" align="left">${item.checkNo}</td>
<td font-size="11px"  colspan="2" align="left">${item.method}</td>
<td font-size="11px" colspan="4" align="left">${item.customer}</td>
<td font-size="11px"  colspan="4" align="left">${item.memo}</td>
<td font-size="11px" colspan="2" align="right">${item.amount}</td>
</tr>
</#list>
<tr>
<td>&nbsp;</td>
</tr></table>
<table style="height: 50px;" width="100%"><tr class="totalrow" style="height: 48px;">
<td style="height: 50px;" colspan="10" v-align="bottom" align="left" font-size="11px"><strong>Deposit Total</strong></td>
<td style="height: 50px;" colspan="2">&nbsp;</td>
<td style="height: 50px;" colspan="2" v-align="bottom" align="right" font-size="11px"><b>${contents.contents.totalAmount}</b></td>
</tr></table>
</body>
</pdf>

Leave a comment

Your email address will not be published. Required fields are marked *