is there a way to only import price data on Netsuite - netsuite

I need to have 400+ price levels on Netsuite, but for the life of me, I can't find a way to add them through imports. From what I've seen and tried, Netsuite only allows you to upload items that reference existing price levels but doesn't allow you to upload new ones. Does anyone know how this could be done?

Price levels are scriptable.
Since this is just a one time job you could do this in a console window (inspect any editable standard record and find/show the console)
You will likely run into a governance error running this on 400 names but just
note the last name successfully created
refresh the page you have open
delete the names lines down through the last successful one
re-run the script
repeat until they are all created.
require(['N/record'], record=>{
const names = [
'Test Level 1' // use your whole list of names
'Test Level 2', // etc
];
names.forEach(n=>{
try{
const pr = record.create({type:'pricelevel'});
pr.setValue({fieldId:'name', value:n});
// make your array of names more complex to handle discounts etc.
//pr.setValue({fieldId:'discountpct', value:xx});
pr.save();
console.log('created', n);
}catch(e){
console.error(n, e);
}
});
console.log('done');
});

Related

Returning a record at the before load stage using nlapiLoadRecord in a User Event

I want to display a button on a Sales order only if a custom field on the Sales Order is populated. I have a User Event script (shown below) which runs "before load" to add the button. That part works but I want nlapiLoadRecord to return a record at the "before load" stage so I can check to see if the field is populated or not. I have not been successful in returning a record and I don't know if this is actually possible [?] Can someone help me out?
function BeforeLoad(type, form) {
if (type=='view') {
form.setScript('customscript_instruction_script');
form.addButton("custpage_mybutton", "Instructions", "instruction_click();");
}
}
If you just want to get the value of a field from the actual record that is being loaded, there is no need to call nlapiLoadRecord(). You can simply retrieve the value using nlapiGetFieldValue():
if (type=='view') {
var customFieldValue = nlapiGetFieldValue('custbody_mycustomfield');
if(customFieldValue === "123") {
form.setScript('customscript_instruction_script');
form.addButton("custpage_mybutton", "Instructions", "instruction_click();");
}
}
However if the custom field is from a different record, you will need to retrieve it either by loading that record or running a search. In general nlapiLookupField() would be the most lightweight option.

Node.js + Redis multiple lookups

I'm new to key value stores, but I'd like to learn. As a personal project, I'm trying to build an inventory management system with Node.js and Redis. Let's assume this is the correct technology to use for the moment.
If I had a simple system, that needs to track the number of widgets at a particular location, with the ability to look up details by widget or by location, my understanding according to https://matt.sh/thinking-in-redis-part-one is to store separate "custom indexes" to look up by location and by item.
In node.js to save a new entry then, we would create the entry with hmset, add the entry to the 2 indexes with sadd:
redis.hmset([
key,
'attr1', entry.attr1,
'attr2', entry.attr2,
'attr3', entry.attr3,
],
function(err) {
// add entry to location set
var locationKey = 'location:' + entry.location;
redis.sadd(locationKey, key, function(err) {
redis.expire(locationKey, 900);
});
// add entry to widget set
var widgetKey = 'widget:' + widget.id;
redis.sadd(widgetKey, key, function(err) {
redis.expire(widgetKey, 900);
});
redis.expire(key, 900);
}
);
Now if we wanted to move all widgets from one location to another, we'd need to get all entries from the widget set, add the entry to the new location index, and remove it from the old index:
// move all widgets to another location
redis.smembers('widget:' + widget.id, function(err, entryKeys) {
entryKeys.forEach(function(entryKey) {
// get entry for rebroadcast
redis.hgetall(entryKey, function(err, result) {
if (result) {
// add entry to new location's index
var locationKey = 'location:' + location;
redis.sadd(locationKey, entryKey, function(err) {
redis.expire(locationKey, 900);
});
// remove entry from old location's index
redis.srem('location:' + result.location, entryKey);
}
});
});
});
My concern is the number of requests that need to be made for each command. Adding an entry, will cost 3 inserts for the data itself, and 3 more assuming we want to expire the data. Moving all widgets will require 1+n inserts, n reads, and n deletes.
If this were for a real time game with hundreds or thousands of requests a second, is it ok for each command to require this many calls? Is this normal for a redis implementation?
Yes.
Redis is that fast. But do a benchmark on your machine, or similar production machine, that will run redis. It is included in redis itself.. (Post it back here, I'd be interested as well.)
Redis has a lot of commands at its disposal, and your data organization might allow cheaper calls, or calls-less-often. That will depend how you lay out the data model. There is not really a "query language" like SQL that can do lots of stuff in the query or combine queries into a single one. You are meant to hit redis a lot, which is a different philosophy than SQL (to some extent).
This personal project will allow you to see what works and what could be made better, so kudos on the effort. Good luck!

How can I add the tracking number to the message the users receive?

I have tried editing uc_order module
function uc_order_token_list($type = 'all') {
...
$tokens['order']['order-tracking-number'] = t('The tracking number of the order.');
...
}
function uc_order_token_values($type, $object = NULL) {
...
$values['order-tracking-number'] = uc_tracking_get_order_tracking_numbers($order);
}
Email Message:
[order-first-name] [order-last-name], Your order number [order-link] at [store-name] has been updated. Order status: [order-status] Order tracking number: [order-tracking-number] Order comment: [order-last-comment] Browse to the following page to login to your account and view your order details: [site-login] Thanks again, [store-name] [site-slogan]
But in the message the user receives, the tracking number is not listed.
Actually this did work, I just did not have an actual tracking number for my order since it was a test order, it never actually got shipped.

NetSuite Sublist/child record does not update/refresh in edit mode

If the form I am on is in edit mode, and I add items to the sublist (A child custom record) via my suitescript I can not get the list that is visible to the customer to refresh/update.
I have attempted to use the following command, but then found that it only works on a static / read only list.
// Refresh the package contents list
nlapiRefreshLineItems('recmachcustrecord_myCustomRecord');
Is there a way to force a sublist/child record to update its view when the parent transaction form is in edit mode?
On my form I have clicked my "Do Something" button which is to create child records. After the records are created the transaction form does not update the sublist. When I exit edit mode the form then realizes the new lines and displays them.
Thank you,
You may have other fields on the record that are not saved yet.
In order to do what you want you'd have to save the record and reopen it with your script.
Here is an example from Netsuite help of saving and reopening a record:
try
{
//committing the phone call record to the database
var callId = nlapiSubmitRecord(call, true);
nlapiLogExecution('DEBUG', 'call record created successfully', 'ID = ' + callId);
//Redirect the user to the newly created phone call
nlapiSetRedirectURL('RECORD', 'phonecall', callId, false, null);
}
catch (e)
{
nlapiLogExecution('ERROR', e.getCode(), e.getDetails());
}

How to display arbitrary, schemaless data in HTML with node.js / mongodb

I'm using mongodb to store application error logs as json documents. I want to be able to format the error logs as HTML rather than returning the plain json to the browser. The logs are properly schemaless - they could change at any time, so it's no use trying to do this (in Jade):
- var items = jsonResults
- each item in items
h3 Server alias: #{item.ServerAlias}
p UUID: #{item.UUID}
p Stack trace: #{item.StackTrace}
h3 Session: #{item.Session}
p URL token: #{item.Session.UrlToken}
p Session messages: #{item.Session.SessionMessages}
as I don't know what's actually going to be in the JSON structure ahead of time. What I want is surely possible, though? Everything I'm reading says that the schema isn't enforced by the database but that your view code will outline your schema anyway - but we've got hundreds of possible fields that could be removed or added at any time so managing the views in this way is fairly unmanageable.
What am I missing? Am I making the wrong assumptions about the technology? Going at this the wrong way?
Edited with extra info following comments:
The json docs look something like this
{
"ServerAlias":"GBIZ-WEB",
"Session":{
"urltoken":"CFID=10989&CFTOKEN=f07fe950-53926E3B-F33A-093D-3FCEFB&jsessionid=84303d29a229d1",
"captcha":{
},
"sessionmessages":{
},
"sessionid":"84197a667053f63433672873j377e7d379101"
},
"UUID":"53934LBB-DB8F-79T6-C03937JD84HB864A338",
"Template":"\/home\/vagrant\/dev\/websites\/g-bis\/code\/webroot\/page\/home\/home.cfm, line 3",
"Error":{
"GeneratedContent":"",
"Mailto":"",
"RootCause":{
"Message":"Unknown tag: cfincflude.",
"tagName":"cfincflude",
"TagContext":[
{
"RAW_TRACE":"\tat cfhome2ecfm1296628853.runPage(\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/home\/home.cfm:3)",
"ID":"CFINCLUDE",
"TEMPLATE":"\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/home\/home.cfm",
"LINE":3,
"TYPE":"CFML",
"COLUMN":0
},
{
"RAW_TRACE":"\tat cfdisplay2ecfm1093821753.runPage(\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/display.cfm:6)",
"ID":"CFINCLUDE",
"TEMPLATE":"\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/display.cfm",
"LINE":6,
"TYPE":"CFML",
"COLUMN":0
}
]
}
}
... etc, but is likely to change depending on what the individual project that generates the log is configured to trigger.
What I want to end up with is a formatted HTML page with headers for each parent and the children listed below, iterating right through the data structure. The Jade sample above is effectively what we need to output, but without hard-coding that in the view.
Mike's analysis in the comments of the problem being that of creating a table-like structure from a bunch of collections that haven't really got a lot in common is bang-on. The data is relational, but only within individual documents - so hard-coding the schema into anything is virtually impossible as it requires you to know what the data structure looks like first.
The basic idea is what #Gates VP described. I use underscore.js to iterate through the arrays/objects.
function formatLog(obj){
var log = "";
_.each(obj, function(val, key){
if(typeof(val) === "object" || typeof(val) === "array"){
// if we have a new list
log += "<ul>";
log += formatLog(val);
log += "</ul>";
}
else{
// if we are at an endpoint
log += "<li>";
log += (key + ": " + val);
log += "</li>";
}
});
return log;
}
If you call formatLog()on the example data you gave it returns
ServerAlias: GBIZ-WEBurltoken: CFID=10989&CFTOKEN=f07fe950-53926E3B-F33A-093D-3FCEFB&jsessionid=84303d29a229d1sessionid: 84197a667053f63433672873j377e7d379101UUID: 53934LBB-DB8F-79T6-C03937JD84HB864A338Template: /home/vagrant/dev/websites/g-bis/code/webroot/page/home/home.cfm, line 3GeneratedContent: Mailto: Message: Unknown tag: cfincflude.tagName: cfincfludeRAW_TRACE: at cfhome2ecfm1296628853.runPage(/home/vagrant/dev/websites/nig-bis/code/webroot/page/home/home.cfm:3)ID: CFINCLUDETEMPLATE: /home/vagrant/dev/websites/nig-bis/code/webroot/page/home/home.cfmLINE: 3TYPE: CFMLCOLUMN: 0RAW_TRACE: at cfdisplay2ecfm1093821753.runPage(/home/vagrant/dev/websites/nig-bis/code/webroot/page/display.cfm:6)ID: CFINCLUDETEMPLATE: /home/vagrant/dev/websites/nig-bis/code/webroot/page/display.cfmLINE: 6TYPE: CFMLCOLUMN: 0
How to format it then is up to you.
This is basically a recursive for loop.
To do this with Jade you will need to use mixins so that you can print nested objects by calling the mixin with a deeper level of indentation.
Note that this whole thing is a little ugly as you won't get guaranteed ordering of fields and you may have to implement some logic to differentiate looping on arrays vs. looping on JSON objects.
You can try util.inspect. In your template:
pre
= util.inspect(jsonResults)

Resources