Logic for Custom Tax calculation

Cretee a UserEvent Script

Eg: jj_ue_Custom_Tax_Calculation_RSPDC-1361.js

/**

 * @NApiVersion 2.1

 * @NScriptType UserEventScript

 */

define([‘N/record’],

    /**

 * @param{record} record

 */

    (record) => {

        /**

         * Defines the function definition that is executed before record is loaded.

         * @param {Object} scriptContext

         * @param {Record} scriptContext.newRecord – New record

         * @param {string} scriptContext.type – Trigger type; use values from the context.UserEventType enum

         * @param {Form} scriptContext.form – Current form

         * @param {ServletRequest} scriptContext.request – HTTP request information sent from the browser for a client action only.

         * @since 2015.2

         */

        const beforeLoad = (scriptContext) => {

          let newRecord = scriptContext.newRecord;

          let recordType=newRecord.type;

          // log.debug(“recordType”,recordType);

          if(recordType===“customrecord_jj_proforma_invoices”){

            if (scriptContext.type == scriptContext.UserEventType.EDIT) {

              let form = scriptContext.form;

              form.addButton({

                  id: ‘custpage_jj_create_project’,

                  label: ‘Preview Tax’,

                  functionName: ‘previewTaxDetails’

              });

              log.debug(“Button Added”)

              form.clientScriptModulePath = ‘./jj_cs_populate_tax_details_RSPDC-1361.js’;

              log.debug(“Client Script Caalled”);

          }

        }

        }

        /**

         * Defines the function definition that is executed before record is submitted.

         * @param {Object} scriptContext

         * @param {Record} scriptContext.newRecord – New record

         * @param {Record} scriptContext.oldRecord – Old record

         * @param {string} scriptContext.type – Trigger type; use values from the context.UserEventType enum

         * @since 2015.2

         */

        function beforeSubmit(context) {

          var newRecord = context.newRecord;

          let recordType=newRecord.type;

          if (context.type !== context.UserEventType.CREATE && context.type !== context.UserEventType.EDIT) {

            return;

        }

          // Get the customer ID from the transaction record

          if(recordType===‘invoice’){

            var placeofSupply = newRecord.getValue({ fieldId: ‘custbody_in_gst_pos’ });

            log.debug(“placeofSupply”,placeofSupply);

            var customerId = newRecord.getValue({ fieldId: ‘entity’ });

            if (customerId) {

                // Load customer record to check SIZ (SEZ) checkbox

                var customerRecord = record.load({

                    type: record.Type.CUSTOMER,

                    id: customerId

                });

                // Check if the SIZ checkbox is enabled

                var isSEZ = customerRecord.getValue({ fieldId: ‘custentity_jj_siz’ });

                var custSubsidiary = customerRecord.getValue({ fieldId: ‘subsidiary’ });

                log.debug(“custSubsidiary”,custSubsidiary);

                log.debug(“isSEZ”,isSEZ);

                if (isSEZ) {

                    // If SEZ is checked, set all tax-related fields to zero

                    var lineCount = newRecord.getLineCount({ sublistId: ‘item’ });

                    log.debug(“lineCount”,lineCount);

                    // Iterate through each tax detail line

                    for (var i = 0; i < lineCount; i++) {

                        // Set tax rate to 0% for each line

                        log.debug(“For loop Started”)

                        newRecord.setSublistValue({

                            sublistId: ‘item’,

                            fieldId: ‘custcol_in_hsn_code’,  // Assuming ‘taxrate’ is the correct field ID

                            line: i,

                            value:        // Setting the tax rate to 0%

                        });

                    }

                }

            }

          }

      }

        /**

         * Defines the function definition that is executed after record is submitted.

         * @param {Object} scriptContext

         * @param {Record} scriptContext.newRecord – New record

         * @param {Record} scriptContext.oldRecord – Old record

         * @param {string} scriptContext.type – Trigger type; use values from the context.UserEventType enum

         * @since 2015.2

         */

        const afterSubmit = (scriptContext) => {

        }

        return {beforeLoad, beforeSubmit, afterSubmit}

    });

Create A Client Script

Eg: jj_cs_populate_tax_details_RSPDC-1361.js

/**

 * @NApiVersion 2.1

 * @NScriptType ClientScript

 * @NModuleScope SameAccount

 */

define([‘N/search’, ‘N/record’, ‘N/ui/message’, ‘N/log’], function (search, record, message, log) {

  /**

   * Save record function for regular save logic

   * @param {Object} context – Script context

   * @returns {boolean} – Return true to continue saving

   */

  function saveRecord(context) {

    return true;

  }

  /**

   * Preview the tax details by removing existing lines and adding new tax details

   */

  function previewTaxDetails() {

    let currentRecord = getCurrentRecord();

    if (currentRecord) {

      let recordType = currentRecord.type;

      if (recordType === “customrecord_jj_proforma_invoices”) {

        let sublist = ‘recmachcustrecord_jj_proforma_invoices_items’;

        let taxSublist = ‘recmachcustrecord_jj_tax_details_new’;

        try {

          removeExistingTaxLines(currentRecord, taxSublist);

          addTaxDetails(currentRecord, sublist, taxSublist);

          message.create({

            title: “Tax Preview”,

            message: “Tax details have been previewed successfully!”,

            type: message.Type.CONFIRMATION

          }).show();

        } catch (error) {

          log.error(‘Error in previewTaxDetails’, error);

        }

      }

    }

  }

  /**

   * Get the current record object

   * @returns {Object} – Current record object

   */

  function getCurrentRecord() {

    try {

      let currentRecord = require(‘N/currentRecord’).get();

      return currentRecord;

    } catch (error) {

      log.error(‘Error in getCurrentRecord’, error);

    }

    return null;

  }

  /**

   * Remove all existing tax lines from the tax sublist

   * @param {Object} currentRecord – The current record object

   * @param {string} taxSublist – The tax sublist ID

   */

  function removeExistingTaxLines(currentRecord, taxSublist) {

    try {

      let taxLineCount = currentRecord.getLineCount({ sublistId: taxSublist });

      if (taxLineCount > 0) {

        for (let j = taxLineCount 1; j >= 0; j) {

          currentRecord.removeLine({

            sublistId: taxSublist,

            line: j,

            ignoreRecalc: true

          });

        }

      }

    } catch (error) {

      log.error(‘Error in removeExistingTaxLines’, error);

    }

  }

  /**

   * Add new tax details to the tax sublist based on the items in the invoice sublist

   * @param {Object} currentRecord – The current record object

   * @param {string} sublist – The invoice sublist ID

   * @param {string} taxSublist – The tax sublist ID

   */

  function addTaxDetails(currentRecord, sublist, taxSublist) {

    try {

      let lineCount = currentRecord.getLineCount({ sublistId: sublist });

      let nexusProforma = currentRecord.getValue({ fieldId: “custrecord_jj_nexus” });

      log.debug(“nexusProforma”, nexusProforma);

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

        let itemData = getItemData(currentRecord, sublist, i);

        let customerRecord = getCustomerRecord(itemData.customerID);

        let subsidiaryRecord = getSubsidiaryRecord(customerRecord.getValue({ fieldId: ‘subsidiary’ }));

        let transactionId = getTransactionId(

          subsidiaryRecord.getText({ fieldId: ‘dropdownstate’ }).toLowerCase(),

          itemData.placeOfSupply.split(‘-‘)[1].trim().toLowerCase()

        );

        let regType = getSubsidiaryRegType(subsidiaryRecord, nexusProforma);

        let gstTaxRules = getGSTTaxRules(regType, itemData, customerRecord, transactionId);

        gstTaxRules.run().each(function (result) {

          addTaxLine(currentRecord, taxSublist, itemData, result);

          return true;

        });

      }

    } catch (error) {

      log.error(‘Error in addTaxDetails’, error);

    }

  }

  /**

   * Retrieve item data from the invoice sublist

   * @param {Object} currentRecord – The current record object

   * @param {string} sublist – The sublist ID

   * @param {number} index – Line index

   * @returns {Object} – Item data object

   */

  function getItemData(currentRecord, sublist, index) {

    try {

      let itemId = currentRecord.getSublistValue({ sublistId: sublist, fieldId: ‘custrecord_jj_line_item_items’, line: index });

      let itemnameText = currentRecord.getSublistText({ sublistId: sublist, fieldId: ‘custrecord_jj_line_item_items’, line: index });

      let hsnSacCodeID = currentRecord.getSublistValue({ sublistId: sublist, fieldId: ‘custrecord_jj_tax_hsn_sac_code’, line: index });

      let lineAmount = currentRecord.getSublistValue({ sublistId: sublist, fieldId: ‘custrecord_jj_line_item_amount’, line: index });

      let placeOfSupply = currentRecord.getText({ fieldId: ‘custrecord_jj_place_of_supply’ });

      let customerID = currentRecord.getValue({ fieldId: ‘custrecord_jj_entity’ });

      return { itemId, itemnameText, hsnSacCodeID, lineAmount, placeOfSupply, customerID };

    } catch (error) {

      log.error(‘Error in getItemData’, error);

    }

    return null;

  }

  /**

   * Load the customer record by customer ID

   * @param {number} customerID – The customer ID

   * @returns {Object} – Customer record object

   */

  function getCustomerRecord(customerID) {

    try {

      return record.load({

        type: record.Type.CUSTOMER,

        id: customerID

      });

    } catch (error) {

      log.error(‘Error in getCustomerRecord’, error);

    }

    return null;

  }

  /**

   * Load the subsidiary record by subsidiary ID

   * @param {number} subsidiaryId – The subsidiary ID

   * @returns {Object} – Subsidiary record object

   */

  function getSubsidiaryRecord(subsidiaryId) {

    try {

      return record.load({

        type: ‘subsidiary’,

        id: subsidiaryId

      });

    } catch (error) {

      log.error(‘Error in getSubsidiaryRecord’, error);

    }

    return null;

  }

  /**

   * Get transaction ID based on state comparison

   * @param {string} subsidiaryState – Subsidiary state

   * @param {string} placeOfSupplyState – Place of supply state

   * @returns {number} – Transaction ID

   */

  function getTransactionId(subsidiaryState, placeOfSupplyState) {

    try {

      return (subsidiaryState === placeOfSupplyState) ? 1 : 2;

    } catch (error) {

      log.error(‘Error in getTransactionId’, error);

    }

    return null;

  }

  /**

   * Retrieve the GST registration type for the subsidiary

   * @param {Object} subsidiaryRecord – Subsidiary record object

   * @param {string} nexusProforma – Nexus ID for the proforma invoice

   * @returns {string|null} – Registration type

   */

  function getSubsidiaryRegType(subsidiaryRecord, nexusProforma) {

    try {

      let subListId = ‘taxregistration’;

      let lineCount = subsidiaryRecord.getLineCount({ sublistId: subListId });

      for (let k = 0; k < lineCount; k++) {

        let nexusLine = subsidiaryRecord.getSublistValue({ sublistId: subListId, fieldId: ‘nexus’, line: k });

        if (nexusProforma == nexusLine) {

          return subsidiaryRecord.getSublistValue({ sublistId: subListId, fieldId: ‘custpage_in_reg_type’, line: k });

        }

      }

    } catch (error) {

      log.error(‘Error in getSubsidiaryRegType’, error);

    }

    return null;

  }

  /**

   * Retrieve GST tax rules based on item data and customer details

   * @param {string} regType – Registration type

   * @param {Object} itemData – Item data object

   * @param {Object} customerRecord – Customer record object

   * @param {number} transactionId – Transaction ID

   * @returns {Object} – Search object for GST tax rules

   */

  function getGSTTaxRules(regType, itemData, customerRecord, transactionId) {

    try {

      return search.create({

        type: “customrecord_in_gst_tax_rate_rule”,

        filters: [

          [“custrecord_in_gst_rate_rule_com_reg_type”, “anyof”, regType],

          “AND”,

          [“custrecord_in_gst_rate_rule_available_on”, “anyof”, “2”],

          “AND”,

          [“custrecord_in_gst_rate_rule_vend_regtype”, “anyof”, customerRecord.getValue({ fieldId: ‘custentity_in_gst_vendor_regist_type’ })],

          “AND”,

          [“custrecord_in_gst_rate_rule_hsn_code”, “anyof”, itemData.hsnSacCodeID],

          “AND”,

          [“custrecord_in_gst_rate_rule_supply_class”, “anyof”, transactionId],

          “AND”,

          [“custrecord_in_gst_rate_rule_taxable”, “is”, “T”]

        ],

        columns: [

          search.createColumn({ name: “custrecord_in_gst_rate_rule_rate”, label: “GST Rate” }),

          search.createColumn({ name: “custrecord_in_gst_rate_rule_tax_type”, join: “CUSTRECORD_IN_GST_RATE_RULE_FK”, label: “Tax Type” }),

          search.createColumn({ name: “custrecord_in_gst_rate_rule_tax_code”, join: “CUSTRECORD_IN_GST_RATE_RULE_FK”, label: “Tax Code” }),

          search.createColumn({ name: “custrecord_in_gst_rate_rule_tax_rate”, join: “CUSTRECORD_IN_GST_RATE_RULE_FK”, label: “Tax Rate” })

        ]

      });

    } catch (error) {

      log.error(‘Error in getGSTTaxRules’, error);

    }

    return null;

  }

  /**

   * Add a new tax line to the tax sublist

   * @param {Object} currentRecord – The current record object

   * @param {string} taxSublist – The tax sublist ID

   * @param {Object} itemData – Item data object

   * @param {Object} result – Tax rule search result

   */

  function addTaxLine(currentRecord, taxSublist, itemData, result) {

    try {

      let taxRate = parseFloat(result.getValue({ name: “custrecord_in_gst_rate_rule_tax_rate”, join: “CUSTRECORD_IN_GST_RATE_RULE_FK” }).replace(‘%’, )).toFixed(0);

      let taxAmount = (itemData.lineAmount * taxRate) / 100;

      currentRecord.selectNewLine({ sublistId: taxSublist });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_line_type’,

        value: ‘Item’,

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_name_tax’,

        value: itemData.itemnameText,

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_net_amount’,

        value: itemData.lineAmount,

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_tax_type’,

        value: result.getValue({ name: “custrecord_in_gst_rate_rule_tax_type”, join: “CUSTRECORD_IN_GST_RATE_RULE_FK” }),

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_tax_code’,

        value: result.getValue({ name: “custrecord_in_gst_rate_rule_tax_code”, join: “CUSTRECORD_IN_GST_RATE_RULE_FK” }),

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_tax_basis’,

        value: itemData.lineAmount,

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_tax_rate’,

        value: taxRate,

        ignoreFieldChange: true

      });

      currentRecord.setCurrentSublistValue({

        sublistId: taxSublist,

        fieldId: ‘custrecord_jj_tax_amount’,

        value: taxAmount,

        ignoreFieldChange: true

      });

      currentRecord.commitLine({ sublistId: taxSublist });

    } catch (error) {

      log.error(‘Error in addTaxLine’, error);

    }

  }

  return {

    saveRecord: saveRecord,

    previewTaxDetails: previewTaxDetails

  };

});

Modify the Code According to your Requiremnt if needed

Deploy the user event Script in the respective Record.

Leave a comment

Your email address will not be published. Required fields are marked *