Accessing sub lists from netsuite - netsuite

I'm trying to access the json data in the format liike below...
{"subscriptions":
"recmachcustrecord2": [{
"custrecord_acceptable_min_shelf_life": "60",
"custrecord_item": {
"internalid": "399",
"name": "ABS2002-PACK"
}
}, {
"custrecord_acceptable_min_shelf_life": "60",
"custrecord_item": {
"internalid": "400",
"name": "ABS2003-PACK"
}
}]
}
I have written like
var subrec = salesRepRec.getSublistSubrecord({
sublistId: 'recmachcustrecord2',
fieldId: 'custrecord_item',
line: 0
});
{"type":"error.SuiteScriptError","name":"FIELD_1_IS_NOT_A_SUBRECORD_FIELD","message":"Field custrecord_item is not a subrecord field.","stack":["anonymous(N/serverRecordService)","onAfterSubmit(/SuiteScripts/cus.js:23)"],"cause":{"type":"internal error","code":"FIELD_1_IS_NOT_A_SUBRECORD_FIELD","details":"Field custrecord_item is not a subrecord field.","userEvent":"aftersubmit","stackTrace":["anonymous(N/serverRecordService)","onAfterSubmit(/SuiteScripts/cus.js:23)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}
mainly i want access the "internalid": "400",
"name": "ABS2003-PACK" these fields.
how can i access the using the suite script 2.0
Thanks in Advance!

AFAIK NetSuite does not allows creating a custom sublist subrecord. Although in you case, you only need to fetch internalid and itemid from the subrecord which can be achieved as below
{
custrecord_item: {
internalId: salesRepRec.getSublistValue({ sublistId: 'recmachcustrecord2', fieldId: 'custrecord_item', line: 0 }),
name: salesRepRec.getSublistText({ sublistId: 'recmachcustrecord2', fieldId: 'custrecord_item', line: 0 })
}
}

Related

How to set Invoice Tax Code in SuiteScript 2.1

I'm having some issues with setting the Tax Code on a Line Item related to an Invoice, this is the JSON for 1 of the Invoice Items I am passing to a RESTlet:
{
"item": {
"items": [
{
"taxCode": "8",
"quantity": 1,
"item": "7",
"description": "description",
"amount": 2280.00
}
]
}
}
The SuiteScript parses the JSON and sets the fields where necessary, I am able to set every other type of field, apart from the tax code, I have tried passing the Id as String and an Integer, as well as passing it as an object, like the below 2 examples, but I keep on getting errors no matter what I do.
"taxcode": {
"items": [
{ "id" : 8 }
]
}
"taxcode": {
{ "id" : 8 }
}
This is my RESTlet SuiteScript that iterates over the items and sets the relevant field values, as mentioned above; this is working for all other fields, it's just the tax code I am having issues with
for (let i of req[cust][key].items) {
// Select the sublist line
invoice.selectNewLine({
sublistId: key.toLowerCase()
});
// Iterate over the fields
for (let j in i) {
try {
// If the current field is an object
if (i[j] instanceof Object) {
// Get the subrecord
var child = invoice.getCurrentSublistSubrecord({
sublistId: key.toLowerCase(),
fieldId: j.toLowerCase()
});
// Set it's fields field
for (let k in i[j]) {
// Set the field and value
child.setValue({
fieldId: k.toLowerCase(),
value: i[j][k]
});
}
// Commit the line
invoice.setValue({
fieldId: j.toLowerCase(),
value: child
});
} else {
log.debug(
"setCurrentSublistValue",
JSON.stringify({
sublistId: key.toLowerCase(),
fieldId: j.toLowerCase(),
value: i[j]
})
);
// Set the fields
invoice.setCurrentSublistValue({
sublistId: key.toLowerCase(),
fieldId: j.toLowerCase(),
value: i[j]
});
}
} catch (e) {
log.debug(127, j);
log.debug(128, e);
}
}
// Commit the line
invoice.commitLine({
sublistId: key.toLowerCase()
});
}
Any ideas?
WORST API EVER!
You have to set the TaxCode last... or something else that is being set wipes it out -_-
Doesn't work:
{
"item": {
"items": [
{
"taxCode": "8",
"quantity": 1,
"item": "7",
"description": "description",
"amount": 2280.00
}
]
}
}
Works perfectly fine:
{
"item": {
"items": [
{
"quantity": 1,
"item": "7",
"description": "description",
"amount": 2280.00,
"taxCode": "8"
}
]
}
}

Use ONLY the external id of an item to create an invoice in Netsuite using Suitescript

Is it possible to create an invoice using item's external id and not internal id using a Restlet? I can accomplish this in Postman like this:
"item": {
"items": [
{
"amount": 120.0,
"item": {
"externalid": "12878"
},
"taxCode": {
"id": "13"
}
}
]
}
But when I try to set the same in Restlet, it throws an error.
var currentItem = items[i];
record.selectNewLineItem('item');
record.setCurrentLineItemValue('item', 'externalid', currentItem["exId"]);
record.setCurrentLineItemValue('item', 'quantity', currentItem["quantity"]);
record.setCurrentLineItemValue('item', 'rate', currentItem["rate"]);
record.setCurrentLineItemValue('item', 'taxcode', currentItem["taxcode"]);
record.commitLineItem('item');
{"error":{"code":"INVALID_KEY_OR_REF","message":"Invalid item reference key 12878 for subsidiary 1."}}
What you'd need to do is search for the items by external id.
var extIds = items.map(function(it){ return it.exId});
var items = nlapiSearchRecord('item', null, [
new nlobjSearchFilter('externalid', null, 'anyof', extIds)
], [
new nlobjSearchColumn('externalid')
]);
// check for null return and throw error
var extIdMap = {};
items.forEach(function(ref){
extIdMap[ref.getValue('externalid')] = ref.getId();
});
//then instead of record.setCurrentLineItemValue('item', 'externalid', currentItem["exId"]);
record.setCurrentLineItemValue('item', 'item', extIdMap[currentItem["exId"]]);

NetSuite SS 2.0: Salesorder Custom address

We are currently importing Salesorder from 3rd party,
The Salesorder creation is done fine.
We are struggling with the shipping address, we need to create a custom shipping address at each new salesorder.
when we use the following code, only the shipzip is shown in the salesorder, do you see any reason for that?
var shippingDetails = order[k].shipping_address;
log.debug('shipping',shippingDetails);
salesOrder.setValue('shipaddresslist', null);
salesOrder.setValue('shipcountry', shippingDetails.country_iso_code.substring(0,2));
log.debug('shipcountry',
salesOrder.getValue({
fieldId: 'shipcountry'
})
);
salesOrder.setValue('shipisresidential', 'T');
salesOrder.setValue('shipattention', 'Adresse de livraison');
log.debug('shipattention',
salesOrder.getValue({
fieldId: 'shipattention'
})
);
salesOrder.setValue('shipaddressee', shippingDetails.civility +' '+shippingDetails.firstname+' '+shippingDetails.lastname);
log.debug('shipaddressee',
salesOrder.getValue({
fieldId: 'shipaddressee'
})
);
salesOrder.setValue('shipaddrphone', shippingDetails.phone);
salesOrder.setValue('shipaddr1', shippingDetails.street_1);
salesOrder.setValue('shipaddr2', shippingDetails.street_2);
salesOrder.setValue('shipcity', shippingDetails.city);
//salesOrder.setValue('shipstate', 'CA');
salesOrder.setValue('shipzip', shippingDetails.zip_code);
as a workaround we try to use instead the below code, how can we have the carriage return?:
salesOrder.setValue('shipaddress', shippingDetails.civility +' '+shippingDetails.firstname+' '+shippingDetails.lastname +'\n'+shippingDetails.street_1+'\n'+shippingDetails.zip_code+' '+shippingDetails.city);
To correctly set a Billing or Shipping address on a Sales Order using SuiteScript 2.0 you must use the subrecord method.
Here is a full working example of creating a sales order with the specified Customer Internal ID and a single valid Item Internal ID
You can adapt it to suit your needs.
/**
*#NApiVersion 2.x
*/
require(['N/record'], function (record) {
var VALID_CUSTOMER_ID = 14907; // A valid Customer Internal ID for testing
var VALID_ITEM_ID = 7006; // A valid Item Internal ID for testing
// Example address details
var shippingDetails = { "country_iso_code": "USA", "civility": "civilty", "firstname": "firstname", "lastname": "lastname", "phone": "0123456789", "street_1": "Street 1", "street_2": "Street 2", "city": "Bell", "shipstate": "California", "zip_code": "90201" };
var billingDetails = { "country_iso_code": "USA", "civility": "civilty", "firstname": "firstname", "lastname": "lastname", "phone": "0123456789", "street_1": "Street 1", "street_2": "Street 2", "city": "Bell", "shipstate": "California", "zip_code": "90201" };
function CreateSalesOrder() {
// Create our new sales order
var salesOrder = record.create({
type: record.Type.SALES_ORDER,
isDynamic: true,
defaultValues: { entity: VALID_CUSTOMER_ID }
});
// Add a line item (just for testing / example)
salesOrder.selectNewLine({sublistId: 'item'});
salesOrder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'item',
value: VALID_ITEM_ID
});
salesOrder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'quantity',
value: 1
});
salesOrder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'amount',
value: 1
});
salesOrder.commitLine({sublistId: 'item'});
// Set our billing address
salesOrder.setValue({
fieldId: 'billaddresslist',
value: null // Needed to override default address
});
var billaddrSubrecord = salesOrder.getSubrecord({fieldId: 'billingaddress'});
billaddrSubrecord.setValue({
fieldId: 'country',
value: billingDetails.country_iso_code.substring(0,2)
});
billaddrSubrecord.setValue({
fieldId: 'isresidential',
value: 'T'
});
billaddrSubrecord.setValue({
fieldId: 'attention',
value: 'Adresse de livraison'
});
billaddrSubrecord.setValue({
fieldId: 'addressee',
value: billingDetails.civility +' '+billingDetails.firstname+' '+billingDetails.lastname
});
billaddrSubrecord.setValue({
fieldId: 'addrphone',
value: billingDetails.phone
});
billaddrSubrecord.setValue({
fieldId: 'addr1',
value: billingDetails.street_1
});
billaddrSubrecord.setValue({
fieldId: 'addr2',
value: billingDetails.street_2
});
billaddrSubrecord.setValue({
fieldId: 'city',
value: billingDetails.city
});
billaddrSubrecord.setValue({
fieldId: 'state',
value: billingDetails.state
});
billaddrSubrecord.setValue({
fieldId: 'zip',
value: billingDetails.zip_code
});
// Set our shipping address
salesOrder.setValue({
fieldId: 'shipaddresslist',
value: null // Needed to override default address
});
var shipaddrSubrecord = salesOrder.getSubrecord({fieldId: 'shippingaddress'});
shipaddrSubrecord.setValue({
fieldId: 'country',
value: shippingDetails.country_iso_code.substring(0,2)
});
shipaddrSubrecord.setValue({
fieldId: 'isresidential',
value: 'T'
});
shipaddrSubrecord.setValue({
fieldId: 'attention',
value: 'Adresse de livraison'
});
shipaddrSubrecord.setValue({
fieldId: 'addressee',
value: shippingDetails.civility +' '+shippingDetails.firstname+' '+shippingDetails.lastname
});
shipaddrSubrecord.setValue({
fieldId: 'addrphone',
value: shippingDetails.phone
});
shipaddrSubrecord.setValue({
fieldId: 'addr1',
value: shippingDetails.street_1
});
shipaddrSubrecord.setValue({
fieldId: 'addr2',
value: shippingDetails.street_2
});
shipaddrSubrecord.setValue({
fieldId: 'city',
value: shippingDetails.city
});
shipaddrSubrecord.setValue({
fieldId: 'state',
value: shippingDetails.state
});
shipaddrSubrecord.setValue({
fieldId: 'zip',
value: shippingDetails.zip_code
});
// Save our new sales order
salesOrder.save({ignoreMandatoryFields: true});
}
CreateSalesOrder();
});
Working Example Video
After an hour of fighting here's a 2021 update. When in doubt, RTM: https://6396621-sb1.app.netsuite.com/app/help/helpcenter.nl?fid=section_4704101831.html
//Create the custom shipping address
let shipaddr = so.getSubrecord('shippingaddress');
shipaddr.setValue('country', order.shippingAddress.country.id);
shipaddr.setValue('phone', order.deliveryphone);
shipaddr.setValue('isresidential', 'T');
shipaddr.setValue('attention', '');
shipaddr.setValue('addressee', order.shippingAddress.addressee);
shipaddr.setValue('addr1', order.shippingAddress.address1);
shipaddr.setValue('city', order.shippingAddress.city);
shipaddr.setValue('state', order.shippingAddress.state);
shipaddr.setValue('zip', order.shippingAddress.postcode);
log.debug('Shipping',shipaddr);
//Create the custom billing address
let billaddr = so.getSubrecord('billingaddress');
billaddr.setValue('country', order.billingAddress.country.id);
billaddr.setValue('phone', order.billingAddress.phone);
billaddr.setValue('isresidential', 'T');
billaddr.setValue('attention', '');
billaddr.setValue('addressee', order.billingAddress.addressee);
billaddr.setValue('addr1', order.billingAddress.address1);
billaddr.setValue('city', order.billingAddress.city);
billaddr.setValue('state', order.billingAddress.state);
billaddr.setValue('zip', order.billingAddress.postcode);
log.debug('Billing',billaddr);

SuiteScript add item at beforeLoad when creating a new sales order

I want to add a line item at beforeLoad event. An item is added after the page is loaded. However, I don't think I can use the line item i just created. available quantity, onhand quantity, units, price level are not added automatically. Inventory Detail button is not there. Any advise?
function beforeLoad(context) {
var record = context.newRecord;
record .insertLine({"sublistId": "item", "line": 0});
record .setSublistValue({"sublistId": "item", "fieldId": "item", "value": 57, "line": 0});
record .setSublistValue({"sublistId": "item", "fieldId": "quantity", "value": 1, "line": 0});
}
You could try CLIENT SCRIPT - change to scriptContext.currentRecord.
if (scriptContext.mode == "create") {
var record = *scriptContext.currentRecord;*
record.selectNewLine({sublistId: "item" });
record.setCurrentSublistValue({sublistId: "item", fieldId: "item", value: 57 });
record.setCurrentSublistValue({sublistId: "item", fieldId: "quantity", value: 1});
record.commitLine({sublistId:"item"});
}

NetSuite Restlet - USER_ERROR

I am creating this script to write the invoice in NetSuite. However, when I send the data this error appears: "The approval status field should only be used when the approval routing preference is selected."
PS: in the interface the same error occurs when trying to save.
Can you help me? Here's the code:
/**
* #NApiVersion 2.x
* #NScriptType restlet
* #author Adriano Barbosa
* #since 2019.2
*/
define(['N/record', 'N/file', 'N/log', 'N/search'], function (record, file, log, search) {
function vpc_contas_receber(context) {
if ( context.cnpj_forn ) {
var id_forn;
search.create({ type: "customer",
filters: [
[ "custentity_enl_cnpjcpf", "is", context.cnpj_forn ]
],
columns: [
search.createColumn({ name: "internalid", label: "ID interna" })
]
}).run().each(function(result) {
id_forn = result.id;
return true;
});
if ( !id_forn ) {
log.debug({ title: 'Erro', details: 'Fornecedor ' + context.cnpj_forn + ' não localizado!' });
return { status: 'Erro', mensagem: 'Fornecedor ' + context.cnpj_forn + ' não localizado!' }
} else if ( context.nf ) {
var id_nf_existe, nf_existe, num_fat;
search.create({ type: "invoice",
filters: [
[ "type", "anyof", "CustInvc" ], "AND",
[ "custbody_enl_fiscaldocnumber", "is", context.nf ]
],
columns: [
search.createColumn({ name: "custbody_enl_fiscaldocnumber", label: "Número da Nota Fiscal" }),
search.createColumn({ name: "formulatext", formula: "SUBSTR({tranid}, 0)", label: "nº fatura" })
]
}).run().each(function(result) {
id_nf_existe = result.id;
nf_existe = result.getValue({ name: 'custbody_enl_fiscaldocnumber' });
num_fat = result.getValue({ name: 'formulatext' });
});
if ( nf_existe ) {
log.debug({ title: 'NF ' + nf_existe + ' já cadastrada!', details: 'VPC: ' + id_nf_existe + '; ' + 'Nº Fatura: ' + num_fat });
return {
status: 'NF ' + nf_existe + ' já cadastrada!',
mensagem: 'VPC: ' + id_nf_existe + '; ' + 'Nº Fatura: ' + num_fat
}
} else {
vpc = record.create({ type: 'invoice', isDynamic: true })
.setValue({ fieldId: 'entity', value: id_forn })
.setValue({ fieldId: 'memo', value: context.obs })
.setValue({ fieldId: 'location', value: 1 })
.selectNewLine({ sublistId: 'item' })
.setCurrentSublistValue({ sublistId: 'item', fieldId: 'item', value: 27901 })
.setCurrentSublistValue({ sublistId: 'item', fieldId: 'rate', value: context.valor })
.commitLine({ sublistId: 'item' })/*
.setValue({ fieldId: 'custbody_rsc_dtvencboleto', value: new Date(context.venc_blt) })*/
.setValue({ fieldId: 'custbody_enl_operationtypeid', value: 15 })
.setValue({ fieldId: 'custbody_enl_order_documenttype', value: 7 })
.setValue({ fieldId: 'custbody_enl_fiscaldocnumber', value: context.nf })/*
.save({ enableSourcing: true, ignoreMandatoryFields: true })*/
if ( context.venc_blt ) {
var venc_blt = new Date(context.venc_blt);
venc_blt.setDate(venc_blt.getDate());
vpc.setValue({ fieldId: 'custbody_rsc_dtvencboleto', value: venc_blt });
}
var id_vpc = vpc.save({ enableSourcing: true, ignoreMandatoryFields: true });
try {
var bodyObject = {};
var load_id_vpc = record.load({ type: 'invoice', id: id_vpc });
bodyObject['id_vpc'] = id_vpc;
bodyObject['doc_vpc'] = load_id_vpc.getValue({ fieldId: 'tranid' });
bodyObject['memo'] = load_id_vpc.getValue({ fieldId: 'memo' }) || '';
bodyObject['valor'] = load_id_vpc.getSublistValue({ sublistId: 'item', fieldId: 'rate', line: 0 }).toFixed(2);
bodyObject['nf'] = load_id_vpc.getValue({ fieldId: 'custbody_enl_fiscaldocnumber' });
bodyObject['venc_blt'] = load_id_vpc.getValue({ fieldId: 'custbody_rsc_dtvencboleto' });
log.debug({ title: 'VPC["Contas a Receber"] cadastrado com sucesso!', details: bodyObject });
return { 'status': 'Sucesso!', 'infoVPC': bodyObject }
} catch (e) {
log.debug({ title: 'Erro', details: e });
return { status: 'Erro!', mensagem: e }
}
}
}
}
// forn = search.create({ type: "vendor",
// filters: [
// [ "custentity_enl_cnpjcpf", "is", context.fornecedor ]
// ],
// columns: [
// search.createColumn({ name: "internalid", label: "ID interna" })
// ]
// }).run().getRange({ start: 0, end: 1 })
}
return { 'post': vpc_contas_receber }
});
As the message indicates:
to use the Approval Status field, you must activate Approval Routing for invoices.
To do so, go to Setup -> Accounting -> Accounting Preferences -> Tab "Approval Routing" and check the Transactions(s) on which you want to manage approvals. This will make the "Approval Status" available for use.

Resources