Closing Work Orders

Client Needs To Close Work Orders Using A Scheduled Script

define(["N/email", "N/error", "N/record", "N/search", "N/file"],
/**
 * @param{email} email
 * @param{error} error
 * @param{record} record
 * @param{search} search
 */ (email, error, record, search, file) => {
    const EMAIL_AUTHOR = 586154;
    const EMAIL_RECIPIENT = 3;
    /**
     * @description Function to remove comma and new line in a string
     * @param {string} data
     * @returns {string}
     */
    const escapeComma = (data) => {
      try {
        let result = data.toString().replaceAll(/,/g, "");
        result = result.toString().replaceAll(/\n/g, "");
        return result;
      } catch (error) {
        log.error("Error @escapeComma", error);
        return data;
      }
    };
    /**
     * @description Check whether the given parameter argument has value on it or is it empty.
     * ie, To check whether a value exists in parameter
     * @param {*} parameter parameter which contains/references some values
     * @param {*} parameterName name of the parameter, not mandatory
     * @returns {Boolean} true if there exist a value else false
     */
    const checkForParameter = (parameter) => {
      try {
        if (
          parameter !== "" &&
          parameter !== null &&
          parameter !== undefined &&
          parameter !== false &&
          parameter !== "null" &&
          parameter !== "undefined" &&
          parameter !== " " &&
          parameter !== "false"
        ) {
          return true;
        } else {
          return false;
        }
      } catch (e) {
        log.error("error@checkForParameter", e);
        return false;
      }
    };

    /**
     * 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 {
        return search.create({
          type: "workorder",
          filters: [
            ["type", "anyof", "WorkOrd"],
            "AND",
            ["status", "anyof", "WorkOrd:D"],
            "AND",
            ["cogs", "is", "F"],
            "AND",
            ["mainline", "is", "T"],
            "AND",
            ["shipping", "is", "F"],
            "AND",
            ["formulanumeric: {built} - {quantity}", "greaterthanorequalto", "0"],
          ],
          columns: [
            search.createColumn({
              name: "internalid",
              sort: search.Sort.ASC,
              label: "Internal ID",
            }),
            search.createColumn({ name: "trandate", label: "Date" }),
            search.createColumn({ name: "tranid", label: "Document Number" }),
            search.createColumn({ name: "quantity", label: "Quantity" }),
            search.createColumn({ name: "item", label: "Item" }),
            search.createColumn({ name: "built", label: "Built" }),
          ],
        });
      } catch (e) {
        log.error({ title: "error in getInputData", details: e });
        return [];
      }
    };

    /**
     * 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) => {
      let data = JSON.parse(reduceContext.values[0]);
      let reduceValues = data.values;
      let workorderID = reduceValues?.internalid?.value;
      let date = reduceValues.trandate;
      let documentNumber = reduceValues.tranid;
      let quantity = reduceValues.quantity;
      let item = reduceValues?.item?.text;
      let built = reduceValues.built;
      try {
        let completionRecord = record
          .transform({
            fromType: record.Type.WORK_ORDER,
            fromId: workorderID,
            toType: record.Type.WORK_ORDER_CLOSE,
            isDynamic: true,
          })
          .save();
        if (!checkForParameter(completionRecord)) {
          reduceContext.write({
            key: workorderID,
            value: [date, documentNumber, quantity, item, built, " "],
          });
        }
      } catch (error) {
        log.error("Error @reduceContext", error);
        reduceContext.write({
          key: workorderID,
          value: [date, documentNumber, quantity, item, built, error.message],
        });
      }
    };

    /**
     * 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) => {
      try {
        let header =
          "Record Id,Date,Document Number,Quantity,Item,Built, Reason\n";
        let content = "";
        summaryContext.output.iterator().each(function (key, value) {
          value = JSON.parse(value);
          content =
            content +
            escapeComma(key) +
            "," +
            escapeComma(value[0]) +
            "," +
            escapeComma(value[1]) +
            "," +
            escapeComma(value[2]) +
            "," +
            escapeComma(value[3]) +
            "," +
            escapeComma(value[4]) +
            "," +
            escapeComma(value[5]) +
            "\n";
          return true;
        });
        if (checkForParameter(content)) {
          let fileObj = file.create({
            name: "Details of unprocessed Work Orders_.csv",
            fileType: file.Type.CSV,
            contents: header + content,
            encoding: file.Encoding.UTF8,
          });
          let subject = "Unprocessed Work Orders";
          checkForParameter(fileObj) &&
            email.send({
              author: EMAIL_AUTHOR,
              recipients: EMAIL_RECIPIENT,
              subject: subject,
              body:
                "Hi " +
                ",<br><br>Details of unprocessed work orders are attached here. <br><br>Thank you",
              attachments: [fileObj],
            });
        }
      } catch (error) {
        log.error("Error @summaryContext", error);
      }
    };

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

Leave a comment

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