Adding credits applied details in the email template as a table.

The credits applied cannot be fetched in the beforeSubmit and afterSubmit contexts from the payment record. It can be accessed in the beforeLoad context.

 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */

define(['N/record', 'N/search', 'N/ui/serverWidget', 'N/email', 'N/render', 'N/format'],
    /**
     * @param{record} record
     * @param{search} search
     * @param{serverWidget} serverWidget
     */
    (record, search, serverWidget, email, render, format) => {


        const CURRENCY_MAP = {   //prod
            "CAD": '$',
            "USD": '$',
            "NZD": '$',
            "EUR": '€',
            "GBP": '£',
            "AUD": '$'
        }


        /**
         * Function to get the date in required format
         * @param {string} dateValue 
         * @returns {string}
         */
        function formatDate(dateValue) {
            if (dateValue) {
                let formattedDate = format.parse({ value: dateValue, type: format.Type.DATE });
                return format.format({ value: formattedDate, type: format.Type.DATE, format: 'DD/MM/YYYY' });
            }
            return '';
        }


        /**
         * Function to get the total value for the transactions from which credit amount is applied.
         * @param {string} refNum 
         * @returns {object}
         */
        function getTotalValue(refNum) {
            try {
                let transactionSearchObj = search.create({
                    type: "transaction",
                    filters:
                        [
                            ["type", "anyof", "CustCred", "CustPymt", "Journal"],
                            "AND",
                            ["numbertext", "is", refNum],
                            "AND",
                            ["mainline", "is", "T"]
                        ],
                    columns:
                        [
                            search.createColumn({ name: "amount", label: "Amount" }),
                            search.createColumn({ name: "amountremaining", label: "Amount Remaining" })
                        ]
                });
                let totalamt, remainingAmt;
                transactionSearchObj.run().each(function (result) {
                    totalamt = parseFloat(result.getValue({ name: "amount", label: "Amount" }));
                    remainingAmt = parseFloat(result.getValue({ name: "amountremaining", label: "Amount Remaining" }));
                    return false;
                });
                return {
                    totalamt: totalamt,
                    remainingAmt: remainingAmt
                };
            } catch (e) {
                log.error("error@getTotalValue", e);
                return {};
            }
        }


        /**
         * Function to set the applied to transaction details in the email template
         * @param {object} newRec 
         * @returns {object}
         */
        function setAppliesToValueToEmailTemPlate(newRec, currencySymbol) {
            try {
                let lineCount = newRec.getLineCount({ sublistId: 'apply' });
                let tableRows = '';
                let totalPayment = 0;
                for (let i = 0; i < lineCount; i++) {
                    let applySelected = newRec.getSublistValue({
                        sublistId: 'apply',
                        fieldId: 'apply',
                        line: i
                    });
                    if (applySelected == true) {
                        let applyDate = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'applydate',
                            line: i
                        });
                        // Format the date in the desired format (DD/MM/YYYY)
                        let formattedDate;
                        if (applyDate) {
                            formattedDate = formatDate(applyDate)
                        }
                        let trasactionType = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'trantype',
                            line: i
                        });
                        let invoiceNum = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'refnum',
                            line: i
                        });
                        let type = '';
                        if (trasactionType == 'CustInvc') {
                            type = "Invoice";
                        }
                        let description = type + ' #' + invoiceNum;
                        let originalAmt = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'total',
                            line: i
                        });
                        let payment = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'amount',
                            line: i
                        });
                        totalPayment += parseFloat(payment);
                        let discount = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'disc',
                            line: i
                        });
                        let amountTobePaid = newRec.getSublistValue({
                            sublistId: 'apply',
                            fieldId: 'due',
                            line: i
                        });
                        // calculate the open balce value 
                        let openBalance = amountTobePaid - payment - discount;
                        // add the table rows for the applied to details
                        tableRows += `<tr>` +
                            '<td align="center" colspan="4">' + formattedDate + '</td>' +
                            '<td align="center" colspan="20">' + description + '</td>' +
                            '<td align="right" colspan="4">' + (originalAmt ? currencySymbol + originalAmt : '') + '</td>' +
                            '<td align="right" colspan="4">' + (payment ? currencySymbol + payment : '') + '</td>' +
                            '<td align="right" colspan="4">' + (discount ? currencySymbol + discount : '') + '</td>' +
                            '<td align="right" colspan="4">' + currencySymbol + (openBalance.toFixed(2) || '0.00') + '</td>' +
                            '</tr>';
                    }
                }
                return { tableRows: tableRows, totalPayment: totalPayment.toFixed(2) };
            } catch (e) {
                log.error("error@setAppliesToValueToEmailTemPlate", e);
                return {};
            }
        }


        /**
         * Function to set the credir applied details in the email template
         * @param {object} newRec 
         * @param {string} currencySymbol
         * @returns {object}
         */
        function setCreditValues(newRec, currencySymbol) {
            try {
                let lineCount = newRec.getLineCount({ sublistId: 'credit' });
                let tableRows = '';
                let totalCredit = 0;
                if (lineCount) {
                    for (let i = 0; i < lineCount; i++) {
                        let creditSelected = newRec.getSublistValue({
                            sublistId: 'credit',
                            fieldId: 'apply',
                            line: i
                        });
                        if (creditSelected == true) {
                            let creditDate = newRec.getSublistValue({
                                sublistId: 'credit',
                                fieldId: 'creditdate',
                                line: i
                            });
                            // Convert applyDate to a JavaScript Date object
                            let formattedDate;
                            if (creditDate) {
                                formattedDate = formatDate(creditDate)
                            }
                            let trasactionType = newRec.getSublistText({
                                sublistId: 'credit',
                                fieldId: 'trantype',
                                line: i
                            });
                            let refNum = newRec.getSublistValue({
                                sublistId: 'credit',
                                fieldId: 'refnum',
                                line: i
                            });
                            let type;
                            if (trasactionType == 'CustInvc') {
                                type = "Invoice";
                            } else if (trasactionType == 'CustCred') {
                                type = "CreditMemo";
                            } else if (trasactionType == 'CustPymt') {
                                type = "Payment";
                            } else if (trasactionType == 'Journal') {
                                type = 'Journal';
                            } else {
                                type = '';
                            }
                            let description = type + ' #' + refNum;
                            let dueAmt = newRec.getSublistValue({
                                sublistId: 'credit',
                                fieldId: 'due',
                                line: i
                            });
                            let payment = newRec.getSublistValue({
                                sublistId: 'credit',
                                fieldId: 'amount',
                                line: i
                            });
                            totalCredit += parseFloat(payment);
                            let discount = newRec.getSublistValue({
                                sublistId: 'credit',
                                fieldId: 'disc',
                                line: i
                            });
                            let totalCreditValue = getTotalValue(refNum); // to get the balance from the corresponding record
                            let totalVal = Math.abs(totalCreditValue.totalamt);
                            let openBalance = totalCreditValue.remainingAmt || '0.00';
                            //Add table rows for the credits applied details
                            tableRows += `<tr>` +
                                '<td align="center" colspan="4">' + formattedDate + '</td>' +
                                '<td align="center" colspan="20">' + description + '</td>' +
                                '<td align="right" colspan="4">' + '-' + currencySymbol + totalVal + '</td>' +
                                '<td align="right" colspan="4">' + '-' + currencySymbol + payment + '</td>' +
                                '<td align="right" colspan="4">' + (discount ? currencySymbol + discount : '') + '</td>' +
                                '<td align="right" colspan="4">' + '-' + currencySymbol + openBalance + '</td>' +
                                '</tr>';
                        }
                    }
                }
                return { tableRows: tableRows, totalCredit: totalCredit.toFixed(2) };
            } catch (e) {
                log.error("error@setCreditValues", e);
                return {};
            }
        }


        /**
        * Function to set the sublist values to email template
        * @param {string} emailBody 
        * @param {object} newRec 
        * @returns {string}
        */
        function setValuesToEmailTemplate(emailBody, newRec) {
            try {
                let currencyCode = newRec.getValue({
                    fieldId: 'currencysymbol'
                });
                let currencySymbol = CURRENCY_MAP[currencyCode] || '$';
                let appliesToData = setAppliesToValueToEmailTemPlate(newRec, currencySymbol);
                let appliesToRows = appliesToData.tableRows;
                let totalPayment = appliesToData.totalPayment;
                let creditsAppliedData = setCreditValues(newRec, currencySymbol);
                let creditRows = creditsAppliedData.tableRows;
                // Combine all rows
                let allRows = appliesToRows + creditRows;
                // Apply alternate row shading
                let rows = allRows.split('<tr');
                let tableRows = '';
                // add shading to table rows
                for (let i = 1; i < rows.length; i++) { // Start from 1 because split will create an empty first element
                    let rowColor = (i % 2 === 0) ? '#ffffff' : '#e3e3e3';
                    tableRows += '<tr style="background-color: ' + rowColor + ';"' + rows[i];
                }
                // Create the table HTML
                let tableHtml = '<table class="itemtable" style="width:833px; margin-top: 10px;">' +
                    '<thead>' +
                    '<tr>' +
                    '<th align="center" colspan="4">Date</th>' +
                    '<th align="center" colspan="20">Description</th>' +
                    '<th align="center" colspan="4">Original Amount</th>' +
                    '<th align="center" colspan="4">Payment</th>' +
                    '<th align="center" colspan="4">Discount</th>' +
                    '<th align="center" colspan="4">Open Balance</th>' +
                    '</tr>' +
                    '</thead>' +
                    '<tbody>' + tableRows + '</tbody></table>';
                let totalCredit = creditsAppliedData.totalCredit;
                let total = Math.abs(totalPayment - totalCredit);
                tableHtml += '</tbody></table>';
                emailBody = emailBody.replace('[PAYMENT_SUMMARY_TABLE]', tableHtml);
                emailBody = emailBody.replace('TOTAL_VALUE', currencySymbol+total.toFixed(2));
                return emailBody;
            } catch (e) {
                log.error("error@setValuesToEmailTemplate", e);
                return '';
            }
        }


        /**
         * Function to get the customer email
         * @param {string} id 
         * @returns {string}
         */
        function getCustomerEmail(id){
            try{
                let customerpaymentSearchObj = search.create({
                    type: "customerpayment",
                    filters:
                    [
                       ["type","anyof","CustPymt"], 
                       "AND", 
                       ["internalid","anyof",id], 
                       "AND", 
                       ["mainline","is","T"]
                    ],
                    columns:
                    [
                       search.createColumn({
                          name: "email",
                          join: "customer",
                          label: "Email"
                       })
                    ]
                 });
                 let custEmail;
                 customerpaymentSearchObj.run().each(function(result){
                    custEmail = result.getValue({
                        name: "email",
                        join: "customer",
                        label: "Email"
                     })
                    return false;
                 });
                 return custEmail;
            }catch(e){
                log.error("error@getCustomerEmail",e);
                return '';
            }
        }


        /**
        * Defines the function definition that is executed before record is loaded.
        * @param {Object} scriptContext
        * @param {Record} scriptContext.newRecord - New record
        * @param {string} scriptContext.type - Trigger type; use values from the context.UserEventType enum
        * @since 2015.2
        */
        const beforeLoad = (scriptContext) => {
            try {
                let newRec = scriptContext.newRecord;
                let id = newRec.id;
                let recType = newRec.type;
                if (recType == 'customerpayment') {
                    let emailSendFlag = newRec.getValue({
                        fieldId: 'custbody_jj_payment_receipt_flag'
                    });
                    let customerName = newRec.getText({
                        fieldId: 'customer'
                    });
                    let recepient = getCustomerEmail(id);
                    log.debug("recepient",recepient);
                    if (id && emailSendFlag === true) { // checking for the condition that the custom checkbox is true.
                        let mergeResult = render.mergeEmail({ // taking the template to add the cotent table
                            templateId: 517,
                            entity: null,
                            recipient: null,
                            supportCaseId: null,
                            transactionId: id,
                            customRecord: null
                        });
                        let emailSubject = mergeResult.subject;
                        let emailBody = mergeResult.body;
                        emailBody = emailBody.replace("CUSTOMERNAME", customerName);
                        emailBody = setValuesToEmailTemplate(emailBody, newRec);
                        if(recepient){
                            email.send({
                                author: 58001,
                                recipients: recepient,
                                subject: emailSubject,
                                body: emailBody,
                                relatedRecords: {
                                    transactionId: id
                                }
                            });
                            log.debug("email sent");
                        }
                        //After email sent, set the custom checkbox as false.
                        record.submitFields({
                            type: record.Type.CUSTOMER_PAYMENT,
                            id: id,
                            values: {
                                custbody_jj_payment_receipt_flag: false
                            },
                            options: {
                                enableSourcing: false,
                                ignoreMandatoryFields: true
                            }
                        });
                    }
                }
            } catch (e) {
                log.error("error@beforeLoad", e);
            }
        }


        /**
        * Defines the function definition that is executed before record is submitted.
        * @param {Object} scriptContext
        * @param {Record} scriptContext.newRecord - New record
        * @param {Record} scriptContext.oldRecord - Old record
        * @param {string} scriptContext.type - Trigger type; use values from the context.UserEventType enum
        * @since 2015.2
        */
        const beforeSubmit = (scriptContext) => {
            try {
                let newRec = scriptContext.newRecord;
                let recType = newRec.type;
               // make the custom checkbox created  as true to get the trigger for email sending in before load cotext
                    if (scriptContext.type == 'create') {
                        newRec.setValue({
                            fieldId: 'custbody_jj_payment_receipt_flag',
                            value: true,
                            ignoreFieldChange: true
                        });
                    }
            
            } catch (e) {
                log.error("error@beforeSubmit", e);
            }
        }
        return { beforeLoad, beforeSubmit }
    });



Leave a comment

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