<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Erick</title>
    <description>The latest articles on DEV Community by Erick (@smith288).</description>
    <link>https://dev.to/smith288</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F103155%2F5654ceb0-db77-4ba3-a2a4-1accd8630d7a.jpeg</url>
      <title>DEV Community: Erick</title>
      <link>https://dev.to/smith288</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smith288"/>
    <language>en</language>
    <item>
      <title>Hello? It's GIT you're looking for</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Tue, 27 Feb 2024 21:57:00 +0000</pubDate>
      <link>https://dev.to/smith288/hello-its-git-youre-looking-for-4839</link>
      <guid>https://dev.to/smith288/hello-its-git-youre-looking-for-4839</guid>
      <description>&lt;p&gt;(sing to this)&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=uixkkqOQoD0"&gt;https://www.youtube.com/watch?v=uixkkqOQoD0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎶I've been coding all alone,&lt;br&gt;
In the glow of my laptop screen,&lt;br&gt;
But my code's got bugs, they're everywhere,&lt;br&gt;
And my coffee's getting cold, it seems.🎶&lt;/p&gt;

&lt;p&gt;🎶I just wanna Ctrl + Z,&lt;br&gt;
But my fingers, they're getting tired,&lt;br&gt;
And I wonder if you ever feel,&lt;br&gt;
Like your syntax has expired.🎶&lt;/p&gt;

&lt;p&gt;(Chorus)&lt;br&gt;
🎶Hello, is it Git you're looking for?&lt;br&gt;
I can see it in your merge request,&lt;br&gt;
I can see it in your code.🎶&lt;/p&gt;

&lt;p&gt;🎶You're just a push away,&lt;br&gt;
But I know you're so far away,&lt;br&gt;
'Cause I can't seem to resolve,&lt;br&gt;
All these conflicts that we've made.🎶&lt;/p&gt;

&lt;p&gt;(Verse 2)&lt;br&gt;
🎶I've been staring at this screen,&lt;br&gt;
For what feels like days on end,&lt;br&gt;
And I'm hoping that you'll branch out,&lt;br&gt;
And help me debug this trend.🎶&lt;/p&gt;

&lt;p&gt;🎶I just wanna pull you close,&lt;br&gt;
And sync up our commits,&lt;br&gt;
'Cause without you, my dear colleague,&lt;br&gt;
My code's just full of misfits.🎶&lt;/p&gt;

&lt;p&gt;(Chorus)&lt;br&gt;
🎶Hello, is it Git you're looking for?&lt;br&gt;
I can see it in your merge request,&lt;br&gt;
I can see it in your code.🎶&lt;/p&gt;

&lt;p&gt;🎶You're just a push away,&lt;br&gt;
But I know you're so far away,&lt;br&gt;
'Cause I can't seem to resolve,&lt;br&gt;
All these conflicts that we've made.🎶&lt;/p&gt;

&lt;p&gt;(Bridge)&lt;br&gt;
🎶I'm reaching out for you,&lt;br&gt;
But my branch is out of date,&lt;br&gt;
And though I try to rebase,&lt;br&gt;
It's like I'm stuck in a state.🎶&lt;/p&gt;

&lt;p&gt;🎶I just wanna Git with you,&lt;br&gt;
And make this codebase shine,&lt;br&gt;
'Cause with you by my side,&lt;br&gt;
We'll deploy our code just fine.🎶&lt;/p&gt;

&lt;p&gt;(Chorus)&lt;br&gt;
🎶Hello, is it Git you're looking for?&lt;br&gt;
I can see it in your merge request,&lt;br&gt;
I can see it in your code.🎶&lt;/p&gt;

&lt;p&gt;🎶You're just a push away,&lt;br&gt;
But I know you're so far away,&lt;br&gt;
'Cause I can't seem to resolve,&lt;br&gt;
All these conflicts that we've made.🎶&lt;/p&gt;

&lt;p&gt;Yes.  This was dumb as hell... Sorry for wasting your time.&lt;/p&gt;

</description>
      <category>parody</category>
      <category>song</category>
      <category>git</category>
      <category>source</category>
    </item>
    <item>
      <title>Netsuite Searching with SuiteScript 2.0 "Snyder" cut</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Wed, 18 Oct 2023 19:53:10 +0000</pubDate>
      <link>https://dev.to/smith288/netsuite-searching-with-suitescript-20-snyder-cut-531m</link>
      <guid>https://dev.to/smith288/netsuite-searching-with-suitescript-20-snyder-cut-531m</guid>
      <description>&lt;p&gt;Suppose you read my first &lt;a href="https://dev.to/smith288/netsuite-searching-with-suitescript-20-2k51"&gt;Netsuite Search with SuiteScript 2.0&lt;/a&gt; tutorial but you want a BIT more information?  First, if you haven't, read the first tutorial.  &lt;/p&gt;

&lt;p&gt;Then read this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 *@NApiVersion 2.x
 *@NScriptType UserEventScript
 */
define(['N/search', 'N/log'],
    function(search, log) {
        return {beforeLoad: beforeLoad};

        function beforeLoad(context){

            var srch = search.create({type: 'itemfulfillment', filters: [], columns:[]};

            var srchResults = srch.run();

            srchResults.each(function(result){
                log.debug('Result', result.id);
            });
        }
    }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the search.create, there's filters and columns.  For filters, they are arrays of search.createFilter() objects that look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var filters = [search.createFilter({name: 'fieldtosearch', operator: 'anyof', values: ['value1', 'value2', 'value3']})];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give you a single object in the needed array.  You can obviously add more as needed.&lt;/p&gt;

&lt;p&gt;For columns array, you can use it a few ways.  It can be an array of strings like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var columns = ['field1', 'field2', 'recordid.field3'];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var columns = [{name: 'field1'}, {name: 'field2'}, {name: 'field3', join: 'recordid'}];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the two are very similar but one has a join as part of the object and the other is simply a string with a dot to denote the joined record?  It can get pretty complete and I would recommend playing around in the Netsuite Script Debugger to test various ways to create your searches within SuiteScript 2.*.&lt;/p&gt;

&lt;p&gt;That's a more advanced usage of a search in Suitescript 2.0.  It's a little more complex than Suitescript 1.0 but it offers a much more modular and flexible design pattern.&lt;/p&gt;

&lt;p&gt;I hope this helps any noobs learning Netsuite's SuiteScript. I know me being self-taught, these types of articles were a Godsend to me to help explain code more than a generic API document of functions and properties.  &lt;/p&gt;

</description>
      <category>netsuite</category>
      <category>suitescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How do I check if a bundle is installed in Netsuite?</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Wed, 18 Oct 2023 19:28:23 +0000</pubDate>
      <link>https://dev.to/smith288/how-do-i-check-if-a-bundle-is-installed-in-netsuite-1mc0</link>
      <guid>https://dev.to/smith288/how-do-i-check-if-a-bundle-is-installed-in-netsuite-1mc0</guid>
      <description>&lt;p&gt;&lt;em&gt;"I want to see if the customer has Ship Central installed prior to doing my cool feature.  How do I do that?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a word, simple. You search for a custom record type of a record that would exist in the bundle you want to check for. &lt;/p&gt;

&lt;p&gt;In my example, I would like to see if the customer has the Netsuite Ship Central bundle installed.  All you have to do is use the little known search type called 'customrecordtype' against the column 'scriptid'.&lt;/p&gt;

&lt;p&gt;Check out this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function doesRecordExist(scriptId) {
    var customRecordTypeSearch = search.create({
        type: "customrecordtype",
        filters: [["scriptid", "is", scriptId]],
        columns: ["scriptid"]
    });

    var searchResult = customRecordTypeSearch.run().getRange({
        start: 0,
        end: 1
    });
    custom_exists = searchResult.length &amp;gt; 0;
    return custom_exists;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can run it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(doesRecordExist('customrecord_packship_shipmanifest')){
    // DO SOMETHING COOL
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give it a whirl.  It's a great method to verify something exists prior to enabling a feature in your own bundle.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to watch more cat videos with Netsuite Scheduled Scripts</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Fri, 27 Jan 2023 03:38:43 +0000</pubDate>
      <link>https://dev.to/smith288/how-to-watch-more-cat-videos-with-netsuite-scheduled-scripts-1mca</link>
      <guid>https://dev.to/smith288/how-to-watch-more-cat-videos-with-netsuite-scheduled-scripts-1mca</guid>
      <description>&lt;p&gt;Are you tired of manually running your Suitelet scripts every time you want to update your inventory? Well, look no further than Netsuite's Suitelet 2.0 Scheduled Scripts! These bad boys will take care of all your automation needs and free up your time for more important things... like cat videos on YouTube.&lt;/p&gt;

&lt;p&gt;For example, let's say you're running a retail business and you want to automatically mark items as "Out of Stock" when they hit a certain inventory threshold. Instead of constantly checking and updating your inventory manually, you can set up a Suitelet 2.0 Scheduled Script to do it for you.&lt;/p&gt;

&lt;p&gt;Here's a quick and easy example of how to set up your own scheduled script:&lt;/p&gt;

&lt;p&gt;Create a new Suitelet script in your Netsuite account&lt;br&gt;
In the script's parameters, set the execution to "Scheduled" and specify the schedule frequency (daily, weekly, etc.)&lt;br&gt;
In the script's code, add a search to find all items with a quantity less than or equal to your desired "Out of Stock" threshold.&lt;br&gt;
Loop through the search results and update each item's "Out of Stock" field to "T" (for true)&lt;br&gt;
Save and deploy your script&lt;br&gt;
And that's it! Your script will now run on the schedule you specified and keep your inventory up-to-date without you lifting a finger (well, except for the finger you used to click the "Deploy" button).&lt;/p&gt;

&lt;p&gt;Let's say you're running an e-commerce business on Netsuite and you want to be notified when certain items are running low on stock. With Suitelet 2.0, you can set up a scheduled script that checks your inventory levels every day at a certain time and sends you an email notification if any items fall below a certain threshold.&lt;/p&gt;

&lt;p&gt;Here's a quick example of what that script might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @NApiVersion 2.x
 * @NScriptType ScheduledScript
 */
define(['N/search', 'N/email'], function(search, email) {

    function execute(context) {
        var lowStockItems = [];

        // Run a search to find all items with stock below 10
        var inventorySearch = search.create({
            type: 'item',
            filters: [
                ['inventorynumber','lessthan','10']
            ],
            columns: ['itemid']
        });

        inventorySearch.run().each(function(result) {
            lowStockItems.push(result.getValue('itemid'));
            return true;
        });

        // If we found any low stock items, send an email notification
        if (lowStockItems.length &amp;gt; 0) {
            var emailSubject = 'While you were watching cat videos - Low Stock Alert';
            var emailBody = 'The following items are running low on stock: ' + lowStockItems.join(', ');

            email.send({
                to: 'your.email@example.com',
                subject: emailSubject,
                body: emailBody
            });
        }
    }

    return {
        execute: execute
    };
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So don't let manual updates bring you down, let Suitelet 2.0 Scheduled Scripts do the heavy lifting for you. Now, if you'll excuse me, I'm off to watch some more cat videos.&lt;/p&gt;

</description>
      <category>gratitude</category>
      <category>dotnet</category>
      <category>news</category>
    </item>
    <item>
      <title>SuiteScript 2.0 - Using Map-Reduce to retrieve large set of records.</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Thu, 19 Jan 2023 15:32:41 +0000</pubDate>
      <link>https://dev.to/smith288/suitescript-20-using-map-reduce-to-retrieve-large-set-of-records-24bf</link>
      <guid>https://dev.to/smith288/suitescript-20-using-map-reduce-to-retrieve-large-set-of-records-24bf</guid>
      <description>&lt;p&gt;If you've noticed, Netsuite is very controlled in how they allow partners access their data without safeguards.  And trying to collect large sets of data or process them can be tough but with a little bit of ingenuity, you can. &lt;/p&gt;

&lt;p&gt;This script is a Map/Reduce script, which is a type of script that allows you to process large amounts of data in smaller chunks. &lt;/p&gt;

&lt;p&gt;Here is a SuiteScript 2.0 script that retrieves all customer records from NetSuite and logs the internal ID and company name for each record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @NApiVersion 2.x
 * @NScriptType MapReduceScript
 */
define(['N/search'], function(search) {
    function getInputData() {
        var customerSearch = search.create({
            type: search.Type.CUSTOMER,
            columns: ['internalid', 'companyname']
        });
        return customerSearch;
    }

    function map(context) {
        var searchResult = JSON.parse(context.value);
        log.debug({
            title: 'Customer Record',
            details: 'Internal ID: ' + searchResult.values['internalid'].value + ', Company Name: ' + searchResult.values['companyname'].value
        });
    }

    return {
        getInputData: getInputData,
        map: map
    };
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script uses the search module to create a search for customer records and retrieve the internal ID and company name for each record. The map function is then used to iterate through the search results and log the internal ID and company name for each record.&lt;/p&gt;

&lt;p&gt;This code snippet can be helpful for retrieving large amount of data and customizing the output in NetSuite.&lt;/p&gt;

</description>
      <category>netsuite</category>
      <category>suitescript</category>
      <category>mapreduce</category>
      <category>oracle</category>
    </item>
    <item>
      <title>What's up with Netsuite's UserEvents Governance?</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Thu, 29 Dec 2022 15:15:39 +0000</pubDate>
      <link>https://dev.to/smith288/netsuite-suitescript-userevents-governance-n94</link>
      <guid>https://dev.to/smith288/netsuite-suitescript-userevents-governance-n94</guid>
      <description>&lt;p&gt;SuiteScript 2.0 UserEvents are a powerful tool for customizing and extending the functionality of NetSuite, allowing you to write scripts that are triggered by specific user actions within the platform. However, it's important to keep in mind that UserEvents are subject to certain governance limitations that can affect their performance and reliability. In this post, we'll take a look at what these limitations are and how you can work within them to get the most out of your UserEvents.&lt;/p&gt;

&lt;p&gt;First, let's start by discussing what UserEvents are and how they work. UserEvents are scripts that are triggered by specific actions taken by users within NetSuite, such as creating a new record or changing an existing one. These scripts can be used to perform a variety of tasks, including validating data, sending emails, or updating other records in the system.&lt;/p&gt;

&lt;p&gt;One of the key benefits of using UserEvents is that they allow you to customize the behavior of NetSuite in real-time, without requiring any additional user input or intervention. This makes them particularly useful for automating business processes and improving efficiency.&lt;/p&gt;

&lt;p&gt;However, it's important to keep in mind that UserEvents are subject to certain governance limitations that can affect their performance and reliability. These limitations are designed to ensure that UserEvents do not negatively impact the performance of the NetSuite system, and to prevent abuse of the platform by rogue scripts.&lt;/p&gt;

&lt;p&gt;One of the main governance limitations for UserEvents is the maximum execution time allowed for a script. NetSuite imposes a maximum execution time of 10 minutes for UserEvents, which means that any script that runs for longer than this will be terminated. This limitation is in place to prevent UserEvents from consuming too many system resources and negatively impacting the performance of the platform.&lt;/p&gt;

&lt;p&gt;To work within this limitation, it's important to design your UserEvents in a way that minimizes their execution time. This might involve optimizing your script's code, breaking up long-running processes into smaller chunks, or using techniques like batch processing to handle large volumes of data.&lt;/p&gt;

&lt;p&gt;Another governance limitation to be aware of is the maximum number of records that can be processed by a UserEvent in a single execution. NetSuite imposes a maximum of 1000 records per execution, which means that any script that attempts to process more than 1000 records in a single run will be terminated.&lt;/p&gt;

&lt;p&gt;To work within this limitation, you'll need to design your UserEvents to process records in smaller batches, rather than trying to process all of the records in a single execution. This might involve using a loop or cursor to iterate over the records, and processing them in smaller chunks.&lt;/p&gt;

&lt;p&gt;It's also worth noting that UserEvents are subject to NetSuite's standard governance limits for scripts, which include limits on the number of API calls and database operations that can be made in a single execution. These limits are in place to ensure that scripts do not consume too many system resources and negatively impact the performance of the platform.&lt;/p&gt;

&lt;p&gt;UserEvents are subject to several governance limits that are designed to ensure that they do not negatively impact the performance of the NetSuite system. These limits include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Maximum execution time: NetSuite imposes a maximum execution time of 10 minutes for UserEvents, which means that any script that runs for longer than this will be terminated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maximum number of records: NetSuite imposes a maximum of 1000 records per execution for UserEvents, which means that any script that attempts to process more than 1000 records in a single run will be terminated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Governance units: UserEvents are also subject to NetSuite's standard governance units (GUs) limit, which is a measure of the system resources consumed by a script. The maximum number of GUs that can be consumed by a UserEvent in a single execution is dependent on the account's subscription level and may vary.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's important to keep these limits in mind when designing your UserEvents, and to optimize your scripts to minimize their impact on the system. This might involve optimizing your code, breaking up long-running processes into smaller chunks, or using techniques like batch processing to handle large volumes of data.&lt;/p&gt;

&lt;p&gt;In summary, UserEvents are a powerful tool for customizing and extending the functionality of NetSuite, but it's important to keep in mind that they are subject to certain governance limitations that can affect their performance and reliability. By designing your UserEvents to minimize their execution time and stay within the limits for the number of records and API calls, you can ensure that your scripts run smoothly and efficiently within the NetSuite platform.&lt;/p&gt;

</description>
      <category>netsuite</category>
      <category>suitescript</category>
      <category>userevents</category>
      <category>governance</category>
    </item>
    <item>
      <title>Changing our Integration with Netsuite</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Mon, 18 Feb 2019 21:03:03 +0000</pubDate>
      <link>https://dev.to/smith288/integration-with-netsuite-163g</link>
      <guid>https://dev.to/smith288/integration-with-netsuite-163g</guid>
      <description>&lt;p&gt;So Netsuite decided they will be implementing 2FA for logins.  This makes things rather difficult for me as our integration was using basic username/password Authorization header calls.  Essentially, in Netsuite, you can't use username/password for web service calls anymore. &lt;/p&gt;

&lt;p&gt;They have varying methods of authentication they allow for in order to utilize their services.  They have a SOAP service and then they provide a RESTful type of method that allows you to write your own script and assign the callback functions to verbs.  It's actually quite flexible and powerful with the various actions one can do. I recommend looking into RESTlets in Netsuite's documentation if you're unfamiliar.&lt;/p&gt;

&lt;p&gt;This brings me to Netsuite's authentication methods.  You can use username and password, Session ID (virtually unusable...but capable) and OAuth 1.0 for integration into their web services platform.&lt;/p&gt;

&lt;p&gt;Many of our partners used the username and password authentication due to the simplicity of setup.  Obviously, this can create problems when passwords expire or a client wants to eliminate access but our scheduled jobs continue to try to access Netsuite from inside our platform until you can't.  Netsuite is sunsetting the username/password capability soon.&lt;/p&gt;

&lt;p&gt;So with all that said, I have decided I'll work from the inside out.  I am going to rewrite my integration from within Netsuite using a variety of Suitescript events and calling out to our own RESTful API which will accept the data.&lt;/p&gt;

&lt;p&gt;This may cause some problems for debugging or troubleshooting any possible errors but we also have an endpoint we will write errors to that will essentially duplicate the execution log of a script.  With the exception of invalid license keys to our API, we should be able to generally troubleshoot most issues.&lt;/p&gt;

&lt;p&gt;I will use UserEventScripts to attach actions of records to trigger Map/Reduce scripts to loop through unimported records and throttle the calls on our end using our own governance methods tweaking it based on customer commitments ($$$).  &lt;/p&gt;

&lt;p&gt;I will also use a public Suitelet webhook that will do nothing more than wake up, obtaining updated info by retrieving info via our RESTful api and then going back to sleep. Clean.&lt;/p&gt;

&lt;p&gt;Using a combination of RESTlets, Suitelets, and javascript, I will beat permission issues related to users who don't have access to needed records, slower data transfer times and clunky popups that call unfamiliar UIs possibly confusing user experience.  Rounding out a good, fast, and usable solution all without needing to use OAuth.&lt;/p&gt;

</description>
      <category>netsuite</category>
      <category>webhooks</category>
      <category>restful</category>
      <category>suitescript</category>
    </item>
    <item>
      <title>Netsuite Searching with SuiteScript 2.0</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Mon, 18 Feb 2019 20:37:48 +0000</pubDate>
      <link>https://dev.to/smith288/netsuite-searching-with-suitescript-20-2k51</link>
      <guid>https://dev.to/smith288/netsuite-searching-with-suitescript-20-2k51</guid>
      <description>

&lt;p&gt;What even is Netsuite?&lt;/p&gt;

&lt;p&gt;Netsuite is fast becoming the most popular cloud-based (cloud-based; noun, it's just a flipping web site on the internet... &lt;em&gt;sigh&lt;/em&gt;) ERP platform.  ERP stands for Enterprise Resource Planning.  So it will handle inventory, human resources, manage an online store.  You get the idea.  The cool thing about Netsuite is that it's EXTREMELY customizable for the user.  You can add fields, scripts, records... Many solution providers make a living out of providing services that plug right into their platform.  &lt;/p&gt;

&lt;p&gt;With that out of the way, Netsuite provides a developer with a large toolset to interact with their platform. They call it "SuiteScript" but what it really is, is Javascript but built into their server's infrastructure.  &lt;/p&gt;

&lt;p&gt;They have a variety of types you can code against also.  Client-side, scheduled, Mass update, Map/Reduce, User events and a few others... Each type interacts with Netsuite a little bit differently based on what you're aiming to do.&lt;/p&gt;

&lt;p&gt;In my example, I want to focus on a user event script.  For brevity, it is just a script you can assign to run either before a page loads, before submit or after submit.  &lt;/p&gt;

&lt;p&gt;For starters, Netsuite has pretty good documentation now but I want to offer up something a little more simple.&lt;/p&gt;

&lt;p&gt;Using an asynchronous module definition (AMD) philosophy, we can plug in what we need for our custom script.  For more information on this, please read &lt;a href="https://requirejs.org/docs/why.html"&gt;this&lt;/a&gt; and it will give more background on it.&lt;/p&gt;

&lt;p&gt;How this is done is we define our modules, assign them a variable and use them within the sealed function.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 *@NApiVersion 2.x
 *@NScriptType UserEventScript
 */
define(['N/search', 'N/log'],
    function(search, log) {
        return {beforeLoad: beforeLoad};

        function beforeLoad(context){

            var srch = search.create({type: 'itemfulfillment', filters: [], columns:[]};

            var srchResults = srch.run();

            srchResults.each(function(result){
                log.debug('Result', result.id);
            });
        }
    }
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So let's step through what's going on:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 *@NApiVersion 2.x   &amp;lt;--- Required to declare what API version (2.0, 2.x or 2.X)
 *@NScriptType UserEventScript &amp;lt;--- Required to declare what type of suitescript this is, in this case, a UserEventScript
 */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;define(['N/search', 'N/log'], &amp;lt;--- Defining what Netsuite modules we wish to use The 'N/search' and 'N/log' are my most utilized modules
    function(search, log) { &amp;lt;-- Defining the globals to the modules we defined above
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        return {beforeLoad: beforeLoad} &amp;lt;--- Returning the callback function to the assignable return variable. In this case, beforeLoad is being used.  beforeSubmit and afterSubmit is also available to us.

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also change how we declare this by just writing the callback function in line with the assignment by doing the following.  I find it more readable buy referencing the function instead of writing it inline but that's a personal preference.&lt;/p&gt;

&lt;p&gt;The context parameter is standard for the UserEventScript and contains valuable information for us such as script information or other entry point information specific to that script.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        return {beforeLoad: function(context){/* stuff */}};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now the meat and potatoes.  The callback function that is running for the beforeLoad&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
        function beforeLoad(context){

            // Initialize an array of filter objects based on a (name, condition, value struct)
            var myFilters = [{'internalid', 'is', '1234'}];

            // Initialize an array of columns you want to return
            var myColumns = ['name'];

            // Create search object by declaring the type and any filters and columns that you want to return
            var srch = search.create({type: 'itemfulfillment', filters: myFilters, columns: myColumns};

            // Run the created search (the run routine only runs 1000 max so if you need more, you would want to use the runPaged() routine 
            var srchResults = srch.run();

            // Loop through the array of results using either by inlining the function callback or by assigning the function to the each function.  In this scenario, I do use the inline callback for readability. I'm weird and inconsistent that way.
            srchResults.each(function(result){
                // Log to the script's execution log in debug verbosity of the result and it's build in id property
                log.debug('Result', result.id);
            });
        }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's really the most basic usage of a search in Suitescript 2.0.  It's a little more complex than Suitescript 1.0 but it offers a much more modular and flexible design pattern.&lt;/p&gt;

&lt;p&gt;I hope this helps any noobs learning Netsuite's SuiteScript. I know me being self-taught, these types of articles were a Godsend to me to help explain code more than a generic API document of functions and properties.  &lt;/p&gt;


</description>
      <category>netsuite</category>
      <category>suitescript20</category>
      <category>suitescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Netsuite SuiteScript 2.0 Client Side onLoad Hackery</title>
      <dc:creator>Erick</dc:creator>
      <pubDate>Fri, 21 Sep 2018 02:30:38 +0000</pubDate>
      <link>https://dev.to/smith288/netsuite-suitescript-20-client-side-onload-hackery-2hpn</link>
      <guid>https://dev.to/smith288/netsuite-suitescript-20-client-side-onload-hackery-2hpn</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa90e2pgkoahdxhc1qhj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa90e2pgkoahdxhc1qhj.gif" alt="banner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When my company moved from Suitescript 1.0 to 2.0 (because, well, why not?) one thing we needed was to listen to the browser's message listener from another browser tab when some event occurred.  &lt;/p&gt;

&lt;p&gt;In order to do that, I needed script to listen upon load.  Netsuite doesn't provide a feature to let us load a client side script on page load very easily.  We had to create a UserEvent script that would call a function on load that would then assign an INLINEHTML custom field type to the form with the required function.&lt;/p&gt;

&lt;p&gt;Check it out&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @NApiVersion 2.x
 * @NScriptType UserEventScript
 */

define(['N/runtime'],
    function (runtime) {

        return {
            beforeLoad: beforeLoad
        };

        function beforeLoad(context) {

            if (runtime.executionContext.toUpperCase() == 'USERINTERFACE') {
                var inline = context.form.addField({
                    id: 'custpage_attachmessage',
                    label: 'not shown',
                    type: 'INLINEHTML',
                });
                inline.defaultValue = "&amp;lt;script&amp;gt;jQuery(function($){ require(['/SuiteScripts/clientSuiteScript.js'], function(mod){ mod.pageInit();});});&amp;lt;/script&amp;gt;";
            }
        }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the client suitescript will roughly look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * @NApiVersion 2.x
 * @NScriptType ClientScript
 */

define(['N/currentRecord'],

    function (currentRecord) {

        function pageInit() {
            window.addEventListener("message", browser_ReceiveMessage, false);
            console.log('Added Listener...');

        }

        return {
            pageInit: pageInit
        }

        function browser_ReceiveMessage(event) {

            var curRec = currentRecord.get();
            console.log('Current Record ID', curRec.id)
        }
    }

);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then on load, the console will output the currentRecord's id.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>netsuite</category>
      <category>suitescript20</category>
      <category>client</category>
    </item>
  </channel>
</rss>
