How to properly deploy a customer record script with NetSuite's suiteScript? - deployment

Currently I'm writing an example script to get the hang of the suiteScript environment and get a better idea of how it all works. Right now I've written a script that looks like it should create and save a new customer record upon deployment. I dont run into any errors loading the script into NetSuite and I put the code through a debugger and the syntax seems right.
'''
/**
* #NApiVersion 2.x
* #NScriptType ClientScript
*/
define(["N/record"], function (r) {
function creatCustomer() {
var customer = record.create({
type: record.Type.CUSTOMER,
isDynamic: false,
defaultValues: null
});
customer.setValue(
{fieldId: "firstname", value: "James", ignoreFieldChange: false},
{fieldId: "lastname", value: "Halpert"},
{fieldId: "subsidiary",value: "Training 7"},
{fieldId: "email", value: "JHalpert#DM.com"},
{fieldId: "company Name",value: "Dunder Mifflin Test"}
);
customer.save({
enableSourcing: true,
ignoreMandatoryFields: false
});
}
return {
saveRecord: creatCustomer
};
});
'''
I think the problem might be deployment, but I don't know exactly what it could be. The script gets deployed but I can't find the customer record anywhere.

You should use the Netsuite help to read about script types and script type entry points. In particular client scripts are not generally used the way you have set that up.
This question has almost nothing in it regarding script deployment issues. (I'd expect to see at least one screen shot of the deployment screen)
For what you have written each time one of the deployment target records is saved a new customer record save will be attempted.
However the script you posted will error because:
the subsidiary value should be the internalid of the subsidiary - not the subsidiary name.
you are declaring 'N/record' as function(r) but then using it like record.create
record.setValue doesn't take a list of fieldId/value pairs
It may error if the user submitting the record doesn't have permissions to create customers.
It will likely error the second time it runs because a non-unique user name is being given. (Though this depends on how your account is configured)
One way to 'play' with scripts is to open a console window on any record in edit mode (and for some other screens) and you can run individual scripts like:
require(["N/record"], function (record) {
var customer = record.create({
type: record.Type.CUSTOMER,
isDynamic: false,
defaultValues: null
});
customer.setValue({fieldId: "firstname", value: "James"}); //, ignoreFieldChange: false}, <- this is for dynamic mode and client scripts
customer.setValue({fieldId: "lastname", value: "Halpert"});
customer.setValue({fieldId: "subsidiary",value: "Training 7"});
customer.setValue({fieldId: "email", value: "JHalpert#DM.com"});
customer.setValue({fieldId: "company Name",value: "Dunder Mifflin Test"});
var custId = customer.save({
enableSourcing: true,
ignoreMandatoryFields: false
});
console.log('created customer ', custId);
});

Related

Update presence member status causing presence member list to display updated user as only member

In Ably, Im using
Ably React hook
In the documentation, there is a way to update member status when monitoring what users have entered a room.
const [presenceData, updateStatus] = usePresence("your-channel-name", "initial state");
// The `updateStatus` function can be used to update the presence data for the current client
updateStatus("new status");
This is where I'm having an issue. I take the presence Data and generate a list of users like this.
const [presenceData, updateStatus] = usePresence(
channel,
{
id: user.id,
name: user.name,
isModerator: false,
},
(presenceUpdate) => {
presenceUpdate.action === "update" && console.log({ presenceUpdate });
}
So my list generates correctly. In the callback, I see that the data(presenceUpdate) is updated correctly. When a user enters the room they are displayed correctly. When I start updating the status (ie: change the isModerator flag to true), the presenceData list shows the incorrect user data. It shows the updated user twice (assuming two users are in the room).
updateStatus({...user, isModerator: true})
When using channeling with presenceMember data together, updateStatus has weird side effects.
const [channel] = useChannel("your-channel-name", (message) => {
console.log(message);
});
When you use updateStatus, are you just supposed to pass the updated member data or is there something else you need to do so your presenceMember data shows the correct information?
What Im expecting:
presenceData = [{id: 1, name: 'John', isModerator:false},{id:2, name: 'Steve', isModerator: true}]
What Im getting when I try updating Steve by setting isModerator to true:
presenceData = [{id:2, name: 'Steve', isModerator: true},{id:2, name: 'Steve', isModerator: true}]
Any ideas on what I'm doing wrong?
I figured it out. You cant update anyone else's member data besides your own. I assumed I can have one user update the status of other users but what ends up happening is everyone's status is updated with the object in updateStatus(object). To make sure you dont update other users' data property, have some check that lets you decide if you are the user that is updating your status. This way, the updateStatus function is only called for that user and not for everyone else.

How do I update record in mongoDB/Mongoose with case insensitive input

I am new to MongoDB/Mongoose, and I am having an issue with PUT request to update the phone number of name with duplicate entry.
Objective: My front end can take in person's name and its phone number. Whenever it takes in a name that already exist in our record, it will ask user if they want to replace the number. Furthermore, name input should be case insensitive, meaning as long as spelling is right, it should update the phone number.
e.g. If {name: Test, number: 123} exist in our record, inputting {name: TEST, number: 456} will provide a pop-up menu confirming if user want to change their name. If selected Ok, the record would change to {name: Test, number:456} while reflecting its change on front end side and on backend DB.
Currently, my schema is defined as following (on a different file).
const personSchema = new mongoose.Schema({
name: String,
number: String,
})
Current code for updating functionality is following, which does work for most part:
app.put('/api/persons/:id', (req, res, next) => {
const body = req.body
const person = {
name: body.name,
number: body.number,
}
Person.findByIdAndUpdate(req.params.id, person, { new: true })
.then(updatedPerson => res.json(updatedPerson))
.catch(err => next(err))
// catch is for error handling
})
Main issue: However, above code does not work when I input a name with same name but with different casing. For instance, Name "Test" and "TEST" is considered differently. Primary source of error, based on what I printed out on console, is that the ID is different and thus my code can't find the same entry.
i.e. ID for storing record with name "Test" is different from the ID of new entry {name: TEST, number: 123} and hence my input entry ID doesn't exit in my database.
Above is bit weird sense whenever I input the name with same case, it does work.
Based on some searching, I found a different stackoverflow suggestion that uses regex and findoneandupdate, so I tried the following:
app.put('/api/persons/:id', (req, res, next) => {
const body = req.body
const person = {
name: body.name,
number: body.number,
}
// for testing purpose,
// this prints out the correct name
Person.find({ name: new RegExp(`^${body.name}$`, `i`) })
.then(result => {
console.log(result[0])
})
Person.findOneAndUpdate({ name: new RegExp(`^${body.name}$`, `i`) }, person, { new: true })
.then(updatePerson => {
res.json(updatePerson)
})
.catch(err => next(err))
})
There was few issue with this:
Casing of person's name changes (so if the new input has name of "TEST", it will change it all caps when it is supposed to preserve the casing of initial entry)
Above worked via REST Client extension on VS code, which is similar to Postman. However actually testing on frontend had a same issue of not finding ID.
I was wondering what is the correct way to update the entry with either findByIdAndUpdate (preferably) or findOneAndUpdate while taking case insensitive entry and preserving the name.
For reference, following is what my front end looks like:
You can add a field query_name : String that is the lowercase version of the name.
I would use mongoose hooks.
const personSchema = new mongoose.Schema({
name: String,
number: String,
original_name : String
})
personSchema.pre('save', function(next) {
this.query_name = this.name.toLowerCase();
next();
});
You can read more about it and maybe find another solution here
https://mongoosejs.com/docs/middleware.html
Note:
*Don't use arrow function because it does't have 'this' property.

Ag-Grid Server Side Row Group Key Creator

When using Ag-Grid's server side row model, I am unable to send a custom group key to the server in order to do proper group by queries.
My row data is a simple JSON structure but with one composite object.
row = {
athlete: '',
age: '',
country: {
name: 'Ireland',
code: 'IRE'
},
...
}
I am using the server side row model. To get the grid to display the country name is simple enough as I use the following column definition.
{
headerName: "Country",
colId: "country",
valueGetter: "data.country.name",
enableRowGroup: true
}
However, when I group by the Country column ag-grid sends the groupKey as 'Ireland' from my example above. But I need the group key to be the country code, 'IRE'. I cannot figure out how to generate a groupKey when using the server-side row model.
I have seen the keyCreator method, but this only works for client-side row model. In addition, I have seen the Tree Data Mode which has a callback for getServerSideGroupKey(dataItem) but then callback only gets used when gridOptions.treeData = true and when the treeData option is set to true, a "Group" column is always displayed regardless if a grouping is happening or not. I tested this out by setting isServerSideGroup: function(dataItem) {return false;}
Any help would be appreciated.
I was able to solve this issue by using the dot notation for the column definition's field attribute and a custom cellRenderer.
{
headerName: "Country",
colId: "country",
field: "country.code",
enableRowGroup: true,
cellRenderer: function (params) {
return params.data.country.name;
}
}
This allowed me to display the correct data point from the custom object and when doing server side actions, ag-grid will send the datapoint contained within the field attribute.

sailsjs one-way associations confusion

I am having a hard time wrapping my head around associations with sailsjs.
I have 2 models
Services
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
model: 'users',
via: 'id',
},
},
Users
attributes: {
email: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string'
}
},
So, a service is tied to a user (matching the id of the user).
I used to do a call like http://localhost:1337/Services?userId=userId
Now I would like to transition to associations using the above model attributes.
This works by calling the ID of the service just fine (it includes the users data as well), however if all i have is the user, how could I get the service
Doing the same call (http://localhost:1337/Services?userId=userId) returns and empty object.
Am I forced to actually have a one-to-one or one-to-many association? I don't understand why I can no longer use the userId field (stored in the DB) to do queries once I start using associations. I guess I am looking for the best of both worlds here.
EDIT:
Let me try make this more clear. Before trying to do associations, I could call this URL (using blueprint)
http://localhost:1337/Services?userId=userId
The Services model used to look like this
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
type: 'string',
required: true,
},
},
Then when a user is created, a service for that user is created with the userId matching the ID in the Users table.
Now I would like to implement associations using the above model scheme.
However, because (my best guess) the userId field of the service is mapped to the Users model, I am unable to search for a Server using the userId field that is stored.
I hope that makes sense? In another words, tryin to call
http://localhost:1337/Services?userId=userId
returns nothing when using associations but does return a value when I don't use associations

Saving a Dgrid JsonRest-based Store

I have a dgrid that has editable date fields. Above it, I have a "Save" button that calls grid.save. When I hit the button, it makes an XHR request back to the store's target, but does not provide any data back to the server for me to save (i.e. POST is empty). Right now it is hardwired to query item id 1900, as you can see in the code below.
Here is how the store is initiated:
var store = new JsonRest({
target: "/safari/resources/1900/calendarObjects/",
sortParam: "sort",
idProperty: "id",
properties: {
startDate:{
format: "date-time"
},
endDate:{
format: "date-time"
}
}
});
And here is the grid:
var grid = new declare([OnDemandGrid, dgridEditor, Keyboard, Selection, DijitRegistry])({
store: store,
query: {responseType: "json" },
bufferRows: 40,
loadingMessage: "Loading...",
columns: [
{field: "oid", label: "Object ID"},
dgridEditor({field: "startDate", name: "Start Date", editorArgs: { selector: 'date', datePattern: 'yyyy-MM-dd', locale: 'en-us' }}, DateTextBox),
dgridEditor({field: "startTime", name: "Start Time"}, TimeTextBox, "click"),
dgridEditor({field: "endDate", name: "End Date"}, DateTextBox, "click"),
dgridEditor({field: "endTime", name: "End Time"}, TimeTextBox, "click"),
{field: "endDateOid", label: "End OID"}
],
}, "grid");
The save button looks like this:
registry.byId("saveButton").on("click", function (){
grid.save();
});
Like I said, after I click "save," a new XHR request fires, but if it is sending any data back to the server, I'm not sure where it is going. I had my backend print up all of the HTTP headers it received and didn't see anything.
UPDATE (January 2, 2013): Upgraded server backend to use a traditional RESTful URL, which seems to make Dojo slightly happier, but it still is using GET instead of PUT and fails to actually send anything to save.
UPDATE (January 5, 2013): Is there any reason why JsonRest would call GET before calling PUT? I'm wondering if my program needs to return certain data before the program is willing to go do the PUT (and thus the problem isn't the GET but whatever comes next)... But, this is entirely speculation. I've reached a dead end.
I'm not sure whether this will work, you can have a look at https://github.com/SitePen/dgrid/blob/master/test/JsonRest.html
window.grid = new (declare([Grid, Selection, Keyboard]))({
store: testStore,
getBeforePut: false,
columns: columns
}, "grid");
and you can try to set the property getBeforePut to false.