I'm trying to transform an item fulfillment to invoice. I created a custom field called "freight cost" and I"m trying to get the value of that field and transfer it over to the invoice and add two lines to the item sublist: "FREIGHT" and "HANDLING". However, I'm getting an error when I try to get the value of the freight cost.
Here's my code:
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
*/
define(['N/record', 'N/log'],
function(record, log) {
function afterSubmit(context) {
var orderId = context.newRecord;
var freightCost = orderId.record.getValue({
fieldId:'custbody_freight_cost'
});
log.error({
title: 'Freight Cost',
details: freightCost
});
var invoiceRecord = record.transform({
fromType: record.Type.ITEM_FULFILLMENT,
fromId: orderId,
toType: record.Type.INVOICE,
isDynamic: true
});
log.error({
title: 'Debug Entry',
details: invoiceRecord
});
var freightLine = invoiceRecord.insertLine({
sublistId:'item',
item: 3,
ignoreRecalc: true
});
var handlingLine = invoiceRecord.insertLine({
sublistId:'item',
item: 4,
ignoreRecalc: true
});
var freightSaver = invoiceRecord.setCurrentSublistValue({
sublistId:'item',
fieldId:'custbody_freight_cost',
value: freightCost,
ignoreFieldChange: true
});
var rid = invoiceRecord.save();
}
return {
afterSubmit: afterSubmit
};
});
And here's the error I'm getting:
org.mozilla.javascript.EcmaError: TypeError: Cannot call method "getValue" of undefined (/SuiteScripts/complexInvoice.js#12)
The reason you're getting that error is because you are calling the .getValue method on the record object instead of the orderId object. I would recommend renaming your variables to avoid some confusion as I have done below.
Another issue I see occurring in this script is that you are not allowed to transform an Item Fulfillment into an Invoice in SuiteScript. You can only transform a Sales Order into an Invoice. If you want to look at all the possible transformations you can make in SuiteScript open up NetSuite help and search for record.transform(options).
Lastly, it looks like you're adding sublist lines to the new invoice in an unusual way. See my code below for an example of how to add lines to an invoice record in "dynamic" mode.
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
*/
define(["N/record", "N/log"], function (record, log) {
function afterSubmit(context) {
// Gather your variables
var newRec = context.newRecord;
var freightCost = newRec.getValue({
fieldId: 'custbody_freight_cost'
});
var salesOrderId = newRec.getValue({ // Here we are getting the sales order id to use in the transform function
fieldId: 'createdfrom'
});
log.error({
title: 'Freight Cost',
details: freightCost
});
// Transform the Sales Order into an Invoice
var invoiceRecord = record.transform({
fromType: record.Type.SALES_ORDER,
fromId: salesOrderId,
toType: record.Type.INVOICE,
isDynamic: true
});
log.error({
title: 'Debug Entry',
details: invoiceRecord
});
// Add lines to the invoice like this, this is the correct way when the record is in "dynamic" mode
invoiceRecord.selectNewLine({
sublistId: 'item'
});
invoiceRecord.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'item',
value: 3
});
invoiceRecord.commitLine({
sublistId: 'item'
});
invoiceRecord.selectNewLine({
sublistId: 'item'
});
invoiceRecord.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'item',
value: 4
});
invoiceRecord.commitLine({
sublistId: 'item'
});
// Here is how you set a body field
invoiceRecord.setValue({
fieldId: 'custbody_freight_cost',
value: freightCost,
ignoreFieldChange: true
});
// Submit the record
var rid = invoiceRecord.save();
log.debug('Saved Record', rid);
}
return { afterSubmit: afterSubmit };
});
Related
I am New to Netsuite.
I am trying to archive the following functionality,
I created a code that will create an Invoice through API - (Completed & worked).
I want to change the Tax values to zoho for the Invoice that is created through the above.(ISSUE)
Here is my following code:
define(['N/log'], function (log) {
/**
* User Event 2.0 example showing usage of the Submit events
*
* #NApiVersion 2.x
* #NModuleScope SameAccount
* #NScriptType UserEventScript
* #appliedtorecord customer
*/
var exports = {};
function beforeSubmit(context) {
try
{
var currentRecord = context.newRecord;
log.debug({
title: 'currentRecord',
details: currentRecord
});
var sublistName = "item";
var sublistFieldName = "taxcode";
var line = context.line;
var subsidiary_id = currentRecord.getValue({fieldId:'subsidiary'});
var inv_type = currentRecord.getText({
fieldId: 'custbody3'
});
log.debug({
title: 'inv_type',
details: inv_type
});
log.debug({
title: 'subsidiary_id',
details: subsidiary_id
});
if (subsidiary_id == 6)
{
if (inv_type == "Services") {
if (sublistName === 'item') {
var lines = currentRecord.getLineCount({sublistId: 'item'});
log.debug({title:'lines',details:lines});
for (var i = 0; i < lines; i++) {
var descriptionValue = currentRecord.getSublistValue({
sublistId: sublistName,
fieldId: "description",
line: i
})
log.debug({
title: 'descriptionValue',
details: descriptionValue
});
log.debug({title: 'sets',details: /NON-JP/ig.test(currentRecord.getSublistValue({
sublistId: sublistName,
fieldId: "description",
line: i
}))});
if (/JP/ig.test(currentRecord.getSublistValue({
sublistId: sublistName,
fieldId: "description",
line: i
})))
{
currentRecord.setSublistValue({
sublistId: 'item',
fieldId: 'taxcode',
value: 6880,
ignoreFieldChange: true,
enableSourcing: true,
line: i
});
currentRecord.setSublistValue({
sublistId: 'item',
fieldId: 'taxrate1',
value: "10.0",
ignoreFieldChange: true,
enableSourcing: true,
line: i
});
}
currentRecord.setSublistValue('item', 'taxrate1', i, 10.0);
}
}
}
}
} catch (e) {
log.error('Error in validateLine', e);
}
}
return {
beforeSubmit: beforeSubmit
};
});
The Code logic and getValue method and other functionalities are working perfectly Except for submit
I tried to submit the newlyu updated line value in netsuite but the record is not getting submitted.
Can you help me to identify the issue I am doing.
Thanks in advance
Remove the ignoreFieldChange and enableSourcing parameters from your setSublistValue calls. I am not sure if your logging statements will work -- we typically always convert the details field to a string before logging, by using something like JSON.stringify.
You'll also want to check the script deployment for the logging there to make sure there aren't any syntax errors or other exceptions being thrown.
You're setting the variable line at the beginning to context.line but the current context is beforeSubmit, therefore, it will be undefined. I can see that you're not using this variable anywhere but it is worth noting that. line is only available in Client contexts such as fieldChange, validateField, and such...
Also, in the last setSublistValue you're providing several parameters when the Record.setSublistValue method receives an object, just like you did on the previous setSublistValue calls.
I have tried everything to get this working but no matter what I do, I always get the following error from NetSuite:
error code: USER_ERROR error message: {"type":"error.SuiteScriptError","name":"USER_ERROR","message":"Please enter value(s) for: Serial/Lot Number","stack":["anonymous(N/serverRecordService)"...
This occurs when I try to commit the line.
What I am attempting to do (in a RESTlet) is programatically create a Work Order Completion (WOC) for an existing Work Order (WO). I have it working for the first operation. However, for the final operation, which requires an Inventory Detail, I am getting the error. Here is my code (I have removed error checking, etc for better clarity):
/**
* #NApiVersion 2.x
* #NScriptType restlet
*/
define(['N/runtime', 'N/error', 'N/record', 'N/search'], function(runtime, error, record, search) {
return {
get : function(datain) {
var wo = record.load({
type: record.Type.WORK_ORDER,
id: datain.woid
});
var woc = record.transform({
fromType: record.Type.WORK_ORDER,
fromId: datain.woid,
toType: record.Type.WORK_ORDER_COMPLETION,
isDynamic: true,
defaultValues: {
isbackflush: 'F',
}
});
woc.setText({
fieldId: "startoperation",
text: "20"
});
woc.setText({
fieldId: "endoperation",
text: "20"
});
woc.setText({
fieldId: "completedquantity",
text: "230"
});
var invdetail = woc.getSubrecord({
fieldId: "inventorydetail"
});
invdetail.selectNewLine({
sublistId: "inventoryassignment",
});
invdetail.setCurrentSublistValue({
sublistId: "inventoryassignment",
fieldId: "binnumber",
value: 29
});
invdetail.setCurrentSublistValue({
sublistId: "inventoryassignment",
fieldId: "quantity",
value: 230
});
invdetail.setCurrentSublistText({
sublistId: "inventoryassignment",
fieldId: "issueinventorynumber",
text: "abc"
});
invdetail.commitLine({
sublistId: "inventoryassignment",
});
woc.save();
var results = {
woc: woc
};
return JSON.stringify(results);
}
}
});
I have tried everything I can think of. Using setCurrentSublistValue() and setCurrentSublistText(), setting the value to an existing lot, new lot, etc, etc.
However, no matter what I do, NS always responds with the "Please enter value(s) for: Serial/Lot Number" error as if it is not set.
Thoughts, ideas, suggestions???
Thanks!
Try using receiptinventorynumber for your fieldId.
invdetail.setCurrentSublistValue({
sublistId: 'inventoryassignment',
fieldId: 'receiptinventorynumber',
value: 'lotNumber'
});
invdetail.commitLine({sublistId: 'inventoryassignment'});
I seem to be in a bit of a pickle, I have written an app that lets my client perform an inventory count but am unable to to update the 'inventorycount' record with the new count values for each item.
I have tried updating the 'countquantity' value directly but it ignores this, I am now trying to load the record specified in 'countline', but this doesn't seem to be working either.
My code is as follows (written in TypeScript):
/**
* Update a InventoryCount with a new set of counts
* #parameters
* {
* service: inventorycount,
* method: update,
* id: 12345,
* inventory: [{
* upccode: 98765,
* total: 543
* }]
* }
*/
public update() {
const rec = Record.load({
type: Record.Type.INVENTORY_COUNT,
id: this.parameters.id,
isDynamic: true
});
this.parameters.inventory.forEach(item => {
this.updateLine(rec, item);
});
return rec.save();
}
/**
* Update a single item within the sublist of an inventory count.
* We update the memo field and the try update the quantity counted.
*
* #param rec the inventorycount record loaded in update
* #param item the item object loaded from parameters
*/
private updateLine(rec, item) {
// fetch the internalid from the upccode
const internalId = this.upccodeToInternalid(item.upccode);
// fetch the line number by the given item internal id
const itemLine = rec.findSublistLineWithValue({
sublistId: "item",
fieldId: "item",
value: internalId
});
// select the line to make modifications on
rec.selectLine({
sublistId: "item",
line: itemLine
});
// get the current memo so we can append to it
const currentMemo = rec.getCurrentSublistValue({
sublistId: "item",
fieldId: "memo"
});
// update the memo field with our new string
rec.setCurrentSublistValue({
sublistId: "item",
fieldId: "memo",
value: this.mergeMemo(currentMemo, item.areas)
});
// get the current item count and append our new count
const currentQuantity = rec.getCurrentSublistValue({
sublistId: "item",
fieldId: "countquantity"
});
const newQuantity = currentQuantity + item.total;
rec.commitLine({sublistId: "item"});
this.setCount(rec, newQuantity, itemLine);
}
/**
* Set a new count value for the item provided
*
* #param rec the inventorycount record containing the item
* #param value the new value we would like to save for the item count
* #param iline the sublist item line for the item to be modified
*/
private setCount(rec, value, iline) {
// select the line to make modifications on
rec.selectLine({
sublistId: "item",
line: iline
});
// get the record with the count quantity
const countId = rec.getCurrentSublistValue({
sublistId: "item",
fieldId: "countline"
});
this.filters = [];
this.filters.push(
Search.createFilter({
name: "line",
operator: Search.Operator.EQUALTO,
values: countId.toString()
})
);
const srch = Search.create({
type: Search.Type.TRANSACTION,
filters: this.filters,
columns: [
"internalid",
"quantity",
"line"
]
});
let intid;
srch.run().each(r => {
intid = r.getValue('internalid');
return true;
});
const crec = Record.load({
type: Record.Type.INVENTORY_COUNT,
id: intid,
isDynamic: false
});
crec.setValue('quantity', value);
return crec.save();
}
Bonus karma for anyone who can also update the inventorycount status.
There are a number of issues with your code.
It looks like you are loading the same inventory count record in the update() method and in the setCount() method.
If you are planning this as a general method I have a suspicion that your barcode to internal id method is going to eat up governance. Since your code is working on a single Inventory Count transaction you should load and cache the barcodes in a single search for all items on the transactions.
I still don't understand where you are getting countline from. This is not an inventorycount sublist value unless something completely new is in 2018.2
The following bit of sample code may help. It works in a console window. Note if you are using bins you'll also have to make sure you have the correct bin as well as the correct line. If you are working with serialized or lot numbered items you'll need to enter countdetail subrecords
require(['N/record'], function(record) {
var countRec = record.load({
type: 'inventorycount',
id: 9946,
isDynamic: true
});
console.log(countRec.getLineCount('item'));
countRec.selectLine({
sublistId: 'item',
line: 0
});
console.log(countRec.getSublistValue({
sublistId: 'item',
line: 0,
fieldId: 'countquantity'
}) + 'in bin: ' + countRec.getCurrentSublistValue({
sublistId: 'item',
fieldId: 'binnumber'
}));
try {
var detailRec = countRec.getCurrentSublistSubrecord({
sublistId: 'item',
fieldId: 'countdetail'
}); // only for serialized and lot numbered items
console.log(JSON.stringify(detailRec));
} catch (e) {
console.error(e);
}
countRec.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'countquantity',
value: 44
});
countRec.commitLine({
sublistId: 'item'
});
console.log(countRec.save());
});
I'm having some trouble transforming a sales order to item fulfillment. Here is my code:
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
*/
define(['N/record', 'N/log'],
function(record, log) {
function afterSubmit(context) {
var orderId = context.newRecord.id;
var fulfillmentRecord = record.transform({
fromType: record.Type.SALES_ORDER,
fromId: orderId,
toType: record.Type.ITEM_FULFILLMENT,
isDynamic: true
});
fulfillmentRecord.setValue({
fieldId: 'location',
value: 'San Francisco'
});
log.error({
title: 'Debug Entry',
details: fulfillmentRecord
});
var rid = fulfillmentRecord.save();
}
return {
afterSubmit: afterSubmit
};
});
I keep getting this error, which is a little confusing because I don't know what they mean by "stack":
{"type":"error.SuiteScriptError",
"name":"USER_ERROR",
"message":"Please provide values for the following fields in the Items list: Location",
"stack":["anonymous(N/serverRecordService)",
"afterSubmit(/SuiteScripts/fulfillmentCreator.js:23)"],
"cause":{
"type":"internal error",
"code":"USER_ERROR",
"details":"Please provide values for the following fields in the Items list: Location",
"userEvent":"aftersubmit",
"stackTrace":["anonymous(N/serverRecordService)","afterSubmit(/SuiteScripts/fulfillmentCreator.js:23)"],"notifyOff":false},"id":"","notifyOff":false}
I see that you have set the location field at the header but based on the error, you will also need to set the location field on the item sublist.
Looking at the record browser, I cannot see any location field on Fulfillment header https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2020_1/script/record/itemfulfillment.html
This should work:-
function afterSubmit(context) {
var orderId = context.newRecord.id;
var fulfillmentRecord = record.transform({
fromType: record.Type.SALES_ORDER,
fromId: orderId,
toType: record.Type.ITEM_FULFILLMENT,
isDynamic: true
});
var lineCount = fulfillmentRecord.getLineCount({sublistId:'item});
for(var i=0;i<lineCount; i++){
fulfillmentRecord.selectLine({sublistId:'item',line:i});
fulfillmentRecord.setCurrentSublistValue({
sublistId:'item',
fieldId: 'location',
value: '123' //Enter the location internal id, instead of name i.e San Francisco
});
}
log.error({
title: 'Debug Entry',
details: fulfillmentRecord
});
var rid = fulfillmentRecord.save();
}
This error comes when Netsuite can't fetch value that you are assigning in the script. Location is List/Record type. And you are setting location based on value. Try to use setText instead of setValue.
I'm trying to create a restlet that can create a bin transfer.
My code is almost complete, I can create line item fields also.
The only thing that I can't do is to fill up the inventory detail because I don't know the fields in Subrecords. How can inpect the field id in the sub records line items columns?
define([ 'N/record', 'N/search'], function(r, s) {
function onSendRequst(context)
{
var rec = r.create({
type: context.recordtype,
isDynamic: true
});
rec.setValue( 'location', context.from_location_id );
rec.setValue( 'transferlocation', context.to_location_id );
rec.setValue( 'memo', context.memo );
for( var i = 0; i < context.inventory.length; i++)
{
var inv = context.inventory;
// Create sublist Record
rec.selectNewLine({
sublistId: 'inventory',
line: i+1
});
rec.setCurrentSublistValue({
sublistId: 'inventory',
fieldId: 'item',
value: inv[i].item_ndc
});
rec.setCurrentSublistValue({
sublistId: 'inventory',
fieldId: 'adjustqtyby',
value: inv[i].qty
});
rec.commitLine({
sublistId: 'inventory'
});
// **CREATE A SUB RECORD**
var itemInventorySubrecord = r.getSublistSubrecord({
sublistId: 'item',
fieldId: 'inventorydetail',
line: x
});
}
var recordId = rec.save({
enableSourcing: true,
ignoreMandatoryFields: true
});
return recordId;
}
return {
post: onSendRequst
}
});
You can find the field IDs for inventory detail under the Inventory Detail entry in the Records Browser. Subrecords are available in the SuiteScript Records Browser just like regular records.