Saturday 27 July 2019

How to access Sublist using Workflows ?

Accessing Sublist using workflows is pretty much possible using Suiteflow. 

As per the draft version from release notes of 2019.2 is :
 you can set the following workflow actions to execute on supported sublists:

■ Return User Error
■ Set Field Value
■ Set Field Display Type

This enhancement increases the functionality on sublists and allows for greater customization of workflows. For an overview of SuiteFlow actions, including action properties, triggers, and conditions, see the help topic Workflow Actions.
To set an action to execute on a sublist, in a workflow, select the state that you want to add the action to. Click the New Action icon in the context panel. In the New Action window, click an action. In the Triggering Client Fields section of the Workflow Action window, choose Sublist, and complete the parameters and conditions section of the action. When you are done entering the action details, click Save. For more information, see the help topic Creating an Action.

For more details, please download the release notes from SuiteAnswers.

Tuesday 23 July 2019

how to implement Token based authentication in NetSuite ?


Token Based Authentication in NetSuite:


NetSuite supports token-based authentication (TBA) a robust, industry standard-based mechanism that increases overall system security. 

This authentication mechanism enables client applications to use a token to access NetSuite through APIs, eliminating the need for RESTlets or web services integrations to store user credentials.

Tokens can be used instead of usernames and passwords.

Benefits of  using the TBA:

     -  Safer and Easier to manage.
2         -  Programmatically can create Tokens.
3         - Password rotation policies don’t apply to Tokens, like if any password that is expired then you  don’t               need to worry about it

.Below are the steps which needs to be followed to setup TBA in NetSuite:

1             
        -  Enable the Token Based Authentication feature in NetSuite.
2      -  Setup the TBA roles with permissions.
3      -  Assign the TBA Roles to the users.
4      -  Setup applications for Token based authentications.
5      -  Create User Tokens.

Here is how to implement in detail:

      -  Enable the Token Based Authentication feature in NetSuite.

N 1. Navigate to Enable Features page: 
s     Setup -> Company -> Enable Features:
       
      Under Suite cloud Tab -> Under Manage Authentication Section -> Select "Token Based Authentication.
     It will as you to take action on "Terms of Service" , select "I agree" button. Then click on save button.


2. Setup the TBA roles with permissions.

Once the service is enabled, we can assign below Token-based Authentication Permissions to any role: (Except Administrator)

Access Token Management
  • Users (Non Administrator role) with this role can create and revoke access tokens for user with TBA role enabled. 
  • A user who doesn't have "Administrator" role cannot create tokens for administrator.
  • Cannot create access for their own use.
  • Cannot use access tokens to login through RESTLets or WebServices.     


       User Access Tokens
  •  Users with this permission can manage their own tokens using the Manage Access Tokens link in the Settings portlet, and they can log in using a token.
  • Users can use access to login through RESTLets or WebServices.
Log in using Access Tokens
  • Users with only this permission can log in using a token, that is, they can to use tokens to call a RESTlet.
  • Cannot create their own access tokens through a link in the Settings portlet, or by calling the token endpoint.
Create a new Role and assign TBA permissions to it:

Go to Setup -> Users/ Roles - > Manage Roles -> New

Go to the role in create/Edit mode, Under Permissions Tab: Select the any of the TBA permissions as per the requirement and save the role.



Assign the TBA Roles to the users:

Now, after creating the role, then go to the employee record to whom you want assign, 
Lists -> Employees -> List -> Select the employee (Select New if you want to create):

In Access Subtab - > Roles -> Add the newly created role, and save the employee record.



Setup applications for Token based authentications.

             We can see all the Integration applications in the below navigation:
              Setup -> Integrations -> Manage Integrations -> List (we can see all the 3rd party integration applications list)

           For our test, we are creating new Integration, like below:

If the State is Enabled means:  if you want to permit connections from the external application represented by this integration record. 

If the State is Blocked means : if you want to prevent such connections.

Click on the Token-Based Authentication check box under "Authentication" subtab and save the integration record.



Once the Integration is saved then the "Application ID" will be generated automatically.

And under "Authentication" section, We can see "Consumer Key" and "Consumer Secret".

For Security reasons the Consumer key/Secret displays only one time. If suppose you forget the the key then you will need to reset them to obtain new values.

Create User Tokens:

We can assign user Tokens with below navigation:

               Setup -> Users/Roles -> Access Tokens -New
\
       Select the Application which needs to be integrated, then select the user (it will list the employee name who has the TBA roles), select the TBA role, Token Name field is populated with a concatenation of Application Name, User, and Role. Enter your own name for this token, if desired.

After saving this record, system will generate automatically a Token ID and Token Secret which will only displayed for one time.
            
       Creating own Tokens:
        
                 Go to Home -> Settings portlet -> Manage Token (here we can see list of the my access tokens ).





























Sunday 14 July 2019

Understand CTA report in netsuite


CTA – Report - Cumulative Translation Adjustment Report

The cumulative translation adjustment (CTA) for a currency translation adjustment is an entry in the “Accumulated Other Comprehensive Income” section of the translated balance sheet, reflecting gains and losses caused by exchange rate fluctuations over the years.

Understand CTA Account:
-          Cumulative Translation Adjustment (CTA) is a special type of account that is required for consolidated balance sheets in NetSuite OneWorld accounts with multi-currency enabled.

-          The CTA is used on the consolidated balance sheet to make it balance despite differing foreign exchange rate types.
-          In NetSuite it is configured as “Equity” type.
-          No Currency is defaulted.
-          General Rate Type – Historical, Cash flow Rate – Historical.

Understand the Exchange Rates from Consolidated Exchange Rates:

Average – This rate is calculated from a weighted average of the exchange rates for transactions applied during the period to accounts with a general rate type of Average.
Current – Also referred to as ending rate. This rate is based on the currency exchange rate that is effective at the end of the reported upon period.
Historical – This rate is calculated from a weighted average of the exchange rates for transactions applied during the period to accounts with a general rate type of Historical.
  • General Rate Type:
This General Rate Type uses in all in the income statement, balance sheet, and other general purposes.
    • Current - for all balance sheet accounts other than equity accounts
    • Average - for all income statement accounts
    • Historical - for all equity accounts
  • Cash Flow Rate Type:
This Cash Flow Rate Type uses in all Cash Flow statements.
    • Average - for all accounts
So, here the CTA account is “Equity” type, hence it has the General Rate Type as “Historical” and Cash Flow Rate Type as “Average”.

  
Example:
If a U.S.-based company wishes to operate in Germany, it must convert some of its U.S. dollars to euros for purposes of purchasing or renting property, paying employees, paying German taxes, etc. In addition, German citizens or businesses that work with this U.S.-based company will pay with euros. The company will create its financial statements in one currency, the dollar. It must convert the value of its business activities conducted in Germany with the euro back to dollars via an exchange rate.

Key points of CTA report in NetSuite:

1.       This report is available only for OneWorld accounts with the Multiple Currencies and Accounting features enabled. 
2.       The Financial Statements permission is required to access the report.
3.       The CTA Balance Audit report shows the contribution from individual accounts to the CTA during the selected period. 
4.       The rows in the CTA Balance Audit report follow the same order as the rows of the Balance Sheet.
5.       The CTA represents the cumulative foreign currency gain or loss resulting from the net investment in the subsidiary.

The CTA – Balance Audit Report has below columns:

1.       Starting Balance Sheet (As of <period>) – The period is the one before the period selected in the From field in the footer.
Local Balance – Balance of the ledger account till the period end (as per this last period end)
General Rate – Rate Type used to convert exchange rate
Consolidate Balance – This is equal to the Local Balance multiplied by the General Rate. The total in this column ties to the CTA amount in the Balance Sheet for the period before the one selected in the From field in the footer.

Example: if you are running CTA report for July month, then Starting Balance sheet shows till June End.
2.     Net Posting (<period>) – The period is the period or range of periods set in the From and To fields in the footer.
Local Balance: Current period balance (based on From and To fields)
Cash Flow Rate: It has the exchange rate value which converts based on CTA account configuration.  (in my account it is historical type)
General Rate: : It has the exchange rate value which converts based on CTA account configuration.  (in my account it is historical type)
Consolidated Balance – This is equal to the Local Balance multiplied by the General Rate.
Example : This has the current period balance based on the From and To Fields selected in the report.
Ending Balance Sheet (As of <period>) – The period is the one set in the To field in the footer.
o    Local Balance: this ledger has the last period ending balance + current period ledger balance.
o    General Rate: It has the exchange rate value which converts based on CTA account configuration.  (in my account it is historical type)
o    Consolidated Balance – This is equal to the Local Balance multiplied by the General Rate. The total in this column ties to the CTA amount in the Balance Sheet for the ending period in the range of periods.

CTA Analysis
o    Beginning Balance Rate Difference Contribution – This equals the Beginning Balance Translated at Ending Implied Rate minus Starting Balance Sheet Consolidated Balance.
o    Net Posting Rate Difference Contribution – This equals Net Posting Consolidated Balance minus Net Posting Consolidated Balance at Cash Flow Rate Contribution.
o    Net Posting Consolidated Balance at Cash Flow Rate Contribution – This equals Net Posting Local Balance multiplied by the Net Posting Cash Flow Rate.
o    Total CTA Contribution – Beginning Balance Rate Difference Contribution plus Net Posting Rate Difference Contribution plus Net Posting Consolidated Balance at Cash Flow Rate Contribution

To run the report – Go to Reports -> Financial -> click on CTA Balance Audit report.


I would like to give credits to NetSuite, for the wonderful documentation provided, it helped me a lot understand the report. For more information i would prefer, SuiteAnswers.

Thanks,
Ramu

Friday 5 July 2019

How to create a custom page (form) using suitelets ?


-          ->suitelets are extensions of the SuiteScript API that allow you to build custom NetSuite pages and backend logic.

-          ->Suitelets are server-side scripts that operate in a request-response model, and are invoked by HTTP GET or POST requests to system generated URLs.
-          Using suitelets we can create custom pages like forms, assistant pages , linked pages.
Custom Page Components:
We need to know below 4 main components before we create custom NetSuite Pages:
1.       Page Type: This determines how the information should display on the screen.
2.       Object Members: these are the elements those needs to be added to the screen.
3.       Member Properties: Each member object can be modified by changing it’s properties like hiding or making mandatory.
4.       Page Layout: This controls how each of the member objects arranged on the page.

Here is an example of creating a custom netsuite form using suitelets:

I have created an employee on boarding page, where I’m capturing some information of employee and with that I’m creating employee record, and after clicking on the submit button navigating to the employee record whose employee details are captured in on boarding kit.

Below is the sample code :

/**

 * @NApiVersion 2.x
 * @NScriptType Suitelet
 * @NModuleScope SameAccount
 */
define(['N/email', 'N/record', 'N/redirect', 'N/ui/serverWidget'],
/**
 * @param {email} email
 * @param {record} record
 * @param {redirect} redirect
 * @param {serverWidget} serverWidget
 */
function(email, record, redirect, serverWidget) {
   
    /**
     * Definition of the Suitelet script trigger point.
     *
     * @param {Object} context
     * @param {ServerRequest} context.request - Encapsulation of the incoming request
     * @param {ServerResponse} context.response - Encapsulation of the Suitelet response
     * @Since 2015.2
     */
    function onRequest(context) {
   
    var request = context.request;
    var response  = context.response;
   
    if (request.method == 'GET'  ) {
   
    // title of the page
        var form = serverWidget.createForm ({
       
        title : 'Employee On-Boarding'
        });
       
        // field Groups in the page
        var empInfo = form.addFieldGroup ({
       
        id : 'custpage_empinfo',
        label : 'Employee Information'
       
        });
       
        var meetwSup =  form.addFieldGroup ({
       
        id : 'custpage_meetwsup',
        label : 'Meeting with Supervisor'
       
        });
       
        var welEmail = form.addFieldGroup ({
       
        id : 'custpage_wecmem',
        label : 'Welcome Email',
       
        });
       
        var firstName = form.addField({
       
        id : 'custpage_firstname',
        label : 'First Name',
        type : serverWidget.FieldType.TEXT,
        container : 'custpage_empinfo'
       
        });
       
        firstName.isMandatory = true;
       
        var midlName = form.addField({
       
        id : 'custpage_middlename',
        label : 'Middle Name',
        type : serverWidget.FieldType.TEXT,
        container : 'custpage_empinfo'
       
        });
       
        var lastName = form.addField({
       
        id : 'custpage_lastname',
        label : 'Last Name',
        type : serverWidget.FieldType.TEXT,
        container : 'custpage_empinfo'
       
        });
       
        lastName.isMandatory = true;
       
        var email = form.addField({
       
        id : 'custpage_email',
        label : 'Email',
        type : serverWidget.FieldType.EMAIL,
        container : 'custpage_empinfo'
       
        });
        
        var supervisor = form.addField({
       
        id : 'custpage_supervisor',
        label : 'Supervisor',
        type : serverWidget.FieldType.SELECT,
        container : 'custpage_empinfo',
        source : 'employee'
       
        });
       
        supervisor.isMandatory = true;
       
        var subs = form.addField({
       
        id : 'custpage_subsidiary',
        label : 'Subsidiary',
        type : serverWidget.FieldType.SELECT,
        source : 'subsidiary',
        container : 'custpage_empinfo'
       
        });
       
        subs.isMandatory = true;
       
        var fldTitle = form.addField({
       
        id : 'custpage_title',
        label : 'Title',
        type : serverWidget.FieldType.TEXT,
        container : 'custpage_meetwsup'
       
        });
       
       
        fldTitle.isMandatory = true;
       
        var fldMessage = form.addField({
       
        id : 'custpage_message',
        label : 'Message',
        type : serverWidget.FieldType.TEXTAREA,
        container : 'custpage_meetwsup'
       
        });
       
        fldMessage.isMandatory = true;
       
        var fldWelTitle = form.addField({
       
        id : 'custpage_weltitle',
        label : 'Title',
        type : serverWidget.FieldType.TEXT,
        container : 'custpage_wecmem'
       
        });
       
        fldWelTitle.isMandatory = true;
       
        var fldWelMessage = form.addField({
       
        id : 'custpage_welmessage',
        label : 'Message',
        type : serverWidget.FieldType.TEXTAREA,
        container : 'custpage_wecmem'
       
        });
       
        fldWelMessage.isMandatory = true;
       
        // update the page layout
        firstName.updateBreakType({
        breakType : serverWidget.FieldBreakType.STARTCOL
        });
       
        midlName.updateBreakType({
        breakType : serverWidget.FieldBreakType.STARTROW
        });
       
        lastName.updateBreakType({
        breakType : serverWidget.FieldBreakType.STARTROW
    });
       
//update the field display type
        midlName.updateDisplaySize({
        height : 0,
        width : 10
        });
       
        fldMessage.updateDisplaySize({
        height : 12,
        width : 60
        });
       
        fldWelMessage.updateDisplaySize({
        height : 12,
        width : 60
        });
           
        email.updateBreakType({
        breakType : serverWidget.FieldBreakType.STARTCOL
        });
       

        fldTitle.defaultValue = 'Welcome meeting with your Supervisor';
        fldMessage.defaultValue = 'Meet and Greet your supervisor and Team';
       
        fldWelTitle.defaultValue = 'Welcome to smartERP!';
        fldWelMessage.defaultValue = "Hi,"+'\n'+'\n'+"We'd like to welcome you to smartERP. Please feel to reachout us to any questions."+'\n'+'\n'+'Best Regards,'+'\n'+'smartERP HR';

        var button = form.addSubmitButton({
        label : 'Process Employee Details'
        });
       
        context.response.writePage(form);
    } else { // POST method
    // get the field details and store on variables
    var fName = request.parameters.custpage_firstname;
    var mName = request.parameters.custpage_middlename;
    var lName = request.parameters.custpage_lastname;
    var empEmail = request.parameters.custpage_email;
    var sprvsr = request.parameters.custpage_supervisor;
    var subs = request.parameters.custpage_subsidiary;
   
// Create the employee record using the above parameters
    var employeeObj = record.create({
   
    type : record.Type.EMPLOYEE,
    isDynamic : true,
   
    });
   
    employeeObj.setValue('firstname', fName);
    employeeObj.setValue('lastname', lName);
    employeeObj.setValue('email', empEmail);
    employeeObj.setValue('supervisor', sprvsr);
    employeeObj.setValue('subsidiary', subs);
   
// save the employee record
    var empID = employeeObj.save();
   
//go to the employee record which is created.
    redirect.toRecord ({
   
    type : record.Type.EMPLOYEE,
    id   : empID,
    isEditMode : true
    });
    }
   
    }

    return {
        onRequest: onRequest
    };
    
});

Before Submitting :
: