Skip to Content
Author's profile photo Mark Wagener

BSAO – Mapping – Adding Tax Details on Invoice items (SD | Supplier)

This Blog is inspired by BSAO – Mapping – Adding Tax Details on PO items by Joe Dutra (thanks very much for sharing it and for your offer of assistance).

This is a code snippet to demonstrate how to get the tax information from SAP and map it to the cXML INVC document, so it is transmitter to Buyers over the Ariba Network.

This development was done for German tax scenario. Error handling could be further enhanced (exception handling of standard methods). It is not tested for service lines and all other scenarios. Moreover standard SAP FM are used for convesion of currency amount (string) to decimal. Please be aware that these FM could de deleted by SAP during upgrades.

We will map the following fields with the tax details from the ECC PO.

Configuration

We will share the CC Invoice configuration, maintaining the SAP Tax code to cXML Classification relationship at the SPRO activity:

Integration with Other SAP Components –> SAP Business Suite Integration Component for Ariba –> Application-Specific Settings –> SAP ERP Integration Component for Ariba –> Integration for Vendors –> Define Mapping Settings for Billing Documents –> MAP SAP ERP SD Tax Code to cXML Tax Category

Development

Use the BAdI ARBERP_OUTBOUND_MAPPING, method map_vbrk_to_invc_out to map the Tax details fields. In the example bellow, the method invc_itm_map_tax_code was created to encapsulate all the Tax Details relevant changes.

Method

method invc_itm_map_tax_code.

    types: begin of ty_condition,
             knumv type konv-knumv,
             kposn type konv-kposn,
             kschl type konv-kschl,
             kawrt type konv-kawrt,
             kbetr type konv-kbetr,
             waers type konv-waers,
             mwsk1 type konv-mwsk1,
             kwert type konv-kwert,
           end of ty_condition.

    data t_condition type table of ty_condition.
    field-symbols <fs_condition> type ty_condition.

    field-symbols <fs_item> type line of arberp_xinvc_t_dtl_item.

    data mo_config_instance type ref to if_arberp_config_access.
    data mo_helper_out_instance type ref to if_arberp_helper_int_out.

    data ls_ext_tax_category type arberp_s_taxc_sd.
    data ls_taxdetail type line of arberp_xinvc_t_tax_detail.
    data lf_tax_rate  type msatz_f05l.
    data ls_t001      type t001.
    data lc_tax_desc  type text1_007s.
    data lv_tax_rate_decimals type i.
    data ls_kposn type konv-kposn.
    data ls_gross_amount type konv-kwert.
    data ls_net_amount type konv-kwert.

    data: ls_content  type string,
          ls_xml_lang type string.

    "Initialize helpers
    mo_config_instance     = cl_arberp_config_factory=>get_instance( ).

    call method cl_arberp_helper_factory_int=>get_instance_helper_int_out
      importing
        eo_instance = mo_helper_out_instance.

    "get tax conditions
    select   knumv
             kposn
             kschl
             kawrt
             kbetr
             waers
             mwsk1
             kwert
    from konv
    into corresponding fields of table t_condition
    where knumv = pi_condition_no
      and kschl = 'MWST'.

    if sy-subrc is not initial.
      " error handling here
      if 1 = 2. message e021(zov_ariba). endif. "#EC MG_MISSING "for where-used-list
      zov_cl_utilities=>add_message_static_bapi( exporting    pi_id =  'ZOV_ARIBA'
                                                              pi_number = '021'
                                                              pi_type = 'E'
                                                              pi_message_v1 = pi_condition_no
                                                    changing  pie_t_message = pie_t_messages ).
      pie_skip_sending = abap_true.
    endif.

    " Get Company Country
    call function 'FI_COMPANY_CODE_DATA'
      exporting
        i_bukrs      = pi_company_code
      importing
        e_t001       = ls_t001
      exceptions
        system_error = 1.

    if sy-subrc is not initial.
      " error handling here
      if 1 = 2. message e022(zov_ariba). endif. "#EC MG_MISSING "for where-used-list
      zov_cl_utilities=>add_message_static_bapi( exporting   pi_id =  'ZOV_ARIBA'
                                                             pi_number = '022'
                                                             pi_type = 'E'
                                                             pi_message_v1 = pi_company_code
                                                   changing  pie_t_message = pie_t_messages ).
      pie_skip_sending = abap_true.
    endif.

    "create <TAX> for each item
    loop at pie_item_detail assigning <fs_item>.
      "use filled reference field
      clear ls_kposn.
      ls_kposn = <fs_item>-invoice_detail_item_reference-line_number.       "<fs_item>-invoice_detail_item_reference-line_number has no "real" initial value,
      "therefore "if <fs_item>-invoice_detail_item_reference-line_number is initial" did not work
      if ls_kposn is initial.
        ls_kposn = <fs_item>-invoice_line_number.
      endif.

      "get corresponding tax condition record for this item
      read table t_condition
      assigning <fs_condition>
      with key kposn = ls_kposn.

      if sy-subrc = 0.
        "Get the Tax category from the configuration -> see CL_ARBERP_VBRK_INVC_OUT-map_invc_summary
        "lines 11139 - 1155
        mo_config_instance->get_sd_invc_tax_category(
          exporting
            iv_customer_id      = pi_payer "KUNRG
            iv_tax_code         = <fs_condition>-mwsk1
            iv_country_code     = pi_country
          importing
            es_ext_tax_category = ls_ext_tax_category
        ).

        if ls_ext_tax_category is initial.
          "error
          if 1 = 2. message e102(arberp_map_sd). endif. "#EC MG_MISSING "for where-used-list
          zov_cl_utilities=>add_message_static_bapi( exporting pi_id =  if_arberp_t100_map_sd_c=>gc_msg_class_name
                                                               pi_message_v1 = <fs_condition>-mwsk1
                                                               pi_number = if_arberp_t100_map_sd_c=>gc_msgno_102
                                                               pi_type = 'E'
                                                     changing  pie_t_message = pie_t_messages ).
          pie_skip_sending = abap_true.
        endif.

        if <fs_condition>-waers is initial.
          "take it from pi_currency
          <fs_condition>-waers = pi_currency.
        endif.

        "Set tax-rate and adjust decimals if necessary
        lf_tax_rate = <fs_condition>-kbetr.

        " IDOC logic: currently wrong amount of decimals, work-around and change from 2 to 3 decimal places
        " adopted from see CL_ARBERP_VBRK_INVC_OUT-map_invc_summary lines 1160 - 1164
        describe field <fs_condition>-kbetr decimals lv_tax_rate_decimals.
        if lv_tax_rate_decimals eq 2.
          divide lf_tax_rate by 10.
        endif.

        "Get Tax description -> adopted from see CL_ARBERP_VBRK_INVC_OUT-map_invc_summary lines 1211 - 1219
        call method mo_helper_out_instance->get_tax_description
          exporting
            iv_comp_code            = pi_company_code
            iv_tax_code             = <fs_condition>-mwsk1
            iv_langu                = pi_salesorg_lang
          importing
            ev_tax_code_description = ls_content
            ev_tax_code_xml_lang    = ls_xml_lang.

        "*--------------------------------------------------------------------*
        "*       Map the tax rate and category to the cxml
        "*--------------------------------------------------------------------*
        clear ls_taxdetail.
        " Tax Amount
        <fs_item>-tax-money-currency = <fs_condition>-waers.
        <fs_item>-tax-money-content = <fs_condition>-kwert.

        "convert gross_amount (string) to currency
        call function 'HRCM_STRING_TO_AMOUNT_CONVERT'
          exporting
            string            = <fs_item>-gross_amount-money-content
            decimal_separator = '.'
          importing
            betrg             = ls_gross_amount
          exceptions
            convert_error     = 1
            others            = 2.
        if sy-subrc <> 0.
          if 1 = 2. message e000(zov_ariba). endif. "#EC MG_MISSING "for where-used-list
          zov_cl_utilities=>add_message_static_bapi( exporting  pi_id =  'ZOV_ARIBA'
                                                                pi_message_v1 = sy-msgid
                                                                pi_message_v2 = sy-msgno
                                                                pi_message_v3 = sy-msgv1
                                                                pi_message_v4 = sy-msgv2
                                                                pi_number = '000'
                                                                pi_type = sy-msgty
                                                      changing  pie_t_message = pie_t_messages ).
          pie_skip_sending = abap_true.
        endif.

        "convert net_amount (string) to currency
        call function 'HRCM_STRING_TO_AMOUNT_CONVERT'
          exporting
            string            = <fs_item>-net_amount-money-content
            decimal_separator = '.'
          importing
            betrg             = ls_net_amount
          exceptions
            convert_error     = 1
            others            = 2.
        if sy-subrc <> 0.
          if 1 = 2. message e000(zov_ariba). endif. "#EC MG_MISSING "for where-used-list
          zov_cl_utilities=>add_message_static_bapi( exporting  pi_id =  'ZOV_ARIBA'
                                                                pi_message_v1 = sy-msgid
                                                                pi_message_v2 = sy-msgno
                                                                pi_message_v3 = sy-msgv1
                                                                pi_message_v4 = sy-msgv2
                                                                pi_number = '000'
                                                                pi_type = sy-msgty
                                                      changing  pie_t_message = pie_t_messages ).
          pie_skip_sending = abap_true.
        endif.

        add <fs_condition>-kwert to ls_gross_amount.
        <fs_item>-gross_amount-money-content = ls_gross_amount. "also add tax-amount to gross-amount
        add <fs_condition>-kwert to ls_net_amount.
        <fs_item>-net_amount-money-content = ls_net_amount. "also add tax-amount to net-amount

        if pi_purpose = 'lineLevelCreditMemo'.                                              "set negative-sign as this is a Credit Memo
          multiply <fs_item>-tax-money-content by -1.
        endif.
        " SAP Tax Code
        <fs_item>-tax-description-xml_lang = ls_xml_lang.
        <fs_item>-tax-description-content = <fs_condition>-mwsk1.
        " Category and rate
        ls_taxdetail-category = ls_ext_tax_category-ext_tax_type.
        ls_taxdetail-percentage_rate = lf_tax_rate.
        "TaxPointDate
        "TaxPointDate is mandatory when tax is VAT. The date when the VAT becomes due.
        "Ariba checks only the presence, so you can use the invoice date.
        "create timestamp, use invoice date
        mo_helper_out_instance->convert_date_to_iso8601(
            exporting iv_date = pi_invoice_date
*                  iv_time =  sy-timlo                                                      "no need to provide time, system uses default time
            importing ev_date_iso = ls_taxdetail-tax_point_date ).
        " Taxable Amount
        if lf_tax_rate <> 0.
          ls_taxdetail-taxable_amount-money-content = <fs_condition>-kawrt.
          if pi_purpose = 'lineLevelCreditMemo'.                                            "set negative-sign as this is a Credit Memo
            multiply ls_taxdetail-taxable_amount-money-content by -1.
          endif.
        endif.
        ls_taxdetail-taxable_amount-money-currency =  <fs_condition>-waers.
        " Tax Amount
        ls_taxdetail-tax_amount-money-content = <fs_condition>-kwert.
        if pi_purpose = 'lineLevelCreditMemo'.                                              "set negative-sign as this is a Credit Memo
          multiply ls_taxdetail-tax_amount-money-content by -1.
        endif.
        ls_taxdetail-tax_amount-money-currency = <fs_condition>-waers.
        " exemptDetail
        if lf_tax_rate = 0.
          ls_taxdetail-exempt_detail = 'exempt'.            "#EC NOTEXT
        endif.
        " TaxLocation = Tax Jurisdiction
*        ls_taxdetail-tax_location-content = ls_po_item-taxjurcode.
*        ls_taxdetail-tax_location-xml_lang = ls_xml_lang.

        " description
        call function 'TAX_CODE_TEXT_GET'
          exporting
            i_langu               = ls_t001-spras
            i_bukrs               = pi_company_code
            i_mwskz               = <fs_condition>-mwsk1
          importing
            e_text1               = lc_tax_desc
          exceptions
            text_not_found        = 1
            company_not_found     = 2
            country_not_found     = 3
            tax_procedure_missing = 4
            others                = 5.
        if sy-subrc is initial.
          ls_taxdetail-description-content = lc_tax_desc.
          ls_taxdetail-description-xml_lang = ls_xml_lang.
        else.
          " error handling here
          if 1 = 2. message e024(zov_ariba). endif. "#EC MG_MISSING "for where-used-list
          zov_cl_utilities=>add_message_static_bapi( exporting pi_id =  'ZOV_ARIBA'
                                                              pi_message_v1 = ls_t001-spras
                                                              pi_message_v2 = pi_company_code
                                                              pi_message_v3 = <fs_condition>-mwsk1
                                                              pi_number = '024'
                                                              pi_type = 'E'
                                                    changing  pie_t_message = pie_t_messages ).
          pie_skip_sending = abap_true.
        endif.
        "add tax information to item
        append ls_taxdetail to  <fs_item>-tax-tax_detail.
        "--------------------------------------------------------------------*
      else.
        "error -> could not create tax for this item, as no tax condition record was
        "found for this item
        if 1 = 2. message e023(zov_ariba). endif. "#EC MG_MISSING "for where-used-list
        zov_cl_utilities=>add_message_static_bapi( exporting pi_id =  'ZOV_ARIBA'
                                                              pi_message_v1 = ls_kposn
                                                              pi_message_v2 = pi_condition_no
                                                              pi_number = '023'
                                                              pi_type = 'E'
                                                    changing  pie_t_message = pie_t_messages ).
        pie_skip_sending = abap_true.
      endif.
    endloop.
  endmethod.

 

Signature

 methods invc_itm_map_tax_code
    importing pi_invoice_no    type vbeln
              pi_invoice_date  type vbrk-fkdat
              pi_purpose       type string
              pi_payer         type kunrg
              pi_condition_no  type knumv
              pi_country       type landtx
              pi_currency      type waerk
              pi_company_code  type bukrs
              pi_salesorg_lang type spras
    changing  pie_item_detail  type arberp_xinvc_t_dtl_item
              pie_t_messages   type bapirettab
              pie_skip_sending type xfeld.

For the missing method  ADD_MESSAGE_STATIC_BAPI of class ZOV_CL_UTILITIES you can use:

method ADD_MESSAGE_STATIC_BAPI.
    data wa_message type line of BAPIRETTAB.

    clear wa_message.

    wa_message-id = pi_id.
    wa_message-type = pi_type.
    wa_message-number = pi_number.
    wa_message-message_v1 = pi_message_v1.
    wa_message-message_v2 = pi_message_v2.
    wa_message-message_v3 = pi_message_v3.
    wa_message-message_v4 = pi_message_v4.

    append wa_message to pie_t_message.
endmethod.

Result

Here is the cXML output for an Invoice with Tax data:

<Tax>
   <Money currency="EUR">475.00 </Money>
   <Description xml:lang="de">A1</Description>
   <TaxDetail category="vat" percentageRate="19.000 " taxPointDate="2018-01-25T12:00:00+01:00">
      <TaxableAmount>
         <Money currency="EUR">2500.00 </Money>
      </TaxableAmount>
      <TaxAmount>
         <Money currency="EUR">475.00 </Money>
      </TaxAmount>
     <Description xml:lang="de">Ausgangssteuer 19%</Description>
   </TaxDetail>
</Tax>

Make sure to also set

<InvoiceDetailLineIndicator isTaxInLine="yes"/>

on <InvoiceDetailRequestHeader> level!

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michelle Crapo
      Michelle Crapo

      Very nice!!!  I love the code snippets. I love examples from the "fiance" side of SAP. That is my weakness. Ready things like this could make it another strength for me. A definite bookmark.

      Thank you!

      Michelle