Automate drawings Attachment

The client would like to attach the drawings of the item stored in the file cabinet to the corresponding item record

Jira Code: GTILC-397

/**
 * @NApiVersion 2.1
 * @NScriptType MapReduceScript
 */
/*************************************************************************************
 ***********
 * Graph Tech Guitar Labs
 *
 * GTILC-397 : Automation for adding drawings to its associated items
 *
 *
 *************************************************************************************
 ***********
 *
 *
 * Author: Jobin and Jismi IT Services LLP
 *
 * Date Created : 14-July-2023
 *
 * Description: This script is used to automatically attach drawings pdf to the assembly item record
 *
 * REVISION HISTORY
 *
 * @version 1.0 GTILC-397 : 14-July-2023 : Created the initial build by JJ0177
 *
 *
 *************************************************************************************
 **********/
define(['N/record', 'N/search', 'N/email', 'N/runtime'],

    (record, search, email, runtime) => {
        /**
         * Function to check whether the field has an empty value or not.
         * @param {parameter} parameter - fieldValue
         * @returns {boolean} true - if the value is not empty
         * @returns {boolean} false - if the value is empty
         */
        function checkForParameter(parameter) {
            try {
                if (parameter != "" && parameter != null && parameter != undefined && parameter != "null" && parameter != "undefined" && parameter != " " && parameter != false && parameter != '' && parameter != ' ') {
                    return true;
                } else {
                    return false;
                }
            }
            catch (e) {
                log.debug({
                    title: "Error @ empty check Function: ", details: e.name + ' : ' + e.message
                });
            }
        }
        /**
           * Saved search function to check whether items exist with similar drawings name
           * @param drawingPdfName{string}- drawings name
           * @returns itemsArray - array containing the items with similar drawings name
           */
        function searchItemsWithPdfName(drawingPdfName) {
            try {
                let itemsArray = [];
                let itemSearchObj = search.create({
                    type: "item",
                    filters:
                        [
                            ["type", "anyof", "Assembly"],
                            "AND",
                            ["name", "contains", drawingPdfName],
                            "AND",
                            ["custitem_jj_is_attached_gtilc_397", "is", "F"],
                            "AND",
                            ["isinactive", "is", "F"]

                        ],
                    columns:
                        [
                            search.createColumn({ name: "internalid", label: "Internal ID" })
                        ]
                });
                itemSearchObj.run().each(function (result) {
                    let itemId = result.getValue({
                        name: "internalid",
                        label: "Internal ID"
                    })
                    itemsArray.push(itemId);
                    return true;
                });
                return itemsArray;

            } catch (error) {
                log.debug("error @searchItemsWithPdfName", error);
                return [];
            }
        }
        /**
         * Defines the function that is executed at the beginning of the map/reduce process and generates the input data.
         * @param {Object} inputContext
         * @param {boolean} inputContext.isRestarted - Indicates whether the current invocation of this function is the first
         *     invocation (if true, the current invocation is not the first invocation and this function has been restarted)
         * @param {Object} inputContext.ObjectRef - Object that references the input data
         * @typedef {Object} ObjectRef
         * @property {string|number} ObjectRef.id - Internal ID of the record instance that contains the input data
         * @property {string} ObjectRef.type - Type of the record instance that contains the input data
         * @returns {Array|Object|Search|ObjectRef|File|Query} The input data to use in the map/reduce process
         * @since 2015.2
         */

        const getInputData = (inputContext) => {

            try {
                let today = new Date();
                let date = String(today.getDate()).padStart(2, '0');
                let daysBefore = date - 1;
                let month = String(today.getMonth() + 1).padStart(2, '0');
                let year = today.getFullYear();
                today = month + '/' + date + '/' + year;
                let twoDaysBefore = month + '/' + daysBefore + '/' + year;
                let fileSearchObj = search.create({
                    type: "file",
                    filters:
                        [
                            ["created", "within", twoDaysBefore, today],
                            "AND",
                            ["folder", "anyof", "295744"]
                        ],
                    columns:
                        [
                            search.createColumn({
                                name: "name",
                                sort: search.Sort.ASC,
                                label: "Name"
                            }),
                            search.createColumn({
                                name: "internalid",
                                label: "Internal ID"
                            })
                        ]
                });
                let drawingsNameArray = [], drawingsName;
                fileSearchObj.run().each(function (result) {
                    let drawingsObj = {};
                    drawingsName = result.getValue({
                        name: "name",
                        sort: search.Sort.ASC,
                        label: "Name"
                    })
                    let regex = /^(.*?)\s+drawing/;
                    let match = drawingsName.match(regex);

                    drawingsObj.newDrawingsName = match ? match[1] : null;
                    drawingsObj.drawingsId = result.getValue({
                        name: "internalid",
                        label: "Internal ID"
                    })
                    drawingsNameArray.push(drawingsObj);
                    return true;
                });

                return drawingsNameArray;
            } catch (error) {
                log.debug("error @getInput", error);
            }
        }
        /**
         * Defines the function that is executed when the reduce entry point is triggered. This entry point is triggered
         * automatically when the associated map stage is complete. This function is applied to each group in the provided context.
         * @param {Object} reduceContext - Data collection containing the groups to process in the reduce stage. This parameter is
         *     provided automatically based on the results of the map stage.
         * @param {Iterator} reduceContext.errors - Serialized errors that were thrown during previous attempts to execute the
         *     reduce function on the current group
         * @param {number} reduceContext.executionNo - Number of times the reduce function has been executed on the current group
         * @param {boolean} reduceContext.isRestarted - Indicates whether the current invocation of this function is the first
         *     invocation (if true, the current invocation is not the first invocation and this function has been restarted)
         * @param {string} reduceContext.key - Key to be processed during the reduce stage
         * @param {List<String>} reduceContext.values - All values associated with a unique key that was passed to the reduce stage
         *     for processing
         * @since 2015.2
         */
        const reduce = (reduceContext) => {
            try {
                let missMatchObj = {};
                let dataObj = JSON.parse(reduceContext.values[0]);
                let drawingsPdfName = dataObj.newDrawingsName;
                let drawingPdfId = dataObj.drawingsId;
                let pdfNameArray = drawingsPdfName.split("-");
                let pdfNameArray1 = pdfNameArray[1];
                if (pdfNameArray1.length != 2) {
                    missMatchObj.missedDrawingPdfName = drawingsPdfName;

                }

                else {
                    let isItemsExist = searchItemsWithPdfName(drawingsPdfName);
                    if (checkForParameter(isItemsExist)) {
                        for (let i = 0; i < isItemsExist.length; i++) {
                            record.attach({
                                record: {
                                    type: 'file',
                                    id: drawingPdfId
                                },
                                to: {
                                    type: 'assemblyitem',
                                    id: isItemsExist[i]
                                }
                            });
                            record.submitFields({
                                type: record.Type.ASSEMBLY_ITEM,
                                id: isItemsExist[i],
                                values: {
                                    'custitem_jj_is_attached_gtilc_397': true
                                },
                                options: {
                                    enableSourcing: false,
                                    ignoreMandatoryFields: true
                                }
                            });
                        }
                    }
                }
                if (checkForParameter(missMatchObj.missedDrawingPdfName)) {
                    reduceContext.write({
                        key: 'File error',
                        value: missMatchObj.missedDrawingPdfName
                    })

                }

            } catch (error) {
                log.debug("error @reduce", error);
            }
        }

        /**
         * Defines the function that is executed when the summarize entry point is triggered. This entry point is triggered
         * automatically when the associated reduce stage is complete. This function is applied to the entire result set.
         * @param {Object} summaryContext - Statistics about the execution of a map/reduce script
         * @param {number} summaryContext.concurrency - Maximum concurrency number when executing parallel tasks for the map/reduce
         *     script
         * @param {Date} summaryContext.dateCreated - The date and time when the map/reduce script began running
         * @param {boolean} summaryContext.isRestarted - Indicates whether the current invocation of this function is the first
         *     invocation (if true, the current invocation is not the first invocation and this function has been restarted)
         * @param {Iterator} summaryContext.output - Serialized keys and values that were saved as output during the reduce stage
         * @param {number} summaryContext.seconds - Total seconds elapsed when running the map/reduce script
         * @param {number} summaryContext.usage - Total number of governance usage units consumed when running the map/reduce
         *     script
         * @param {number} summaryContext.yields - Total number of yields when running the map/reduce script
         * @param {Object} summaryContext.inputSummary - Statistics about the input stage
         * @param {Object} summaryContext.mapSummary - Statistics about the map stage
         * @param {Object} summaryContext.reduceSummary - Statistics about the reduce stage
         * @since 2015.2
         */
        const summarize = (summaryContext) => {
            let contents = '';

            summaryContext.output.iterator().each(function (key, value) {
                contents += value + '\n';
                return true;

            });
            email.send({
                author: 1143760,
                recipients: 'litha.mukunthan@jobinandjismi.com',
                subject: 'Inconsistent Drawing File Names Detected',
                body: ' Hi,\n\n The file name of Drawings PDF  do not follow the desired format. Please review the following files where mismatches have been found:\n' + contents + '\n Thank You'

            });


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

Leave a comment

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