I am trying to write a UserEvent script which prompts the user for a confirmation when they attempt to edit a sales order which has already had it's picking ticket printed. Below is my code:
define(['N/record', 'N/search', 'N/log', 'N/runtime', 'N/ui/dialog'], function (record, search, log, runtime, dialog) {
/**
*#NApiVersion 2.1
*#NScriptType UserEventScript
*/
var result = true;
function beforeSubmit(context) {
var order = context.oldRecord;
var orderStatus = order.getValue({fieldId: "status"});
if(orderStatus != "Billed") {
var orderInternalID = order.getValue({fieldId: "id"});
log.debug("id", orderInternalID);
var systemnoteSearchObj = search.create({
type: "systemnote",
filters:
[
["recordid","equalto",String(orderInternalID)],
"AND",
["field","anyof","TRANDOC.BPRINTEDPICKINGTICKET"],
"AND",
["newvalue","is","T"]
],
columns:
[
search.createColumn({
name: "record",
sort: search.Sort.ASC,
label: "Record"
}),
search.createColumn({name: "name", label: "Set by"}),
search.createColumn({name: "date", label: "Date"}),
search.createColumn({name: "context", label: "Context"}),
search.createColumn({name: "type", label: "Type"}),
search.createColumn({name: "field", label: "Field"}),
search.createColumn({name: "oldvalue", label: "Old Value"}),
search.createColumn({name: "newvalue", label: "New Value"}),
search.createColumn({name: "role", label: "Role"})
]
});
var searchResultCount = systemnoteSearchObj.runPaged().count;
log.debug("systemnoteSearchObj result count",Number(searchResultCount));
if(Number(searchResultCount) > 0) {
var options = {
title: 'WARNING: Pick Ticket Printed',
message: 'The pick ticket has already been printed for this sales order. Are you sure you want to edit?'
};
dialog.confirm(options).then(confirm).catch(cancel);
}
}
log.debug("result", result);
return result;
}
function confirm(reason) {
log.debug("User confirmed save.", reason);
result = true;
return true;
}
function cancel(reason) {
log.debug("User cancelled save.", reason);
result = false;
return false;
}
return {
beforeSubmit: beforeSubmit
}
});
When I deploy this script on the Edit event and try to edit and save the order, I get no confirmation dialog and instead receive the following error:
TypeError: dialog.confirm(...).then is not a function [at Object.beforeSubmit. From what I've seen, this type of error occurs when you attempt to use .then() on a function which does not return a promise. However, in the documentation for dialog.confirm(), it clearly states that the function does in fact return a promise.
Why am I receiving this error and how can I avoid it to achieve the goal of the script?
A User Event script runs on the server side and thus cannot render UI components (there's no browser instance or window object to render on). You'll likely need to transition this logic to the saveRecord event of a Client Script.
Related
Trying to run a Suitelet script to call a search and transform into an invoice. But before going into the next step I have encountered the message below:
Fail to evaluate script: All SuiteScript API Modules are unavailable while executing your define callback.
My script:
/**
* #NApiVersion 2.x
* #NScriptType Suitelet
*/
require(['N/search','N/log'], function (search,log) {
function onRequest(context) {
// Search
// ### ORDERS TO BILL
var salesorderSearchObj = search.create({
type: "salesorder",
filters:
[
["type","anyof","SalesOrd"],
"AND",
["status","anyof","SalesOrd:E","SalesOrd:F"],
"AND",
["mainline","is","T"]
],
columns:
[
search.createColumn({name: "amount", label: "Amount"}),
search.createColumn({name: "entity", label: "Name"}),
search.createColumn({name: "account", label: "Account"}),
search.createColumn({
name: "datecreated",
sort: search.Sort.DESC,
label: "Date Created"
}),
search.createColumn({name: "billeddate", label: "Date Billed"}),
search.createColumn({name: "statusref", label: "Status"})
]
});
var searchResultCount = salesorderSearchObj.runPaged().count;
log.debug( {"title":"salesorderSearchObj result count", "details":searchResultCount});
salesorderSearchObj.run().each(function(result){
// .run().each has a limit of 4,000 results
return true;
});
}
return {
onRequest: onRequest
};
});
It is to map and reduce selected sales orders.
Load search.
Map by transforming selected orders into one (by customer).
Reduce into one invoice/cash sale.
AS bknights suggested, script samples provided by NetSuite are just part of a script and they are not complete scripts. So before using them, you need to make sure your script is valid and complete.
As for the error message Fail to evaluate script, all of your script(which uses NetSuite modules) needs to be in a function inside the callback. i.e Suitelet has one entryPoint onRequest so shifting all of your script (in callback) under it should work.
example:
/**
* #NApiVersion 2.x
* #NScriptType Suitelet
*/
define(['N/search'], function (search) {
function onRequest(context) {
// Your search and order transform code should be here
// ### ORDERS TO BILL
}
return {
onRequest: onRequest
};
});
For further reading check this out.
Using the below JSON String which i use to render a dojo treegrid on my Xpages application:
var data= {identifier: 'name',
label: 'continent',
items: [
{"name": "Africa", "field": "continent", "children": "[
{ "name":"Egypt", "field":"country" },
{ "name":"Kenya", "field":"country", "children":"[
{ "name":"Nairobi", "field":"city" },
{ "name":"Mombasa", "field":"city" } ]"
]},
{ "name":"Sudan", "field":"country", "children":"[
{ "name":'Khartoum', "field":"city" }]"
},
{ "name":'Asia', "field":"continent", "children":"[
{ "name":"China", "field":"country" },
{ "name":"India", "field":"country"},
{ "name":"Russia", "field":"country" },
{ "name":"Mongolia", "field":"country" } ]"
}
}
]}
i try to create an onClick event, every time i clcik on the node i got an alert Execute of node undefined How do i get the actaull value of item?
var store= new dojo.data.ItemFileReadStore({data: data});
var model = new dijit.tree.ForestStoreModel({
store: store,
query: {field:"continent"},
labelAttr :"name"
rootId: 'id',
rootLabel: 'continent',
childrenAttrs: ['children']
});
var grid = new dojox.grid.TreeGrid({
treeModel: model,
showRoot: true,
openOnDblClick:true,
onClick : function(item, node, evt){
var id=store.getValue(item,"name");
alert("Execute of node " + id)
}
}, 'treeGrid');
grid.startup();
I would suggest checking what store is when the onclick event is triggered. Bear in mind the onclick event will be attached as client-side JavaScript to each item. I suspect it will not be running in the context where you write it, but is a discrete function. So it only has access to the variables passed into the function - item, node and evt - and will not have access to variables declared outside the scope of the function, e.g. store.
You may be able to navigate from the itemor node variables to the data store.
We are using Backgrid which allows you to define grid columns with an array of Javascript objects which it converts to a collection. We are trying to take advantage of this to have configurable validation on a column by column basis, so we might have the following where we've added a "validator" function to a couple of the columns:
[
{
label: "Delete",
name: "delete",
cell: "boolean"
},
{
label: "Alias",
name: "alias",
cell: "string",
sortType: "toggle",
validator: function (value) {
return true;
}
},
{
label: "Assigned Server",
name: "assignedServer",
cell: "string",
sortType: "toggle",
validator: function (value) {
return new Error("Cannot Assign Server")
}
}
]
We are listening to edits to the grid in the following prescribed manner and for the purposes of this question we can ignore the model argument to the function but concentrate on the column (delete, alias or assignedServer from above) which is itself a model in a collection. So far I have a snippet of code leveraging underscore.js's _.filter that returns the validatableColumns but I want to take this further and end up with an object of the format {name: validator, etc...}. Bearing in mind my specific use case, what is a succinct way to create an object from a Backbone collection that maps model values to one another?
certificateGrid.listenTo(certificateCollection, "backgrid:edited", function (model, column) {
var validatableColumns = _.filter(column.collection.models, function (c) {
return c.get('validator');
});
//etc.
Using _.reduce seems to do the trick:
var validatorFns = _.reduce(column.collection.models, function (fns, model) {
var validator = model.get('validator');
if (model.get('validator')) {
fns[model.get('name')] = validator;
}
return fns;
}, {});
I have an OnDemandGrid with one column that I want to populate with a custom Dojo widget I built. The data used to populate each of these widgets comes from a Solr query. Since I am expecting possibly thousands of search results, I need to use a JsonRest object to make the queries and handle pagination. Here's what I have so far:
The store:
var store = new JsonRest ({
target: "/solr/json/response",
});
Creating the grid:
var grid = new (declare([OnDemandGrid, Pagination])) ({
store: store,
getBeforePut: false,
columns: [
{
label: "Test",
field: "first",
renderCell: myRenderFunction //To render the custom widget
}
]
}, "grid");
grid.startup();
myRenderFunction:
var myRenderFunction = function(object, data, cell) {
var widget = new MyCustomWidget({
doc: object,
foo: bar
}, cell.appendChild(document.createElement("div"));
widget.startup();
return widget;
}
Sample Solr response, in JSON form:
{
"response":{
"docs":[
{
"foo": "Hello",
"bar": "World"
},
{
"foo": "Easy as",
"bar": "ABC"
},
{
"foo": "Simple as",
"bar": "Do re mi"
}
]
},
"highlighting": { ... },
"numFound": "74",
"start": 0
}
I have followed a few examples online demonstrating how to do this using JsonRest and any of the dgrid flavors (and they all worked), but when I try to render the widget to the grid nothing shows up and I get a TypeError: transform(...) is null.
Is there any reason why I can't render my widget to the grid?
I ran into the same problem trying to use Solr results with dgrid and JsonRest.
JsonRest uses QueryResults as a wrapper for what it returns.
Your problem is that QueryResults accepts only arrays or promises and you're currently giving it an object.
In order to give QueryResults the docs array, write a custom JsonRest store similar to:
define([
"dojo/Deferred", "dojo/io-query", "dojo/_base/declare", "dojo/request/xhr",
"dojo/store/JsonRest", "dojo/store/util/QueryResults"
], function (Deferred, ioQuery, declare, xhr, JsonRest, QueryResults) {
return declare([JsonRest], {
target: '/solr/json/response',
idProperty: 'foo',
query: function (query, options) {
var results, total, count = options.count, start = options.start;
if (start > 0 || count >= 0) {
query.start = start;
query.rows = ((options.hasOwnProperty('count') &&
count !== Infinity) ? count : 25);
} else {
console.error('Missing start and count arguments');
return;
}
results = new Deferred();
results.total = new Deferred();
xhr(this.target, {
query: ioQuery.objectToQuery(query),
handleAs: 'json',
headers: {
Accept: this.accepts
}
}).then(function (data) {
total = data.response.numFound;
results.total.resolve(total);
results.resolve(data.response.docs);
}, function (e) {
console.error(e.response.status + '. ' + e.message);
});
return new QueryResults(results);
}
});
});
I also recommend waiting to use a custom renderCell function until after you get dgrid properly populated.
edit: OnDemandGrid is not going to work with the Pagination extension.
So decide whether you want discreet paging controls or infinite scroll (paging handled by dgrid).
See Pagination and OnDemand docs.
I am trying to integrate select2 in backgrid.js. Backgridjs has extension support for select2 and the code for that is
{
name: "gender",
cell: Backgrid.SelectCell.extend({
optionValues: [["Male", "m"], ["Female", "f"]]
}),
label: "Gender (SelectCell)"
}
so based on this i tried something like the below since i have to load values to select2 box from the server
var FetchSecurities = Backbone.Model.extend({
url : Hexgen.getContextPath("/referencedata/securities")
});
var fetchSecurities = new FetchSecurities();
{
name: "security",
label: "Security",
cell: Backgrid.Extension.Select2Cell.extend({
optionValues: fetchSecurities.fetch({
success : function() {
for(var objectPlace in fetchSecurities.attributes) {
[[fetchSecurities.attributes[objectPlace].security],[fetchSecurities.attributes[objectPlace].security]];
}
}
}),
})
}
but i get this exception, I am sure i make mistake when constructing the value for the select2 box but don't know how to fix it, Please help me to get it done.
Uncaught TypeError: 'optionValues' must be of type {Array.<Array>|Array.<{name: string, values: Array.<Array>}>}