Created
August 22, 2025 16:40
-
-
Save bleonard/9e415db628daf4f8ba9443eb2303dfe8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| *@NApiVersion 2.x | |
| *@NScriptType Restlet | |
| */ | |
| // eslint-disable-next-line no-undef | |
| define(["N/record", "N/log", "N/search"], function (record, log, search) { | |
| // It does this thing where it's "line 1" object key instead of an array. make it an array. | |
| function normalize_sublists(sublists) { | |
| var out = {}; | |
| // get all sublist names without for...in | |
| var subNames = Object.keys(sublists || {}); | |
| for (var i = 0; i < subNames.length; i++) { | |
| var name = subNames[i]; | |
| var block = sublists[name]; | |
| // only treat plain objects (not arrays) as sublists | |
| if (block && typeof block === "object" && !Array.isArray(block)) { | |
| var linesArr = []; | |
| // extract keys in block | |
| var blkKeys = Object.keys(block); | |
| // collect just the "line N" entries | |
| for (var j = 0; j < blkKeys.length; j++) { | |
| var k = blkKeys[j]; | |
| if (/^line\s+\d+$/.test(k)) { | |
| linesArr.push({ | |
| idx: parseInt(k.replace("line ", ""), 10), | |
| value: block[k], | |
| }); | |
| } | |
| } | |
| // sort by numeric index, then strip out the idx wrapper | |
| linesArr.sort(function (a, b) { | |
| return a.idx - b.idx; | |
| }); | |
| var flat = []; | |
| // eslint-disable-next-line no-redeclare | |
| for (var j = 0; j < linesArr.length; j++) { | |
| flat.push(linesArr[j].value); | |
| } | |
| out[name] = flat; | |
| } else { | |
| // leave arrays or primitives untouched | |
| out[name] = block; | |
| } | |
| } | |
| return out; | |
| } | |
| function load_row(input) { | |
| log.debug("load_row", "Starting with input: " + JSON.stringify(input)); | |
| if (!input.id) { | |
| log.error("load_row", "No id provided in input"); | |
| throw new Error("No id provided"); | |
| } | |
| if (!input.recordtype) { | |
| log.error("load_row", "No recordtype provided in input"); | |
| throw new Error("No recordtype provided"); | |
| } | |
| var loadedRecord = record.load({ | |
| type: input.recordtype, | |
| id: input.id, | |
| isDynamic: true, | |
| }); | |
| var loadColumns = input.load_columns; | |
| if (loadColumns && ["all", "columns"].includes(input.load_key)) { | |
| for (var i = 0; i < loadColumns.length; i++) { | |
| var column = loadColumns[i]; | |
| var text = loadedRecord.getText({ fieldId: column }); | |
| if (text !== undefined) { | |
| loadedRecord.load[column + "_text"] = text; | |
| } | |
| } | |
| } | |
| log.debug( | |
| "load_row", | |
| "Successfully loaded record type: " + | |
| input.recordtype + | |
| ", id: " + | |
| input.id | |
| ); | |
| return loadedRecord; | |
| } | |
| function output_row_json(row) { | |
| var out = JSON.parse(JSON.stringify(row)); | |
| if (out.sublists) { | |
| log.debug("output_row_json ", "Normalizing sublists"); | |
| out.sublists = normalize_sublists(out.sublists); | |
| } else { | |
| log.debug( | |
| "output_row_json", | |
| "No sublists to normalize: " + JSON.stringify(Object.keys(out)) | |
| ); | |
| } | |
| return out; | |
| } | |
| function delete_row(row) { | |
| log.debug( | |
| "delete_row", | |
| "Starting deletion for record type: " + row.type + ", id: " + row.id | |
| ); | |
| record.delete({ | |
| type: row.type, | |
| id: row.id, | |
| }); | |
| log.audit( | |
| "delete_row", | |
| "Successfully deleted record type: " + row.type + ", id: " + row.id | |
| ); | |
| } | |
| function coerce_value(row, fieldId, value, state) { | |
| log.debug( | |
| "coerce_value", | |
| "Coercing field: " + | |
| fieldId + | |
| ", value: " + | |
| JSON.stringify(value) + | |
| " state: " + | |
| JSON.stringify(state) | |
| ); | |
| if (value === null || value === undefined) { | |
| log.debug("coerce_value", "Value is null/undefined, returning null"); | |
| return null; | |
| } | |
| var field = null; | |
| try { | |
| if (state["selected_sublist"]) { | |
| field = row.getSublistField({ | |
| sublistId: state["selected_sublist"], | |
| fieldId: fieldId, | |
| line: state["selected_sublist_line_num"] || 0, | |
| }); | |
| } else { | |
| field = row.getField({ fieldId: fieldId }); | |
| } | |
| } catch (e) { | |
| log.error("coerce_value", "Error getting field: " + e.message); | |
| throw e; | |
| } | |
| if (!field) { | |
| var errorMsg = | |
| "Field not found: " + | |
| fieldId + | |
| " in " + | |
| row.type + | |
| " state: " + | |
| JSON.stringify(state); | |
| log.error("coerce_value", errorMsg); | |
| throw new Error(errorMsg); | |
| } | |
| // types | |
| // text | |
| // date | |
| // rate | |
| // datetime | |
| // select | |
| // checkbox | |
| // currency | |
| // integer | |
| // float | |
| // phone | |
| // url | |
| var type = field.type; | |
| log.debug("coerce_value", "Field type: " + type + " for field: " + fieldId); | |
| if (type === "date" && typeof value === "string") { | |
| var [m, d, y] = value.split("/"); | |
| var dateValue = new Date(Number(y), Number(m) - 1, Number(d)); | |
| log.debug( | |
| "coerce_value", | |
| "Converted date string to Date object: " + dateValue | |
| ); | |
| return dateValue; | |
| } | |
| if (type === "datetime" && typeof value === "string") { | |
| // iso format: e.g. 2020-09-20T13:45:00Z | |
| var datetimeValue = new Date(value); | |
| log.debug( | |
| "coerce_value", | |
| "Converted datetime string to Date object: " + datetimeValue | |
| ); | |
| return datetimeValue; | |
| } | |
| return value; | |
| } | |
| function get_text_field(fieldId) { | |
| // returns real field name | |
| if (fieldId.slice(-5) === "_text") { | |
| return fieldId.slice(0, -5); | |
| } | |
| return null; | |
| } | |
| function set_row_field(row, fldName, value) { | |
| try { | |
| log.debug( | |
| "set_row_field", | |
| "Set field: " + fldName + " = " + JSON.stringify(value) | |
| ); | |
| var realName = get_text_field(fldName); | |
| if (realName) { | |
| row.setText(realName, value); | |
| } else { | |
| value = coerce_value(row, fldName, value, {}); | |
| row.setValue(fldName, value); | |
| } | |
| } catch (e) { | |
| log.error( | |
| "set_row_field", | |
| "Error setting field " + fldName + ": " + e.message | |
| ); | |
| throw e; | |
| } | |
| } | |
| function set_subrecords(row, subrecords, state) { | |
| log.debug( | |
| "set_subrecords", | |
| "Starting with subrecords: " + JSON.stringify(Object.keys(subrecords)) | |
| ); | |
| for (var subrecordId in subrecords) { | |
| var subrecord = subrecords[subrecordId]; | |
| var mode = subrecord.mode; | |
| log.debug( | |
| "set_subrecords", | |
| "Processing subrecord: " + subrecordId + ", mode: " + mode | |
| ); | |
| if (mode !== "set") { | |
| var errorMsg1 = | |
| "Unsupported subrecord mode (" + subrecordId + "): " + subrecord.mode; | |
| log.error("set_subrecords", errorMsg1); | |
| throw new Error(errorMsg1); | |
| } | |
| for (var i = 0; i < subrecord.items.length; i++) { | |
| var item = subrecord.items[i]; | |
| log.debug( | |
| "set_subrecords", | |
| "Processing subrecord item: " + i + " for subrecord: " + subrecordId | |
| ); | |
| var my_subrecord = null; | |
| try { | |
| if (state["selected_sublist"]) { | |
| // in a sublist | |
| my_subrecord = row.getCurrentSublistSubrecord({ | |
| sublistId: state["selected_sublist"], | |
| fieldId: subrecordId, | |
| }); | |
| } else { | |
| // not in a sublist | |
| my_subrecord = row.getSubrecord({ | |
| fieldId: subrecordId, | |
| }); | |
| } | |
| } catch (e) { | |
| log.error("set_subrecords", "Error getting subrecord: " + e.message); | |
| throw e; | |
| } | |
| if (!my_subrecord) { | |
| var errorMsg2 = "Subrecord not found: " + subrecordId; | |
| log.error("set_subrecords", errorMsg2); | |
| throw new Error(errorMsg2); | |
| } | |
| var fields = item.fields || {}; | |
| log.debug( | |
| "set_subrecords", | |
| "Setting data for subrecord: " + subrecordId | |
| ); | |
| for (var fieldId in fields) { | |
| var value = fields[fieldId]; | |
| set_row_field(my_subrecord, fieldId, value); | |
| } | |
| } | |
| } | |
| log.debug("set_subrecords", "Completed processing all subrecords"); | |
| } | |
| function set_sublists(row, sublists, state) { | |
| log.debug( | |
| "set_sublists", | |
| "Starting with sublists: " + JSON.stringify(Object.keys(sublists)) | |
| ); | |
| for (var sublistId in sublists) { | |
| state["selected_sublist"] = sublistId; | |
| var sublist = sublists[sublistId]; | |
| log.debug( | |
| "set_sublists", | |
| "Sublist: " + sublistId + " = " + JSON.stringify(sublist) | |
| ); | |
| var mode = sublist.mode; | |
| var lineCount = row.getLineCount({ sublistId: sublistId }); | |
| log.debug( | |
| "set_sublists", | |
| "Processing sublist: " + | |
| sublistId + | |
| ", mode: " + | |
| mode + | |
| " lineCount: " + | |
| lineCount | |
| ); | |
| if (mode === "reset") { | |
| // remove all existing lines backwards | |
| var toRemove = row.getLineCount({ sublistId: sublistId }); | |
| log.debug( | |
| "set_sublists", | |
| "Resetting sublist, removing " + toRemove + " lines" | |
| ); | |
| for (var i = toRemove - 1; i >= 0; i--) { | |
| row.removeLine({ sublistId: sublistId, line: i }); | |
| } | |
| lineCount = 0; | |
| } else if (mode === "replace") { | |
| log.debug( | |
| "set_sublists", | |
| "Replace mode, existing line count: " + lineCount | |
| ); | |
| } else if (mode === "add") { | |
| log.debug( | |
| "set_sublists", | |
| "Add mode, existing line count: " + lineCount | |
| ); | |
| } else if (mode === "upsert") { | |
| log.debug( | |
| "set_sublists", | |
| "Upsert mode, existing line count: " + lineCount | |
| ); | |
| } else { | |
| // eslint-disable-next-line no-redeclare | |
| var errorMsg = "Unsupported sublist mode (" + sublistId + "): " + mode; | |
| log.error("set_sublists", errorMsg); | |
| throw new Error(errorMsg); | |
| } | |
| // eslint-disable-next-line no-redeclare | |
| for (var i = 0; i < sublist.items.length; i++) { | |
| var item = sublist.items[i]; | |
| log.debug( | |
| "set_sublists", | |
| "Processing sublist item: " + i + " for sublist: " + sublistId | |
| ); | |
| var sublistLineNum = 0; | |
| try { | |
| if (mode === "upsert") { | |
| // upsert is a hash of fields and values | |
| // it needs to match each | |
| var lookup = item.upsert || item.delete; // one of the other | |
| if (!lookup) { | |
| // eslint-disable-next-line no-redeclare | |
| var errorMsg = | |
| "No lookup found for sublist item upsert: " + | |
| sublistId + | |
| " " + | |
| JSON.stringify(item); | |
| log.error("set_sublists", errorMsg); | |
| throw new Error(errorMsg); | |
| } | |
| var foundNum = -1; | |
| for (var fieldId in lookup) { | |
| var value = lookup[fieldId]; | |
| // can't coerce here because it will match on the wrong line | |
| var lineNumber = row.findSublistLineWithValue({ | |
| sublistId: sublistId, | |
| fieldId: fieldId, | |
| value: value, | |
| }); | |
| if (lineNumber < 0) { | |
| foundNum = -1; | |
| break; // need a new one | |
| } else if (foundNum < 0) { | |
| foundNum = lineNumber; | |
| } else if (foundNum !== lineNumber) { | |
| // second one didn't match the first | |
| foundNum = -1; | |
| break; // need a new one | |
| } else { | |
| // they were on the same line | |
| } | |
| } | |
| if (item.upsert) { | |
| // adding or updating | |
| if (foundNum < 0) { | |
| log.debug("set_sublists", "Selected new line: no upsert match"); | |
| row.selectNewLine({ sublistId: sublistId }); | |
| sublistLineNum = 0; | |
| } else { | |
| log.debug( | |
| "set_sublists", | |
| "Selected existing line upsert match: " + foundNum | |
| ); | |
| row.selectLine({ sublistId: sublistId, line: foundNum }); | |
| sublistLineNum = foundNum; | |
| } | |
| } else if (item.delete) { | |
| // deleting it | |
| if (foundNum < 0) { | |
| log.debug( | |
| "set_sublists", | |
| "Deleting sublist line: but no upsert match" | |
| ); | |
| } else { | |
| log.debug("set_sublists", "Deleting sublist line: " + foundNum); | |
| row.removeLine({ sublistId: sublistId, line: foundNum }); | |
| } | |
| continue; | |
| } else { | |
| // eslint-disable-next-line no-redeclare | |
| var errorMsg = | |
| "Unknown upsert action: " + | |
| sublistId + | |
| " " + | |
| JSON.stringify(item); | |
| log.error("set_sublists", errorMsg); | |
| throw new Error(errorMsg); | |
| } | |
| } else if (mode === "replace" && i < lineCount) { | |
| log.debug("set_sublists", "Selected existing line: " + i); | |
| row.selectLine({ sublistId: sublistId, line: i }); | |
| sublistLineNum = i; | |
| } else { | |
| log.debug("set_sublists", "Selected new line"); | |
| row.selectNewLine({ sublistId: sublistId }); | |
| sublistLineNum = 0; | |
| } | |
| } catch (e) { | |
| log.error("set_sublists", "Error selecting line: " + e.message); | |
| throw e; | |
| } | |
| state["selected_sublist_line_num"] = sublistLineNum; | |
| var fields = item.fields || {}; | |
| var subrecords = item.subrecords; | |
| log.debug( | |
| "set_sublists", | |
| "Setting fields: " + JSON.stringify(Object.keys(fields)) | |
| ); | |
| // eslint-disable-next-line no-redeclare | |
| for (var fieldId in fields) { | |
| // eslint-disable-next-line no-redeclare | |
| var value = fields[fieldId]; | |
| log.debug( | |
| "set_sublists", | |
| "Set sublist field: " + fieldId + " = " + JSON.stringify(value) | |
| ); | |
| try { | |
| var textFieldId = get_text_field(fieldId); | |
| if (textFieldId) { | |
| log.debug( | |
| "set_sublists", | |
| "Setting text field: " + | |
| textFieldId + | |
| " = " + | |
| JSON.stringify(value) | |
| ); | |
| row.setCurrentSublistText({ | |
| sublistId: sublistId, | |
| fieldId: textFieldId, | |
| text: value, | |
| }); | |
| } else { | |
| value = coerce_value(row, fieldId, value, state); | |
| log.debug( | |
| "set_sublists", | |
| "Setting value field: " + | |
| fieldId + | |
| " = " + | |
| JSON.stringify(value) | |
| ); | |
| row.setCurrentSublistValue({ | |
| sublistId: sublistId, | |
| fieldId: fieldId, | |
| value: value, | |
| }); | |
| } | |
| } catch (e) { | |
| log.error( | |
| "set_sublists", | |
| "Error setting sublist field " + fieldId + ": " + e.message | |
| ); | |
| throw e; | |
| } | |
| } | |
| if (subrecords) { | |
| log.debug( | |
| "set_sublists", | |
| "Processing subrecords for sublist item: " + i | |
| ); | |
| set_subrecords(row, subrecords, state); | |
| } | |
| try { | |
| row.commitLine({ sublistId: sublistId }); | |
| log.debug("set_sublists", "Committed line for sublist: " + sublistId); | |
| } catch (e) { | |
| log.error("set_sublists", "Error committing line: " + e.message); | |
| throw e; | |
| } | |
| delete state["selected_sublist_line_num"]; | |
| } | |
| // remove any extra lines from the back | |
| if (mode === "replace") { | |
| var linesToRemove = lineCount - sublist.items.length; | |
| if (linesToRemove > 0) { | |
| log.debug( | |
| "set_sublists", | |
| "Removing " + linesToRemove + " extra lines from end" | |
| ); | |
| // eslint-disable-next-line no-redeclare | |
| for (var i = lineCount - 1; i >= sublist.items.length; i--) { | |
| row.removeLine({ sublistId: sublistId, line: i }); | |
| } | |
| } | |
| } | |
| delete state["selected_sublist"]; | |
| } | |
| log.debug("set_sublists", "Completed processing all sublists"); | |
| } | |
| function generateRandomString(length) { | |
| var chars = | |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
| var result = ""; | |
| for (var i = 0; i < length; i++) { | |
| result += chars.charAt(Math.floor(Math.random() * chars.length)); | |
| } | |
| return result; | |
| } | |
| function process_mutation(row, mutation) { | |
| var action = mutation.action; | |
| log.debug( | |
| "process_mutation", | |
| "Processing mutation: " + JSON.stringify(mutation) | |
| ); | |
| switch (action) { | |
| case "set": | |
| log.debug("process_mutation", "Mutation set field: " + mutation.field); | |
| set_row_field(row, mutation.field, mutation.value); | |
| break; | |
| case "clear": | |
| log.debug( | |
| "process_mutation", | |
| "Mutation clear field: " + mutation.field | |
| ); | |
| set_row_field(row, mutation.field, null); | |
| break; | |
| case "unique": | |
| log.debug( | |
| "process_mutation", | |
| "Mutation unique field: " + mutation.field | |
| ); | |
| var fldName = mutation.field; | |
| var max_length = mutation.field_length || 30; | |
| var random_length = mutation.random_length || 6; | |
| var name = row.getValue({ fieldId: fldName }) || ""; | |
| var randomString = generateRandomString(random_length); | |
| if (name.length + randomString.length + 1 > max_length) { | |
| name = name.substring(0, max_length - randomString.length - 2); | |
| } | |
| name = name + " " + randomString; | |
| set_row_field(row, fldName, name); | |
| break; | |
| default: | |
| var errorMsg = "Unsupported mutation action: " + action; | |
| log.error("process_mutation", errorMsg); | |
| throw new Error(errorMsg); | |
| } | |
| } | |
| function set_row_data(row, input) { | |
| log.debug("set_row_data", "Starting with input: " + JSON.stringify(input)); | |
| var fields = input.fields || {}; | |
| var mutations = input.mutations; | |
| var sublists = input.sublists; | |
| var subrecords = input.subrecords; | |
| log.debug( | |
| "set_row_data", | |
| "Processing " + Object.keys(fields).length + " fields" | |
| ); | |
| for (var fldName in fields) { | |
| var value = fields[fldName]; | |
| set_row_field(row, fldName, value); | |
| } | |
| if (mutations) { | |
| log.debug( | |
| "set_row_data", | |
| "Processing " + mutations.items.length + " mutations" | |
| ); | |
| for (var i = 0; i < mutations.items.length; i++) { | |
| var mutation = mutations.items[i]; | |
| process_mutation(row, mutation); | |
| } | |
| } | |
| if (sublists) { | |
| log.debug("set_row_data", "Processing sublists"); | |
| set_sublists(row, sublists, {}); | |
| } | |
| if (subrecords) { | |
| log.debug("set_row_data", "Processing subrecords"); | |
| set_subrecords(row, subrecords, {}); | |
| } | |
| log.debug("set_row_data", "Completed setting row data"); | |
| } | |
| // function row_to_json(row) { | |
| // log.debug("row_to_json", "Converting row to JSON"); | |
| // try { | |
| // var jsonResult = JSON.stringify(row); | |
| // log.debug("row_to_json", "Successfully converted row to JSON"); | |
| // return jsonResult; | |
| // } catch (e) { | |
| // log.error("row_to_json", "Error converting row to JSON: " + e.message); | |
| // throw e; | |
| // } | |
| // } | |
| // Get a standard NetSuite record | |
| function _read(input) { | |
| log.audit( | |
| "_read", | |
| "Starting GET operation with input: " + JSON.stringify(input) | |
| ); | |
| var row = load_row(input); | |
| log.audit( | |
| "_read", | |
| "Successfully completed GET operation for record type: " + | |
| input.recordtype + | |
| ", id: " + | |
| input.id | |
| ); | |
| return output_row_json(row); | |
| } | |
| // Delete a standard NetSuite record | |
| function _delete(input) { | |
| log.audit( | |
| "_delete", | |
| "Starting DELETE operation with input: " + JSON.stringify(input) | |
| ); | |
| try { | |
| var row = load_row(input); | |
| // TODO dependant records first | |
| delete_row(row); | |
| var result = JSON.stringify({ id: input.id }); | |
| log.audit( | |
| "_delete", | |
| "Successfully completed DELETE operation for record type: " + | |
| input.recordtype + | |
| ", id: " + | |
| input.id | |
| ); | |
| return result; | |
| } catch (e) { | |
| log.error("_delete", "DELETE operation failed: " + e.message); | |
| throw e; | |
| } | |
| } | |
| function _search(input) { | |
| log.debug( | |
| "_search", | |
| "Starting SEARCH operation with input: " + JSON.stringify(input) | |
| ); | |
| var inputSearchOptions = input.search; | |
| if (inputSearchOptions) { | |
| log.audit("_search", "search options provided"); | |
| } else { | |
| if (!input.recordtype) { | |
| log.error("_search", "No recordtype or search provided in input"); | |
| throw new Error("No recordtype provided"); | |
| } | |
| if (Array.isArray(input.ids) && input.ids.length === 0) { | |
| // it causes an error if no ids are provided | |
| log.audit("_search", "No ids provided, returning empty array"); | |
| return { items: [] }; | |
| } | |
| if (!Array.isArray(input.ids)) { | |
| log.error("_search", "No ids array or search provided in input"); | |
| throw new Error("No ids array provided"); | |
| } | |
| log.audit("_search", "Creating list ids search options"); | |
| inputSearchOptions = { | |
| type: input.recordtype, | |
| filters: [["internalid", "anyof", input.ids]], | |
| columns: input.search_columns || [], | |
| }; | |
| } | |
| log.debug( | |
| "_search", | |
| "Performing SEARCH operation with options: " + | |
| JSON.stringify(inputSearchOptions) | |
| ); | |
| // the search some how mutates the columns array, so we need to clone it | |
| var loadColumns = (input.load_columns || []).slice(); | |
| log.debug("_search", "Load columns: " + JSON.stringify(loadColumns)); | |
| try { | |
| var searchObj = search.create(inputSearchOptions); | |
| var items = []; | |
| searchObj.run().each(function (result) { | |
| // has id, recordType, values | |
| var item = JSON.parse(JSON.stringify(result)); | |
| log.debug("_search", "Item Result: " + JSON.stringify(item)); | |
| if (["getvalue"].indexOf(input.load_key) >= 0) { | |
| log.debug("_search", "Getting values for record: " + item["id"]); | |
| var load = {}; | |
| for (var i = 0; i < searchObj.columns.length; i++) { | |
| var column = searchObj.columns[i]; | |
| var key = column.join | |
| ? column.join + "." + column.name | |
| : column.name; | |
| load[key] = result.getValue(column); | |
| var text = result.getText(column); | |
| if (text !== undefined) { | |
| load[key + "_text"] = text; | |
| } | |
| } | |
| item["load"] = load; | |
| } else if (["all", "columns"].indexOf(input.load_key) >= 0) { | |
| log.debug("_search", "Loading record: " + item["id"]); | |
| var row = load_row({ | |
| id: item["id"], | |
| recordtype: item["recordType"] || input.recordtype, | |
| }); | |
| switch (input.load_key) { | |
| case "all": | |
| log.debug("_search", "Loaded all record: " + item["id"]); | |
| item["load"] = output_row_json(row); | |
| break; | |
| case "columns": | |
| log.debug("_search", "Loading columns for record: " + item["id"]); | |
| var load = {}; // eslint-disable-line no-redeclare | |
| // eslint-disable-next-line no-redeclare | |
| for (var i = 0; i < loadColumns.length; i++) { | |
| var columnName = loadColumns[i]; | |
| log.debug( | |
| "_search", | |
| "Loading column: " + columnName + " for record: " + item["id"] | |
| ); | |
| load[columnName] = row.getValue({ fieldId: columnName }); | |
| log.debug( | |
| "_search", | |
| "Loaded column: " + columnName + " for record: " + item["id"] | |
| ); | |
| var text = row.getText({ fieldId: columnName }); // eslint-disable-line no-redeclare | |
| if (text !== undefined) { | |
| load[columnName + "_text"] = text; | |
| } | |
| } | |
| item["load"] = load; | |
| break; | |
| default: | |
| throw new Error("Unsupported load key: " + input.load_key); | |
| } | |
| } | |
| items.push(item); | |
| return true; // Continue iteration | |
| }); | |
| var out = { items: items }; | |
| log.audit( | |
| "_search", | |
| "Successfully completed SEARCH operation for record type: " + | |
| input.recordtype + | |
| ", id: " + | |
| input.id | |
| ); | |
| return out; | |
| } catch (e) { | |
| log.error("_search", "SEARCH operation failed: " + e.message); | |
| throw e; | |
| } | |
| } | |
| function _create(input) { | |
| log.audit( | |
| "_create", | |
| "Starting CREATE operation with input: " + JSON.stringify(input) | |
| ); | |
| if (!input.recordtype) { | |
| log.error("_create", "No recordtype provided in input"); | |
| throw new Error("No recordtype provided"); | |
| } | |
| var row = record.create({ | |
| type: input.recordtype, | |
| isDynamic: true, | |
| }); | |
| log.debug("_create", "Created new record of type: " + input.recordtype); | |
| set_row_data(row, input); | |
| var savedRecord = row.save(); | |
| log.audit( | |
| "_create", | |
| "Successfully saved new record with id: " + savedRecord | |
| ); | |
| log.audit( | |
| "_create", | |
| "Successfully completed CREATE operation for record type: " + | |
| input.recordtype | |
| ); | |
| return output_row_json(row); | |
| } | |
| // Upsert a NetSuite record from request param | |
| function _update(input) { | |
| log.audit( | |
| "_update", | |
| "Starting UPDATE operation with input: " + JSON.stringify(input) | |
| ); | |
| var row = load_row(input); | |
| set_row_data(row, input); | |
| var savedRecord = row.save(); | |
| log.audit("_update", "Successfully saved record with id: " + savedRecord); | |
| log.audit( | |
| "_update", | |
| "Successfully completed UPDATE operation for record type: " + | |
| input.recordtype + | |
| ", id: " + | |
| input.id | |
| ); | |
| return output_row_json(row); | |
| } | |
| function _select(input) { | |
| // outputs select options for a field | |
| log.audit( | |
| "_select", | |
| "Starting SELECT operation with input: " + JSON.stringify(input) | |
| ); | |
| if (!input.recordtype) { | |
| log.error("_select", "No recordtype provided in input"); | |
| throw new Error("No recordtype provided"); | |
| } | |
| if (!input.field) { | |
| log.error("_select", "No field provided in input"); | |
| throw new Error("No field provided"); | |
| } | |
| var row = null; | |
| if (input.id) { | |
| row = load_row({ | |
| recordtype: input.recordtype, | |
| id: input.id, | |
| }); | |
| } else { | |
| row = record.create({ | |
| type: input.recordtype, | |
| isDynamic: true, | |
| }); | |
| } | |
| // some have to set up the row to get valid options (input.fields) | |
| set_row_data(row, input); | |
| var field = row.getField({ fieldId: input.field }); | |
| var options = field.getSelectOptions(); | |
| var out = { | |
| items: options, | |
| }; | |
| return out; | |
| } | |
| function _router(context) { | |
| var method = context.method; | |
| var methods = { | |
| read: _read, | |
| search: _search, | |
| create: _create, | |
| update: _update, | |
| delete: _delete, | |
| select: _select, | |
| }; | |
| if (methods[method]) { | |
| try { | |
| return methods[method](context.input || {}); | |
| } catch (e) { | |
| log.error(method, method + " operation failed: " + e.message); | |
| throw e; | |
| } | |
| } else { | |
| log.error("_post", "Unknown method: " + method); | |
| throw new Error("Unknown method: " + method); | |
| } | |
| } | |
| // return the methods we want to expose | |
| return { | |
| post: _router, | |
| }; | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment