22 Tax Calculation Opcode Workflows

Learn about the Oracle Communications Billing and Revenue Management (BRM) tax calculation opcode workflows.

Topics in this document:

Opcodes Described in This Chapter

Table 22-1 lists the opcodes described in this chapter.

Caution:

  • Always use the BRM API to manipulate data. Changing data in the database without using the API can corrupt the data.

  • Do not use SQL commands to change data in the database. Always use the API.

Calculating Taxes during Billing

Taxes are calculated during rating and during billing. During rating, taxes are calculated by ECE. You can customize tax calculation in rating by using ECE extensions.

To calculate taxes during billing,

  1. For each rated event, PCM_OP_RATE_EVENT reads the PIN_FLD_RATES_USED array in the input flist to determine what pricing to apply. This pricing information determines how the taxable amount is treated.

  2. PCM_OP_RATE_EVENT calls PCM_OP_RATE_POL_TAX_LOC to determine whether custom processing or default processing is used to determine the tax-related locales.

    • If default processing is used, PCM_OP_RATE_EVENT retrieves the locales from the database.

    • If custom processing is used, control is handed to PCM_OP_RATE_POL_TAX_LOC, which determines which locales to use.

    The locales are used during the tax calculation process to determine jurisdiction. BRM stores up to four tax locales for the current account, session, and event.

    See "Retrieving Tax Location Data" for more information on the tax locales and how to customize their retrieval.

  3. PCM_OP_RATE_EVENT also checks the PIN_FLD_EXEMPTIONS array in /account objects to determine whether all or part of the purchase amount is exempt from taxes.

  4. PCM_OP_RATE_EVENT returns a revised set of objects for the event. This can include PIN_FLD_TAXES and PIN_FLD_EXEMPTIONS arrays to indicate tax amounts that were calculated immediately by PCM_OP_RATE_TAX_CALC.

  5. The event is taxable, PCM_OP_RATE_EVENT calls PCM_OP_BILL_CYCLE_TAX. If the event is nontaxable, PCM_OP_RATE_EVENT does nothing.

  6. If a transaction is not already open, PCM_OP_BILL_CYCLE_TAX opens one.

    If PCM_OPFLG_CALC_ONLY is set, the transaction is opened with the flag PCM_TRANS_OPEN_READONLY.

  7. PCM_OP_BILL_CYCLE_TAX calls PCM_OP_RATE_TAX_CALC to perform the actual tax calculation. See "How PCM_OP_RATE_TAX_CALC Calculates Taxes" for information.

  8. PCM_OP_BILL_CYCLE_TAX receives the tax data from PCM_OP_RATE_TAX_CALC in the PIN_FLD_TAXES array.

  9. PCM_OP_BILL_CYCLE_TAX does one of the following:

    • Creates an /event/billing/cycle/tax object with the taxable amount if there were any deferred taxes.

    • If PCM_OP_BILL_CYCLE_TAX was called with the PCM_OPFLG_CALC_ONLY flag set, it still performs the tax calculation but does not create the /event/billing/cycle/tax object.

      Instead, the PCM_OP_BILL_CYCLE_TAX output flist contains the PIN_FLD_RESULTS array, an flist with the information that would have been used to create the /event/billing/cycle/tax object.

  10. PCM_OP_BILL_CYCLE_TAX sets the /event/billing/cycle/tax object status to inactive.

  11. PCM_OP_BILL_CYCLE_TAX commits the transaction if one was opened.

How PCM_OP_RATE_TAX_CALC Calculates Taxes

PCM_OP_RATE_TAX_CALC determines the taxation Data Manager (DM) or custom taxation method to be used for an event. It sends the input flist to the DM or the custom tax calculation method for calculation. It receives the information it needs to calculate taxes from the following input fields:

  • The tax code of the BRM charge offer mapped to a charge offer code that is recognized by the taxation software. The tax code also identifies the taxation DM or the custom tax calculation method to be used.

  • The purchase amount to be taxed from the PIN_FLD_TAXES array. Each element of the PIN_FLD_TAXES array represents a separate tax calculation method.

    Note:

    If the tax calculation software or custom policy is not specified in the tax code, taxes are not calculated.

  • The locations that are involved in the transaction to be taxed. This includes ship-from, ship-to, order origin, and order accept addresses for sales and use taxation.

    Note:

    For telecommunications taxation, the address fields contain additional information (NPA-NXX or geocodes) for origin, termination, and charge-to numbers.

  • The date and time of the transaction from the PIN_FLD_START_T and PIN_FLD_END_T fields. PIN_FLD_START_T is used to compute PIN_FLD_ELAPSED_TIME or duration (that is, the difference between the end time and start time).

  • Tax exemption information, including exemption information based on tax jurisdiction, from the PIN_FLD_EXEMPTIONS array.

  • The tax supplier ID from the PIN_FLD_TAX_SUPPLIER field.

  • Other optional values such as the account's bill object in the PIN_FLD_BILL_OBJ field and telecommunications values such as incorporated, residence, and regulated flags.

PCM_OP_RATE_TAX_CALC checks for the following errors:

  • Missing or nonvalid PIN_FLD_TAX_CODE field.

  • Nonvalid PIN_FLD_TAXPKG_TYPE field, which is derived from PIN_FLD_TAX_CODE field and the taxcodes_map file.

  • Missing or nonvalid tax database entry.

PCM_OP_RATE_TAX_CALC returns an output flist with a revised PIN_FLD_TAXES array containing the tax data that the tax calculation software or the custom tax calculation method returns. The calculated taxes are sorted by jurisdiction.

If the PCM_OPFLG_CALC_ONLY flag is set, PCM_OP_RATE_TAX_CALC performs the tax calculation and returns the tax rate and amount. The tax data is not written to the database, however.

How PCM_OP_RATE_TAX_CALC Validates Addresses and VAT Certificates

You can call PCM_OP_RATE_TAX_CALC in jurisdiction-check-only mode during account creation to perform address or VAT certificate number validation. You specify jurisdiction-check-only mode by using the PIN_FLD_COMMAND input field. The following modes are supported:

  • If PIN_FLD_COMMAND is set to 1, it sends an address to the taxation DM for verification and additionally returns the geocode and county information in the PIN_FLD_NAMEINFO array if the address was successfully validated.

  • If PIN_FLD_COMMAND is set to 2, it sends a VAT certificate number to the tax DM for validation.

    Note:

    The VAT certificate number validation is supported only for a custom tax calculation implementation. It is not supported by the default BRM tax calculation functions.

In jurisdiction-check-only mode, PCM_OP_RATE_TAX_CALC returns 1 if the jurisdiction is valid and 0 if it is not.

Policy Opcodes Called by PCM_OP_RATE_TAX_CALC

PCM_OP_RATE_TAX_CALC calls the following policy opcodes that you can customize to modify the tax data or to use custom tax calculation:

Modifying Tax Data Before Calculating Taxes

Use PCM_OP_RATE_POL_PRE_TAX to modify data before you send the data to the taxation DM for calculating taxes.

This opcode is called by PCM_OP_RATE_TAX_CALC before determining the tax package to use for tax calculation.

By default, PCM_OP_RATE_POL_PRE_TAX returns the input flist as the output flist. You can customize the opcode to perform these functions:

  • Identify the geocode for an address and provide it to the taxation DM.

  • Add a tax exemption to the input flist before sending the flist to the taxation DM.

  • Change the tax exemption from a percentage to a set amount. For example, deduct x amount from the taxable amount because the first x amount is exempt from taxes.

In addition, the opcode source file contains commented code for enhancements available to Vertex Communications Tax Q Series users.

Customizing Vertex Communications Tax Q Series to Override ZIP Codes

For Vertex Communications Tax Q Series, the PCM_OP_RATE_POL_PRE_TAX policy source file contains commented code to instruct the Vertex Communications Tax Q Series taxation software to override the ZIP code. This enables the Vertex DM to charge taxes for nontelephony events by using Vertex Communications Tax Q Series.

To customize Vertex Communications Tax Q Series to override ZIP codes:

  1. Open the PCM_OP_RATE_POL_PRE_TAX policy source file with a text editor.

  2. Uncomment the code.

  3. Define the OVERRIDE_BY_ZIP symbol.

  4. Save and close the file.

  5. Recompile the opcode.

Customizing Vertex Communications Tax Q Series to Provide Custom Input Tax Data

For Communications Tax Q Series, you can modify PCM_OP_RATE_POL_PRE_TAX source code to use a customized input flist to the taxation DM for tax data. The taxation DM checks the input flist. If it includes the PIN_FLD_STATUS_FLAGS field with the value 1, the DM sets all custom fields included in the flist and then calls the tax package to calculate taxes.

Note:

When you create the customized flist, make sure that you express the field values on the basis of Vertex field data types. Add the correct data type and value for each Vertex attribute that you want to customize. To see your customized flist, you can use PIN_ERR_LOG_FLIST in debug mode.

To customize PCM_OP_RATE_POL_PRE_TAX:

  1. Open BRM_SDK_home/source/sys/fm_rate_pol/fm_rate_pol_pre_tax.c file.

  2. Add the code from "Source Code for Customizing PCM_OP_RATE_POL_PRE_TAX" to the fm_rate_pol_pre_tax() function after the OVERRIDE_BY_ZIP section.

  3. Add optional fields to customize the tax calculation process (the source code includes a comment about how to add new fields).

  4. Define the USE_VERTEX_Q_SERIES symbol.

  5. Add stda.h and ctqa.h to the Include section of the file.

  6. Set the value of customized_flag to 1, if it is not already set to that value.

  7. Save and close the file.

  8. Copy the stda.h and ctqa.h files from the Vertex_home/inc directory to the BRM_SDK_home/source/sys/fm_rate_pol directory.

  9. To the Makefile, add CFLAGS += -DPORT_UNIXANSI.

  10. Recompile the opcode.

Source Code for Customizing PCM_OP_RATE_POL_PRE_TAX
#ifdef USE_VERTEX_Q_SERIES
/***************************************************************************
      /*****************************************************************
      * FOLLOWING MANDATORY FIELDS SHOULD BE FILLED WITH CORRECT VALUES.
      * YOU CAN CUSTOMIZE THE MANDATORY AND OPTIONAL FIELDS.
      * HERE IS THE LIST OF MAPPING FIELDS.
      * VERTEX DATATYPE => MAPPING FIELD              =>PORTAL DATATYPE
      *
      * eCtqString    =>PIN_FLD_VERTEX_CTQ_STR        =>PIN_FLDT_STR
      * eCtqInt       =>PIN_FLD_VERTEX_CTQ_INT        =>PIN_FLDT_INT
      * eCtqFloat     =>PIN_FLD_VERTEX_CTQ_FLOAT      =>PIN_FLDT_DECIMAL
      * eCtqDouble    =>PIN_FLD_VERTEX_CTQ_DOUBLE     =>PIN_FLDT_DECIMAL
      * eCtqLong      =>PIN_FLD_VERTEX_CTQ_LONG       =>PIN_FLDT_DECIMAL
      * eCtqDate      =>PIN_FLD_VERTEX_CTQ_DATE       =>PIN_FLDT_TSTAMP
      * eCtqTime      =>PIN_FLD_VERTEX_CTQ_TIME       =>PIN_FLDT_TSTAMP
      * eCtqTimestamp =>PIN_FLD_VERTEX_CTQ_TIMESTAMP  =>PIN_FLDT_TSTAMP
      * eCtqBool      =>PIN_FLD_VERTEX_CTQ_BOOL       =>PIN_FLD_INT
      * eCtqChar      =>PIN_FLD_VERTEX_CTQ_CHAR       =>PIN_FLDT_STR
      * eCtqEnum      =>PIN_FLD_VERTEX_CTQ_ENUM       =>PIN_FLDT_ENUM
      *
      * YOU CAN ADD ONE FIELD LIKE THE FOLLOWING FLIST FORMAT.
      0 PIN_FLD_FIELD_NAMES   ARRAY[] allocated 20, used 2
              1     PIN_FLD_TYPE             ENUM [0]
              1     PIN_FLD_VERTEX_CTQ_STR    STR [0]
      * USE PROPER MAPPING FIELD TO SET VALUE OF VERTEX FIELD.
      * IF YOU ADD SOME STRING FIELD(eCtqString),THEN SET VALUE FOR THAT FIELD
      * USING PIN_FLD_VERTEX_CTQ_STR.FOR DETAILS,SEE THE ABOVE TABLES.
      ******************************************************************/
      pin_flist_t     *cust_flistp = NULL;
      pin_flist_t     *field_name_flistp = NULL;
      tCtqAttribType  attribute_type = eCtqHandle ;
      time_t          now_t = 0;
      pin_decimal_t   *value_decimal = NULL;
      int32           value_int = 0;
      char            temp_buf[255] = { '\0' };
  
      int32           customized_flag = 1;/* SET TO 1 FOR CUSTOMIZATION */
  
      cust_flistp = PIN_FLIST_CREATE(ebufp);
  
      /*****************************************************************
       * IMPORTANT:SET customized_flag to 1 IF YOU WANT TO CUSTOMIZE THE
       * VERTEX FIELDS.
       *****************************************************************/
  
      PIN_FLIST_FLD_SET(cust_flistp, PIN_FLD_STATUS_FLAGS,
              (void *)&customized_flag, ebufp);
  
      /* FIELD:eCtqAttribCategoryCode NATURE:Mandatory Field */
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribCategoryCode, ebufp);
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf ,"04") ;
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,
              (void *)temp_buf,ebufp);
  
      /* FIELD:eCtqAttribServiceCode NATURE:Mandatory Field */
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribServiceCode, ebufp);
  
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf,"01" );
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,
              (void *)temp_buf,ebufp);
  
      /* FIELD:eCtqAttribOriginGeoCode NATURE:Mandatory Field */
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribOriginGeoCode, ebufp);
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf ,"390290740" );
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,
              (void *)temp_buf,ebufp);
  
      /* FIELD:eCtqAttribTerminationGeoCode NATURE:Mandatory Field */
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribTerminationGeoCode, ebufp);
  
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf,"390296350") ;
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,(void *)temp_buf,
              ebufp);
  
      /* FIELD:eCtqAttribInvoiceDate NATURE:Mandatory Field */
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribInvoiceDate, ebufp);
      attribute_type=eCtqDate;
      now_t = pin_virtual_time((time_t *)NULL);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_DATE,&now_t,
              ebufp);
  
      /* FIELD:eCtqAttribTaxableAmount NATURE:Mandatory Field */
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribTaxableAmount, ebufp);
      attribute_type = eCtqDouble;
      value_decimal = pbo_decimal_from_str("100.00",ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_DOUBLE,
              (void *)value_decimal,ebufp);
  
  
      /**********************************************************************
       * YOU CAN ADD OPTIONAL FIELDS LIKE BELOW FLIST
       *
       * field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp,
              PIN_FLD_FIELD_NAMES,eCtqAttribBilledLines, ebufp);
       * attribute_type = eCtqInt;
       * PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
       * int value_int = 01
       * PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_INT,
              (void *)&value_int,ebufp);
       **********************************************************************/
       field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribBilledLines, ebufp);
       attribute_type = eCtqInt;
       value_int = 01;
       PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
       PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_INT,
              (void *)&value_int,ebufp);
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribSaleResaleCode, ebufp);
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf ,"S" );
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,
              temp_buf,ebufp);
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribChargeToGeoCode, ebufp);
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf ,"390296350" );
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,
              temp_buf,ebufp);
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribCallMinutes, ebufp);
      attribute_type = eCtqDouble;
      value_decimal = pbo_decimal_from_str("10.0",ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_DOUBLE,
              (void *)value_decimal,ebufp);
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribUserArea, ebufp);
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf ,"Interstate/Toll");
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,temp_buf,
              ebufp);
  
      field_name_flistp = PIN_FLIST_ELEM_ADD(cust_flistp, PIN_FLD_FIELD_NAMES,
              eCtqAttribInvoiceNumber, ebufp);
      attribute_type = eCtqString;
      temp_buf[0]='\0';
      strcpy(temp_buf ,"DEMO-002");
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_TYPE,
              (void *)&attribute_type,ebufp);
      PIN_FLIST_FLD_SET(field_name_flistp,PIN_FLD_VERTEX_CTQ_STR,temp_buf,
              ebufp);
  
      PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
              "op_rate_pol_pre_tax customized flist", cust_flistp);
      PIN_FLIST_CONCAT(ret_flistp,cust_flistp,ebufp);
      if (value_decimal) {
              pbo_decimal_destroy(&value_decimal);
      }
  
      PIN_FLIST_DESTROY_EX(&cust_flistp,NULL);
***************************************************************************/
#endif

Modifying Tax Data After Calculating Taxes

You can customize PCM_OP_RATE_POL_POST_TAX to modify any data in the output returned by the tax calculation software after tax calculation. For example, you can modify the opcode to perform these functions:

  • Change how the CM logs any messages that are returned from the external taxation DMs.

  • Add a surcharge to the tax amount in the output flist returned from the taxation DM, as shown in the following example:

    void fm_rate_pol_post_tax(...)
    {
    /* loop through array of incoming taxes */
      while(t_flistp = PIN_FLIST_ELEM_GET_NEXT(in_flistp, PIN_FLD_TAXES,
          &elemid, 1, &cookie, ebufp)) != (pin_flist_t*)NULL) {
         /* add a surcharge to the SUBTOTAL array */
          cnt = PIN_FLIST_ELEM_COUNT(t_flist, PIN_FLD_SUBTOTAL, ebufp))
          s_flistp = PIN_FLIST_ELEM_ADD(t_flistp, PIN_FLD_SUBTOTAL, cnt++, ebufp);
    ...
         /* add the entries to the SUBTOTAL array */
          PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_TAX, (void*)&tax, ebufp);
          PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_SUBTYPE, (void*)&taxType, ebufp);
    ...
      }
    }Error Handling
      

By default, PCM_OP_RATE_POL_POST_TAX returns the input flist as the output flist, without the PIN_FLD_MESSAGES array. It also logs any messages returned from the taxation DM as specified in the tax_return_loglevel entry of the CM pin.conf file.

PCM_OP_RATE_POL_POST_TAX default implementation handles errors as follows:

  • Logs messages as specified in the tax_return_loglevel entry in the CM pin.conf file. The default is to log only warnings.

  • If an error occurs while reading the tax_return_loglevel entry, sets the error buffer to INVALID_CONF.

Overriding Customer Tax Locale for Purchases

By default, BRM calculates the taxes your customers owe for purchases using their shipped-to address (stored in an /account object's PIN_FLD_NAMEINFO array). You can instead configure BRM to calculate the tax amount using a customer's real-time location when purchasing a bundle (or deal), buying a charge offer (or product), or topping up a prepaid account.

To do so, configure your custom client application to call the following opcodes:

  • PCM_OP_SUBSCRIPTION_PURCHASE_DEAL

  • PCM_OP_SUBSCRIPTION_PURCHASE_PRODUCT

  • PCM_OP_PYMT_TOPUP

You pass in the customer's real-time location to the opcode using the PIN_FLD_LOCALE input flist field or using zone maps.

Real-Time Location Using PIN_FLD_LOCALE

Set the PIN_FLD_LOCALE input flist field to the customer's current location in the following format:

"City;State;Zipcode;Country"

For example:

"Austin;TX;78741;US"

The following shows a sample PCM_OP_PYMT_TOPUP input flist for setting a customer's real-time location to Chicago:

0 PIN_FLD_PROGRAM_NAME                   STR [0] "testnap"
0 PIN_FLD_POID                          POID [0] 0.0.0.1 /account 91058 8
0 PIN_FLD_LOCALE                         STR [0] "Chicago;IL;60634;US"
0 PIN_FLD_INHERITED_INFO           SUBSTRUCT [0] allocated 1, used 1
1 PIN_FLD_TOPUP_INFO                   ARRAY [0] allocated 4, used 4
2       PIN_FLD_BILLINFO_OBJ            POID [0] 0.0.0.1 /billinfo 94130 0
2       PIN_FLD_BAL_GRP_OBJ             POID [0] 0.0.0.1 /balance_group 93298 0
2       PIN_FLD_TOPUP_AMT            DECIMAL [0] 19
2         PIN_FLD_PAYINFO              ARRAY [0] allocated 4, used 4
3             PIN_FLD_ACCOUNT_OBJ       POID [0] 0.0.0.1 /account 91058 8
3             PIN_FLD_POID              POID [0] 0.0.0.1 /payinfo/cc -1 0
3             PIN_FLD_PAY_TYPE          ENUM [0] 10003
3             PIN_FLD_CC_INFO          ARRAY [0] allocated 9, used 9
4                 PIN_FLD_SECURITY_ID    STR [0] "ID"
4                 PIN_FLD_NAME           STR [0] "John Evans"
4                 PIN_FLD_DEBIT_EXP      STR [0] "Expiration"
4                 PIN_FLD_DEBIT_NUM      STR [0] "DebitNumber"
4                 PIN_FLD_COUNTRY        STR [0] "US"
4                 PIN_FLD_ZIP            STR [0] "94065"
4                 PIN_FLD_STATE          STR [0] "CA"
4                 PIN_FLD_CITY           STR [0] "Redwood City"
4                 PIN_FLD_ADDRESS        STR [0] "100 Oracle Pkwy"

Real-Time Location Using Zone Maps

Set the following opcode input flist fields:

  • PIN_FLD_ZONEMAP_NAME: Set this to the name of the zone map to use.

  • PIN_FLD_ZONEMAP_TARGET: Set this to the name of the end-leaf node in the zone map.

The following shows a sample PCM_OP_SUBSCRIPTION_PURCHASE_DEAL input flist for setting a customer's real-time location using zone maps:

0 PIN_FLD_POID              POID [0] 0.0.0.1 /account 101267 7 
0 PIN_FLD_SERVICE_OBJ       POID [0] 0.0.0.1 /service/ip 98643 6 
0 PIN_FLD_PROGRAM_NAME       STR [0] "testnap" 
0 PIN_FLD_ZONEMAP_TARGET     STR [0] "3"
0 PIN_FLD_ZONEMAP_NAME       STR [0] "TestZoneMap2"
0 PIN_FLD_DEAL_INFO    SUBSTRUCT [0] allocated 20, used 7 
1    PIN_FLD_PRODUCTS      ARRAY [0] allocated 35, used 35 
2       PIN_FLD_FLAGS        INT [0] 1

Note:

To use this method, you must have configured a zone map with the specified name and target.

Using Custom Tax Rates

If your business uses a simple tax calculation method, you may not need to use a tax calculation software package. You can use custom tax rates instead. In simple cases, you can implement taxation using built-in features that do not require programming.

If your business requires a more complex tax structure but does not require the full capabilities of one of the taxation packages, you can implement custom tax rates by modifying the two taxation policy opcodes:

  • PCM_OP_CUST_POL_TAX_INIT: This policy opcode caches tax rate information from either the taxcodes_map file (Patch Set 4 and earlier releases) or the /config/taxcodes_map object (Patch Set 5 and later releases). Then, it calls either the PCM_OP_CUST_POL_TAX_CALC policy opcode (if no tax calculation software is configured) or the taxation DM (if tax calculation software is configured).

    PCM_OP_CUST_POL_TAX_INIT is not called by any other opcode.

  • PCM_OP_CUST_POL_TAX_CALC: This policy opcode performs the actual tax calculation for all tax codes with a package code of U (user-defined). By default, PCM_OP_CUST_POL_TAX_CALC reads the custom tax rate from cache and uses this simple calculation method to calculate the taxes:

    tax = amount * rate 

To use custom tax rates, do the following:

  1. Define your tax rates as required for your BRM 12.0 Patch Set release. See "Creating Tax Codes" in BRM Calculating Taxes.
  2. Modify the source file for PCM_OP_CUST_POL_TAX_INIT (BRM_SDK_home/source/sys/fm_cust_pol/fm_cust_pol_tax_init.c) to implement your customizations.
    1. To load tax code data in a different format, define a data structure in fm_cust_pol_tax_init.c for your custom tax rates.
    2. Perform any other customizations required in fm_cust_pol_tax_init.c to implement your custom tax features.
  3. If necessary for your customizations, modify the source file for PCM_OP_CUST_POL_TAX_CALC (BRM_SDK_home/source/sys/fm_cust_pol_tax_calc.c).
  4. Compile fm_cust_pol_tax_init.c and fm_cust_pol_tax_calc.c by using the makefile in the BRM_SDK_home/source/sys/fm_cust_pol directory.
  5. Copy the compiled shared library files to BRM_home/lib, replacing the existing versions.
  6. Open the CM configuration file (pin.conf) and ensure that the following entries in the fm_module section are enabled (not commented out):
    - cm fm_module BRM_home/lib/fm_cust.so fm_cust_config - pin
    - cm fm_module BRM_home/lib/fm_cust_pol.so fm_cust_pol_config fm_cust_pol_tax_init pin
  7. Stop and restart the CM.

Using Geocodes to Calculate Taxes

A geocode is a geographic code that is used to determine a tax jurisdiction. Different tax calculation software packages use different geocode systems and update them frequently. To use geocodes to calculate taxes, you must modify PCM_OP_RATE_POL_PRE_TAX to query the geocoder and obtain the geocode for an account during account creation. The geocoder maps the address or postal code of the account to a unique geocode.

If a geocode is available during tax calculation, the tax package uses it to calculate the tax. If a geocode is not available, the tax calculation software chooses the geocode with the highest tax rate from a list of geocodes it finds for that account address.

Note:

The tax calculation software itself cannot map an address to a unique geocode.

To use geocodes to calculate taxes:

  1. Using Storable Class Editor, create a /profile storable class and add the PIN_FLD_GEOCODE field to it.

    If you have configured more than one tax calculation package, create an array that contains separate PIN_FLD_GEOCODE fields for the tax calculation package. The index values should represent the tax packages:

    • 0 specifies a custom tax package.

    • 2 specifies the WorldTax package.

    • 3 specifies the Sales Tax Q Series package.

    • 4 specifies the Communications Tax Q Series package.

  2. Modify PCM_OP_CUST_POL_VALID_NAMEINFO to store the geocode in the new PIN_FLD_GEOCODE field of the /profile object if the address was validated successfully.

  3. Implement PCM_OP_RATE_POL_PRE_TAX to perform the following functions:

    • Obtain the geocode from the /profile object.

    • Set the geocode in the PIN_FLD_SHIP_TO or PIN_FLD_SHIP_FROM field in the taxes array in the input flist to the taxation DM.

      For example, the opcode should change this field value:

      PIN_FLD_SHIP_TO STR [0] "Cupertino; CA; 95012; US; []"
        

      to include the geocode in the square brackets []:

      PIN_FLD_SHIP_TO STR [0] "Cupertino; CA; 95012; US; [050850860]"
        
  4. Set the location mode to geocode by supplying 1 as the value for the PIN_FLD_LOCATION_MODE field in the PIN_FLD_TAXES array of the input flist.

    When you set the location mode to geocode, the taxation DM passes the geocode instead of the address to the tax calculation module.

    For example:

    PIN_FLD_LOCATION_MODE  ENUM[0] 1
      

After calculating the taxes, the taxation DM returns the jurisdiction (address and geocode) where tax rates were applied in the PIN_FLD_TAXES array of the output flist:

PIN_FLD_NAME STR[0] "US: CA: Santa Clara: Cupertino: 95012 : [050850860]"

Adding Tax Information to Accounts

To add tax information to an account, use PCM_OP_CUST_SET_TAXINFO.

This opcode adds the following data:

  • VAT certificate

  • Tax exemptions

  • Tax incorporation

  • Tax residence

To do so, PCM_OP_CUST_SET_TAXINFO adds or updates values for the following fields in the taxinfo array of an /account object:

  • PIN_FLD_VAT_CERT

  • PIN_FLD_EXEMPTIONS

  • PIN_FLD_INCORPORATED_FLAG

  • PIN_FLD_RESIDENCE_FLAG

For example, when an account is created and a VAT certificate number or exemption information is provided, PCM_OP_CUST_SET_TAXINFO is called. PCM_OP_CUST_SET_TAXINFO performs these functions:

  • Modifies existing data or adds information to the PIN_FLD_TAXINFO array of the /account object by using the field values provided in the input flist.

  • If a VAT certificate number is not provided, replaces the value of PIN_FLD_VAT_CERT in the account object with an empty ("") string.

  • If exemption information is not provided, deletes the PIN_FLD_EXEMPTIONS array.

  • If the field values provided in the input flist contain the PIN_FLD_INCORPORATED_FLAG or PIN_FLD_RESIDENCE_FLAG flag, adds or updates these values in the account object.

Validating Tax Information

To customize how tax information is validated, use PCM_OP_CUST_POL_VALID_TAXINFO. This opcode validates the VAT certificate number to prevent nonvalid numbers, which cause failures in tax calculations.

By default, PCM_OP_CUST_POL_VALID_TAXINFO checks for the VAT certificate data and performs these functions:

  • If the VAT certificate number provided is a string, zero in length, returns the validation result PASS.

  • If the following tax_valid entry in the CM pin.conf file is not set or is set to 0, returns the validation result FAIL.

    #Enables or disables validation of the VAT certificate number. 
    #1 means Enable; 0, which is the default, means Disable.
    - fm_cust_pol  tax_valid 0 
      

You can customize PCM_OP_CUST_POL_VALID_TAXINFO to use a custom tax calculation software to validate the VAT certificate number. For example, instead of calling PCM_OP_RATE_TAX_CALC, you can query your custom VAT validation function by rewriting the function do_vat_cert_validation in PCM_OP_CUST_POL_VALID_TAXINFO source file.

Retrieving Tax Calculation Data

See the following topics:

Retrieving a List of Tax Codes

To retrieve a list of tax codes, use PCM_OP_RATE_POL_GET_TAXCODE. This opcode returns a list of all tax codes that were loaded from the taxcodes.map file and cached by the CM during initialization. For example, Pricing Center uses this opcode to display a list of taxcodes used to configure rate plans for taxation. You can customize this opcode to return additional cached tax code information.

This opcode is not called by any opcode.

PCM_OP_RATE_POL_GET_TAXCODE takes an account POID as input and performs these functions:

  • Obtains the database number from the POID.

  • Searches the CMs in-memory cache for tax codes.

  • Returns an array of tax code names in the output flist.

PCM_OP_RATE_POL_GET_TAXCODE returns a list of the tax code names cached from the taxcodes_map file by the CM during initialization.

Retrieving a List of Tax Suppliers

To retrieve a list of tax suppliers, use PCM_OP_RATE_POL_GET_TAX_SUPPLIER. You can customize this opcode by modifying the fields on the output flist. You can specify which fields are validated by adding or removing them from the input flist.

PCM_OP_RATE_POL_GET_TAX_SUPPLIER takes an account POID as input and performs these functions:

  • Obtains the database number from the POID.

  • Performs a global search for tax suppliers.

  • Returns a list of tax suppliers with all the relevant fields in the output flist.

This opcode is not called by any opcode.

Retrieving Tax Supplier Data

To retrieve tax supplier data, use PCM_OP_RATE_POL_MAP_TAX_SUPPLIER. You can customize this opcode to change how a tax supplier is derived for a specific BRM event.

This opcode is called by PCM_OP_BILL_TAX_EVENT.

This opcode can function in either of two ways:

  • If a tax_supplier_map file is used with a corresponding entry in the CM pin.conf file, this opcode searches the tax_supplier_map file by company ID based on the charge offer name and ship to categories. If a matching entry is found, it returns that entry from the tax_supplier_map file. If no matching entry exists, the opcode returns NULL as the address of the flist.

  • If the tax_supplier_map file does not exist or the CM pin.conf entry does not specify using a tax_supplier_map file, this opcode tries to find the tax_supplier object POID in the PIN_FLD_PRODUCTS array of the account object.

PCM_OP_RATE_POL_MAP_TAX_SUPPLIER also retrieves the utility flag, which is used for telecommunication (telco) taxation, from the PIN_FLD_REGULATED_FLAG field of the /profile/tax_supplier object and returns it on the output flist.

Retrieving Tax Location Data

To customize the way PCM_OP_RATE_EVENT obtains the locations for tax jurisdictions, use PCM_OP_RATE_POL_TAX_LOC. This opcode returns the locations for an event, which are then used to establish jurisdictions for tax calculation.

Note:

For a telephony event, the locations contain additional information, which is enclosed in square ([]) brackets.

For example, you can obtain the value for the PIN_FLD_ORDER_ACCEPT field from a different source. Additionally, you can provide a geocode instead of an NPA/NXX for telephony events.

PCM_OP_RATE_POL_TAX_LOC takes an account POID as input and returns these fields:

  • PIN_FLD_SHIP_TO: The ship-to address; for telephony events, the call termination number.

  • PIN_FLD_SHIP_FROM: The ship-from address; for telephony events, the call origination number.

  • PIN_FLD_ORDER_ACCEPT: The order accept address; for telephony events, the charge-to number.

  • PIN_FLD_ORDER_ORIGIN: The order origin address.

It returns them in four strings with this syntax:

city; state_abbreviation;zipcode; country;[code,location,international_indicator]

where:

  • code is the geocode or NPA/NXX.

  • location specifies the type of code:

    • 0: Address

    • 1: Geocode

    • 2: NPA/NXX

  • international_indicator specifies the type of call:

    • 1: North America numbering plan

    • 2: North America originated, overseas terminated

    • 3: North America originated, overseas terminated and billed

    • 4: IOC North America originated, overseas terminated

    • 5: Overseas originated, North America terminated

    • 6: IOC North America originated, overseas terminated and billed

    • 7: Overseas originated, overseas terminated

For example:

1  PIN_FLD_SHIP_TO            STR [0] "Cupertino; CA; 95014; USA;[408572,2,1]"
1  PIN_FLD_SHIP_FROM          STR [0] "Englewood; CO; 80112; USA;[060050006000,1,1]"
1  PIN_FLD_ORDER_ORIGIN       STR [0] "Englewood; CO; 80112; USA;[060050006000,1,1]"
1  PIN_FLD_ORDER_ACCEPT       STR [0] "Englewood; CO; 80112; USA;[060050006000,1,1]"
1  PIN_FLD_LOCATION_MODE     ENUM [0] 1
1  PIN_FLD_INTERNATIONAL_IND  INT [0] 1

By default, PCM_OP_RATE_POL_TAX_LOC uses the sources for locations described in Table 22-2:

Table 22-2 PCM_OP_RATE_POL_TAX_LOC Source Locations

Location Default Source

PIN_FLD_SHIP_TO

The account billing address, obtained from the PIN_FLD_NAMEINFO array of the /account object.

PIN_FLD_SHIP_FROM

Same as PIN_FLD_ORDER_ACCEPT

PIN_FLD_ORDER_ACCEPT

The value for the fm_rate_pol provider_loc entry in the CM pin.conf file. For information on the default PIN_FLD_ORDER_ACCEPT location, see the fm_rate_pol provider_loc entry in the CM pin.conf file.

PIN_FLD_ORDER_ORIGIN

Same as PIN_FLD_ORDER_ACCEPT.

Retrieving Additional Tax Data from Vertex Communications Tax Q Series

When you perform tax calculation by using Vertex Communications Tax Q Series, it returns tax data in an input flist to the BRM API. The tax data is then processed and stored in the BRM database. For a list of data that Vertex Communications Tax Q Series returns to the BRM API by default, see "Default Tax Data Returned by Vertex Communications Tax Q Series" for more information.

You can also customize BRM to request and store additional data from Vertex Communications Tax Q Series by performing the following:

  1. Requesting additional data from Vertex Communications Tax Q Series.

    See "Requesting Additional Data from Vertex Communications Tax Q Series" for more information.

  2. Retrieving the additional tax data returned by Vertex Communications Tax Q Series.

    See "Requesting Additional Data from Vertex Communications Tax Q Series" for more information.

  3. Storing the additional tax data in the BRM database.

    See "Storing the Requested Vertex Tax Data in the BRM Database" for more information.

Default Tax Data Returned by Vertex Communications Tax Q Series

Vertex Communications Tax Q Series makes its attributes available to other applications through data handles. BRM uses tax data from the following two data handles only:

  • The Register Transaction data handle, which defines tax transaction attributes.

  • The Register Transaction Tax Detail data handle, which defines tax jurisdiction attributes.

Vertex Communications Tax Q Series sends tax attributes to the BRM API in the following input flist structures:

  • PIN_FLD_TAXES input flist array: Contains the result of a tax calculation at the transaction level.

  • PIN_FLD_TAXES.PIN_FLD_SUBTOTAL input flist array: Contains the result of a tax calculation at the jurisdiction level, such as at the Federal level or at the State level. In each jurisdiction, the taxes are broken into subtypes, such as 911 and DEAF.

Table 22-3 shows the tax attributes that are sent to the BRM API by default and the flist structure in which the attribute is passed:

Table 22-3 Default BRM Tax Attributes and flist Structure

Vertex Communications Tax Q Series Data Handle Vertex Communications Tax Q Series Attributes BRM Input Flist Structure

Register Transaction data handle

  • eCtqAttribChargeToLocationMode

  • eCtqAttribChargeToPostalCode

  • eCtqAttribTaxedGeoCodeOverrideCode

  • eCtqAttribInvoiceDate

  • eCtqAttribBilledLines

  • eCtqAttribInvoiceNumber

  • eCtqAttribServiceCode

  • eCtqAttribCategoryCode

  • eCtqAttribCreditCode

  • eCtqAttribDescriptionFlag

  • eCtqAttribTaxedGeoCodeIncorporatedCode

  • eCtqAttribFederalExemptFlag

  • eCtqAttribStateExemptFlag

  • eCtqAttribCountyExemptFlag

  • eCtqAttribCityExemptFlag

  • eCtqAttribWriteJournal

Note: The eCtqAttribWriteJournal attribute is retrieved from the Register Subsystem data handle.

PIN_FLD_TAXES array

Register Transaction Tax Detail data handle

  • eCtqAttribTrunksTaxed

  • eCtqAttribTaxCode

  • eCtqAttribLinkTaxAmount

  • eCtqAttribRowCount

PIN_FLD_TAXES.PIN_FLD_SUBTOTAL array

Requesting Additional Data from Vertex Communications Tax Q Series

You can request additional tax data from Vertex Communications Tax Q Series by customizing PCM_OP_RATE_POL_PRE_TAX. Vertex Communications Tax Q Series returns the requested tax data in the input flist to PCM_OP_RATE_POL_POST_TAX.

To request additional tax data:

  • Customize PCM_OP_RATE_POL_PRE_TAX to request data from the following two Vertex data handles: Register Transaction data handle and Register Transaction Tax Detail data handle.

  • Add custom output flist fields to PCM_OP_RATE_POL_PRE_TAX. To request additional tax data, add the flist fields shown in bold below to the PIN_FLD_RESULTS output flist array:

    0 PIN_FLD_RESULTS           ARRAY [0] allocated 20, used 1
    1   PIN_FLD_TAXES                 [0] allocated 20, used 1
    2     PIN_FLD_FIELD_NAMES   ARRAY [ArrayIndexValue] allocated 20, used 2
    3       PIN_FLD_TYPE         ENUM [0] VertexDataType
    1   PIN_FLD_SUBTOTAL              [0] allocated 20, used 1
    2     PIN_FLD_FIELD_NAMES   ARRAY [ArrayIndexValue] allocated 20, used 2
    3       PIN_FLD_TYPE         ENUM [0] VertexDataType

    where:

    • The PIN_FLD_TAXES structure specifies that you are requesting data from the Vertex Register Transaction data handle. All elements under this array must reference attributes from the Register Transaction data handle only.

    • The PIN_FLD_SUBTOTAL structure specifies that you are requesting data from the Vertex Register Transaction Tax Detail data handle. All elements under this array must reference attributes from the Register Transaction Tax Detail data handle only.

    • ArrayIndexValue specifies the Vertex Communications Tax Q Series attribute ID that you are requesting. For example, set the PIN_FLD_FIELD_NAMES array index to 304 to request the eCtqAttribTrunksTaxed attribute.

    • VertexDataType specifies the Vertex data type ID for the Vertex Communications Tax Q Series attribute you are requesting. Supported Vertex data types include the following:

      • eCtqInt

      • eCtqString

      • eCtqBool

      • eCtqFloat

      • eCtqDouble

      • eCtqLong

      • eCtqDate

For example, the following shows custom output flist fields for requesting additional tax data:

0 PIN_FLD_RESULTS                ARRAY [0] allocated 20, used 1 
1   PIN_FLD_TAXES                      [0] allocated 20, used 1 
2     PIN_FLD_FIELD_NAMES        ARRAY [271] allocated 20, used 2 
3       PIN_FLD_TYPE              ENUM [0] 3 
1   PIN_FLD_SUBTOTAL                   [0] allocated 20, used 1 
2     PIN_FLD_FIELD_NAMES        ARRAY [285] allocated 20, used 2 
3       PIN_FLD_TYPE              ENUM [0] 10 

Retrieving Additional Tax Data

The additional data you request from Vertex Communications Tax Q Series is returned in the PCM_OP_RATE_POL_POST_TAX input flist. You can customize the BRM API to retrieve the tax data from the input flist fields and process it according to your business needs.

Vertex Communications Tax Q Series returns the additional data in the following PCM_OP_RATE_POL_POST_TAX input flist structure under the PIN_FLD_TAXES array or the PIN_FLD_TAXES.PIN_FLD_SUBTOTAL array:

  • If passed in the PIN_FLD_TAXES array, the data is for one tax transaction. This information is from the Register Transaction data handle.

  • If passed in the PIN_FLD_TAXES.PIN_FLD_SUBTOTAL array, the tax data is for one jurisdiction. This information is from the Register Transaction Tax Detail data handle.

    1  PIN_FLD_FIELD_NAMES           ARRAY [ArrayIndexValue] allocated 20, used 3
    2    PIN_FLD_TYPE                      ENUM [0] VertexDataType
    2    PIN_FLD_VERTEX_CTQ_BRMDataType   INT [0] BRMTaxData

    where:

    • ArrayIndexValue specifies the Vertex Communications Tax Q Series attribute ID. For example, enter 295 to request data from the eCtqAttribTaxedGeoCode attribute.

    • VertexDataType specifies the data type ID of the Vertex Communications Tax Q Series attribute. For example, enter 3 for the eCtqInt data type.

    • BRMTaxData is the tax data from the specified Vertex Communications Tax Q Series attribute.

    • PIN_FLD_VERTEX_CTQ_BRMDataType is the name of the input flist field that contains the tax data. Table 22-4 specifies the name of the BRM input flist field that corresponds to each Vertex data type.

      Table 22-4 BRM Input flist for Vertex Data Type

      BRM Data Type Vertex Data Type

      INT

      eCtqInt

      STR

      eCtqString

      BOOL

      eCtqBool

      FLOAT

      eCtqFloat

      DOUBLE

      eCtqDouble

      LONG

      eCtqLong

      STR

      Important: This field will contain the date in Vertex Communications Tax Q Series format (CCYYMMDD). This is different from the mapping for custom input fields, in which eCtqDate is mapped to PIN_FLD_VERTEX_CTQ_TIMESTAMP.

      eCtqDate

For example, the following shows a simple PCM_OP_RATE_POL_POST_TAX input flist. The flist fields for the additional tax data are shown in bold.

# number of field entries allocated 20, used 2
0 PIN_FLD_POID                  POID [0] 0.0.0.1 /account 27225 0
0 PIN_FLD_EVENT_OBJ             POID [0] 0.0.0.1 /event/billing/cycle/tax 11111 0
0 PIN_FLD_TAXES                ARRAY [0] allocated 20, used 3
1   PIN_FLD_TAXPKG_TYPE         ENUM [0] 0
1   PIN_FLD_TAX              DECIMAL [0] 0.70
1   PIN_FLD_FIELD_NAMES         ARRAY [295] allocated 20, used 3  // Array index = eCtqAttribTaxedGeoCode
2     PIN_FLD_TYPE              ENUM [0] 10
2     PIN_FLD_VERTEX_CTQ_STR     STR [0] "123456789"
1   PIN_FLD_SUBTOTAL           ARRAY [0] allocated 20, used 10
2     PIN_FLD_TAX            DECIMAL [0] 0.70
2     PIN_FLD_TYPE              ENUM [0] 0
2     PIN_FLD_NAME               STR [0] "US; CA; Sunnyvale; ; 94086"
2     PIN_FLD_AMOUNT_GROSS   DECIMAL [0] 19.88
2     PIN_FLD_PERCENT        DECIMAL [0] 0.035000
2     PIN_FLD_AMOUNT_TAXED   DECIMAL [0] 19.88
2     PIN_FLD_AMOUNT_EXEMPT  DECIMAL [0] 0.00
2     PIN_FLD_SUBTYPE           ENUM [0] 0
2     PIN_FLD_DESCR              STR [0] "Excise"
2     PIN_FLD_LOCATION_MODE     ENUM [0] 0
2     PIN_FLD_FIELD_NAMES       ARRAY [304] allocated 20, used 3  // Array index = eCtqAttribTrunksTaxed
3       PIN_FLD_TYPE            ENUM [0] 3
3       PIN_FLD_VERTEX_CTQ_INT   INT [0] 1

Each PIN_FLD_TAXES array element results in a single balance impact. All tax data from the PIN_FLD_TAXES array element is stored in the BRM /event object in the PIN_FLD_BAL_IMPACTS array.

Each PIN_FLD_TAXES.PIN_FLD_SUBTOTAL array element results in a single balance impact for a jurisdiction. All tax data for that jurisdiction is stored in the BRM /event object in the PIN_FLD_TAX_JURISDICTIONS array.

Note:

Sometimes, a Vertex attribute may be missing from the PCM_OP_RATE_POL_POST_TAX input flist. This could be due to an exception condition. For example:

  • If taxes do not apply because of an undefined service code. In this case, the PIN_FLD_SUBTOTAL array will have a zero tax amount but none of the additional output fields.

  • If BRM requested a nonapplicable attribute. For example, if BRM requested the eCtqAttribOriginGeoCode attribute when calculating taxes for a wireless service based on the PPU location passed in as a ZIP code.

Storing the Requested Vertex Tax Data in the BRM Database

All additional Vertex Communications Tax Q Series data that you request is returned in the PCM_OP_RATE_POL_POST_TAX input flist. To customize the opcode to store the additional data in the BRM database:

Creating a Custom Storable Class for Vertex Tax Data

To store the additional data from Vertex Communications Tax Q Series, create a custom tax storable class, such as /custom/tax/ctq_output. The structure of the custom tax storable class should be similar to the following flist:

Note:

Make sure you define all fields in the custom tax storable class.

PIN_FLD_POID
PIN_FLD_ACCOUNT_OBJ
PIN_FLD_EVENT_OBJ
   PIN_FLD_CUSTOM_TAX_BAL_IMPACTS           ARRAY
      PIN_FLD_CUSTOM_TAX_TAXED_GEO_CODE     STR
...
   PIN_FLD_CUSTOM_TAX_TAX_JURISDICTIONS     ARRAY
      PIN_FLD_ELEMENT_ID                    INT
      PIN_FLD_CUSTOM_TAX_TRUNKS_TAXED       INT
Storing Vertex Tax Data in Your Custom Storable Class

To store the additional Vertex Communications Tax Q Series tax data in your custom tax storable class, customize PCM_OP_RATE_POL_POST_TAX as follows:

  1. Add the following compiler directives to include Vertex Communications Tax Q Series compiler definitions. Copy these files from the Vertex Communications Tax Q Series installation directory to the directory in which the policy source code resides.

    #include "stda.h"
    #include "ctqa.h"
  2. In the policy source code directory, modify Makefile to add the -DPORT_UNIXANSI Compiler option.

    For example, you can use the CFLAGS variable as follows:

    CFLAGS += -DPORT_UNIXANSI
  3. Create a new flist instance of your custom tax storable class and set PIN_FLD_EVENT_OBJ of this instance in the /event object.

  4. In your custom tax storable class:

    • Add a PIN_FLD_CUSTOM_TAX_BAL_IMPACTS array element for each PIN_FLD_TAXES element passed in the PCM_OP_RATE_POL_POST_TAX input flist.

    • In the PIN_FLD_CUSTOM_TAX_BAL_IMPACTS element, set each custom tax storable class field to its corresponding value from the PIN_FLD_TAXES input flist array. For example, set the PIN_FLD_CUSTOM_TAX_TAXED_GEO_CODE storable class field to the value in the PIN_FLD_VERTEX_CTQ_STR input flist field.

    • Add a PIN_FLD_CUSTOM_TAX_TAX_JURISDICTIONS array element for each PIN_FLD_TAXES.PIN_FLD_SUBTOTAL element passed in the PCM_OP_RATE_POL_POST_TAX input flist.

    • In the PIN_FLD_CUSTOM_TAX_TAX_JURISDICTIONS element, set each custom tax storable class field to its corresponding value from the PIN_FLD_SUBTOTAL input flist array. For example, set the PIN_FLD_CUSTOM_TAX_TRUNKS_TAXED storable class field to the value in the PIN_FLD_VERTEX_CTQ_INT input flist field.

    • Link each PIN_FLD_CUSTOM_TAX_TAX_JURISDICTIONS element to its corresponding parent PIN_FLD_CUSTOM_TAX_BAL_IMPACTS element by using the PIN_FLD_ELEMENT_ID field.

      Note:

      BRM uses this same method to link PIN_FLD_TAX_JURISDICTIONS elements to corresponding parent PIN_FLD_BAL_IMPACTS elements in the /event object.

  5. Create an instance of your custom tax storable class in the BRM database by calling PCM_OP_CREATE_OBJ.

  6. Drop the PIN_FLD_FIELD_NAMES arrays from PCM_OP_RATE_POL_POST_TAX output flist, because they are no longer needed.

    Note:

    • In the rare case that no taxes are computed, the policy input flist will include a single PIN_FLD_TAXES element set to 0 and no PIN_FLD_SUBTOTAL elements. Likewise, when a jurisdiction check is performed to validate the account address, the policy input flist will not include a PIN_FLD_TAXES element. In both cases, you do not need to create a new instance of your custom tax storable class.

    • For event-time taxation, the PCM_OP_RATE_POL_POST_TAX input flist does not include the PIN_FLD_EVENT_OBJ field.

    • For reporting purposes, you can relate a taxed event's default tax fields with the additional tax fields by using the /event POID as the join criterion between the /event object and your custom tax object.