How to update Salesforce through NetSuite? - salesforce

How would you go about updating Salesforce with NetSuite data?
I know that you would need to use Suitescript 2.0 and some sort of token authentication.

I have a suitescript 2.0 user event script that does just this, It makes a connection to salesforce and updates netsuite customer fields to salesforce accounts.
The script will update three custom fields on the salesforce account: NSID, sync, syntime.
/**
*#NApiVersion 2.x
*#NScriptType UserEventScript
*/
define(['N/https', 'N/search', 'N/record'],
function (https, search, record)
{
_HTTPS = https;
_SEARCH = search;
_RECORD = record;
//handle after submition of customer on create and edit
function afterSubmit(context)
{
var body;
var NSID;
var sfEntityID;
var sync;
var syncTime;
var accountURL;
var response;
var recordData = {};
//If customer is getting deleted reflect that to SF
if(context.type === "delete")
NSID = 'deleted';
else
NSID = context.newRecord.id;
//get the SF account ID
sfEntityID = context.newRecord.getValue({fieldId:"custentity_sf_account_id"});
if (sfEntityID == undefined || sfEntityID == "") //If there is no SFID stop
{
log.debug("afterSubmit","No sfEntityID on customer with NSID: " + NSID);
return;
}
var date = new Date();
var month = date.getUTCMonth() + 1; // jan = 0
if (month < 10)
{
month = "0" + month;
}
syncTime = date.getUTCFullYear() + '-' + month + '-' + date.getUTCDate() + 'T' + date.getUTCHours() + ':' + date.getUTCMinutes() + ':' + date.getUTCSeconds() + '.000Z';
//login to SF (loginSalesforceNLAP controls sandbox/production login)
body = loginSalesforceNLAP();
//check if I got an access token back
if(body.access_token == undefined || body.access_token == "")
{
log.debug('afterSubmit','could not get SF access token');
return;
}
//set fields that will be updated on SF account
recordData.Netsuite_Internal_ID__c = NSID;
recordData.Sync__c = true;
recordData.Synced_Time__c = syncTime;
recordData = JSON.stringify(recordData);
//send update request
response = _HTTPS.post({
url: (getURL(body) + "/sobjects/Account/" + sfEntityID + "?_HttpMethod=PATCH"),
body: recordData,
headers: {"Authorization": "OAuth " + body.access_token,"Content-Type": "application/json"}
});
log.debug("response",response);
//log an error if it occurred
if(response.code != 204)
{
log.debug("afterSubmit","Could not update sf Account: " + sfEntityID + ' NSID: ' + NSID);
return;
}
//success message
log.debug("afterSubmit","successfully updated sf Account: " + sfEntityID + ' NSID: ' + NSID);
return;
}
return {afterSubmit: afterSubmit};
});
//get max SF version for SF update request
function getURL(body)
{
var max
var arr
var header = {"Authorization": "OAuth " + body.access_token };
var recordData = {};
var url = body.instance_url + "/services/data/";
response = _HTTPS.get({
url: url,
body: recordData,
headers: header
});
if(response.code == 200 || response.code == 204)
{
arr = JSON.parse(response.body)
for(var i = 0; i < arr.length; i++)
{
//find max version
if(!max || parseInt(arr[i]["version"]) > parseInt(max["version"]))
max = arr[i];
}
return body.instance_url + max.url;
}
else
return "";
}
//Connect to Salesforce instance and obtain the Access Token used for subsequent Salesforce calls this session
function loginSalesforceNLAP()
{
//production
var clientID = "3MVG9QDx8IX8nP5SpP0endmsendmeMepopopBvuB074i_7h7fakehoB0hnnhK7FyfTUgxH2234vR6QPoVXpDE";
var clientSecret = "1231232320412308455";
var securityToken = "N0bx9dI321F732aO12iC33gm6";
var username = "sflogin#login.com";
var password = "password";
var loginURL = "https://login.salesforce.com/services/oauth2/token";
var header = [];
header['Content-Type'] = 'application/json;charset=UTF-8';
var recordData = {};
var url = loginURL + "?grant_type=password&client_id=" + clientID + "&client_secret=" + clientSecret + "&username=" + username + "&password=" + password + securityToken;
try
{
response = _HTTPS.post({
url: url,
body: recordData,
headers: header
});
response = JSON.parse(JSON.stringify(response));
if (response.code == 200 || response.code == 204)
return JSON.parse(response.body); //return body
}
catch (er02)
{
log.error('ERROR:loginSalesforceNLAP', er02);
}
return "";
}
In order to get clientID, clientSecret, and the security token follow these steps: https://developer.salesforce.com/forums/?id=906F0000000AfcgIAC

Related

How to map and send emails to specific users who don't meet a certain criteria in Javascript/GAS

I am new in Javascript and bit by bit I have used resources here on StackOverflow to build on a project that uses external API to get time entries for users from the 10k ft project management system. I have finally have different functions together as follows:
Calls for user details which includes user_id
Get the time entries and sums up for every user who's approval has a value (pending or approval) in a specific date range. Those without approval will be ignored in the summation and their total entries left at 0.
My challenge now is to have only those with 0 as total hours of time entries receive emails to update their time entries. This code doesn't seem to select only those with 0 and send emails specifically to them. I will appreciate any pointers and/or assistance. after sending the email, this should be recorded on Google sheet
var TKF_URL = 'https://api.10000ft.com/api/v1/';
var TKF_AUTH = 'auth'
var TKF_PGSZ = 2500
var from = '2020-01-20'
var to = '2020-01-26'
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + TKF_AUTH
}
};
function getUsers() {
var userarray = [];
var lastpage = false;
var page = 1;
do {
// gets 10kft data
var users = read10k_users(page);
// writes data from current page to array
for (var i in users.data) {
var rec = {};
// pushing of mandatory data
rec.id = users.data[i].id;
rec.display_name = users.data[i].display_name;
rec.email = users.data[i].email;
userarray.push(rec);
}
// checks if this is the last page (indicated by paging next page link beeing null
if (users.paging.next != null) {
lastpage = false;
var page = page + 1;
} else {
lastpage = true;
}
}
while (lastpage == false);
return (userarray);
return (userarray);
}
function read10k_users(page) {
var endpoint = 'users?';
var url = TKF_URL + endpoint + 'per_page=' + TKF_PGSZ + '&auth=' + TKF_AUTH + '&page=' + page;
var response = UrlFetchApp.fetch(url, options);
var json = JSON.parse(response);
//Logger.log(json.data)
return (json);
}
function showTimeData() {
var users = getUsers()
var time_array = [];
for (var i = 0; i < users.length; i++) {
// Logger.log(users[i].id)
var url = 'https://api.10000ft.com/api/v1/users/' + users[i].id + '/time_entries?fields=approvals' + '&from=' + from + '&to=' + to + '&auth=' + TKF_AUTH + '&per_page=' + TKF_PGSZ;
var response = UrlFetchApp.fetch(url, options);
var info = JSON.parse(response.getContentText());
var content = info.data;
var total_hours = 0;
for (var j = 0; j < content.length; j++) {
if (content[j].approvals.data.length > 0) {
total_hours += content[j].hours;
}
}
Logger.log('User name: ' + users[i].display_name + ' ' + 'User id: ' + users[i].id + ' ' + 'total hours: ' + total_hours+ ' ' + 'Email: ' + users[i].email)
}
}
function sendMail(showTimeData){
var emailAddress = user.email;
var message = 'Dear ' + user.display_name + 'Please update your details in the system'
var subject = ' Reminder';
MailApp.sendEmail(emailAddress, subject, message);
}
I was able to get a solution for this as follows:
for (var j = 0; j < content.length; j++) {
if (content[j].approvals.data.length > 0) {
total_hours += content[j].hours;
}
}
Logger.log('User name: ' + users[i].display_name + ' ' + 'User id: ' + users[i].id + ' ' + 'total hours: ' + total_hours + ' ' + 'Email: ' + users[i].email)
if (total_hours == 0) {
sendMail(users[i])
}
}
}
function sendMail(user) {
var emailAddress = user.email;
var message = 'Dear ' + user.display_name + 'Please update your details in the system'
var subject = ' Reminder';
MailApp.sendEmail(emailAddress, subject, message);
}

How to query Salesforce from NetSuite SuiteScript 2.0?

How would you go about querying Salesforce from a NetSuite suitescript?
Here is an example of querying Users from Salesforce in SuiteScript 2.0.
/**
*#NApiVersion 2.x
*#NScriptType UserEventScript
*/
define(['N/https', 'N/record'],
function (https, record)
{
//handle the bs if its being created
function afterSubmit(context)
{
var body;
var response;
var recordData = {};
var queryURL;
body = loginSalesforceNLAP(); //login to SF
//error check the login
if(body.access_token == undefined || body.access_token == "")
{
log.debug("afterSubmit","Could not access SF");
return;
}
//check this email exists in SF
response = _HTTPS.get({
url: getURL(body) + "/query/?q=SELECT Id FROM User WHERE Username = user",
body: recordData,
headers: {"Authorization": "OAuth " + body.access_token,"Content-Type": "application/json"}
});
if(response.code != 200)
{
log.debug('afterSubmit', 'Could not query SF ' + response.code + ' ');
return;
}
//Check results (only 1 should be returned)
var b = JSON.parse(response.body);
if (b.totalSize == 1)
{
SFID = b.records[0].Id;
log.debug('afterSubmit', 'Found user in SF with ID ' + SFID);
}
else
{
log.debug('afterSubmit', 'No SF user with username user was found in SF');
return;
}
}
return {afterSubmit: afterSubmit};
});
//get URL of max version of SF
function getURL(body)
{
var max;
var arr;
var header = {"Authorization": "OAuth " + body.access_token };
var recordData = {};
var url = body.instance_url + "/services/data/";
response = _HTTPS.get({
url: url,
body: recordData,
headers: header
});
if(response.code == 200 || response.code == 204)
{
arr = JSON.parse(response.body);
for(var i = 0; i < arr.length; i++)
{
if(!max || parseInt(arr[i]["version"]) > parseInt(max["version"]))
max = arr[i];
}
return body.instance_url + max.url;
}
else
return "";
}
//Connect to Salesforce instance and obtain the Access Token used for subsequent Salesforce calls this session
function loginSalesforceNLAP() {
//production
var clientID = "432432432432432432432432ncK7FyfTUgxH2YNHvR6QPoVXpDE";
var clientSecret = "732323213210608985";
var securityToken = "N0bx9d323231aO321igJ6";
var username = "login#login.com";
var password = "password";
var loginURL = "https://login.salesforce.com/services/oauth2/token";
var header = [];
header['Content-Type'] = 'application/json;charset=UTF-8';
var recordData = {};
var url = loginURL + "?grant_type=password&client_id=" + clientID + "&client_secret=" + clientSecret + "&username=" + username + "&password=" + password + securityToken;
try
{
response = _HTTPS.post({
url: url,
body: recordData,
headers: header
});
response = JSON.parse(JSON.stringify(response));
if (response.code == 200 || response.code == 204)
return JSON.parse(response.body);
}
catch (er02)
{
log.error('ERROR:loginSalesforceNLAP', er02);
}
return "";
}
To find your security token, clientId, and client Secret follow the steps in these links:
https://success.salesforce.com/answers?id=90630000000glADAAY
https://developer.salesforce.com/forums/?id=906F0000000AfcgIAC

AngularJS controller calls a MVC controller - it succeeds but kicks off an error which contains null

I have an AngularJS/MVC application that calls a MVC controller method. The method succeeds in sending an email but goes into the error function and the error variable is null.
Why is it failing?
I tried getting more on the error using a different call but the alert does not appear when using it. I guess because the return is null and can't be resolved.
Here is the AngularJS controller method.
$scope.BookMySeat = function (UserName, SeatNo) {
if (UserName) {
// The UserName is not empty. Check to see of it exists.
dataService.ValidateUsername(UserName).success(function (output) {
if (output == -1)
{
// The user name does NOT exist. Do the insert to the table.
$scope.onclick = !$scope.onclick;
console.log(UserName + SeatNo);
dataService.InsertSeat(UserName, slotNum, SeatNo).success(function (output) {
$scope.bookedSeatList = output;
var imageCollection = new Array(totalseat);
$scope.images = imageCollection;
$scope.imageUrlNotBooked = "../Images/RED.jpg";
$scope.bookcollscope = $scope.bookedSeatList;
console.log($scope.bookcollscope);
var imageCollection1 = new Array($scope.bookedSeatList);
$scope.images1 = imageCollection1;
$scope.imageUrlBooked = "../Images/GREEN.jpg";
// Alert.
alert("Seat number " + SeatNo + " has been booked for : " + UserName);
//----------------------------------------------------------------------------------------------------------
// Send an email using a MVC controller method.
// - Using $http to call to a MVC controller method.
//----------------------------------------------------------------------------------------------------------
var encodedQueryString = encodeURIComponent('emailAddress') + '=' + encodeURIComponent('dc4444#hotmail.com') + '&' + encodeURIComponent('type') + '=' + encodeURIComponent('I') + '&' + encodeURIComponent('seatNbr') + '=' + encodeURIComponent(SeatNo) + '&' + encodeURIComponent('slotNbr') + '=' + encodeURIComponent(0);
$http.get("/Home/SendAlertEmail?" + encodedQueryString).success(function (data) {
// Alert.
alert("An insert email was sent.");
}).error(function (error) {
// Error alert.
alert("Something went wrong with the insert - SendEmail. " + error);
console.log(error);
});
//$http.get("/Home/SendAlertEmail?" + encodedQueryString).success(function (data) {
// // Alert.
// alert("An insert email was sent.");
//}).error(function (xhr) {
// // Error alert.
// alert("Something went wrong with the insert - SendEmail. Status: " + xhr.status + ". Response Text: " + xhr.responseText);
// console.log(error);
//});
}).error(function (output) {
$scope.error = true;
});
}
else
{
// The user name exists.
alert("That passenger name exists. Please enter a UNIQUE passenger name in order to book a seat.");
}
console.log(output);
}).error(function (output) {
$scope.error = true;
});
}
else
{
alert("The passenger name is empty. Please enter a passenger name in order to book a seat.");
}
}
Here is the MVC controller method.
public void SendAlertEmail([FromUri] string emailAddress, [FromUri]string type, [FromUri]int seatNbr, [FromUri]int slotNbr)
{
string strHtmlMessageBody = "";
NetworkCredential NetworkCred = new NetworkCredential();
System.Net.Mail.SmtpClient smtp = new SmtpClient();
try
{
MailMessage mm = new MailMessage();
mm.From = new MailAddress("xxxxx#hotmail.com");
mm.Subject = "From the BookSeat Portal. Passenger Seat Information.";
if (type == "I")
{
strHtmlMessageBody = "<p>Your passenger seat: " + seatNbr + " has been created by the system.</p>";
}
else
{
strHtmlMessageBody = "<p>Your passenger seat number: " + seatNbr + ", slot number: " + slotNbr + " has been deleted by the system.</p>";
}
mm.Body = strHtmlMessageBody;
mm.IsBodyHtml = true;
mm.To.Add(new MailAddress(emailAddress));
smtp.Host = "smtp.live.com";
smtp.EnableSsl = true;
smtp.UseDefaultCredentials = true;
smtp.Port = 587;
NetworkCred.UserName = "xxxxx#hotmail.com";
NetworkCred.Password = "yyyyyyy";
smtp.Credentials = NetworkCred;
smtp.Send(mm);
}
catch (SmtpException smtpEx)
{
throw new Exception("SMTP exception: " + smtpEx);
}
catch (Exception ex)
{
throw new Exception("Sending email exception: " + ex);
}
}
Here is the email sent.

How to call async Task<ActionResult> from angular controller

This is my angular controller
//Save AddNewEmployee functionality
EDC.SaveNewEmployee = function () {
if (EDC.AddNewEmployeeFormValidator.validate()) {
var UserID = '0',
CandidateSubmit = '';
if (EDC.isEdit) {
UserID = EDC.rowIdToEdit;
}
EmployeeDetailService.SaveNewEmployee(EDC.NewEmpAdd, UserID, CandidateSubmit).then(function (response) {
//Close popup window
EDC.AddNewEmployeeWindow.data("kendoWindow").close();
//EDC.NewEmpSave = response;
EDC.EmployeeDetailsGrid.dataSource.read();
});
}
};
Andthis one is my MVC Controller.
public async Task<ActionResult> SavePermanentEmployee(Employee model)
{
//Sending mail to BU
string DisplayName = "New Employee";
//Sending mail to Employee
string EmpDisplayName = "Price credentials";
BAL_Employee objBalEmp = new BAL_Employee();
Price_PMS_DAL.Employee emp = new Price_PMS_DAL.Employee();
emp.ID = model.ID;
emp.EmpID = model.employeeID ?? Convert.ToString(model.employeeID).ToUpper();
emp.ReferredBy = model.referredby;
emp.DOJ = model.dateOfJoining;
emp.Status = 1;
emp.Email = model.email;
emp.BUID = model.businessUnitID;
emp.ShiftID = model.ShiftID;
emp.ModifiedBy = Session["EmpID"].ToString();
var lstNewEmployeeCreated = BAL_Employee.GetEmployees();
var result = lstNewEmployeeCreated.Where(s => s.employeeID == emp.EmpID).FirstOrDefault();
if (result != null)
{
return Json("Employee ID already exists.", JsonRequestBehavior.AllowGet);
}
else
{
int empSave = objBalEmp.UpdateEmployee(emp);
BAL_Login objBalLog = new BAL_Login();
if (empSave == 1)
{
TempData["Datarefresh"] = "refresh";
lstemp = null;
string[] datastr = emp.Email.Split(new string[] { "#" }, StringSplitOptions.None);
int empLoginSave = objBalLog.AddUser(new Price_PMS_DAL.Login { UserName = datastr[0].Trim(), EmpID = emp.EmpID, BUID = emp.BUID, ShiftID = emp.ShiftID });
if (empLoginSave == 1)
{
var data = BAL_Employee.FilterEmployeeByParam("Select TOP 1 * FROM Employee where Status=1 order by EmpID desc");
Price_PMS_DAL.Emp_Leave modelBal = new Price_PMS_DAL.Emp_Leave();
modelBal.EmpID = emp.EmpID;
int empLeavebalSave = objBalEmp.CreateEmployeeLLeaveBalRec(modelBal);
if (empLeavebalSave == 1)
{
Price_PMS_BAL.Models.BusinessUnit.BU Bus = BAL_BU.GetSPBUs().Where(b => b.ID == model.businessUnitID).First();
if (Bus != null)
{
//Sending Mail to BU when new Permanent employee added into the system
StringBuilder str = new StringBuilder();
StringBuilder cc = new StringBuilder();
StringBuilder to = new StringBuilder();
to.Append(#" " + Bus.BUHeadEmailId);
str.Append(#"Hello,<br><br> New Employee named <b>" + model.name + "</b> has been added to " + Bus.BUName + " BU " + " on " + DateTime.Now.ToShortDateString() + ".<br><br> Regards,<br> PRICE");
bool x = await Price_PMS_BAL.Models.Email.Email.SendEmail(cc, to, "New Employee Added", str.ToString(), DisplayName);
//End
}
//Sending Mail to Employee when new Permanent employee added into the system
if (emp != null)
{
StringBuilder str = new StringBuilder();
StringBuilder cc = new StringBuilder();
StringBuilder to = new StringBuilder();
to.Append(#" " + emp.Email);
//Username with last name Split
String[] Emailstring = emp.Email.Split(new[] { '#' });
String username = Emailstring[0];
//Username split with out last name
String[] Uname = username.Split(new[] { '.' });
String Unamestr = Uname[0];
Unamestr = Unamestr.Substring(0, 1).ToUpper() + Unamestr.Substring(1);
var PriceURL = "https://price.dreamorbit.com/";
str.Append(#"Hi " + Unamestr + ",<br><br> Welcome to DreamOrbit. Please login to PRICE (Projects, Resource Information & Cost Estimation) to apply for your leaves and to see your ratings etc. on a regular basis with following credentials:<br><br><br> <b><u>URL</u></b> : <a href=" + PriceURL + " target=_blank>" + PriceURL + "</a> <br> <b><u>Username</u></b> : " + username + "<br> <b><u>Password</u></b> : [Your System Password]<br><br><br> We wish you a long and mutually beneficial association with DreamOrbit. For any queries please reach out to Panchali (panchali.bharali#dreamorbit.com).<br><br> Regards,<br> PRICE");
bool x = await Price_PMS_BAL.Models.Email.Email.SendEmail(cc, to, "PRICE Credentials", str.ToString(), EmpDisplayName);
}
//End
return Json("Saved Successfully", JsonRequestBehavior.AllowGet);
}
else { return Json("Error occurred while saving data ", JsonRequestBehavior.AllowGet); }
}
else
return Json("Error occurred while saving data ", JsonRequestBehavior.AllowGet);
}
else
{
return Json("Error occurred while saving data ", JsonRequestBehavior.AllowGet);
}
}
}
Usually javascript code execute synchronously(default) and javascript has core promise object which is use to make function asynchronous.
Angularjs has core service $q which is use to make function asynchronous.
Angularjs simple example :
angular.module("starter", [])
.controller("myCtrl", function($scope, $q, $http){
var GetData = function(){
var root = 'https://jsonplaceholder.typicode.com';
var defer = $q.defer();
$http({
method: "GET",
url: root + '/posts/1'
}).then(function(response){
//success call back
defer.resolve(response);
}, function(error){
//error callbcall
defer.reject();
});
return defer.promise;
};
$scope.AsynchCall = function(){
GetData().then(function(response){
//success call back
console.log(response);
alert(JSON.stringify(response));
}, function(error){
//error callbcall
console.log(JSON.stringfy(error));
alert(error);
});
};
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="starter" ng-controller="myCtrl">
<button ng-click="AsynchCall()"> Asynch call </button>
</body>
</html>
This is because JSON.stringify will return the return value of the toJSON function if it exists.

AngularJS ng-repeat view not updating after data update

have a some data one my page that is in a ng-repeat.
When the page and data 1st loads the data shows up.
When I move away from the page (using Angular Routing) make a change to the data (gets saved in db) then come back into the page (make call to db get new data) the ng-repeat data does not refresh. I can see the new data loading into the array and it is the new data.
I start the process on the page with
var sp = this;
sp.viewData = [];
sp.employee = [];
sp.ViewDataTwo = [];
$(document).ready(function () {
var testHeader = setInterval(function () { myTimer() }, 1000);
function myTimer() {
if (addHeaderToken() != undefined) {
clearInterval(testHeader);
sp.usageText = "";
if (sessionStorage.getItem(tokenKey) != null) {
sp.associatedInfo = JSON.parse(getassociatedInfo());
loadDataOne();
loadDataTwo();
}
}
}
});
I do this because I need to get my security toke from a JS script that I have no power over changes. So I need to make sure the code has ran to get me the token.
here are the functions I call..
function loadPasses() {
$http.defaults.headers.common.Authorization = "Bearer " + addHeaderToken();
$http.get('/api/Employee/xxx', { params: { employeeId: sp.employeeId } }).then(function (data) {
sp.viewData = data.data;
for (var i = 0; i < $scope. viewData.length; i++) {
sp.passes[i].sortDateDisplay = (data.data.status == "Active" ? data.data.DateStart + "-" + data.data[i].DateEnd : data.data[i].visitDate);
sp.passes[i].sortDate = (data.data[i].status == "Active" ? data.data[i].DateStart: data.data[i].visitDate);
}
});
}
function loadDataTwo () {
$http.defaults.headers.common.Authorization = "Bearer " + addHeaderToken();
if (sessionStorage.getItem(tokenKey) != null) $http.get('/api/Employee',
{
params: { employeeId: sp.employeeId }
}).then(function (data) {
sp.employee = data.data;
var tempPassString = "";
sp.ViewDataTwo = [];
var totalA = 0;
var totalU = 0;
for (var p = 0; p < sp.employee.dataX.length; p++) {
sp.ViewDataTwo.push(sp.employee.dataX[p].description + "(" + /** math to update description **// + ")");
totalA += parseInt(parseInt(sp.employee.dataX[p].Anumber));
totalU += parseInt(sp.employee.dataX[p].Bnumber));
}
sp.usageArr.push(" Total: " + totalA- totalU) + "/" + totalA + " Available");
//$scope.$apply();
});
}
One my view sp.viewData and sp.ViewDataTwo are both in ng-repeats.
Works well on load.. when I go out and come back in. I see the data reloading. But the view does not.
I have hacked the Dom to get it to work for now. But I would like to do it the right way..
Any help.
I have used
$scope.$apply();
But it tells me the digest is already in process;
the views are in a template..
Please help

Resources