NetSuite Suitescript 2.0 How can I access custom item options records? - netsuite

I have a problem that I'm trying to solve in a roundabout way since the straightforward way didn't work.
The task: Retrieve the customizable item options off of a purchase order item (using SuiteScript 2.0).
The partial solution: Currently, I extract the itemId off the PO using
po.getCurrentSublistValue({ sublistId: 'item', fieldId: 'item' });
Then I load the item and extract the item options IDs and labels using
var optionIds = item.getValue({ fieldId: 'itemoptions' });
var optionLabels = item.getText({ fieldId: 'itemoptions' });
For item options that aren't List/Record type, (like freeform text personalization), I can then loop through the item options and extract their text off of the PO item using the following code.
for (var j = 0; j < optionIds.length; j++) {
var option = po.getCurrentSublistText({
sublistId: 'item',
fieldId: optionIds[j].toLowerCase()
});
if (option !== null) {
log.debug({title: 'option found', details: optionLabels[j] + ': ' + option});
}
}
The issue: When the item option is a List/Record type, both getCurrentSublistText and getCurrentSublistValuereturn the internal ID of the list selection. For instance, if I have a custom item option for Shirt Color, and it uses the custom list Color, with Red being internal ID 2, then if my PO has an item with red shirt color on it, the option label will be "Shirt Color", but instead of "Red," the option will be 2, the internal ID from the Color list. I have no idea why getCurrentSublistText doesn't work for this use case, but I've accepted it, and I'm looking for a workaround.
My thought was, since the item option is a record in the UI (my field explorer extension says it has recordType:"itemoptioncustomfield"), I could just load it up using the option ID that I have, and if it has fieldtype:"SELECT", I would get the internal ID of the List/Record selection (fieldId: selectrecordtype) then use search.lookupFields to get the actual value of my item option, instead of the internal ID. The only issue is, I can find no way to load (or search on) an item option. The record type does not seem to exist in SuiteScript (I believe in Suite Talk it does though). Is this a possible task? Even if my workaround can't work, is there another better workaround that I'm not seeing?
Thanks in advance, I'm at a loss here.
Edit: Just to add further attempts, I found the Field.getSelectOptions() function today which looked really promising, since it would list all the select options of the item option and their values I would think. I tested it out on some other more basic fields on the order and it worked, however when I tried using getCurrentSublistField on the item option field (just as I used getCurrentSublistValue and getCurrentSublistText, the field returned was null, so looks like that is another dead end.

Related

How to move sublist fields created from User Event script

I added a sublist field on a transaction. For instance a Sales Order. When you add the field via user event script, it positions the field at the end of the sublist. Is there a way to position the field? This can't be accomplished in the UI as the field is added via script. It's a select type field, so I am trying to modify the list values with client script and can only do that if the field is created in my user even script. My code works perfectly fine, it's just the field is at the end of the sublist line(far right and have to scroll). I am using SuiteScript 1.0 but am open to using 2.0 if I need to.
This is for suitescript 2.0
This has sort of turned into two questions so I will give an answer for one and then the solution, for clarity. The short answer is you cannot move a sublist field when created in a user event (however there is a solution to that.)
you can add a sublist field by getting the sublist and using the sublist.addField method.
function beforeLoad(context){
var form = context.form;
var sublist = form.getSublist({
id : 'item'
});
sublist.addField({
id: 'fieldid you want to use for script reference ect.',
type: serverWidget.FieldType.CHECKBOX, //any supported TYPE
label: 'Label users will see in sublist'
});
}
If done this way, there will be a new column on the end of the items sublist that cannot be moved.
To be able to move the location of the column do the following.
Navigate to
Customization
Lists, Records, & Fields
Transaction Line Fields
add a new field and apply to the sublist you want it used on.
you can assign and id which will be prefixed with custcol so start your id with an _ and give it a name.
Once this is complete you can access the field by id and change the value in your user event script before load
function beforeLoad(context){
var form = context.form;
var sublist = form.getSublist({
id : 'item'
});
sublist.setSublistValue({
id: 'customcol_id_created_in_ui',
line: 1, //line you want to access if needing to set all you will have to loop through and set each one.
value: "your value"
});
}
If you go to the API reference and look at the ui/serverWidget module and navigate to sublist you can find all of the methods and options for manipulating sublist there.
In SuiteScript 2.x you would use the N/ui/serverWidget module, create the field and then use the Form.insertField(options) method, passing in the field you created as options.field and the existing field which you want to insert your field before as options.nextfield. Note that Form refers to the form object passed to the user event script in the scriptContext.
i don't believe there is a SS1.0 equivalent.

How do I do a joined lookup with search.lookupFields()?

I'm trying to get some information about an item, including the item's subsidiary's logo, which naturally requires joining the item to the subsidiary.
The documentation for search.lookupFields says:
You can use joined-field lookups with this method, with the following syntax:
join_id.field_name
So, I duly request the fields I want, including a join on subsidiary:
require(['N/search'], function(search) {
var item = search.lookupFields({
type: search.Type.ITEM,
id: 2086,
columns: ['itemid', 'displayname', 'subsidiary.logo'],
});
log.debug(item);
});
itemid and displayname are fine, but when I try to join another record I get this error:
{
"type":"error.SuiteScriptError",
"name":"SSS_INVALID_SRCH_COLUMN_JOIN",
"message":"An nlobjSearchColumn contains an invalid column join ID, or is not in proper syntax: logo.",
"stack":["doLookupFields(N/search/searchUtil.js)","<anonymous>(adhoc$-1$debugger.user:2)","<anonymous>(adhoc$-1$debugger.user:1)"],
"cause":{
"type":"internal error",
"code":"SSS_INVALID_SRCH_COLUMN_JOIN",
"details":"An nlobjSearchColumn contains an invalid column join ID, or is not in proper syntax: logo.",
"userEvent":null,
"stackTrace":["doLookupFields(N/search/searchUtil.js)","<anonymous>(adhoc$-1$debugger.user:2)","<anonymous>(adhoc$-1$debugger.user:1)"],
"notifyOff":false
},
"id":"",
"notifyOff":false,
"userFacing":false
}
This seems to happen no matter which record and field I try to join. What am I missing?
Although you can return results from multi-select fields, you cannot join to fields on records referenced by multi-select fields (which the subsidiary field on the item record is). Also, you cannot search the logo field on the subsidiary record (not listed in Search Columns under Subsidiary in the NetSuite Records Browser).
This means you have to load the Subsidiary record to get the logo field. In other words:
require(['N/record', 'N/search'], function(record, search) {
var item = search.lookupFields({
type: search.Type.ITEM,
id: 2086,
columns: ['itemid', 'displayname', 'subsidiary'],
});
var subID = item.subsidiary[0].value; //internal id of *first* subsidiary
var subRec = record.load({
type: record.Type.SUBSIDIARY,
id: subID
});
var logo = subRec.getText('logo'); //gets the file name - use getValue to get its ID instead
});
Note that if multiple subsidiaries are set on the item, this only gets the values for the first one. You could iterate through the item.subsidiary result to handle values for multiple subsidiaries if required.
I believe you can't access to the subsidiary record from a lookupfield, you should do a proper search.
https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2018_2/script/record/item.html
You can only join to tables allowed in the Item search object. Try looking for "Subsidiary..." in the Search Results tab within the UI. It's not there. Use the Schema Browser to determine what fields and joins are available.
You cannot think of a NetSuite search as you would any regular SQL search. You have to be cognizant of which fields and which joins can be utilized via the search object.
As people have mentioned, the subsidiary is not a join field available from the item record, one way to achieve what you are trying to do is:
Make a lookup to get the internal id of the subsidiary belonging to the desired item.
Then make a lookup to get the internal id of the logo image (file cabinet image) belonging to the previous subsidiary.
Make another lookup/load the image file to get the URL of the image/logo
You can try to combine the above steps in a single saved search but I think you might need to load the image file to get the URL.
This won't answer your question, but this may help out in the future. The records browser shows everything that you can search and join on, columns and filters, and field IDs. Very useful when building out searches.
NetSuite Records Browser - 2018.2

NetSuite SuiteScript 2.0 how to update Sales Order Item which is part of the Item Group

I'm trying to update Term field on Sales Order Item Line in NetSuite.
I can do that fine using ue (user event script) on beforeSubmit event.
That works when I hit Save button when Sales Order is in Edit mode.
Now, the issue:
I am trying to update Sales Order Item field (Term) BEFORE Save button is hit but AFTER Add button is clicked, for components of Item Group.
I have written a function and added to postSourcing(scriptContaxt) event that does the updating but it works only for NON-Inventory Items.
This does not work for Item Groups.
When Item Group is added to the Sales Order, inventory (components) are automatically populated onto the form.
Does anybody know what event is triggered when components of Item Group are added to the Sales Order form?
Thank you
Kris
OK... Further research and explanation:
This is the code for updating a single filed when Non-Inventory Item is added to the Sales Order (adding SKU number to the Sales Order Line):
function postSourcing(scriptContext)
{
setSalesOrderItemTerm(scriptContext.currentRecord);
}
function setSalesOrderItemTerm(salesorder)
{
var itemId = salesorder.getCurrentSublistValue({
sublistId: 'item',
fieldId: 'item'
});
if(!itemId)
return;
var result = search.create({
type: search.Type.ITEM,
columns: ['custitem_abs_item_term'],
filters: [{name: 'internalid',operator: search.Operator.IS,values: itemId},
{name: 'isinactive',operator: search.Operator.IS,values: 'F'}]
}).run().getRange({start: 0, end: 1});
if(result.length > 0)
{
var term = result[0].getValue('custitem_abs_item_term');
salesorder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'custcol_swe_contract_item_term_months',
value: term
});
}
}
This works absolutely fine for a single, Non-Inventory Item.
On the other hand when I try to add Item Group (this is different than KIT) the Term field (id: custcol_swe_contract_item_term_months) is not being updated from its item, the Term field is updated with value on the Item Group.
FYI. Item Group is constructed with Item Group (Group Header called Group), its components (other Item types i.e. Non-Inventory Items) and Empty Items (called End Group -> usually empty)
So when you have an Item Group that has two Non-Inventory Items in it and you try to add that Item Group to Sales Order those two Non-Inventory items will be automatically added to Sales Order (along with Group and End Group row).
I am trying to find out on what event those two Non-Inventory items are added to Sales Order.
I hope this is more clear now.
Thank you
Kris
My answer below, also applies to this
https://stackoverflow.com/a/44013939/5389329 "Creating a SalesOrder within NetSuite with Item Groups"

Netsuite: Manually modify [invoiced] field in Sales Order > Item subtab

Is there any way to manually modify [invoiced] field in Sales Order > Item subtab via SuiteScript?
Currently I am able to update this field via nlapiTransformRecord(sales order to invoice), but in case there are two item fulfillment for same item, I do not want to combine these together instead I want to show two rows in Invoice. I am able to achieve this by using SelectNewLineItem but the problem is the [invoiced] field is not being updated. Please help. Thanks.
As show in below, if I use SelectLineItem it works perfectly. But SelectNewLineItem somehow failed to update the [invoiced] field.
var newrecords = nlapiTransformRecord('salesorder', results[0][9],
'invoice', {
recordmode : 'dynamic'
});
//Temporary hardcoded this to 2 for testing
if (m == 2) {
newrecords.selectNewLineItem('item');
newrecords.setCurrentLineItemValue('item', 'item',
results[m][10]);
newrecords.setCurrentLineItemValue('item', 'quantity',
results[m][4]);
newrecords.setCurrentLineItemValue('item', 'amount',
results[m][5]);
newrecords.commitLineItem('item');
} else {
var lineNum = newrecords.findLineItemValue('item', 'item',
results[m][10]);
newrecords.selectLineItem('item', lineNum);
newrecords.setCurrentLineItemValue('item', 'item',
results[m][10]);
newrecords.setCurrentLineItemValue('item', 'quantity',
results[m][4]);
newrecords.setCurrentLineItemValue('item', 'amount',
results[m][5]);
newrecords.commitLineItem('item');
}
}
nlapiSubmitRecord(newrecords, false, true);}
I don't believe this is possible.
Basically, there are two types of lines on Invoices - those linked to a Sales Order, and standalone lines. Linked lines will reflect back to the Sales Order, and do not change stock on hand (as that is changed by the Fulfillment), while standalone lines have no connection to the Sales Order.
The only (API supported) way to create an Invoice that is linked back to the Sales Order is using nlapiTransformRecord(). If you then manually add lines with record.selectNewLineItem() they cannot be linked back.

Issue with List Apply in NetSuite

Unable to find a matching line for sublist apply with key: [doc,line] and value: [5489377,1].
I'm seeing this error when I try to update an apply list on a NetSuite transaction object. The "doc" is the internal ID of the object, and the line number seems to correspond to a line number on the object.
Why is this happening? Can't seem to find a solution.
This works for applying a credit memo to a particular invoice. invId is the internalid of the invoice record:
function applyPayment(creditMemo, payAmount, invId){
var didApply = false;
creditMemo.setFieldValue('autoapply', 'F');
if(payAmount === null) payAmount = creditMemo.getFieldValue('amountremaining');
for(var i = 1; i<=creditMemo.getLineItemCount('apply'); i++){
if(invId == creditMemo.getLineItemValue('apply', 'doc', i)){
didApply = true;
creditMemo.setLineItemValue('apply', 'apply', i, 'T');
creditMemo.setLineItemValue('apply', 'amount',i, payAmount);
}else if('T' == creditMemo.getLineItemValue('apply', 'apply', i)) creditMemo.setLineItemValue('apply', 'apply', i, 'F');
}
if(didApply) nlapiSubmitRecord(creditMemo);
}
We were getting this error with the Chargebee-Netsuite integration and the solution was to open the corresponding Accounting Period in Netsuite and rerun the sync.
Like you mentioned, the first number[5489377,1] is the Netsuite internal ID of the affected document. If you navigate to the document in Netsuite and it has a padlock this could be the reason Locked document
Open the Accounting Period for the affected document and rerun the sync. setup/accounting/manage accounting periods Manage accounting periods

Resources