Send an Email when Item Fulfillment is changed to shipped staus

/**

 * @NApiVersion 2.1

 * @NScriptType UserEventScript

 */

define([‘N/record’, ‘N/email’, ‘N/runtime’, ‘N/search’, ‘N/render’],

    /**

     * @param{record} record

     * @param{email} email

     * @param{runtime} runtime

     * @param{search} search

     * @param{render} render

     */

    (record, email, runtime, search, render) => {

        /**

         * Defines the function definition that is executed after 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 afterSubmit = (context) => {

            try {

                let fulfillmentRecord = context.newRecord;

                let fulfillmentId = fulfillmentRecord.id;

                let shipStatus = fulfillmentRecord.getValue({

                    fieldId: “shipstatus”

                })

                log.debug(“shipStatus”, shipStatus);

                // Check conditions: Status changes to “Shipped” or is directly created in “Shipped”

                const oldShipStatus = context.oldRecord ? context.oldRecord.getValue({ fieldId: “shipstatus” }) : null;

                const isStatusChangedToShipped = (oldShipStatus === “A” || oldShipStatus === “B”) && shipStatus === “C”;

                const isDirectlyShipped = !context.oldRecord && shipStatus === “C”;

                if (isStatusChangedToShipped || isDirectlyShipped) {

                    let createdFromSalesorder = checkCreatedFromType(fulfillmentId);

                    if (createdFromSalesorder > 0) {

                        let salesOrderId = fulfillmentRecord.getValue({ fieldId: ‘createdfrom’ });

                        let soNum = fulfillmentRecord.getValue({ fieldId: ‘sonum’ });

                        // Proceed only if created from a Sales Order

                        if (!salesOrderId) return;

                        // Load the associated Sales Order

                        let salesOrder = record.load({

                            type: record.Type.SALES_ORDER,

                            id: salesOrderId

                        });

                        // Get Customer ID

                        let customerId = salesOrder.getValue({ fieldId: ‘entity’ });

                        // let customerName = fulfillmentRecord.getText({ fieldId: ‘entity’ });

                        let customerRecord = record.load({

                            type: record.Type.CUSTOMER,

                            id: customerId

                        });

                        // Check ‘Exclude IF Emails’ field

                        let customerName = customerRecord.getValue({ fieldId: ‘altname’ });

                        log.debug(“customerName”, customerName);

                        let excludeEmails = customerRecord.getValue({ fieldId: ‘custentity_jj_exclude_if_emails’ });

                        log.debug(“excludeEmails”, excludeEmails);

                        if (excludeEmails) return; // Exit if the customer opted out of IF emails

                        // Determine the email address to use

                        let ifEmailAddress = customerRecord.getValue({ fieldId: ‘custentity_jj_if_email_address’ });

                        let primaryEmail = customerRecord.getValue({ fieldId: ’email’ });

                        let emailToSend = ifEmailAddress || primaryEmail; // Use custom IF email if available, otherwise fallback to primary email

                        if (!emailToSend) return; // Exit if no email address is found

                        // Email Content

                        let poNumber = salesOrder.getValue({ fieldId: ‘otherrefnum’ }) || ‘N/A’;

                        //let shipMethod, shipcarrier;

                        let itemfulfillmentSearch = itemFulfillmentDetails(fulfillmentId);

                        log.debug(“itemfulfillmentSearch”, itemfulfillmentSearch);

                        let shipcarrier = ;

                        shipcarrier = itemfulfillmentSearch.shipCarrier;

                        log.debug(“shipcarrier”, shipcarrier);

                        let shipMethod = ;

                        shipMethod = itemfulfillmentSearch.shipMethod;

                        log.debug(“shipMethod”, shipMethod);

let items = itemDetails(fulfillmentRecord);

                        log.debug(“items”, items)

                        let emailSubject = ;

                        let emailBody = ;

                        let package = [];

                        let trackingNumbers = ‘N/A’;

                        let trackingLinkHtml = ‘N/A’;

                        let trackingLinks = ‘N/A’;

                        if ((shipcarrier == ‘nonups’ && shipMethod == “3”) || (shipcarrier == ‘ups’ && shipMethod == “”) || (shipcarrier == ‘nonups’ && shipMethod == “”)) {

                            let packageCount = fulfillmentRecord.getLineCount({ sublistId: ‘package’ });

                            log.debug(“packageCount”, packageCount);

                            for (let i = 0; i < packageCount; i++) {

                                package.push({

                                    trackingNumber: fulfillmentRecord.getSublistValue({ sublistId: ‘package’, fieldId: ‘packagetrackingnumber’, line: i }),

                                });

                            }

                            log.debug(“package”, package)

                            trackingLinks = package.map(pkg => {

                                if (pkg.trackingNumber) {

                                    return `<a href=”https://tools.usps.com/go/TrackConfirmAction_input?strOrigTrackNum=${pkg.trackingNumber}

                       style=”color: blue; text-decoration: underline;”>

                       ${pkg.trackingNumber}

                    </a>`;

                                } else {

                                    return ‘N/A’;

                                }

                            });

                            log.debug(“trackingLinks”, trackingLinks);

                            // If you want to display all the links in a single HTML block, join them with line breaks or commas

                            trackingLinkHtml = trackingLinks.join(‘<br/>’);

                            log.debug(“trackingLinkHtml”, trackingLinkHtml);

                            trackingNumbers = package.length > 0 ? package.map(pkg => pkg.trackingNumber).join(‘, ‘) : ‘N/A’;

                            log.debug(“trackingNumbers”, trackingNumbers);

                        }

                        if ((shipcarrier == ‘ups’ && shipMethod == “686”) || (shipcarrier == ‘ups’ && shipMethod == “685”) || (shipcarrier == ‘ups’ && shipMethod == “4”)) {

                            log.debug(“Inside UPS Handling”, “Handling UPS tracking details”);

                            let upsTrackingNumbers = trackingNumber(fulfillmentId);

                            log.debug(“UPS Tracking Numbers”, upsTrackingNumbers);

                            // Join all UPS tracking numbers into a single query string

                            let trackingQueryString = upsTrackingNumbers.map((num, index) => `InquiryNumber${index + 1}=${num}`).join(“&”);

                            // Create the tracking link

                            trackingLinkHtml = `<a href=”https://www.ups.com/track?TypeOfInquiryNumber=T&${trackingQueryString}

                          style=”color: blue; text-decoration: underline;”>

                          Track Your Packages

                        </a>`;

                            trackingNumbers = upsTrackingNumbers.length > 0 ? upsTrackingNumbers.join(“, “) : ‘N/A’;

                            log.debug(“UPS Tracking Link HTML”, trackingLinkHtml);

                            log.debug(“Tracking Numbers”, trackingNumbers);

                        }

                        let itemHtml = generateItemTable(items);

                        log.debug(“itemHtml”, itemHtml);

                      // Send Email

                        let senderId = 5;

                        if (shipcarrier == ‘nonups’ && shipMethod == “”) {

                            let emailTemplate = render.mergeEmail({

                                templateId: 14,

                                entity: {

                                    type: ’employee’,

                                    id: senderId

                                }

                            });

                            emailSubject = emailTemplate.subject;

                            emailBody = emailTemplate.body

                                .replace(‘{{CUSTOMER_NAME}}’, customerName)

                                .replace(‘{{PO_NUMBER}}’, poNumber)

                                .replace(‘{{ITEM_LIST}}’, itemHtml)

                                .replace(‘{{salesordertranid}}’, soNum);

                        } else {

                            let emailTemplate = render.mergeEmail({

                                templateId: 13,

                                entity: {

                                    type: ’employee’,

                                    id: senderId

                                }

                            });

                            emailSubject = emailTemplate.subject;

                            emailBody = emailTemplate.body

                                .replace(‘{{CUSTOMER_NAME}}’, customerName)

                                .replace(‘{{PO_NUMBER}}’, poNumber)

                                .replace(‘{{ITEM_LIST}}’, itemHtml)

                                .replace(‘{{salesordertranid}}’, soNum);

                            if (trackingNumbers !== ‘N/A’ && trackingLinkHtml !== ‘N/A’) {

                                emailBody = emailBody

                                    .replace(‘{{trackingNumbers}}’, trackingNumbers)

                                    .replace(‘{{TRACKING_LINK}}’, trackingLinkHtml);

                            } else {

                                // If no tracking info, remove the lines completely

                                emailBody = emailBody.replace(‘Tracking numbers:’, );

                                emailBody = emailBody.replace(‘Link to tracking information on carrier website:’, );

                                emailBody = emailBody.replace(‘{{trackingNumbers}}’, );

                                emailBody = emailBody.replace(‘{{TRACKING_LINK}}’, );

                            }

                        }

                        email.send({

                            author: runtime.getCurrentUser().id,

                            recipients: emailToSend,

                            subject: emailSubject,

                            body: emailBody,

                            relatedRecords: {

                                transactionId: fulfillmentRecord.id

                            }

                        });

                    }

                    else {

                        log.debug(“Item Fulfillment is not created from sales order”, “Item Fulfillment is not created from sales order”)

                    }

                }

            } catch (e) {

                log.error(‘Error Sending IF Email’, e.toString());

            }

        }

        /**

         * Function to check the Item fulfillment is created from Sales Order

         * @param {fulfillmentId} fulfillmentId – The internal Id of the item Fulfillment

         * @returns {searchResultCount} – Search result count

         */

        function checkCreatedFromType(fulfillmentId) {

            let itemfulfillmentSearchObj = search.create({

                type: “itemfulfillment”,

                filters:

                    [

                        [“type”, “anyof”, “ItemShip”],

                        “AND”,

                        [“createdfrom.type”, “anyof”, “SalesOrd”],

                        “AND”,

                        [“internalid”, “anyof”, fulfillmentId]

                    ],

                columns:

                    [

                        search.createColumn({ name: “tranid”, label: “Document Number” }),

                    ]

            });

            let searchResultCount = itemfulfillmentSearchObj.runPaged().count;

            log.debug(“itemfulfillmentSearchObj result count”, searchResultCount);

            return searchResultCount;

        }

        /**

       * Function to get the item details

       * @param {fulfillmentRecord} fulfillmentRecord – The fulfillment record

       * @returns {items}

       */

        function itemDetails(fulfillmentRecord) {

            //log.debug(“fulfillmentRecord”, fulfillmentRecord);

            let itemDisplayName = ‘N/A’;

            let item = [];

            let itemCount = fulfillmentRecord.getLineCount({ sublistId: ‘item’ });

            for (let i = 0; i < itemCount; i++) {

                //let itemId = fulfillmentRecord.getSublistValue({ sublistId: ‘item’, fieldId: ‘item’, line: i });

                let itemName = fulfillmentRecord.getSublistValue({ sublistId: ‘item’, fieldId: ‘itemname’, line: i });

                log.debug(“itemName”, itemName);

                itemDisplayName = fulfillmentRecord.getSublistValue({ sublistId: ‘item’, fieldId: ‘displayname’, line: i });

                log.debug(“itemDisplayName”, itemDisplayName);

                let quantity = fulfillmentRecord.getSublistValue({ sublistId: ‘item’, fieldId: ‘quantity’, line: i });

                log.debug(“quantity”, quantity);

                let displayName = itemDisplayName || itemName;

                if (quantity > 0) {

                    item.push({

                        name: displayName,

                        description: fulfillmentRecord.getSublistValue({ sublistId: ‘item’, fieldId: ‘itemdescription’, line: i }),

                        quantity: quantity,

                    });

                }

            }

            return item;

        }

        /**

        * Function to get the tracking number of package

        * @param {fulfillmentId} fulfillmentId – The internal Id of the item Fulfillment

        * @returns {shippigDetailsa}

        */

        function itemFulfillmentDetails(fulfillmentId) {

            let shippigDetails = {}; // Object to store the shipping details

            let itemfulfillmentSearchObj = search.create({

                type: “itemfulfillment”,

                filters: [

                    [“type”, “anyof”, “ItemShip”], // Item Fulfillment type

                    “AND”,

                    [“internalid”, “anyof”, fulfillmentId], // Internal ID of the specific Item Fulfillment

                    “AND”,

                    [“mainline”, “is”, “T”] // Mainline filter

                ],

                columns: [

                    search.createColumn({ name: “shipmethod”, label: “Ship Via” }),

                    search.createColumn({ name: “shipcarrier”, label: “Shipping Carrier” })

                ]

            });

            // Execute the search and process the results

            let searchResult = itemfulfillmentSearchObj.run().getRange({ start: 0, end: 1 }); // Fetch the first result

            if (searchResult && searchResult.length > 0) {

                let result = searchResult[0];

                shippigDetails.shipMethod = result.getValue({ name: “shipmethod” }) || ; // Store ship method

                shippigDetails.shipCarrier = result.getValue({ name: “shipcarrier” }) || ; // Store ship carrier

            } else {

                log.debug(“No results found for the provided fulfillment ID”, fulfillmentId);

            }

            log.debug(“Item Fulfillment Details”, shippigDetails);

            return shippigDetails; // Return the object with shipping details

        }

        function generateItemTable(items) {

            let itemHtml =

                `

            <table style=”width: 100%; border-collapse: collapse;”>

            <thead>

                <tr>

                    <th style=”padding: 8px; text-align: left; background-color: #f0f0f0;”><b>Item</b></th>

                    <th style=”padding: 8px; text-align: left; background-color: #f0f0f0;”><b>Description</b></th>

                    <th style=”padding: 8px; text-align: left; background-color: #f0f0f0;”><b>Quantity</b></th>

                </tr>

            </thead>

            <tbody>

                ${items.map(item => `

                    <tr>

                        <td style=”padding: 8px;”>${item.name}</td>

                        <td style=”padding: 8px;”>${item.description}</td>

                        <td style=”padding: 8px;”>${item.quantity}</td>

                    </tr>

                `).join()}

            </tbody>

        </table>`;

            return itemHtml;

        }

        /**

        * Function to get the tracking number of package

        * @param {fulfillmentId} fulfillmentId – The internal Id of the item Fulfillment

        * @returns {trackingNumbers} – Return tracking numbers

        */

        function trackingNumber(fulfillmentId) {

            // Initialize an array to hold tracking numbers

            let trackingNumbers = [];

            // Create the search for item fulfillment

            var itemfulfillmentSearchObj = search.create({

                type: “itemfulfillment”,

                settings: [{ “name”: “consolidationtype”, “value”: “ACCTTYPE” }],

                filters: [

                    [“type”, “anyof”, “ItemShip”],

                    “AND”,

                    [“internalid”, “anyof”, fulfillmentId],

                    “AND”,

                    [“mainline”, “is”, “T”]

                ],

                columns: [

                    search.createColumn({ name: “tranid”, label: “Document Number” }),

                    search.createColumn({ name: “trackingnumbers”, label: “Tracking Numbers” }),

                    search.createColumn({

                        name: “weightinlbs”,

                        join: “shipmentPackage”,

                        label: “Weight In Pounds”

                    })

                ]

            });

            // Execute the search and process the results

            itemfulfillmentSearchObj.run().each(function (result) {

                // Get the tracking numbers field value

                let trackingNumberField = result.getValue({ name: “trackingnumbers” });

                // Split the tracking numbers if they are comma-separated

                if (trackingNumberField) {

                    let trackingArray = trackingNumberField.split(‘,’);

                    trackingNumbers = trackingNumbers.concat(trackingArray.map(num => num.trim()));

                }

                return true; // Continue to the next result

            });

            log.debug(“trackingNumbers”, trackingNumbers);

            // Return the array of tracking numbers

            return trackingNumbers;

        }

        return { afterSubmit }

    });

Leave a comment

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