why am I getting a "TypeError: Cannot read property 'getLineCount' of undefined" on a beforeSubmit UE script triggered on a Journal Entry record - netsuite

I am unsure how to troubleshoot or what this error means in NetSuites SuiteScript. There I am getting after I hit save on a journal entry is.:
"TypeError: Cannot read property 'getLineCount' of undefined [at Object.beforeSubmit (/SuiteScripts/Set Line Employee ADP ID.js:15:30)]"
I believe the error is with my getLineCount() function on line 15.
Functional Scenario: I am writing a script to populate a custom column field on a Journal entry line from a field on the customer record that is selected in the native entity field on the Journal Entry line.
Context: my script is triggering before submit on create or update of a Journal Entry
Here is my script:
`define (['N/record','N/runtime','N/search','N/log'],(rec,runtime,search,log)=> {
// Logic Of the before submit actions of the script:
function beforeSubmit(context){
//Find how many lines are in this JE
let jeLineNums = context.rec.getLineCount({
sublistId:'line'
});
//log the JE line numbers as a test
log.debug({
title: 'JE lines',
details: jeLineNums
});
// Loop through every line in the Journal Entry
for (let i = 0; i < jeLineNums; i++){
// Find the customer record ID of the customer on the line and store it
let customerid = context.rec.getSublistValue({
sublistId: 'line',
fieldId: 'entity_display',
line: i
});
// Then create a SS with the customer id as a criteria
let customerSearch = search.create({
type: "customer",
filters:
[
["entityid","is",customerid]
],
columns:
[
search.createColumn({
name: "custentity2",
label: "ADP ID"}),
],
});
// Run that ss and Store the ADP ID result into a vairable
function RunSearch(searchVar) {
return searchVar.run()
};
};
RunSearch(customerSearch).each(function(result){
var adpID = result.getValue({
name:'custentity2',
});
return false;
});
//log the JE line numbers as a test
log.debug({
title: 'CustomerADP ID',
details: adpId
});
// Set the Line Employee ADP ID field value to the ADP ID vairable stored
context.rec.setSublistValue({
sublistId: "line",
fieldId: "custcol_mhi_line_adp_id",
line: i,
value: adpId,
});
//End of the loop
};
return {
beforeSubmit: beforeSubmit,
};
});`

For SS2.1, you can do the following:
let { newRecord } = context;
//Find how many lines are in this JE
let jeLineNums = newRecord.getLineCount({
sublistId:'line'
});
Alternatively, for SS2.0:
//Find how many lines are in this JE
var jeLineNums = context.newRecord.getLineCount({
sublistId:'line'
});
"TypeError: Cannot read property 'getLineCount' of undefined [at
Object.beforeSubmit (/SuiteScripts/Set Line Employee ADP
ID.js:15:30)]"
The reason you're getting the error above is because you're trying to read an undefined property from context. The context object doesn't have a rec property. See more details here: beforeSubmit(context)

Related

Set line_item list value in before Load of form in NetSuite

I am trying to update the date of a field if "item_id is 900",
define(['N/record', 'N/search'],
function(record, search){
function salesorderbeforeload(context){
var currentRecord = context.newRecord;
var sublistName="item";
var start_Date="custcol_atlas_contract_start_date";
var end_date="custcol_atlas_contract_end_date";
var lines = currentRecord.getLineCount({sublistId: 'item'});
log.debug({title:'lines',details:lines});
for (var i = 0; i < lines; i++) {
var itemId = (currentRecord.getSublistValue({
sublistId: "item",
fieldId: "item",
line: i
}));
var value=itemId;
if(value=="900")
{
currentRecord.setSublistValue({
sublistId: "item",
fieldId: "custcol_atlas_contract_start_date",
line: 0,
value: "2021-09-09T07:00:00.000Z"
});
}
}
}
return{
beforeLoad: salesorderbeforeload
};
}
);
The above code will fetch the line item id as value , and if the value is 900 it will set the date to the following
Evrything is working perfectly except for this code,
currentRecord.setSublistValue({
sublistId: "item",
fieldId: "custcol_atlas_contract_start_date",
line: 0,
value: "2021-09-09T07:00:00.000Z"
});
record=currentRecord.setSublistValue({
sublistId: "item",
fieldId: "quantity",
line: 0,
value: "3"
});
Even the quantity is not updating.
Thanks in advance
You cannot update existing records so that ultimately will be your issue.
You may be able to fix this in a before submit event when the record is saved or in a Client Event script.
As far as the code supplied though you are not advancing the line index. You should have:
currentRecord.setSublistValue({
sublistId: "item",
fieldId: "custcol_atlas_contract_start_date",
line: i, // NOT 0
value: "2021-09-09T07:00:00.000Z"
});
but after that is your custom field an actual date time or is it a text field?
if you are trying to store a date you'll need to parse your ISO formatted date string to an actual date. This is different from SS1 where dates had to be date formatted strings.
As far as item groups go the custom field needs to be configured to save the value for group items.
There is a checkbox, "Store with Item Groups" on the field definition
Did you try saving the record after all the updates?
You can try this approach where you load the record first, then check for your conditions, accordingly update the fields and then perform a record save.
var objRecord = record.load({
type: record.Type.SALES_ORDER,
id: 157,
isDynamic: true,
});
Then you can iterate over the line items. Use FOR LOOP
for(var j=0; j<numLines; j++) {
//fetch the item_id using getCurrentSublistValue
if(item_id == 900) {
//Perform the setSublistValue
}
}
And finally,
objRecord.save();
Give this a try, even I'm not sure of this approach. Let me know in case of any issues.

Error when trying to removeLine on item_fulfillment

I am trying to transform a sales order to an Item fulfillment and remove some item lines but I get the following error:
name : SSS_INVALID_SUBLIST_OPERATION
message: You have attempted an invalid sublist or line item operation.
You are either trying to access a field on a non-existent line
or you are trying to add or remove lines from a static sublist
My code:
// Transform the record
var objRecord = record.transform({
fromType: record.Type.SALES_ORDER,
fromId: soid,
toType: record.Type.ITEM_FULFILLMENT,
isDynamic: true,
});
// Remove second location
var linecount = objRecord.getLineCount({sublistId: 'item'});
for (var i = 0; i < linecount; i++) {
objRecord.selectLine({sublistId: "item",line: i});
var locationid = objRecord.getCurrentSublistValue({sublistId: 'item',fieldId: 'location'});
if (locationid != 15)
objRecord.removeLine({sublistId: 'item',line: i});
}
There are 10 lines in the Sales order. Only 1 has some quantity allocated and ready to be fulfilled, maybe when I try to delete it that causes the error? But it seems the errors come from something else.
I tried to set: isDynamic: false (same error)
Start deleting from the bottom of the list.
The value of linecount changes after each successful delete. Eventually, i will get a value that doesn't exist anymore.
The problem was not due to the index of the lines but to the operation on the record. On an item fulfillment the function objRecord.removeLine is not available.
To remove rows from the fulfillment item it we have to use :
objRecord.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'itemreceive',
value : false
})

How do you fetch a list of records and then add a checkbox next to corresponding record so to edit and save changes in suiteScript

I want to create a suitelet that could fetch some sales order then be able to edit those on click on submit button, so far I was I'm able to fetch records but I'm not able to add checkboxes and update records in netsuite - suitescript
var list=form.createList({title:"Sales order"});
list.addColumn({
id : 'column1',
type : serverWidget.FieldType.TEXT,
label : 'tranid',
align : serverWidget.LayoutJustification.LEFT
});list.addColumn({
id : 'column2',
type : serverWidget.FieldType.TEXT,
label : 'shipaddress',
align : serverWidget.LayoutJustification.LEFT
});list.addColumn({
id : 'column3',
type : serverWidget.FieldType.TEXT,
label : 'rate',
align : serverWidget.LayoutJustification.LEFT
});
salesorderSearchObj.run().each(function(result){
tranid= result.getValue({name: 'tranid'})
shipaddress= result.getValue({name: 'shipaddress'})
rate= result.getValue({name: 'rate'})
list.addRows({
rows : [{
column1 : tranid,
column2 : shipaddress,
column3 : rate
}]
});
Suite Answer Id 40768 has sample code in SuiteScript 1.0. An outline in 2.0 format is below. The full 1.0 sample from NetSuite is also below. The key is to for the GET req method create the page and display the information as a Sublist instead of a List. Then for all other req methods, get the parameters and take desired action.
2.0 partial outline
define(['N/ui/serverWidget'], function(serverWidget) {
function onRequest(context){
if(context.request.method === 'GET'){
//create page to display results and allow for user input
var form = serverWidget.createForm({
title : 'Simple Form'
});
var sublist = form.addSublist({
id : 'sublistid',
type : serverWidget.SublistType.INLINEEDITOR,
label : 'Inline Editor Sublist'
});
//Add checkbox and atleast internalid
var printField = sublist.addField({
id: 'custpage_rec_process',
label: 'Process',
type: serverWidget.FieldType.CHECKBOX
});
var idField = sublist.addField({
id: 'custpage_rec_id',
label: 'Internal ID',
type: serverWidget.FieldType.TEXT
});
//empty Array to hold Sales Order data
var TranIds = [];
//run search to get Sales Order data
...salesorderSearchObj.run().each(function(result){
//add search column names as columns in the sublist
//add each column value to the sublist
}
//add buttons to sublist and form
sublist.addMarkAllButtons();
sublist.addRefreshButton();
form.addResetButton({label: 'Reset'});
form.addSubmitButton({label: 'Create File'});
//display page for user input
context.response.writePage(form);
} else { //if the previously created/displayed form has been submitted display the following to the user
var req = context.request;
var params = JSON.stringify(context.request.parameters);//can log this to see exactly how the information comes through
//gather submitted data
//take desired action
//display response to user
context.response.writePage('Done');
}
} return {
onRequest: onRequest
}
});
1.0 full sample
function suitelet(request, response){
//Create the form that will be used by the POST and GET requests
var form = nlapiCreateForm('Delete Transactions');
//GET - Show a list of transactions from the search results so the user can select the ones to be deleted
if (request.getMethod() == 'GET' )
{
// Run an existing transaction search
var results = nlapiSearchRecord('transaction', 'customsearch_mass_deletion_results');
// Create a sublist to show the search results
var sublist = form.addSubList('custpage_transaction_list', 'list','Transactions');
// Create an array to store the transactions from the search results
var transactionArray = new Array();
if (results!=null)
{
// Add a checkbox column to the sublist to select the transactions that will be deleted.
sublist.addField('delete','checkbox', 'Delete');
// Add hidden columns for the Internal ID and for the Record type.
// These fields are necessary for the nlapiDeleteRecord function.
sublist.addField('internalid','text', 'Internal ID').setDisplayType('hidden');
sublist.addField('recordtype','text', 'Record Type').setDisplayType('hidden');
// Add a column for the Internal ID link
sublist.addField('internalidlink','text', 'Internal ID');
// Get the the search result columns
var columns = results[0].getAllColumns();
// Add the search columns to the sublist
for(var i=0; i< columns.length; i++)
{
sublist.addField(columns[i].getName() ,'text', columns[i].getName() );
}
// For each search results row, create a transaction object and attach it to the transactionArray
for(var i=0; i< results.length; i++)
{
var transaction = new Object();
// Set the Delete column to False
transaction['delete'] = 'F';
// Set the hidden internal ID field
transaction['internalid'] = results[i].getId();
// Set the hidden record type field
transaction['recordtype'] = results[i].getRecordType();
// Create a link so users can navigate from the list of transactions to a specific transaction
var url = nlapiResolveURL('RECORD', results[i].getRecordType() ,results[i].getId(), null);
internalIdLink = " " + results[i].getId() +" ";
// Set the link
transaction['internalidlink'] = internalIdLink;
// Copy the row values to the transaction object
for(var j=0; j< columns.length ; j++)
{
transaction[columns[j].getName()] = results[i].getValue(columns[j].getName());
}
// Attach the transaction object to the transaction array
transactionArray[i] = transaction;
}
}
// Initiate the sublist with the transactionArray
sublist.setLineItemValues(transactionArray);
sublist.addMarkAllButtons();
form.addSubmitButton('Submit' );
response.writePage( form );
}
//POST - Delete the selected transactions and show a confirmation message
else
{
// Check how many lines in the sublist
var count = request.getLineItemCount('custpage_transaction_list');
// This variable will keep track of how many records are deleted.
var num = 0;
//for each line in the sublist
for(var i=1; i< count+1; i++)
{
//get the value of the Delete checkbox
var deleteTransaction = request.getLineItemValue('custpage_transaction_list', 'delete', i);
// If it's checked, delete the transaction
if(deleteTransaction == 'T')
{
// Get the transaction internal ID
var internalId = request.getLineItemValue('custpage_transaction_list', 'internalid', i);
// Get the transaction type
var recordType = request.getLineItemValue('custpage_transaction_list', 'recordtype', i);
try
{
// Delete the transaction
nlapiDeleteRecord(recordType, internalId);
num++;
}
// Errors will be logged in the Execution Log
catch(ex)
{
nlapiLogExecution('ERROR', 'Error', 'Transaction ID '+ internalId +': '+ ex);
}
}
}
// Show how many records were deleted.
form.addField("custpage_transaction_total", "text").setDisplayType('inline').setDefaultValue(num + " transactions deleted");
response.writePage( form );
}
}

How to fix 'Please enter a value for amount.' when creating NetSuite invoice with restlet?

I'm creating a NetSuite invoice in dynamic mode with SuiteScript 2.0, and when I run commitLine on my first item, it errors with 'Please enter a value for amount.' even though I have already supplied it using setCurrentSublistValue.
The relevant section of code is START CREATING ITEM through FINISHED CREATING ITEM, but I've included the full restlet in case the problem is in my setup.
Here's the JSON data I'm using to generate the item:
{"item":26,"amount":5706.48,"custcol_unit_price":"7.863035405","quantity":725735,"description":"July Impressions - 2019 Digital (April-July) - Custom Affinity (CAF) Dynamic CPM 7.5","line":1}
I'm logging a call to getCurrentSublistValue immediately after the setter, to ensure the system is accepting the value I send, and get 5706.48 back out for amount, so I believe setCurrentSublistValue is inserting it.
/**
*#NApiVersion 2.x
*#NScriptType Restlet
*/
define(['N/record', 'N/error', 'N/log'],
function(record, error, log) {
function post(context) {
log.audit("invoice", context);
var rec = record.create({ type: "invoice", isDynamic: true });
for (var fldName in context) {
if (context.hasOwnProperty(fldName)) {
if (fldName === "trandate") {
rec.setValue(fldName, new Date(context[fldName]));
} else if (fldName === "items") {
var items = context[fldName]
for (var idx in items) {
var item = items[idx]
// START CREATING ITEM
log.audit('item', item)
rec.selectNewLine({ sublistId: 'item' });
for (var itemFldName in item) {
log.audit(itemFldName, item[itemFldName])
rec.setCurrentSublistValue({
sublistId: 'item',
fieldId: itemFldName,
value: item[itemFldName]
})
log.audit("current value", rec.getCurrentSublistValue({ sublistId: 'item', fieldId: itemFldName }))
}
rec.commitLine({ sublistId: 'item' });
// FINISHED CREATING ITEM
}
} else {
rec.setValue(fldName, context[fldName]);
}
}
}
var recordId = rec.save();
return { success: true, message: recordId }
}
return {
post: post
};
}
);
This is the error I'm seeing in the logs (line 34 is the commitLine call):
{"type":"error.SuiteScriptError","name":"USER_ERROR","message":"Please enter a value for amount.","stack":["anonymous(N/serverRecordService)","post(/SuiteScripts/api/submitInvoice.js:34)"],"cause":{"type":"internal error","code":"USER_ERROR","details":"Please enter a value for amount.","userEvent":null,"stackTrace":["anonymous(N/serverRecordService)","post(/SuiteScripts/api/submitInvoice.js:34)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}
Thanks in advance for any insight!
Try setting the quantity to 1. System might be overwriting your value with a calculated value of quantity * amount when you commit the line.
You are setting the Amount first, then the Quantity, and you are not setting the Rate. Because you are working with the record in Dynamic mode, you will need to set field values in the exact same order as you would in the UI, otherwise your data will be off.
If you need to continue working in Dynamic mode, then you will likely need to do a few things:
Ensure that sourcing happens when you set the Item field by setting the forceSyncSourcing option of setCurrentSublistValue to true. This should ensure that any columns dependent on the Item are set correctly.
Ensure you are setting the Item columns in the correct order; probably Item, then Quantity, then Amount. This way, Dynamic mode should hopefully not recalculate your Amount.
I generally avoid this problem entirely by working in Standard mode instead of Dynamic. I have found it extremely rare that I need to work in Dynamic mode. In Standard mode, field order no longer matters as you let the server figure it out after you submit the entire record rather than in real-time as you set each field.

suitescript 2.0:When I use removeSelectOption,throw a 'TypeError Cannot read property "removeSelectOption" of null' error

There is a js error When I use the removeSelectOption to remove all of the dropdown list.The code as follow:
function fieldChanged(scriptContext) {
if(scriptContext.fieldId == 'class'){
var currentRecord = scriptContext.currentRecord;
var brand_id = currentRecord.getValue({fieldId:'class'});
if(brand_id){
var itemList = [];
var itemField = currentRecord.getField({
fieldId: 'item'
});
itemField.removeSelectOption({
value: null,
});
search.create({
type: search.Type.INVENTORY_ITEM,
columns:[{name:'internalid'}],
filters:[
['custitem30',search.Operator.ANYOF,brand_id]
]
}).run().each(function(result){
item_id = result.getValue({
name:'internalid'
});
var in_item = record.load({
type: record.Type.SALES_ORDER,
id: item_id,
});
itemList.push(item_id);
itemField.insertSelectOption({
value: item_id,
text: in_item
});
console.log('item_id:' + item_id);
});
console.log('itemList:' + itemList);
}
}
}
And the api document in help center said -- To remove all options from the list, set this field to null, as follows:
field.removeSelectOption({
value: null,
});
If I want to remove all options from the dropdown list,what should I do?
Thanks.
Create a item saved search
2.Transaction form Item Filter field select that Saved Search.
As your question i assumed that you only show inventory item in item Field.
First of all you have get the field object
var field = currentRecord.getField({
fieldId: 'Your Field ID'
});
then use this below code
field.removeSelectOption({
value: null,
});
you cannot remove the field items from the list that are created from UI and have a source.
you can have a alert for it on field change

Resources