NetSuite Invoice from Case - netsuite

Hoping some one may be able to help me out with this error I am receiving... I am working a custom button on the case record that will create an invoice using fields from the case. I have a custom field that is a multi select of all items that can be needed as part of a case. Not all cases require an item, so I will code in logic or workflow to prevent the button from showing up if an item isn't selected and also lock editing and mark the case status as invoiced with a stage of closed once invoice has been created from the record. My problem is that when testing the suitelet I am getting an error when trying to set the subsidiary field and also department. Here is my error: ["type":"error.SuiteScriptError"."name":"INVALID_FLD_VALUE", "message":"You have entered an Invalid Field Value 2 for the following field: subsidiary"
The customer I am testing with is assigned the subsidiary with a internal Id of 2
Below is a portion of my code, I've tried removing quotes in sub value and also trying to set the subsidiary value using the current record.getValue. both throw the same error
function onRequest(context) {
var custom_id = context.request.parameters.custom_id;
var currentRecord = record.load({
type: record.Type.SUPPORT_CASE,
id: custom_id
});
var newRecord = record.create({
type: record.Type.INVOICE,
isDynamic: true
});
newRecord.setValue({
fieldId: 'customform',
value: 122
});
newRecord.setValue({
fieldId: 'entity',
value: currentRecord.getValue('entity')
});
newRecord.setValue({
fieldId: 'otherrefnum',
value: currentRecord.getValue('casenumber')
});
newRecord.setValue({
fieldId: 'subsidiary', value: '2'
});
newRecord.setValue({
fieldId: 'department',
value: '17'
});
newRecord.selectNewLine({
sublistId: 'item'
});
newRecord.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'item',
//value: 46
value: currentRecord.getValue('custevent_multi_select_work_orders')
});
newRecord.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'quantity',
value: '1'
});
}
Any help much appreciated!

Errors I found:
There is a typo when you are loading the Support Case Record. It should be SUPPORT_CASE
var currentRecord = record.load({
type: record.Type.SUPPORT_CASE,
id: custom_id
});
There are many typos like an inverted comma here, hope you look into it
newRecord.setValue({
fieldId: 'customform',
value: 122'
});
Regarding your main Subsidiary issue, you are passing value (2) using Inverted Commas. Try passing it without those
newRecord.setValue({
fieldId: 'subsidiary',
value: 2
});
OR
newRecord.setValue({
fieldId: 'subsidiary',
value: Number(2)
});
Use inverted commas only to pass String value. For Numerical value, don't use them.
Try these changes and let me know if the problem still persist, there are many possibilities to this error!

I know this isn't exactly what you need, but it is fully functioning and you can make customizations/pick-and-choose parts to use. It's a custom function I've used in the past to create a Sales Order from a Case Record. Best of luck!
/**
* case_createSOButton.js
* #NApiVersion 2.x
* #NScriptType ClientScript
*/
define (['N/record', 'N/currentRecord'],
function (record, currentRecord){
//NetSiuite requires the existence of 1 of their functions
function pageInit(context) {
var currentRecord = context.currentRecord;
}
//Button function to create a Sales order and indicate on the Case record the new Sales Order record
//in the UI on the Script record add this function name to the "Buttons" section
function createSO(){
log.audit('function started', 'Cases - Service Case CS createSO');
var caseRecord = currentRecord.get();
//if record is in create mode than do not allow creation of a Sales Order
//mode property is not available, so base it off of id properrty. ids dont exist until record is saved
var caseId = caseRecord.id;
if (!caseId){
alert('You cannot create a Sales Order while creating a new Case.\nPlease save the Case, then try again.');
return;
}
//if sales order already exists, do not allow creation of a new SO
var associatedSO = caseRecord.getValue({fieldId: 'custevent_case_associated_sales_orde'});
if (associatedSO){
alert('Cannot create a Sales Order since "Associated Sales Order" already exists.');
return;
}
//gather info from user
var memo = prompt("What's the reason for the charge?\nThe text below will be copied onto the Sales Order \"Memo\" field.");
//if user clicks cancel, do not continue
if (memo == null){
return;
}
var description = prompt("Enter a description for the Service Work Item.");
//if user clicks cancel, do not continue
if (description == null){
return;
}
var amount = prompt("Enter an amount for the Service Work Item.\nPlease only enter #s, no letters, decimal/cents optional.");
//if user clicks cancel or there's no # value found, do not continue
var hasNumber = /\d/; //validation for confirming the amount variable is a number
hasNumber = hasNumber.test(amount);
if (amount == null){
return;
}
if(hasNumber == false){
alert('No numbers found in entry, please try again.');
return;
}
alert('Please wait for the process to complete before closing this page.');
//declare static values
var customform = 199;
var subsidiary = 2;
var status = 3;
var specialist = 62736;
var channel = 181;
var totalKW = 0;
var lenderPoints = 0;
var today = new Date();
var itemId = 3566;
var lender = 10;
var loanProduct = 37;
//load customer to gather values
var entity = caseRecord.getValue({fieldId: 'company'});
var customerRec = record.load({type: record.Type.CUSTOMER, id: entity});
var location = customerRec.getValue({fieldId: 'custentity_customer_market'})|| null;
var job = caseRecord.getValue({fieldId: 'custevent_case_associated_project'});
//load associated project to gather values
var projectRec = record.load({type: record.Type.JOB, id: job});
var projectMgr = projectRec.getValue({fieldId: 'custentity_project_manager_customer'})|| null;
var engineer = projectRec.getValue({fieldId: 'custentity31'})|| null;
var installMgr = projectRec.getValue({fieldId: 'custentity_install_manager'})|| null;
var state = projectRec.getValue({fieldId: 'custentity_csegmarke'})|| null;
var region = projectRec.getValue({fieldId: 'custentity_cseg2'})|| null;
var market = projectRec.getValue({fieldId: 'custentity_cseg3'})|| null;
//create SO record, set values
var newSORec = record.create({type: record.Type.SALES_ORDER, isDynamic: true});
newSORec.setValue({fieldId: 'customform', value: customform, ignoreFieldChange: false});
newSORec.setValue({fieldId: 'entity', value: entity});
newSORec.setValue({fieldId: 'job', value: job});
newSORec.setValue({fieldId: 'custbody_sostatus', value: status});
newSORec.setValue({fieldId: 'custbody_total', value: totalKW});
newSORec.setValue({fieldId: 'custbody13', value: lenderPoints});
newSORec.setValue({fieldId: 'custbody_fundingissues', value: memo});
newSORec.setValue({fieldId: 'subsidiary', value: subsidiary});
newSORec.setValue({fieldId: 'custbody_finance_specialist', value: specialist});
newSORec.setValue({fieldId: 'saleseffectivedate', value: today});
newSORec.setValue({fieldId: 'custbody_cseglende', value: lender});
newSORec.setValue({fieldId: 'custbody_csegloan', value: loanProduct});
newSORec.setValue({fieldId: 'custbody_project_manager', value: projectMgr});
newSORec.setValue({fieldId: 'custbody_engineer', value: engineer});
newSORec.setValue({fieldId: 'custbody_installmgr', value: installMgr});
newSORec.setValue({fieldId: 'class', value: channel, forceSyncSourcing: true});
newSORec.setValue({fieldId: 'custbody_csegmarke', value: state, forceSyncSourcing: true});
newSORec.setValue({fieldId: 'custbody_cseg2', value: region, forceSyncSourcing: true});
newSORec.setValue({fieldId: 'custbody_cseg3', value: market, forceSyncSourcing: true});
newSORec.setValue({fieldId: 'location', value: location, forceSyncSourcing: true});
//set default line item(s)
newSORec.selectLine({sublistId: 'item', line: 0});
newSORec.setCurrentSublistValue({sublistId: 'item', fieldId: 'item', value: itemId, ignoreFieldChange: false});
newSORec.setCurrentSublistValue({sublistId: 'item', fieldId: 'description', value: description, ignoreFieldChange: false});
newSORec.setCurrentSublistValue({sublistId: 'item', fieldId: 'rate', value: parseInt(amount), ignoreFieldChange: false});
newSORec.commitLine({sublistId: 'item'});
//save new SO
var newSORecId = newSORec.save({enableSourcing: true, ignoreMandatoryFields: false});
//add SO Rec to Case
record.submitFields({
type: record.Type.SUPPORT_CASE,
id: caseRecord.id,
values: {
custevent_case_associated_sales_orde: newSORecId
},
options: {
//enableSourcing: false, //default is true
ignoreMandatoryFields : true //default is false
}
});
//alert user when SO is created and open in a new tab
alert("The new Sales Order will open in a new tab. \n*Reminder - to save this record if you've made changes.");
var url = 'https://1234567.app.netsuite.com/app/accounting/transactions/salesord.nl?id='+newSORecId
window.open(url, '_blank');
log.audit('function end', 'Cases - Service Case CS createSO');
}//end of create SO funciton
return {
pageInit: pageInit,
createSO: createSO
}
}
);

Related

Netsuite Beforesubmit/Aftersubmit script not saving

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.

NetSuite Client Script 2.0 to Disable Expiry Date Sublist Field on Inventory Detail record

I'm trying to disable the display type of expiry date field on inventory details. The current client script is working for 1st line only or 0 index. I'm trying to completely disable this field for all lines while adding inventory details.
This is my script please tell me what I missed here.
Thanks
function lineInit(scriptContext) {
try {
var currentRecord = scriptContext.currentRecord;
var sublistId = scriptContext.sublistId;
if (sublistId !== 'item') return;
var selectedLine = currentRecord.getCurrentSublistIndex({
sublistId: 'item'
});
log.debug({ title: 'selectedLine', details: JSON.stringify(selectedLine) });
var inventoryDetail = currentRecord.getCurrentSublistSubrecord({
sublistId: "item",
fieldId: "inventorydetail"
});
var expiryDate = inventoryDetail.getCurrentSublistField({
sublistId: "inventoryassignment",
fieldId: "expirationdate"
});
expiryDate.isDisabled = true;
} catch (error) {
log.debug({ title: 'Catch Error', details: error });
}
}
you need to traverse the loop using
var numLines = objRecord.getLineCount({
sublistId: 'item'
});
for the inventory detail sublist (summary) similarly as we do for item sublist then only it will set all the expiry dates to disabled , you have just taken the index "selectedLine" and printed in the log

How to get committed item quantity on after submit event?

i'm trying to get some value from sales order line item, but for some reason i cannot get quantity committed field from the sales order item.
This is the existing code that i'm using:
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
*/
define([
'N/log'
], function(
log
) {
const exports = {};
function afterSubmit(context) {
var newRecord = context.newRecord
switch (context.type) {
case context.UserEventType.CREATE:
return ;
case context.UserEventType.EDIT:
var payload = getSalesOrderItems(newRecord);
log.debug(payload);
break;
default:
throw 'Invalid event type';
}
}
exports.afterSubmit = afterSubmit;
return exports;
});
function getSalesOrderItems(salesRecord)
{
var items = [];
var itemLength = salesRecord.getLineCount({
sublistId : 'item'
});
if (itemLength === 0) throw 'Order does not have any valid item';
for (var index = 0; index < itemLength; index++) {
var item = {};
var itemId = salesRecord.getSublistValue({
sublistId: 'item',
fieldId: 'item',
line: index
});
try {
var itemRecord = record.load({
type: record.Type.SERIALIZED_INVENTORY_ITEM,
id: itemId,
});
} catch (ex) {
if (JSON.parse(ex).name == "SSS_RECORD_TYPE_MISMATCH") {
itemRecord = record.load({
type: record.Type.KIT_ITEM,
id: itemId,
});
}
}
if (!itemRecord) throw ('Item with id ' + itemId + ' does not exist');
item.sku = itemRecord.getValue('itemidorig');
item.quantity_committed = salesRecord.getSublistValue({
sublistId: 'item', fieldId: 'quantitycommitted', line: index
});
item.quantity = salesRecord.getSublistValue({
sublistId: 'item', fieldId: 'quantity', line: index
});
items.push(item)
return items;
}
}
this is the current result.
{
[{
"sku":"EMOST00405",
"quantity":2
}]
}
This is the result that i was expecting.
{
[{
"sku":"EMOST00405",
"quantity_committed": 1,
"quantity":2
}]
}
It works fine when the event is triggered via update order.
Any reply is appreciated.
Your code seems correct but NetSuite returns undefined if you don't have a field on current form(maybe hidden/not added on current form). Make sure to add and show the field on current SO form that you are working on and then try running the code again.

netsuite suitescript2.0 inventorycount

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());
});

itemfulfillment: sublist item field inventorydetail is not a subrecord field

I want to do a bin itemfulfillment in netsuite.
But I can't get an example that works. When I run the below code I am receiving this error:
Sublist item field inventorydetail is not a subrecord field
I need to know what is the correct subrecord name to create an itemfulfillment
Thanks!
var sales_internalid = '2465'; //saleorderid
var einternalid = '110'; //employeeid
var winternalid = '1'; //washsoueid
var sinternalid = '6'; //itemid
var quantity = 1;
var displayname ='iphone';
var shipgroup = 1;
var salesOrder= nlapiCreateRecord('salesorder', sales_internalid, {recordmode: 'dynamic'});
var obj = nlapiTransformRecord('salesorder', sales_internalid, 'itemfulfillment');
obj.selectLineItem('item',1);
obj.setCurrentLineItemValue('item', 'item', sinternalid );
obj.setCurrentLineItemValue('item', 'location', winternalid );
obj.setCurrentLineItemValue('item', 'quantity', 1);
var subrecord= obj.editCurrentLineItemSubrecord('item', 'inventorydetail');
subrecord.selectLineItem('inventoryassignment', 1);
subrecord.selectNewLineItem('inventoryassignment');
subrecord.setCurrentLineItemValue('inventoryassignment', 'inventorynumber', '1');
subrecord.setCurrentLineItemValue('inventoryassignment', 'quantity', '1');
subrecord.commitLineItem('inventoryassignment');
subrecord.commit();
obj.commitLineItem('item');
var fulfillmentOrderId = nlapiSubmitRecord(itemFulfillment, true);
I had this same issue when doing my first Inventory Transfer via code for a client. Turns out the Bin Number field is only a subrecord when the feature "Advanced Bin Management" is enabled. If the account you are working in is setup to just "Use Bins" then the Bin Number field on the line items of transactions is set via its text value. Example is in SS 2.0 but I believe it gets the point across:
newRec = nsRecord.create({
type: nsRecord.Type.INVENTORY_ADJUSTMENT,
isDynamic: true
});
// In dynamic mode must set the subsidiary first.
newRec.setValue({
fieldId: bodyFields.subsidiary,
value: locSub[datain.Location]
});
newRec.setValue({
fieldId: bodyFields.adjustment_Location,
value: datain.Location
});
newRec.setValue({
fieldId: bodyFields.date,
value: date
});
newRec.selectNewLine({
sublistId: columnFields.type
});
newRec.setCurrentSublistValue({
sublistId: columnFields.type,
fieldId: columnFields.item,
value: datain.Item
});
newRec.setCurrentSublistValue({
sublistId: columnFields.type,
fieldId: columnFields.adjust_Qty,
value: datain.Quantity.toString()
});
if (parseFloat(datain.Quantity) > 0) { // If qty is positive must set the Est Unit Cost.
itemVals = nsSearch.lookupFields({
type: nsSearch.Type.ITEM,
id: datain.Item,
columns: fields
});
cost = itemVals.averagecost || itemVals.lastpurchaseprice;
newRec.setCurrentSublistValue({
sublistId: columnFields.type,
fieldId: columnFields.est_Unit_Cost,
value: cost
});
}
//
// Format for binnumbers field is 'ValueText(qty)\rValueText(qty)\rValueText(qty)
// the only exception is in cases of negative qty
//
binText = datain.Bin ? datain.Bin + '(' + datain.Quantity + ')' : '';
newRec.setCurrentSublistValue({
sublistId: columnFields.type,
fieldId: columnFields.bin_Numbers,
value: binText
});
newRec.commitLine({
sublistId: columnFields.type
});
invRecResult.invRecId = newRec.save({
enableSourcing: true,
ignoreMandatoryFields: true
});

Resources