Displaying items by tag: NetSuite

Wednesday, 11 November 2020 15:19

Workflow Email Skript

Advanced “Send Email” Workflow action

 

‘Reply-to’ email address in NetSuite’s native Workflow action can not be set. You can define a ‘Send-from’ a ‘CC and a ‘BCC’ email address as well as only one recipient. This is sufficient in many situations, but some of our customer’s need more features.

 

Features we added to the standard functionality:

 

  • Send email to more than one recipient 
  • Define one or more ‘Reply-to’ email address

 

Our consultants can install the script in any account and then go ahead to configure the workflow action according to customer’s needs.

 

This screenshot shows the fields you can set:



If you like our support, feel invited to vet in touch with us.

 

Kind regards,

Georg Walther

 
 
 
 
 
Published in Script Solution
Wednesday, 04 November 2020 16:07

Salesforce to NetSuite Integration

Do you use Salesforce and NetSuite in your company? You don't want to part with Salesforce as your leading CRM system? Then it makes sense to create an integration between the two systems.

Which data should be synchronized?

At the beginning: we must decide which data should be synchronized and which system should lead for various data tables. As the first step, you could consider products, customers and orders for synchronization. However, this will vary by use case. It should also be considered whether you need a two-way synchronization.
Using the two systems together in a meaningful way can involve a lot of manual efforts. For example, if you would like to have your orders entered in Salesforce and also in NetSuite, you can simply “re-type” them. However, even with a manageable number of orders, this is not an efficient solution and creates high chances for potential human errors.

It is of course also possible to import the data into NetSuite as a CSV file, which is certainly an acceptable solution for many scenarios. But it still means a lot of manual effort. Master data maintenance must also be considered if several systems are used. Even with the slightest discrepancy in the name, you may no longer find the right customer record, for instance. Efficient integration is therefore of great benefit.

Alternatives of automatic integration, which completely replaces manual effort when importing the data

Alta Via can help you connect your two leading cloud systems in an automated, seamless, efficient, stable and flexible way. We have many years of experience in various projects where we developed such integrations.
Generally speaking, there are two broad ways of connecting the two systems:

  1. Via third-party software (such as Celigo, or Dell Boomi)
    This makes sense if you are already using a middleware and want to use it to manage all integrations. Otherwise such a system is an add-on, which generates more costs and administrative efforts. There is no “plug-and-play” solution, so implementation costs need to be considered on top of the rental costs for the third-party platform.
  2. With the help of an interface tailored by Alta Via
    Such a peer-to-peer interface can get as easy or as complex as needed, since it is precisely tailored to the customers’ requirements. The solution is stable and users can monitor it. The effort is limited and manageable in the range of a four-digit amount. There are no recurring license costs associated with it at all.

You should ask yourself the following questions:

What exactly should the integration achieve and cover?
This leads to further detailed questions:

  • Should customer master data be mapped in another system?
  • Should sales / pre-sales transactions (e.g. opportunities, orders, etc.) be mapped in both the systems?
  • How complex are the respective data records?
  • Should a data comparison take place between the systems (e.g. duplicate check)?
  • Which system should be considered as the master reference for which data?
  • From our point of view, these are the questions that will help you to get started with your integration. This will be followed by many very technical and detailed questions that differ depending on the objectives of the integration.

Alta Via will be happy to accompany you through this journey, no matter which type of integration you choose.: Feel free to give us a call.

 

Published in Implementation
Friday, 24 January 2020 16:15

Alta Via Mailchimp connector

Mailchimp is one of the most popular email newsletter tools on the market. 
The usability is very much appreciated by many marketing managers around the world.

Naturally we are looking for ways to transfer data from NetSuite to MailChimp.
Common questions we have when we look for options to integrate: 

Searching a solution that fits

  • Do we really need a middleware to facilitate the integration?
  • Is the price for the middleware justified for this purpose?
  • We just want to sync an email address, do we really have to configure a middleware and maintain it?
  • Our integration needs are very custom. All products on the market are either overkill or not what we need.
  • Make or buy? Should we just start to develop the integration ourselves?

Here, Alta Via has developed a simple approach. No middleware is needed. Only the email address is pushed from NetSuite to Mailchimp and then synced going forward.
The solution is very basic but customizable to the needs of our customers.

How does it work?

In this process, NetSuite is considered to be the leading system for master data (customer’s email address), whereas the email newsletter subscription status is managed in mailchimp.

  • The connector pushes new customers/email addresses to Mailchimp.
  • Mailchimp manages the double opt-in and sends out newsletters.
  • Subscription status changes are synced back from Mailchimp into NetSuite on demand.

In detail:

After installation and configuration of the bundle, and as a first step you need to define your relevant customers, which shall become part of campaigns in mailchimp, through a saved search. The definition is important, as your customer data is precious and you might not want to share all of them.

The name of that search has to be entered in the general settings of your NetSuite account.

Note: Not all customers that you defined to be relevant will be replicated, but only the ones that have the appropriate opt-in status.

NetSuite has four status for email newsletters:

  • Confirmed Opt-In (if the customer agreed to receive campaigns)
  • Soft Opt-In (if the customer can receive opt-in eMails)
  • Soft Opt-Out (if the customer can receive opt-in eMails)
  • Confirmed Opt-Out (the customer can neither receive campaign emails nor opt-in eMails)

Your relevant customers then can be synchronized to the mailchimp account. If the status is one of Soft Opt-In or Soft Opt-Out then the customer email is synced to mailchimp in the status of "pending", meaning that the customer will receive an email from mailchimp to subscribe to a campaign.

If the customer opted-in (Confirmed Opt-In), then the customer’s email is synced to mailchimp in the status of "subscribed", so no additional subscription email will be sent to the customer.

Note: Still in all mailchimp emails you should ensure that the customer can unsubscribe from a campaign.

Customers are added as members to the configured mailchimp member list.
When customer synchronization is started, then NetSuite also reads the subscription status of the customer in mailchimp. If the customer unsubscribed, this status is also stored in the NetSuite system for information.

Note: Subscription status in NetSuite might not be up to date with the status in mailchimp, only after re-syncing the data is up to date.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Published in Implementation
Thursday, 07 November 2019 16:35

Alta Via digging deep into #SuiteScript

A major step in moving SuiteScript to the 21st Century.

As NetSuite recently published SuiteScript 2.1  we were curious and took a deeper look into it. ... Pssst! we can use #ECMAscript 6 now :)
I was very excited when I heard it is coming and finally we have the freedom of using all the newest JavaScript features, so let's try to use it. 

Why would you want to use it?

 If you wanted to use the latest  version of ECMAScript without being forced to transform your code, so that NetSuite would understand it, by e.g. using babel or some other transpiling tool - the solution has just arrived. The new SuiteScript 2.1 (for the time being still in Beta).

The script header:

 My first script with 2.1 started with a question: which value for @version tag should be used. I started with 2.x which in theory should always match the latest version of SuiteScript. Unfortunately this option does not work yet. For the time being 2.x equals 2.0 and if you try to use it 2.x and some of the newest features of javascript you will get syntax errors, so my final header looked like this:

/**
 *
 *  @NApiVersion 2.1
 *  @NScriptType UserEventScript
 */

Next step was to find a way to add a library script. In 2.0 I used to use:

* @NAmdConfig /SuiteScripts/configuration.json

where configuration.json was a file that contained mapping  

{
  "paths": {
    "myLib": "/SuiteScripts/Libraries/myCustomLib",
  }
}

 

Thanks to that I was able to use myLib as a reference to myCustomLib.js in define clause like this:

define(['myLib'],
    function (myLib) {

However, it does not work in 2.1. I thought that maybe you need to use javascript modules instead (@export/@import), but when you try to use them the script is throwing syntax errors. It seems like some defect, or lacking feature in Beta, but the only way for now to add external libraries is to actually use a url in the define clause like:

define(['/SuiteScripts/Libraries/myCustomLib'],
   function (myLib) {

Use Classes:

 After workarounding the problems above, I was able to create a fully operational user event script with libraries attached. Moreover it seems that all the latet ECMAScript features are working (Hurray!) - I could use classes:

 /**
  *
  */
  class ShippingInformation {

  /**
   *
   * @param {*} itf
   * @param {*} itemsData
   */

   constructor(itf, itemsData) {
       this.boxes = [];
       this.itemsData = itemsData;
       this.itf = itf;
      }

Variables: Const and let

Block scope variables and constants :

for (let i = 0; i < count; i++) {

    let item = this.itf.getSublistValue({
    sublistId: 'item',
    fieldId: 'item',
    line: i
    
});

const itemData = this.itemsData[item];

Lambda functions:

 /**
  *
  * @returns {Array}
  */

  hasEmptySpace() {

    const uniqueItems = this.lines.map((line) => line.item).filter((x, i, a) => a.indexOf(x) === i);

    return uniqueItems.length < 3 && this.spaceUsed < 1;

  }

As of now my script works in my customer’s production account without any issues, so i believe 2.1 is stable.

Let's hope that NetSuite will shortly stop to consider SuiteScript 2.1 as a Beta feature and also add support for it in debugger.

 All in all, finally some major step in moving SuiteScript to 21st Century!

 
 
 
 
 
 
 
 
 
Published in Script Solution
Monday, 12 August 2019 14:37

Access more than 10.000 records in a sublist

Filtering invoices on Customer Payments in SuiteScript

Published in Script Solution
Friday, 31 May 2019 15:44

NetSuite's SFTP Module - N/sftp

With NetSuite's SuiteScript 2.0 you have the ability to access ssh servers, commonly known as secure FTP or SFTP.

You can upload or download files from an SFTP server. It is not possible to send files to NetSuite using the SFTP module. If you are looking for that, you can use a RESTLet.

If you are sure, SFTP is the answer to your question, we have a little bit of help for you here:

 

1) Alta Via has developed many SFTP integrations. Contact us if you like us to help you.

 

2) If you want to do this all by yourself, here are four steps you need to follow for a basic setup or test:

 

2.1) What do you need? Your checklist:

  • URL Address (host)
  • Port
  • Folder Name
  • Password
  • Host Key
  • Host Key type (one of these three: dsa, ecdsa, rsa )
  • GUID (Globally Unique Identifier)

While URL, Port, Folder name and password are relatively easy to get (just ask the administrator of the service), you might not easily get the host key.

 

2.2) Host Key

In a Windows command shell or on a Mac in terminal, run this command:

ssh-keyscan -t rsa -p [port] [host]

 

2.3) GUID

This is a unique identifier which the SFTP Module needs to create a connection with the remote server. Just copy the script below and enter the internal ID of the script which will later handle the connection and the domain. (restrictToScriptIds and restrictToDomains). Deploy it as a SuiteLet and run it through the link you find in the deployment.

 

/**
 *@NApiVersion 2.x
 *@NScriptType Suitelet 
 */

define(['N/ui/serverWidget', 'N/log'],
    function (serverWidget, log) {
        function onRequest(context) {
            if (context.request.method === 'GET') {
                var form = serverWidget.createForm({
                    title: 'Guid Form'
                });
                form.addField({
                    id: 'username',
                    type: serverWidget.FieldType.TEXT,
                    label: 'Username'
                });
                form.addCredentialField({
                    id: 'password',
                    label: 'Password',
                    restrictToScriptIds: 'customscript_internal_id',
                    restrictToDomains: 'host of service'
                });
                form.addSubmitButton({
                    label: 'Submit Button'
                });
                context.response.writePage(form);
                return;
            } else {
                var requset = context.request;
                var myPwdGuid = requset.parameters.password;
                log.debug("myPwdGuid", myPwdGuid);
                context.response.write(myPwdGuid);
            }
        }

        return {
            onRequest: onRequest
        };
    }
);

 

2.4) Connection and transfer

The second script handles sending your file to the remote server. This is a workflow action script. You can modify it to be a module and pass sftp credentials and a file.

/**
 *@NApiVersion 2.x
 *@NScriptType WorkflowActionScript
 */

define(['N/sftp', 'N/file', 'N/search'],
    function (sftp, file, search) {
        function onAction(context) {

            var txn = context.newRecord;
            try {
                
                var myPwdGuid = "WHAT YOUR SUITELET CREATED";
                var myHostKey = "WHAT YOU FOUND FROM SSH-KEYSCAN";
                var connection = sftp.createConnection({
                    username: 'YOUR USERNAME',
                    passwordGuid: myPwdGuid,
                    url: 'SERVICE DOMAIN',
                    port: PORT OF SERVICE IS USUALLY 22,
                    directory: 'FOLDER',
                    hostKey: myHostKey
                });

                var uploadFile = file.load({
                    id: 'PATH TO SOME FILE'
                });

                connection.upload({
                    filename: fileName,
                    file: uploadFile,
                    replaceExisting: true
                });
            }
        }

        return {
            onAction: onAction
        }
    }
);
Published in Script Solution
Friday, 24 May 2019 09:56

Payment slip with reference number

In Switzerland it is common to send a payment slip with the invoice. 

 

in german: https://de.wikipedia.org/wiki/Einzahlungsschein_mit_Referenznummer

 

 

How this is done in NetSuite:

With a "Workflow Action Script" the "payment slip" is printed out on the invoice. A separate Advanced HTML template is filled with the data from the invoice and saved with the transaction record. NetSuite also offers the option to send this "payment slip" as a PDF by email together with the invoice.


Alta Via Consulting has developed a bundle for Switzerland that contains this payment slip and other localizations. Contact us for more details. 

Script that creates the PDF:

function createPdf(rec) {
        var renderer;
        var pdf;
        var recObj = getDataObject(rec);

        renderer = render.create();
        renderer.setTemplateByScriptId('CUSTTMPL_AV_ZAHLSCHEIN'); // Load the template CUSTTMPL_AV_ZAHLSCHEIN 125
        renderer.addCustomDataSource({
        format: render.DataSource.JSON, // Expecting an object
        alias: 'record',
        data: JSON.stringify(recObj).replace(/&/g, '&amp;')
    });

    pdf = renderer.renderAsPdf()

    return pdf;
}

 

In order to provide the "Payment slip with reference number" in NetSuite, a check digit must be calculated (among other things). This happens recursively according to "modulo10":

function mod10(bb) {
    var R1 = 0;
    var alg = [0, 9, 4, 6, 8, 2, 7, 1, 3, 5];
    var be = bb.split("");
    var bl = bb.length;
    var Rbb;
    var P1;
    for (i = 0; i < bl; i++)
    {
        Rbb = parseInt(R1) + parseInt(be[i])
        R1 = alg[Rbb % 10]
    }
    P1 = (10 - R1) % 10
    return P1;
}​
Published in Script Solution

Hello,

 

We found that sending an email from a standard netsuite transaction does not allow us to modify the reply-to email address. Receipients are confused or do not reply to the email we want to. Here is a workflow action script which fixes this.

 

NetSuite has an enhancement request, which is currently not in progress. Enhancement # - 76077 

 

var CONST = {
    author_license: [some user id],
    replyTo: 'set this or pull it from somewhere',
    bcc: 'whatever you wish'
}

function sendEmail_WF() {

    var po = nlapiGetNewRecord();

    var emailMerger = nlapiCreateEmailMerger(yourFormId);
    emailMerger.setTransaction(po.getId());
    emailMerger.setEntity('vendor', po.getFieldValue('entity'));
    var mergeResult = emailMerger.merge();
    var subject = mergeResult.getSubject();
    var body = mergeResult.getBody();

    var recipient = getReceipients(po.getFieldValue('entity'));
    if (recipient.length == 0) {
        throw 'There is no email address to send this email to.';
    }

    var attachments = [];
    attachments = getAttachment(attachments, po);
    attachments = getPDF(attachments, po);

    var records = {
        transaction: po.getId()
    }

    if (recipient && recipient != '') {
        nlapiSendEmail(CONST.author_license, recipient, subject, body, null, CONST.bcc, records, attachments, null, null, CONST.replyTo);
    }
}

function getReceipients(vendId) {
    // Here we pull email addresses from the vendor's contacts and also addd the vendor's main email address

    var recipient = [];
    recipient.push(nlapiLookupField('entity', vendId, 'email'));
    var cS = nlapiSearchRecord("contact", null,
        [
            ["company", "anyof", vendId],
            "AND",
            ["custentity_is_po_recipient", "is", "T"],
            "AND",
            ["email", "isnotempty", ""]
        ]
    );
    for (var i = 0; cS && i < cS.length; i++) {
        recipient.push(cS[i].getId());
    }

    var recipientNoDupe = [];
    recipient.forEach(function (recipient) {
        if (recipientNoDupe.indexOf(recipient) < 0) {
            recipientNoDupe.push(recipient);
        }
    });

    return recipientNoDupe;

}

function getAttachment(attachments, po) {
    varcustbody_your_document_field = po.getFieldValue('custbody_your_document_field');
    if (custbody_your_document_field && custbody_your_document_field != '') {
        attachments.push(nlapiLoadFile(custbody_your_document_field));
    }
    return attachments;
}

function getPDF(attachments, po) {
    var paras = [];
    paras.formnumber = 'your transaction form id';
    var file = nlapiPrintRecord('TRANSACTION', po.getId(), 'PDF', paras);
    attachments.push(file);
    return attachments;
}​
Published in Script Solution

CONTACT US!

O NetSuite SuiteCloudDeveloperNetwork rgb 2NetSuite SolutionProvider horiz rgb

NOTE! This site uses cookies and similar technologies.

If you not change browser settings, you agree to it.

I understand