Technical Articles
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
- 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..) - 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. - 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
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.
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.
Thanks for an update! The code looks much better now.
Thanks Franz !
very usefull indeed !
This kind of report should have already been part of the CVI cockpit pre-checks...