Automate statement 10 days before the invoices are due

/**
 * @NApiVersion 2.1
 * @NScriptType MapReduceScript
 */

define(['N/currentRecord', 'N/email', 'N/error', 'N/file','N/xml', 'N/record', 'N/recordContext', 'N/render', 'N/runtime', 'N/search'],
    
    (currentRecord, email, error, file,xml, record, recordContext, render, runtime,search) => {

        const getInputData = (inputContext) => {
            try{

                // search for getting invoices with open status and due date's 11 days equal to today
                var invoiceSearchObj = search.create({
                    type: "invoice",
                    filters:
                        [
                            ["type","anyof","CustInvc"],
                            "AND",
                            ["mainline","is","T"],
                            "AND",
                            ["shipping","is","F"],
                            "AND",
                            ["cogs","is","F"],
                            "AND",
                            ["taxline","is","F"],
                            "AND",
                            ["status","anyof","CustInvc:A"],
                            "AND",
                            ["formulanumeric: CEIL({duedate}-{today})","equalto","11"]
                        ],
                    columns:
                        [
                            search.createColumn({name: "tranid", label: "Document Number"}),
                            search.createColumn({name: "duedate", label: "Due Date/Receive By"}),
                            search.createColumn({name: "internalid", label: "Internal ID"}),
                            search.createColumn({name: "trandate", label: "Date"}),
                            search.createColumn({name: "total", label: "Amount (Transaction Total)"}),
                            search.createColumn({
                                name: "internalid",
                                join: "customer",
                                label: "Internal ID"
                            }),
                            search.createColumn({name: "formulanumeric", label: "Amount (Transaction Total)"}),

                        ]
                });
                var resultArray = [];
                var searchResultCount = invoiceSearchObj.runPaged().count;
                log.debug("invoiceSearchObj result count", searchResultCount);
                if (searchResultCount > 0) {
                    invoiceSearchObj.run().each(function (result) {
                        var resultObj={};
                        resultObj.dueDate = result.getValue({name: "duedate", label: "Due Date/Receive By"});
                        resultObj.internalId = result.getValue({name: "internalid",label: "Internal ID"});
                        resultObj.date= result.getValue({name: "trandate", label: "Date"});
                        resultObj.amountTotal= result.getValue({name: "total", label: "Amount (Transaction Total)"});
                        resultObj.docNum= result.getValue({name: "tranid", label: "Document Number"});
                        resultObj.custId=result.getValue({
                            name: "internalid",
                            join: "customer",
                            label: "Internal ID"
                        })
                        resultArray.push(resultObj);
                        return true;
                    });
                };
                return resultArray;

            }catch (e) {
                log.debug('Error @ GetInputData',e);
                return [];
            }
        }

        const map = (mapContext)=>{
            try{
                var resultObject=JSON.parse(mapContext.value);

                log.debug("resultObject",resultObject)
                var customerId= resultObject.custId;
                //log.debug("customerId",customerId)

                mapContext.write({
                    key:customerId,
                    value:resultObject
                })
            }catch (e) {
                log.debug('Error @ map',e);
                return [];
            }
        }

        const reduce = (reduceContext) => {
            try{

                var custData =  reduceContext.values.map(JSON.parse);
                log.debug("custData",custData)

            if(custData.length!==0) {

                var emailBody = '<div>Dear customer,<br/><br/> Please find attached your statement,<b>thank you for being a valued partner and a prompt payer</b>, we appreciate it very much.<b> This is just a friendly reminder that an invoice (s) will be due within the next 10 days.</b><br/> <br /></div> <table style=" border-collapse: collapse;"><tr style="height:50px;"> <th style="border:solid black; background-color:#45c0e5; font-weight: bold; width:170px; text-align:center;">Document Number</th><th style="border:solid black; background-color:#45c0e5; font-weight: bold; width:100px; text-align:center;">Created Date</th><th style="border:solid black; background-color:#45c0e5; font-weight: bold; width:90px; text-align:center;">Due Date</th><th style="border:solid black;background-color:#45c0e5; font-weight: bold; width:100px; text-align:center;">Total Amount</th></tr>';

                for (var i = 0; i < custData.length; i++) {
                    var customerIds = custData[i].custId;
                    var recURLHyperLink = 'https://tstdrv2570972.app.netsuite.com/app/accounting/transactions/custinvc.nl?id='+custData[i].internalId+'&whence=&cmid';
                    emailBody += '<tr style="height:40px;"><td style="border:solid black; width:170px;"><a href= '+recURLHyperLink+'>'+ custData[i].docNum + '</a></td><td style="border: solid black; width:100px;">' + custData[i].date + '</td><td style="border:solid black; width:90px;">' + custData[i].dueDate + '</td><td style="border: solid black; width:100px;">' + custData[i].amountTotal + '</td></tr>';
                }
                emailBody += '</table><br/><br/>';
                emailBody +='<div>Thank you for your support and business.<br/><br/>A/R Department<br/>ar@corpdesign.com</div>';

                //get email ids
                var custEmails = search.lookupFields({
                    type: "customer",
                    id: customerIds,
                    columns: ["custentitycustentity_jj_operation_email","custentity_jj_accounting_email","email"]
                });
                var opEmail = custEmails.custentitycustentity_jj_operation_email;
                var accEmail = custEmails.custentity_jj_accounting_email;
                var primeEmail = custEmails.email;

                var respEmail = [];
                if (opEmail && opEmail!=='') {
                    respEmail.push(opEmail)
                } else if (accEmail && accEmail!=='') {
                    respEmail.push(accEmail)
                } else if(primeEmail && primeEmail!==''){
                    respEmail.push(primeEmail)
                }

                 if (respEmail.length>0) {
                   

                     var statement = render.statement({
                         entityId: parseInt(customerIds),
                         printMode: render.PrintMode.PDF,

                     });


                    //send email to the user
                    email.send({
                        author:'-5',
                        recipients: respEmail,
                        body: emailBody,
                        subject: 'Statement',
                        attachments: [statement],
                        relatedRecords: {
                            entityId: parseInt(customerIds)
                        }
                    });
                }
            }
            }catch (e) {
                log.debug('Error @ reduceContext',e);

            }
        }
        return {getInputData,map,reduce}
    });

Leave a comment

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