I am having trouble understanding what this error means.
org.mozilla.javascript.EcmaError: ReferenceError: "nlapiSearchRecord"
is not defined. (/SuiteScripts/PreventDuplicateCustomer.js#35)
I am attempting to create a script which searches for a duplicate record based on a specific field which is supposed to be unique. I would like to prevent creating duplicate 'CUSTOMER' records in NetSuite using the following script.
'
Does anyone see anything that jumps of the page as wrong with the code below?
// 2.0
define(["N/error", "N/log"], function (err, 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(scriptContext) {
log.debug({
"title": "Before Submit",
"details": "action=" + scriptContext.type
});
if (doesCustomerExist(scriptContext)) {
throw err.create({
"name": "DUPLICATE_SFDC_ACCOUNT_ID",
"message": "Customer Already Contains SFDC Account Id",
"notifyOff": true
});
}
}
function doesCustomerExist(scriptContext) {
var sfdcAccountId = scriptContext.newRecord.getValue('custentitysfdc_account_id');
if(sfdcAccountId == null || sfdcAccountId == '') return false;
var searchFilter = new nlobjSearchFilter('custentitysfdc_account_id', null, 'is', sfdcAccountId, null);
var searchResult = nlapiSearchRecord('customer', null, searchFilter, null);
return (searchResult != null && searchResult.length > 0);
}
exports.beforeSubmit = beforeSubmit;
return exports;
});
nlapiSearchRecord() is a SuiteScript 1.0 function and you're trying to call it from a SuiteScript 2.0 script.
You need to add the N/search module to your 2.0 script and use the functionality provided in that module to perform a search. In the NetSuite help documentation, navigate to SuiteCloud -> SuiteScript 2.0 -> SuiteScript 2.0 API -> SuiteScript 2.0 Modules -> N/Search Module to learn how to perform a search with SuiteScript 2.0.
Related
Okay, I have decided to strip this one back to the bare bones based on the Netsuite documentation and go from there.
With the below in place I receive the following error still -
"Syntax error: missing : after property id"
Any help is greatly appreciated.
/**
* #NApiVersion 2.0
* #NScriptType UserEventScript
*/
require(['N/task'],
function(task) {
var workflowTask = task.create({taskType: task.TaskType.WORKFLOW_TRIGGER});
workflowTask.recordType = 'customer';
workflowTask.recordId = 107;
workflowTask.workflowId = 3;
var taskId = workflowTask.submit();
return {
workflowTask};
});
Looks like you are missing the entry points for the UserEvent script. I don't see something like
exports.beforeSubmit = beforeSubmit;
exports.beforeLoad = beforeLoad ;
exports.afterSubmit = afterSubmit ;
return exports;
I am trying to build a JS file to place in the file cabinet to reference my most used functions I constantly rebuild. I have been able to access it by placing the script in the file cabinet and using the #NAmdConfig to reference the functions. However, I cannot access the NetSuite modules in these scripts. I cut most of the function off in my example, but if I can return that to my original Map/Reduce script that will suffice. How can I have a third party script of my most used functions while still having access to the NetSuite modules?
/**
* #NApiVersion 2.1
* #NModuleScope public
*/
var MattsFunctions = {
dynamicTransactionSearch:
function (sentId) {
var thisRecord = record.load({
type: record.Type.SALES_ORDER,
id: sentId
})
return thisRecord.id
}
}
I have also tried
/**
* #NApiVersion 2.1
* #NModuleScope public
*/
define(['N/search', 'N/record'],
(search, record) => {
var exports = {};
var MattsFunctions = {
dynamicTransactionSearch:
function (sentId) {
var thisRecord = record.load({
type: record.Type.SALES_ORDER,
id: sentId
})
return thisRecord.id
}
}
exports.MattsFunctions = MattsFunctions
return exports
})
Figured it out. Simply pass the module over in the function you're calling, of course!
In hyperledger composer, we have to specify param and transaction in comments, isn`t compiler suppose to ignore comments? How does this work and why is it necessary to do that in comments?
/**
* A temperature reading has been received for a shipment
* #param {org.acme.shipping.perishable.TemperatureReading}
temperatureReading - the TemperatureReading transaction
* #transaction
*/
function temperatureReading(temperatureReading) {
var shipment = temperatureReading.shipment;
console.log('Adding temperature ' + temperatureReading.centigrade + ' to shipment ' + shipment.$identifier);
if (shipment.temperatureReadings) {
shipment.temperatureReadings.push(temperatureReading);
} else {
shipment.temperatureReadings = [temperatureReading];
}
return getAssetRegistry('org.acme.shipping.perishable.Shipment')
.then(function (shipmentRegistry) {
// add the temp reading to the shipment
return shipmentRegistry.update(shipment);
});
}
See here for more explanation -> https://hyperledger.github.io/composer/reference/js_scripts.html
Decorators within 'comments' are used to annotate the functions with metadata required for runtime processing. A Decorator is an object which adds functionality to another object dynamically, and not uncommon in Javascript.
I am attempting to use wordpress to build a website that integrates google maps. I am doing some overlays with the maps and use the google developers API and Python to make the appropriate javascript. I have successfully written the js files and Python necessary to accomplish this.
My website is built in Worpress and I would like add a page (not the home page) that has n links and each one would populate a box with the corresponding map. I can take care of the layout and design issues but I am at a loss on how to:
a) Include the javascript as a file that
b) gets called upon clicking the link and thus populates that map without calling a new page
That is, the javascript is HUGE because it may include thousands of lat/lon points. Therefore including n of these written into the header is unreasonable. I want to simply call it from filename.js when the link is clicked.
There is a plugin that allows me to include whatever I want in the header. So, if I can find out where to put the *.js files (or txt file) in the directory tree and how to have the corresponding file activated upon click I should be good. Thanks!
This Display different maps with onClick event - Google Maps V3. kind of helps with doing an on-click display but everyone's solution was to make one map. I cannot do that. I am overlaying vast amounts of data.
Here is a way you can get that done. (Jump down to the get started part of the script.)
For brevity, I've included a bunch of scripts in one 'file', but you'll want to break them in to individual files.
You may also need to try the html and js in jsbin js bin example, b/c SO may or may not allow the dynamic loading of js.
(function(undefined) {
/**
* #author (#colecmc)
* #method turn collection into an array
* #param {object} collection - NodeList, HTMLCollection, etc. Should have an "item" method and/or a "length" property
*/
ToArray = collection => Array.prototype.slice.call(collection);
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
Observer = (function(undefined) {
/**
* pub sub
*/
'use strict';
var subUid = -1;
return {
topics: {},
subscribe: function(topic, func) {
/**
* #param {string} topic
* #param {function} func
* #returns {string} - a token such as '3'
* #example Observer.subscribe('any-valid-string',function(name,resp){
console.log(resp.prop);
});
*/
if (!Observer.topics[topic]) {
Observer.topics[topic] = [];
}
var token = (++subUid).toString();
Observer.topics[topic].push({
token: token,
func: func
});
return token;
},
publish: function publish(topic, args) {
/**
* #param {string} topic
* #param {object} args
* #returns {boolean} - true if topic is valid, false otherwise
* #example Observer.publish('any-valid-string',{
prop: 'this is a test'
});
*/
if (!Observer.topics[topic]) {
return false;
}
setTimeout(function() {
var subscribers = Observer.topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func(topic, args);
}
}, 0);
return true;
},
unsubscribe: function unsubscribe(token) {
/**
* #param {string} token - value should be saved from the original subscription
* #example Observer.unsubscribe('2');
* #example Observer.unsubscribe(member); - where member is the value returned by Observer.subscribe();
*/
var m,
forEachTopic = function(i) {
if (Observer.topics[m][i].token === token) {
Observer.topics[m].splice(i, 1);
return token;
}
};
for (m in Observer.topics) {
if (Observer.topics.hasOwnProperty(m)) {
Observer.topics[m].forEach(forEachTopic);
}
}
return false;
}
};
}(undefined));
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
SetAttributes = function(el, attrs) {
/**
* #author (#colecmc)
* #method simple for in loop to help with creating elements programmatically
* #param {object} el - HTMLElement attributes are getting added to
* #param {object} attrs - object literal with key/values for desired attributes
* #example SetAttributes(info,{
* 'id' : 'utswFormInfo'
* 'class' : 'my-class-name'
* });
*/
'use strict';
var key;
for (key in attrs) {
if (attrs.hasOwnProperty(key)) {
el.setAttribute(key, attrs[key]);
}
}
return el;
};
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
GetScript = function(url, fullPath) {
/**
* #author (#colecmc)
* #version 1.0.4
* #requires Swlxws.SetAttributes, Swlxws.Observer
* #method dynamically add script tags to the page.
* #param {string} url - relative path and file name - do not include extension
* #param {string} fullPath - absolute path
* #example GetScript('myLocalScript');
* #example GetScript('','https://www.google-analytics.com/analytics.js');
*/
'use strict';
function onLoad(event) {
var result;
if (event.type === 'load') {
result = 1;
} else {
result = -1;
}
Observer.publish('get-script-onload-complete', {
successful: result,
eventData: event
});
}
var JSPATH = '/js/',
/* or where ever you keep js files */
el = document.createElement('script'),
attrs = {
defer: true,
src: null,
type: 'text/javascript'
};
/** look for a string based, protocol agnostic, js file url */
if (typeof fullPath === 'string' && fullPath.indexOf('http') === 0) {
attrs.src = fullPath;
}
/** look for any string with at least 1 character and prefix our root js dir, then append extension */
if (typeof url === 'string' && url.length >= 1) {
attrs.src = JSPATH + url + '.js';
}
SetAttributes(el, attrs);
el.addEventListener('load', onLoad);
el.addEventListener('error', onLoad);
document.body.appendChild(el);
return el;
};
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
/**
* Get Started
*/
function onClick(event) {
GetScript('', event.target.dataset.namespaceUrl);
}
Observer.subscribe('get-script-onload-complete', function(name, resp) {
/** check to make resp is what you expect, ie: the correct script loaded */
/** then it is safe to use */
});
ToArray(document.querySelectorAll('.load-scripts')).map(script => script.addEventListener('click', onClick, false));
}(undefined));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>How to include js files in header of wordpress pages that are activated on-click</title>
</head>
<body>
Load Google Analytics
</body>
</html>
You can use the function wp_enqueue_script() to load the necessary JS files on only the templates you want.
As for your large data set, I recommend that you cache it in an external .json file and use wp_enqueue_script() to load it only when necessary.
Well if the onclick event suggestion is pretty much what you want and you are just concerned about the large amount of data. Then there are a few ways to tackle it. I am not sure if the dataset is a js file or php/json files but i came across a similar issue on one of my projects, dont remember properly but i was doing something with maxmind's ip/location data set.
So i just splitted the large file into 3 smaller ones. Then i looped through each of the file and if the stuff that i was looking for was found in the file then i just breaked out. And definitely as Brian suggested caching and using a CDN would help a lot.
I have a Phonegap (2.1.0) application that onDeviceready creates a DB and populates a table with info.
Running this locally (using the Ripple emulator) on Chrome works. Tables are being created and populated as required.
After installing the build .apk on my Android device my Eclipse logcat shows:
sqlite returned: error code = 14, msg = cannot open file at line 27712 of [8609a15dfa], db=/data/data/<project>/databases/webview.db
sqlite returned: error code = 14, msg = os_unix.c: open() at line 27712 - "" errno=2 path=/CachedGeoposition.db, db=/data/data/<project>/databases/webview.db
Which I believe according to this post here - can be ignored.
However - I also noticed this error in logcat:
sqlite returned: error code = 1, msg = no such table: latest_events, db=/data/data/<project>/databases/webview.db
I have also - through adb shell - confirmed that the DB is not created:
here: /data/data/com.application/databases.
or here: /data/data/com.application/app_databases
So - my code:
if (!window.openDatabase) {
doMessage('Databases are not supported on this device. Sorry','error');
return;
}else{
consoleLog('all good for storage');
var db;
var shortName = 'MyDB';
var version = '1.0';
var displayName = 'MyDB';
var maxSize = 102400;
function errorHandler(transaction, error) {consoleLog('Error: ' + error.message + ' code: ' + error.code);}
function nullHandler(){};
db = window.openDatabase(shortName, version, displayName,maxSize);
consoleLog('starting table creation');
db.transaction(function(tx){
tx.executeSql( 'CREATE TABLE IF NOT EXISTS latest_events (id integer PRIMARY KEY AUTOINCREMENT,EventID integer,EventLocation text,EventName text,EventDateFrom varchar,EventTime timestamp,EventPresentedBy varchar,EventVenue varchar,EventScript text,RequireRSVP varchar)',[],nullHandler,errorHandler);
db.transaction(function(tx){
tx.executeSql('SELECT count(id) as RowCount FROM device_info ', [],
function(tx, result) {
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
var row = result.rows.item(i);
consoleLog('rowcount: '+row.RowCount);
if(row.RowCount==0){
tx.executeSql('INSERT INTO device_info (device_name, device_platform, device_uuid, device_os_ver, date_last_used) VALUES (?,?,?,?,?)',[device.name, device.platform, device.uuid, device.version, window.bowman_config.siteDate],nullHandler,errorHandler);
//doMessage('device info row added','notice');
}
}
}
},errorHandler);
},errorHandler,successCallBack('2'));
//doMessage('device info row added','notice');
},errorHandler,successCallBack('1'));
}
To add to my woes - on my logcat I do see the console.log output for "all good for storage", and the "starting table creation" messages.
My errorHandler functions are not returning anything and my successCallBack functions are triggered...but no DB created.
Thanks for the help.
When you pass in successCallBack("2") and successCallBack("1") then you are actually invoking them directly so you may be getting false positives on whether or not success has actually been called. You should provide two separate success call backs or just in-line some functions that call console.log("1") for instance.
Today this issue cost me 3 hours. What I tried:
Rewriting the copy database code.
Deleting the app from the emulator / device
Wiping emulator(s)
Cleaning eclipse
Changing file permissions
Validate a working SQLite database file
I solved the problem by copying the code from a shared Dropbox account to another location and refactoring the code in the Android Manifest and java files with another package name.
The application runs beautifully now, i.e. nothing wrong with the code, but somewhere it's muxed up by Dropbox.
I broke the nested functions up into single functions and 'chained' them based on their success or fail. It's actually been a lot simpler than I thought. RTFM it seemed. Thanks for all the help.
simplified:
var db = window.openDatabase("TheApp", "1.0", "The App", 50000000);
db.transaction(queryDB, errorCB, successCB);
// Query the database //
function queryDB(tx) {
//tx.executeSql('SELECT * FROM table", [], querySuccess, errorCB);
}
function querySuccess(tx, results) {
//do more functions here
}
function errorCB(err) {
console.log("Error processing SQL: "+err.code);
}