Skip to Content
Technical Articles
Author's profile photo Franz Emathinger

S/4HANA Conversion / Business Partner / Pre-checks / Linked Customers & Vendors (e.g. error message R1367)

Business Partner implementation is one of the largest work packages in many S/4HANA Conversion (pre-)projects. Therefore, SAP is expanding the toolbox to support customers with this transition (e.g. CVI Cockpit as announced in 2832085 – New Central Cockpit for Customer Vendor Integration (CVI) to Business Partner).

However, some analysis aspects are not covered out of the box yet.

A special topic is linked Customers & Vendors that should become one Business Partner (BP). From my point of view, this is the biggest conceptual benefit of using Business Partners.

Aspects to be considered are

  1. Which numbers are overlapping (same for customer & vendor), but not linked?
    -> These are most likely independent entities.
    -> How much exist? Who is affected?
    -> Based on that information, decide how to move forward (e.g. use the same numbers for BP and customers/vendors, create new ones, use a prefix etc..)
  2. Which entities are linked multiple times?
    -> only 1:1 links are possible. E.g. you cannot link one customer with two vendors.
    -> identify multiple links and determine correct ones.
    -> de-linked incorrect links.
  3. Customers & Vendors to be linked need to have the same general data (ADRC)
    -> 2716945 – CVI: Consistency error – Message no. R1367 points out the fields that need to be aligned
    -> manually this is very cumbersome and error prone
    -> some fields like LANGU_CR cannot even be changed in the UI

Some of these questions can be answered with simple queries easily, other ones are a bit trickier.

It makes sense to create a report to support the process, because a couple of iterations and business involvement are required.

 

The report does not change any data, it is only for analysis purposes.

 

REPORT ztbcvi_prechk.

PARAMETERS: p_equal TYPE xflag RADIOBUTTON GROUP r1, "Which numbers are overlapping, but not linked with each other?
            p_ref   TYPE xflag RADIOBUTTON GROUP r1, "Which entites are linked multiple times?
            p_r1367 TYPE xflag RADIOBUTTON GROUP r1 DEFAULT 'X'. "2716945 - CVI: Consistency error - Message no. R1367

START-OF-SELECTION.

  IF p_equal = abap_true.
    PERFORM same_number_no_link.

  ELSEIF p_ref = abap_true.
    PERFORM multi_links.

  ELSEIF p_r1367 = abap_true.
    PERFORM missmatch_general_data.

  ENDIF.

*&---------------------------------------------------------------------*
*&      Form  MULTI_LINKS
*&---------------------------------------------------------------------*
FORM multi_links.

  SELECT k~kunnr,
         l~name1 AS lif_name1,
         k~name1 AS kun_name1,
         k~loevm AS kun_loevm,
         l~lifnr,
         l~loevm AS lif_loevm,
         ' '  as multi
    FROM lfa1 AS l
    INNER JOIN kna1 AS k ON l~kunnr = k~kunnr
    UNION
    SELECT k~kunnr,
           l~name1 AS lif_name1,
           k~name1 AS kun_name1,
           k~loevm AS kun_loevm,
           l~lifnr,
           l~loevm AS lif_loevm,
          ' ' as multi
    FROM kna1 AS k
    INNER JOIN lfa1 AS l ON k~lifnr = l~lifnr
    INTO TABLE @DATA(linked_CVs).

  DATA(cpy_linked_cv) = linked_CVs.

  LOOP AT cpy_linked_cv ASSIGNING FIELD-SYMBOL(<li>).
    LOOP AT cpy_linked_cv TRANSPORTING NO FIELDS WHERE kunnr = <li>-kunnr AND lifnr <> <li>-lifnr.
      <li>-multi = abap_true.
    ENDLOOP.
    LOOP AT linked_CVs TRANSPORTING NO FIELDS WHERE kunnr <> <li>-kunnr AND lifnr = <li>-lifnr.
      <li>-multi = abap_true.
    ENDLOOP.

  ENDLOOP.
  cl_demo_output=>display( cpy_linked_cv ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  MISSMATCH_GENERAL_DATA
*&---------------------------------------------------------------------*
FORM missmatch_general_data.
  TYPES: BEGIN OF output_structure,
           tablename TYPE  tabname,
           fieldname TYPE  feldname,
           kunnr     TYPE  kunnr,
           kun_loevm TYPE  loevm,
           kun_field TYPE  char100,
           lifnr     TYPE  lifnr,
           lif_loevm TYPE  loevm,
           lif_field TYPE  char100,
         END OF output_structure.


  DATA: difference_cv  TYPE          output_structure,
        differences_cv TYPE TABLE OF output_structure,
        venddescr      TYPE REF TO   cl_abap_structdescr,
        custdescr      TYPE REF TO   cl_abap_structdescr.

  FIELD-SYMBOLS:
    <vend_comp>  TYPE abap_compdescr,
    <cust_comp>  TYPE abap_compdescr,
    <vend_field> TYPE any,
    <cust_field> TYPE any.


  SELECT k~kunnr,
        k~loevm AS kun_loevm,
        l~lifnr,
        l~loevm AS lif_loevm,
        k~adrnr AS cust_adrnr,
        l~adrnr AS vend_adrnr
   FROM lfa1 AS l
   INNER JOIN kna1 AS k ON l~kunnr = k~kunnr
    UNION
    SELECT k~kunnr,
        k~loevm AS kun_loevm,
        l~lifnr,
        l~loevm AS lif_loevm,
        k~adrnr AS cust_adrnr,
        l~adrnr AS vend_adrnr
   FROM lfa1 AS l
   INNER JOIN kna1 AS k ON l~lifnr = k~lifnr
   INTO TABLE @DATA(linked_CVs).

* compare address data
  LOOP AT linked_CVs ASSIGNING FIELD-SYMBOL(<link>).
    SELECT SINGLE * FROM adrc WHERE addrnumber = @<link>-cust_adrnr INTO @DATA(cust_adrc).
    SELECT SINGLE * FROM adrc WHERE addrnumber = @<link>-vend_adrnr INTO @DATA(vend_adrc).

*   Initialize data not to be compared.
    CLEAR: vend_adrc-adrc_uuid,         cust_adrc-adrc_uuid,
           vend_adrc-addrnumber,        cust_adrc-addrnumber,
           vend_adrc-date_from,         cust_adrc-date_from,
           vend_adrc-nation,            cust_adrc-nation,
           vend_adrc-fax_number,        cust_adrc-fax_number ,
           vend_adrc-fax_extens,        cust_adrc-fax_extens,
           vend_adrc-flagcomm2,         cust_adrc-flagcomm2,
           vend_adrc-flagcomm3,         cust_adrc-flagcomm3,
           vend_adrc-flagcomm4,         cust_adrc-flagcomm4,
           vend_adrc-flagcomm5,         cust_adrc-flagcomm5,
           vend_adrc-flagcomm6,         cust_adrc-flagcomm6,
           vend_adrc-flagcomm7,         cust_adrc-flagcomm7,
           vend_adrc-flagcomm8,         cust_adrc-flagcomm8,
           vend_adrc-flagcomm9,         cust_adrc-flagcomm9,
           vend_adrc-flagcomm10,        cust_adrc-flagcomm10,
           vend_adrc-flagcomm11,        cust_adrc-flagcomm11,
           vend_adrc-flagcomm12,        cust_adrc-flagcomm12,
           vend_adrc-flagcomm13,        cust_adrc-flagcomm13,
           vend_adrc-tel_number,        cust_adrc-tel_number,
           vend_adrc-tel_extens,        cust_adrc-tel_extens.

    venddescr ?= cl_abap_typedescr=>describe_by_data( vend_adrc ).
    ASSIGN vend_adrc TO FIELD-SYMBOL(<vend>).

    custdescr ?= cl_abap_typedescr=>describe_by_data( vend_adrc ).
    ASSIGN cust_adrc TO FIELD-SYMBOL(<cust>).

* compare fields
    IF vend_adrc <> cust_adrc.
      LOOP AT venddescr->components ASSIGNING <vend_comp>.
        LOOP AT custdescr->components ASSIGNING <cust_comp> WHERE name = <vend_comp>-name.
          ASSIGN COMPONENT <vend_comp>-name OF STRUCTURE <vend> TO <vend_field>.
          ASSIGN COMPONENT <cust_comp>-name OF STRUCTURE <cust> TO <cust_field>.
          IF <cust_field> <> <vend_field>.
            CLEAR difference_cv.
            difference_cv-tablename = 'ADRC'.
            difference_cv-fieldname = <vend_comp>-name.
            difference_cv-kunnr     = <link>-kunnr.
            difference_cv-kun_loevm = <link>-kun_loevm.
            difference_cv-kun_field = <cust_field>.
            difference_cv-lifnr     = <link>-lifnr.
            difference_cv-lif_loevm = <link>-lif_loevm.
            difference_cv-lif_field = <vend_field>.
            APPEND difference_cv TO differences_cv.
          ENDIF.
        ENDLOOP.
      ENDLOOP.
    ENDIF.
  ENDLOOP.

  cl_demo_output=>display( differences_cv ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SAME_NUMBER_NO_LINK
*&---------------------------------------------------------------------*
FORM same_number_no_link.

  SELECT k~kunnr,
         k~loevm       AS kun_loevm,
         k~name1       AS kun_name1,
         k~ktokd,
         l~lifnr,
         l~loevm       AS lif_loevm,
         l~name1       AS lif_name1,
         l~ktokk
    FROM lfa1 AS l
    INNER JOIN kna1 AS k ON l~kunnr <> k~kunnr AND l~lifnr = k~kunnr
    INTO TABLE @DATA(same_number_no_link).

  cl_demo_output=>display( same_number_no_link ).
ENDFORM.

Hope this report supports you in your transition to S/4HANA, good luck!

Best regards,

Franz

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      Thanks for sharing but I don't quite understand the design of this report.

      Why do you need to use the dictionary structures and a dynpro screen? Output can be handled by using SALV class. Actually there seems to be no need for ALV at all, from what I see, so this could be just data selection followed by cl_demo_output. We shouldn't be using routines anymore either. The ABAP team that is getting ready to move to S/4HANA should really stop writing programs like that, no matter if it's just a utility report.

      It might be a good idea to post the code on Github where at least others could improve it. Please check Clean ABAP guidelines when you get a chance on how to create better programs.

      Thank you.

      Author's profile photo Franz Emathinger
      Franz Emathinger
      Blog Post Author

      Thanks Jelena for taking your time to write your comment. I agree on your feedback and simplified some parts of the source code right away.

      I did not yet see the big advantage of classes over routines for small utility reports, but maybe there is a point in creating a "good habit" for small reports as well. I did not refactor that part yet, as I want to have a look on how to share it via Github first.

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      Thanks for an update! The code looks much better now.

      Author's profile photo Carlos Saavedra
      Carlos Saavedra

      Thanks Franz !

      very usefull indeed !

      This kind of report should have already been part of the CVI cockpit pre-checks...