Wednesday, 24 May 2017

Steps to Hide the Print Button for a User having a Custom Customer Center Role when a Sales Order is Viewed on the Web Store Context

​For a custom Customer Center role having Fulfill Sales Order=None, when a user clicks See Orders in theCustomer Center > view any order > a Print button is displayed. To hide this Print button, here are the steps:

1. Create a user event script by navigating to Customization > Scripting > Scripts > New > User EventUser Event needs to be setup this way: 

Deployments 
Applies to: Sales Order 
Deployed: Yes 
Status: Released 

Scripts
Before Record Load: restrictPrintButtonOnWebStore <-- this is the name of the function 

Script :

function restrictPrintButtonOnWebStore(type, form){ 
        var currentContext = nlapiGetContext(); 
        if (currentContext.getExecutionContext() == 'webstore') { 
                nlapiLogExecution('Debug', 'context', currentContext.getExecutionContext()); 
                userRole = nlapiGetRole(); 
                nlapiLogExecution('Debug', 'nlapiGetRole()', userRole); 
                if(userRole == 1017){ 
                      var button = form.getButton('print'); 
                      button.setVisible(false); 
                } 
                 
        } 
}

Sunday, 7 May 2017

Netsuite Suitescript 2.0

Its been a while since suitescript 2.0 made an appearance into Netsuite with Version 2015 Release 2. Netsuite introduced a SuiteScript 2.0- a complete re-factor of the SuiteScript model driving towards a more modular based development approach. Recently, I was trying to have some hands on it and thought of sharing few keynotes based on my exploration.
Advantages to SuiteScript 2.0
  1. Modular Architecture
  2. Modern JavaScript Syntax and Behavior
  3. New and Improved API Functionality
  4. Asynchronous Client Side Processing (Promises)
  5. New Batch Processing Framework (Map/Reduce Script Type)
Lets see some examples:
Load a record


require(['N/record'], function(RECORDMODULE){

    var recordType = RECORDMODULE.Type.ACCOUNT; //The type of record to load.
    var recordID = 10011; //The internal ID of the existing record in NetSuite.
    var isDynamic = true; //Determines whether to load the record in dynamic mode.

    var loadedRecord = RECORDMODULE.load({
        type: recordType, 
        id: recordID,
        isDynamic: isDynamic,
    });
});


Create Search

We can use search.create to build out our search object or search.load to load a saved search. Then we can  invoke run on the resulting search object. Finally, we will process the results in two ways:
  1. Use the each method and a callback
  2. Use the getRange method to get a specific number of results

In the example below, I've imported N/search into my module as s and shown the usage of the each method.
  • Summary Search (Suitescript 2.0)
// Assuming N/search is imported as `s`
var demoSalesOrderSearch = s.create({
    type: 'salesorder'
    // Use the summary property of a Column to perform grouping/summarizing
    columns: [{
        name: 'salesrep',
        summary: s.Summary.GROUP
    },{
        name: 'internalid',
        summary: s.Summary.COUNT
    }],
    filters: [{
        name: 'mainline',
        operator: 'is',
        values: ['T']
    }]
});

demoSalesOrderSearch.run().each(function (result) {
    var repId = result.getValue({
        "name": "salesrep",
        "summary": s.Summary.GROUP
    });
    var repName = result.getText({
        "name": "salesrep",
        "summary": s.Summary.GROUP
    });
    var orderCount = parseInt(result.getValue({
            "name": "internalid",
            "summary": s.Summary.COUNT
    }), 10);

    log.debug({
        "title": "Order Count by Sales Rep",
        "details": repName + " has sold " + orderCount + " orders."
    });
});
  • Search with criteria search
require(['N/search'], function(SEARCHMODULE){
    
    var type = 'transaction';
    var columns = [];
    columns.push(SEARCHMODULE.createColumn({
        name: 'internalid'
    }));
    columns.push(SEARCHMODULE.createColumn({
        name: 'formulanumeric',
        formula: '{quantity}-{quantityshiprecv}'
    }));
    
    var salesOrdersArray = [1001,2001,3001,4001];
    var filters = [];
    filters.push(['type', 'anyof', 'SalesOrd']);
    filters.push('and');
    filters.push(['mainline', 'is', 'F']);
    filters.push('and');
    filters.push(['internalid', 'anyof', salesOrdersArray]);
        
    var mySearchObj = {};
    mySearchObj.type = type;
    mySearchObj.columns = columns;
    mySearchObj.filters = filters;
    
    var mySearch = SEARCHMODULE.create(mySearchObj);
    var resultset = mySearch.run();
    var results = resultset.getRange(0, 1000);
    for(var i in results){
        var result = results[i];
        var row = {};
        for(var k in result.columns){
            log.debug('Result is ' + result.getValue(result.columns[k])); //result 
        }
    }
});
  • From Saved search
require(['N/search'], function(SEARCHMODULE){
    var savedSearchId = 'customsearch_customsearch';
    var mySearch = SEARCHMODULE.load(savedSearchId);
    var resultset = mySearch.run();
    var results = resultset.getRange(0, 1000);
    for(var i in results){
        var result = results[i];
        for(var k in result.columns){
            log.debug('Result is ' + result.getValue(result.columns[k])); //result
        }
    }
});

If you want to explore more related to Suitescript 2.0 check out the below resources:



Tuesday, 25 April 2017

Common Netsuite Interview Questions II



1. Which Suitescript API has maximum governor limits?
·                      nlapiSetRecoveryPoint
·                      nlapiSubmitCSVImport
·                     nlobjJobManager.submit

2. What is the governor limits allowed for Restlets?
     5,000

3. Which Script has maximum governor limits
     Scheduled Script => 10,000

4. How can you overcome governance issue in case of long running process or scheduled jobs on a large set of data ?
      nlapiYieldScript()

5. What is the difference between record level script and form level script ?
A client script can be deployed in one of two ways: at the record level, or at the form level.
6. When you deploy a client script at the record level, you deploy it globally on one or more record types. The script runs on all forms associated with the record type. By contrast, with a form-level deployment, you attach the script to a custom form associated with a record type, and the script runs only when that form is used.
For example, you could use record-level deployment to configure a client script to run on the employee record type. With this approach, the script run whenever the employee record is used, regardless of which form is being used. With record-level deployment, it is also possible to limit the script by configuring it to be available only to certain audiences. With this approach, the script runs only when the form is used by people in certain roles, groups, or other classifications, as configured on the Audience subtab of the script deployment record. However, with record deployment, you cannot limit the script to only one form. The script behaves the same way on all forms associated with the record type.
By contrast, you could attach the client script to only one custom entry form for the employee record type. If a user then opened an employee record using the standard entry form, the script would not run. You can attach a client script to any custom entry form, custom transaction form, or custom address form. However, you cannot limit the audience for a form-level script.
Note that only client scripts can be deployed at the form level. All other entry point scripts can be deployed at the record level only.
7. What are the event types in a client script ?
    pageInit
    saveRecord
    validateField
    fieldChanged
    postSourcing
    lineInit
    validateLine
    recalc
    validateInsert
    validateDelete
8. What's the Difference Between xedit and edit User Event Types?
When the user event type argument is set to xedit, it means that the execution context for the script is inline edit or mass update. In other words, if a user has inline edited a field on a record (or if the record has been part of a mass update), the user event script will execute. In contrast, user event scripts set to execute when the type argument is set to edit will execute when the record is edited in all other contexts. The script will not execute based on an inline edit or mass update.

9. How Many User Events Can I Have on One Record?

There is no limit to the number of user event scripts you can execute on a particular record type. For example, you could have 10 beforeLoad, 9 beforeSubmit, and 15 afterSubmit executing functions on a Customer record. However, assigning this many executable functions to one record type is highly discouraged, as this could negatively affect user experience with that record type. In other words, if you have 10 beforeLoad scripts that must complete their execution before a record loads into the browser for the user, this may significantly increase the time it takes for the record to load. As a consequence, the user's experience working with the record will be negatively affected.

10. What are the event types in a User event script ?
      Before Load
      Before Submit
      After Submit



Thursday, 6 April 2017

Serialized Inventory Items on Order

Problem Statement:
I’m trying to generate a saved search of serialized inventory items on order. I created an item search using these filters:

Is Serialized item - true
On Order - is greater than 0 (Zero)

If I have the results returned with just basic information - i.e., name, on order number, and average cost, the report returns the correct number of items on order. However, if I add the serial number to the results columns, it shows all the serial numbers records we've ever had for that item type as on order.

Example: we have one of a particular type of machine on order, but we've had five of that same type of machine in the past. If I don't include serial number in the results columns, the report shows (correctly) that we have one of those machines on order. If I include the serial number in the results field (which obviously I want to do), it lists all six of those machines as on order and their individual serial numbers.

Solution :
If you are using an item saved search and receive purchase orders in full, please add the following fields:

Under Criteria > Standard:
a. Transaction Fields... > Status > Purchase Order:Pending Receipt
b. Transaction Fields... > Type > Purchase Order
c. Transaction Fields... > Transaction Serial/Lot Number > is not empty

Under Result > Columns:
a. Transaction Fields... > Transaction Serial/Lot Number


Thursday, 16 March 2017

Cash Sale with Status: Deposited but Need to Change Account

​​
This is a very common scenario where transaction posted wrongly to Undeposited Funds account and the Cash Sale shows Status: Deposited
Since the transaction was posted to Undeposited Funds account and user is unable to change the account.
here is a way this issue can be fixed.

Steps to resolve:
1.    Transactions > Bank > Make Deposits > List Edit the deposit.
2.    Uncheck the cash sale.
3.    Click Save.

The cash sale now displays Not Deposited status and the account can be changed in Edit mode.​

How to Record a Cash Back from a Deposit in Netsuite


You can record cash received back from a deposit when you create the deposit slip in NetSuite. Enter the amount received on the Cash Back subtab on the Deposit page.

To record cash back from a deposit:

  1. Go to Transactions > Bank > Make Deposits (Administrator).
  2. Create a deposit. For more information, see Making Deposits.
  3. Click the Cash Back subtab.
    1. In the Amount field, enter the amount of cash you got back.
    2. Select the account the deposit comes from.
    3. Select a department, class or location.
    4. Enter an optional memo.
  4. Click Add.
    Repeat the steps above for any other cash items you received from deposits.
  5. Click Save.​

Friday, 24 February 2017

Upload a file in to Filecabinet using Webservice

First we need to browse the file using asp:FileUpload control. 
Here is the code :-

 <div>
     <asp:FileUpload ID="fileupload" runat="server" />         
     <asp:Button ID="btnUpload" runat="server" Text="UPLoad"  onclick="btnUpload_Click" />
</div>

Then in the code behind of the button click event we need to write the following code to get the file information:-

//Getting the file path
string path = System.IO.Path.GetFullPathfileupload.PostedFile.FileName;
//getting the file name
string filename = System.IO.Path.GetFileName(fileupload.FileName);                  
//Getting the file content                    
byte[] fileContent = System.IO.File.ReadAllBytes(path);                    
lblSummary.Text = "Upload status: File uploaded!";
//calling the function to add the file to the file cabinet  
AddFile(filename, fileContent); 

In  AddFile(filename, fileContent) we need to search the specific folder in the file cabinet through suitetalk.
Code to search for the specific folder in the file cabinet :

//Contains details on the status of the operation and a reference to the updated 
//record.WriteResponse writeResp = null; 
// To implement a search for Folder through suitetalk , 
//we need to work with FolderSearch and FolderSearchBasic classes.
FolderSearch fldSearch = new FolderSearch();
FolderSearchBasic fldSrearchBasic = new FolderSearchBasic(); 
SearchStringField searchFolder = null;
              
//Name of the folder that we want to search                 
string searchValue = "Demo";                 
//Filtering by the folder name                 
searchFolder = new SearchStringField();
searchFolder.@operator =SearchStringFieldOperator.@is;
//Search operator
searchFolder.operatorSpecified = true;
searchFolder.searchValue = searchValue;
//searchValue is name of the folder "Demo"
fldSrearchBasic.name =searchFolder ;
fldSearch.basic = fldSrearchBasic;
// Search by isActive field which is a boolean
SearchBooleanField isActive = new SearchBooleanField();                 
isActive.searchValue = true;
isActive.searchValueSpecified = true;
// Invoke search() web services operation
SearchResult response = nsService.search(fldSearch); 

Once the search is successful we need to fetch the information from the search result to add the file to the specific folder in filecabinet.


//Now stroring the search result in an array
Record[] arrRecord = (Record[])response.recordList;
// Process response
if (response.status.isSuccess){
lblSummary.Text = "search is successful";
Folder fldr = (Folder)arrRecord[0];
//Getting a specific folder from the search
string fldrId = fldr.internalId;
//Fetching the required folder's internal ID
RecordRef refId = new RecordRef();    
refId.internalId = fldrId;
//Storing the folder id
//File object created to get all the file information 
File objFile = new File(); 
objFile.name = filename; //setting the file name 
objFile.folder = refId;  //setting the folder information  
objFile.content = fileContent; //settig the file content     
writeResp = nsService.add(objFile); //adding file to the file cabinet  
}else{           
          lblSummary.Text = "search not found"; 
          return;   
}









Thursday, 2 February 2017

Hide/Remove the Create Deposit Button on Sales Orders

To hide the Create Deposit button from the sales order form perform the following steps:

--Navigate to Customization > Forms > Transaction Forms
--Click Edit beside Customer Sales Order form
--Click on Actions > Standard Actions subtab
--Uncheck Show field beside Create Deposit
--Save

The Create Deposit button should be removed from the sales orders.

Apply an existing Customer Deposit to an existing Sales Order

Problem:

User pulls up an existing Customer Deposit on edit mode and tries to apply the deposit to an existing sales order. On the Customer Deposit record > Sales Order dropdown, the order is not showing as a selection.

Solution:

1. Edit the sales order and change the form to "Standard Sales Order", "Standard Sales Order – Invoice" or any forms customized from any of these Sales Order forms.

2. For "Standard Sales Order" or any forms customized from this form, on the Billing tab of the sales order record, any of the below should be set:
Terms should be selected

- No Terms or Payment Method is selected
Create Deposit button is only available if the sales order is converted to an invoice. The form used should not be a cash sale type and payment method should not be set on the sales order.

Monday, 5 December 2016

Dynamically Determine the Netsuite Field Type in an Existing Object

Sometimes back I was ran into  an issue in one of my project where we had a requirement to dynamically display the fields to User in a customized UI and the field has to be displayed according to the definition of Netsuite field types. For example say Today someone has added a  new field into the object and marked it as mandatory then irrespective of the type of the filed which has been created it has to be reflected on the customized UI page to the user and should let the user identify the field as mandatory while creating a record.

So below is the script which would dynamically help to determine the mandatory fields in an Object.



function getFields(datain) {
    var record = nlapiCreateRecord ( datain.recordtype );
    var fields = record.getAllFields();
    var requiredFields = {};
    fields.forEach(function(fieldName){
        var field = record.getField(fieldName);
        if(field.mandatory === true) {
            var id = field.getName();
            var field_details = {}
            field_details['Type'] =  field.getType();
            field_details['Label'] =  field.getLabel();
            if(field.getType() == 'select' || field.getType() == 'multiselect') {
                var Options = field.getSelectOptions();
                var selectOptions = {};
                for(var i in Options) {
                    var opt_id = Options[i].getId();
                    selectOptions[opt_id] = Options[i].getText()
                }
                field_details['Options'] =  selectOptions;
            }
            requiredFields[id]=field_details;
        }
    });
    return requiredFields;
 }​

Sunday, 20 November 2016

Netsuite Procure To Pay Process

Procure to Pay

NetSuite streamlines the entire procure to pay process, with employee self-service, approval, management, matching, receiving, payments, and through various reportings. Ensuring a seamless linkage across employee, procurement and finance processes.  





  • PO Entry : NetSuite web base self service makes easy for employees to manage expenses time tracking purchase requisitions and more and just a few clicks employees can create purchase orders. 
  • Approval : NetSuite insurance that purchase orders are in complaint with corporate policy’s and are sent to the real time right to manager for approval. Mangers can review the detail PO approve or rejected and NetSuite will rap the PO appropriately based on the work flow. 
  • Item Receipt : On receipt on the bill NetSuite makes it easy to locate and manage purchase order that was previously created, approved, and received. 
  • Matching : When orders are received without a PA belt, NetSuite minimizes the risk of error by automatically populating the bill screen with data from centralize customer records that could be matched against for accuracy.  
  • AP Bill Approval : Once the AP billing information was been added NetSuite powerful work flow engine makes it easy to set up a approval requirements that eliminates unnecessary spending while enforcing company policy’s and then raps bills to the appropriate approvals. 
  • AP Bill Aging : Approve bills are automatically posted to the AP sub ledgers and general ledger where finance managers can efficiently drill in to reliable aging details provided by Netsuits complete purchasing audit trail. 
  • Bill Payments : To help reduce cost and maintain strong vendors’ relationships NetSuite lets manager set up alerts that insurance bills by their due dates and within discount allowances. NetSuite provides a clear perspective on spending from the purchase order all the way through to vendor record where contact information, schedule activities, message history, and all associated transaction with the vendor are available in one convenient location.
  • Summary : NetSuite Integrates employee, procurement and finance processes and provide complete transparency and control over the entire purchasing process. From PO entry and approval through to receiving to accounts payable. NetSuite ensures a stream line and more effective process while ensuring checks and balances and visibility throughout the process.
  • Tuesday, 27 September 2016

    Publish Search in Site Builder site

    NetSuite customer support assisted me on this and showed me how to get it to work. The steps are:
    1.Check "Display in Web Store" on item records
    2.Change the layout of the Published Saved search to "Standard Dense List Layout"
    3.If needed customize the layout: Setup > Site Builder > Layouts

    Thanks to NetSuite for the assistance here!​​ :)

    Monday, 19 September 2016

    Restricting item to Purchase only

    The scenario was basically where some of the Inventory Item were needed to be restricted to the Purchase Order only and should not appear on the Sales Order.​


    To solve this problem you can add an item filter on a custom sales order form. You need to create a saved search first and then add the search as an item filter.

    Please follow the steps below:
    A. Create a saved item search
    1. Navigate to Lists > Search > Saved Searches > New > Item
    2. Under Criteria subtab, add the required filters.
    3. Under Results subtab, add or remove fields depending on your preference.
    4. Enter a Search Title.
    5. Hit Save.

    B. Add the item filter on custom sales order form
    1. Open the sales order form to be customized.
    2. Navigate to Screen fields > Columns.
    3. Under Item Filter dropdown, select the item saved search you want to determine which items are shown in the Items dropdown on this transaction form.
    4. Hit Save.
    ​​​

    You can also consider using Non-Inventory for Purchase if you don't really intend to sell them.

    If you are creating new inventory items, under the Accounting tab, just leave the Income Account blank to prevent the items from showing up on sales transactions.

    Saturday, 17 September 2016

    Common Netsuite Interview Questions

    What is a Lead and how they are captured in Netsuite ?

    In Accounting a Lead is nothing but an identification of a person or entity that has the interest and authority to purchase a product or service. In Netsuite "Lead" is a standard record object which has several predefined fields to capture the Lead information. 

    What is Lead Generation Process ?

    Lead Generation is the initiation of consumer interest or inquiry into products or services of a business.

    How Leads are converted in Netsuite ?
                               Or
    What is the Lead conversion process in Netsuite ?

    There are two ways a lead can be converted to a prospect or customer in NetSuite:

    If an opportunity, estimate, or sales transaction is entered for the lead, it is automatically converted according to the default statuses you have set up at Setup – Sales – Preferences – Sales Preferences.

    If you use the Lead Conversion feature, you can click the Convert button on the lead record. Converting a lead in this way gives you additional options on which records are created or updated. This is commonly used flow by business-to-consumer, or B2C, sales organizations.

    How does Procure to pay Process works in Netsuite ?

    Netsuite Procure to Pay Process involves the following steps :

    Purchase Order Entry => Purchase Order Approval => Receiving => Matching => Bill Approval


    What is Lead to Cash Process in Netsuite ?

    Lead => Opportunity => Quote => Order => Fulfill => Invoice => Billing

    What is Purchase Order Cycle in Netsuite ?


    PR/PO => Recieving => Update Inventory => Enter Bills => Bills Payment => Accounting Posting

    What is Suitescript ?


    SuiteScript is a JavaScript-based API that gives developers the ability to extend NetSuite beyond the capabilities provided through SuiteBuilder point-and-click customization.
    How do I run a script in NetSuite?
    The overall process for getting a script to run in NetSuite is fairly basic. This process includes:
    1.    Creating a JavaScript file for your script.
    2.    Uploading the file into NetSuite.
    3.    Creating a NetSuite “Script” record for your script.
    4.     Defining script runtime options on a NetSuite Script Deployment page.


    What are the different types of Scripts in Netsuite and How they are used ?


    ·         User Event Scripts: User Event scripts are triggered when users work with records and data changes in NetSuite as they create, open, update, or save records. User Event scripts are useful for customizing the workflow and association between your NetSuite entry forms. These scripts can also be used for doing additional processing before records are entered or for validating entries based on other data in the system.
    ·         Suitelets: Suitelets enable the creation of dynamic web content. Suitelets can be used to implement custom front and backends. Through API support for scripting forms and lists, these Suitelets can also be used to build NetSuite-looking pages. NetSuite tasklinks can be created to launch a Suitelet. These tasklinks can be used to customize existing centers.
    ·         RESTlets: RESTlets are server-side scripts that can be used to define custom, RESTful integrations to NetSuite. RESTlets follow the principles of the REST architectural style and use HTTP verbs, HTTP headers, HTTP status codes, URLs, and standard data formats. They operate in a request-response model, and an HTTP request to a system-generated URL invokes each RESTlet.
    ·         Scheduled Scripts: Scheduled scripts are executed on-demand in real-time or via a user-configurable schedule. Scheduled scripts are useful for batch processing of records.
    ·         Client Scripts: Client scripts are executed on the client. These scripts can be attached to and run on individual forms, or they can be deployed globally and executed on entity and transaction record types. Global client scripts enable centralized management of scripts that can be applied to an entire record type.
    ·         Portlet Scripts: Portlet scripts are used to create custom dashboard portlets. For example, you can use SuiteScript to create a portlet that is populated on-the-fly with company messages based on data within the system.
    ·         Mass Update Scripts: Mass update scripts allows you to programmatically perform custom mass updates to update fields that are not available through general mass updates. You can also use action scripts to run complex calculations, as defined in your script, across many records.
    ·         Workflow Action Scripts: Workflow action scripts allow you to create custom actions that are defined on a record in a workflow.
    ·         Bundle Installation Scripts: Bundle installation scripts fire triggers that execute as part of bundle installation, update, or uninstall. Trigger execution can occur either before install, after install, before update, after update, or before uninstall. These triggers automatically complete required setup, configuration, and data management tasks for the bundle.

    Common Netsuite Interview Questions II