Skip to Content

Purpose

In most of the Business scenarios it is required to validate the master data before loading to the master data objects.

This tool automates the process of validating the master data and also outputs the records along with the appropriate error message which have invalid master data.

Overview

The main features of this tool are:

–       If the master data validation fails due to the integrity check in the transformation, DTP request turns red and the error stack records gets updated.

–       Send an e-mail to the user with erroneous records file as an attachment.

–       Automatically deletes the erroneous DTP and PSA request.

It can be used in the Process Chains for automation of the process.

Configuration Steps

In this document, example of data load from flat file Data Source to DSO is being considered.

1) Enable the Integrity check in the Transformation for master data validation, system will automatically validates the master data records and turns the DTP request red in case the validation fails.

Transformation.png

2) Change the DTP settings for error handling, enable “Update Valid Records, No Reporting (Request Red)” in DTP.

DTP.png

3) Enter Data Source, Target DSO Technical Name and the receiver e-mail address in the program and save it as a variant.

If the master data validation fails due to the integrity check in the transformation, DTP request turns red and the error stack records gets updated.

The program will fetch the error records from the error stack table along with the error messages and send the file to the user as an attachment.

Also, if the Delete DSO & PSA Requests is checked, then it deletes both the erronous DTP request as well as PSA request.

Variant.png

4) Configure this program in the ABAP process type in case of DTP load failure, so as to automate the whole process.

Process Chain.png

Program Code

Make selection screen with following parameters:

1) Data Source technical name.

2) Target DSO technical name

3) Receiver e-mail address

4) Check Box – Delete DSO & PSA request

1) Fetch error request from target DSO

  SELECT rnr UP TO 1 ROWS  INTO gv_rnr FROM rsmonicdp
  WHERE icube   = p_tgt
  AND   status  = ‘@0A@’“Error Status
  ENDSELECT.
  IF sysubrc <> 0.
    “Do nothing
  ENDIF.


2) Fetch SID of the error request:

SELECT SINGLE sid INTO gv_sid FROM /bi0/srequid
  WHERE requid = gv_rnr.
  IF sysubrc = 0.
** Retrieve DTP name
    CLEAR: gv_dtp.

    SELECT SINGLE dtp INTO gv_dtp FROM rsbkrequest
      WHERE requid = gv_sid.
    IF sysubrc = 0.
      “Do nothing
    ENDIF.


3) Retrieve Error Stack table name

** Retrieve Error Stack Table name
  CLEAR gv_odsname.

  SELECT odsname_tech UP TO 1 ROWS
    INTO  gv_odsname
    FROM  rstsods
    WHERE version = ‘A’
    AND   userobj = gv_dtp.
  ENDSELECT.
  IF sysubrc = 0.
    “Do nothing
  ENDIF.

  CREATE DATA gv_generic TYPE TABLE OF (gv_odsname).
  CREATE DATA gv_wa TYPE (gv_odsname).

  ASSIGN gv_generic->* TO <fs_generic>.

  ASSIGN gv_wa->* TO <fs_wa>.

** Retrieve data from error stack table
  SELECT * FROM (gv_odsname)
    INTO TABLE <fs_generic>.
  IF sysubrc <> 0.
    “do nothing
  ENDIF.


4) Retrieve error stack records and its corresponding error messages

DATA: lwa_tab_line   TYPE soli,
        lwa_tab_line2  TYPE soli,
        lv_msg         TYPE string,
        lv_len1        TYPE i,
        lv_len2        TYPE i,
        lv_len3        TYPE i.

  DATA: lv_datapacket_number TYPE i,
        lv_datarecord_number TYPE i,
        lv_tablename         TYPE RSD_TABLNM.

  DATA: lt_error_messages   TYPE STANDARD TABLE OF ty_error_messages,
        lwa_error_messages  TYPE ty_error_messages.

  CONSTANTS: con_tab TYPE c VALUE cl_abap_char_utilities=>horizontal_tab,
             con_cret TYPE c VALUE cl_abap_char_utilities=>cr_lf.

** Identify if the PSA table is partioned or not

  CLEAR lv_tablename.

  lv_tablename = gv_odsname.

  CALL FUNCTION ‘RSDU_PARTITIONS_INFO_GET’
    EXPORTING
      i_tablnm              = lv_tablename
    EXCEPTIONS
      table_not_exists      = 1
      table_not_partitioned = 2
      inherited_error       = 3
      OTHERS                = 4.
  IF sysubrc = 0.
    lv_datapacket_number = 2.
    lv_datarecord_number = 4.
  ELSEIF sysubrc = 2.
    lv_datapacket_number = 2.
    lv_datarecord_number = 3.
  ENDIF.

** Display the error stack table to the output
  LOOP AT <fs_generic> ASSIGNING <fs_wa>.
    CLEAR: lwa_tab_line, lv_len1, lv_len2, lv_len3.
    DO.
      IF syindex = lv_datapacket_number.
        ASSIGN COMPONENT lv_datapacket_number OF STRUCTURE <fs_wa> TO <fs_datapacket>.
      ELSEIF syindex = lv_datarecord_number.
        ASSIGN COMPONENT lv_datarecord_number OF STRUCTURE <fs_wa> TO <fs_datarecord>.
      ELSEIF syindex > lv_datarecord_number.
        ASSIGN COMPONENT syindex OF STRUCTURE <fs_wa> TO <fs_field>.
        IF sysubrc = 0.
          DESCRIBE FIELD <fs_field> LENGTH lv_len2 IN BYTE MODE.
          lv_len3 = lv_len1 + lv_len2.
          IF lv_len3 > 255.
            EXIT.
          ENDIF.
          IF lv_len2 > 0.
            MOVE <fs_field> TO lwa_tab_line+lv_len1(lv_len2).
            CONCATENATE lwa_tab_line con_tab INTO lwa_tab_line.
          ENDIF.
          lv_len1 = lv_len1 + lv_len2 + 1.
          lv_len3 = lv_len1.
          WRITE: <fs_field>.
        ELSE.
          EXIT.
        ENDIF.
      ENDIF.
    ENDDO.
    NEW-LINE.

**  Retrieve corresponding error messages

    REFRESH lt_error_messages.

    SELECT msgid msgno msgty msgv1 msgv2 msgv3 msgv4
    FROM   rsberrorlog
    INTO   TABLE lt_error_messages
    WHERE  request   = gv_sid
    AND    datapakid = <fs_datapacket>
    AND    record    = <fs_datarecord>.
    IF sysubrc EQ 0.
      LOOP AT lt_error_messages INTO lwa_error_messages.

        CLEAR lv_msg.

        CALL FUNCTION ‘FORMAT_MESSAGE’
          EXPORTING
            id        = lwa_error_messagesmsgid
            lang      = ‘-D’
            no        = lwa_error_messagesmsgno
            v1        = lwa_error_messagesmsgv1
            v2        = lwa_error_messagesmsgv2
            v3        = lwa_error_messagesmsgv3
            v4        = lwa_error_messagesmsgv4
          IMPORTING
            msg       = lv_msg
          EXCEPTIONS
            not_found = 1
            OTHERS    = 2.
        IF sysubrc = 0.
          CONCATENATE lwa_tab_line lv_msg INTO lwa_tab_line2.
          CONDENSE lwa_tab_line2.
          CONCATENATE con_cret lwa_tab_line2 INTO lwa_tab_line2.
          APPEND lwa_tab_line2 TO gt_tab_lines.
          CLEAR lwa_tab_line2.
        ENDIF.
      ENDLOOP.
    ENDIF.

  ENDLOOP.

5) Pass the Error Stack records as an attachment to the email id.

DATAlv_subject       TYPE        so_obj_des,
         it_contents      TYPE        soli_tab,
         lv_ref_document  TYPE REF TO cl_document_bcs,
         lv_ref_documentw TYPE REF TO cl_bcs,
         lv_recipient     TYPE REF TO if_recipient_bcs,
         lv_result        TYPE        os_boolean,
         lv_count         TYPE        i,
         lv_size          TYPE        soodobjlen.

  lv_subject = ‘Master Data Validation Failed Records’(001).

** Create document with contents
  CREATE OBJECT lv_ref_document.

  lv_ref_document = cl_document_bcs=>create_document(
        i_type       = ‘HTM’
        i_subject    = lv_subject
        i_length     = ‘1000’
        i_language   = sylangu
        i_importance = ‘1’
        i_text       = it_contents ).

** Creat attachment

  DESCRIBE TABLE gt_tab_lines LINES lv_count.

  lv_size = lv_count * 255.

  CALL METHOD lv_ref_document->add_attachment
    EXPORTING
      i_attachment_type    = ‘XLS’
      i_attachment_subject = ‘Error Records’(002)
      i_attachment_size    = lv_size
      i_att_content_text   = gt_tab_lines.

* CREATING PERSISTENT OBJECT WILL ALLOW YOU TO SET THE DOCUMENT IN THE MAIL
  lv_ref_documentw = cl_bcs=>create_persistent( ).
  CALL METHOD lv_ref_documentw->set_document( lv_ref_document ).

* EMAIL AS GIVEN IN THE SELECTION SCREEN.
  LOOP AT so_rcvr.
    gv_email = so_rcvrlow.
    lv_recipient = cl_cam_address_bcs=>create_internet_address( gv_email ).
    “Add recipient to send request
    CALL METHOD lv_ref_documentw->add_recipient
      EXPORTING
        i_recipient = lv_recipient
        i_express   = ‘X’.
  ENDLOOP.

* SEND THE MAIL
  CALL METHOD lv_ref_documentw->send(
    EXPORTING
      i_with_error_screen = ‘X’
    RECEIVING
      result              = lv_result ).

  IF lv_result = ‘X’.
    NEW-LINE.
    NEW-LINE.
    WRITE:/ ‘E-mail sent successfully’(003).
    COMMIT WORK.
  ELSE.
    NEW-LINE.
    NEW-LINE.
    WRITE:/ ‘Error in sending e-mail’(004).
    ROLLBACK WORK.
  ENDIF.


6) Delete the error request from the target DSO

DATA: lv_msg  TYPE string,
        lv_cube TYPE rsicconticube.

  REFRESH gt_parent_rnr.

  SELECT  parent_rnr INTO TABLE gt_parent_rnr
  FROM rsstatmanreqmap
  WHERE rnr         = gv_rnr
  AND dta_dest      = p_tgt
  AND dta_dest_type = ‘ODSO’.
  IF sysubrc = 0.
    “Do nothing
  ENDIF.

  CLEAR lv_cube.

  lv_cube = p_tgt.

** Delete DSO request only if the check box is checked.
  IF p_dso IS NOT INITIAL.
    CALL FUNCTION ‘RSSM_DELETE_REQUEST’
      EXPORTING
        request                    = gv_rnr
        infocube                   = lv_cube
      EXCEPTIONS
        request_not_in_cube        = 1
        infocube_not_found         = 2
        request_already_aggregated = 3
        request_already_comdensed  = 4
        no_enqueue_possible        = 5
        cube_in_planning_mode      = 6
        OTHERS                     = 7.
    IF sysubrc <> 0.
      CLEAR lv_msg.

      CALL FUNCTION ‘FORMAT_MESSAGE’
        EXPORTING
          id        = symsgid
          lang      = ‘-D’
          no        = symsgno
          v1        = symsgv1
          v2        = symsgv2
          v3        = symsgv3
          v4        = symsgv4
        IMPORTING
          msg       = lv_msg
        EXCEPTIONS
          not_found = 1
          OTHERS    = 2.
      IF sysubrc = 0.
        WRITE:/ lv_msg.
      ENDIF.
    ENDIF.
  ENDIF.


7) Delete corresponding PSA requests

*Retrieve PSA request
  DATA: lv_msg          TYPE string,
        lwa_parent_rnr  TYPE rsrequid.

  DATA: lwa_s_rsseldone TYPE rsseldone,
        lv_new_ds,
        lwa_s_rsis      TYPE rsis,
        lv_applnm       TYPE rsapplapplnm,
        lwa_s_rsdchabas TYPE rsdchabas.

  CONSTANTS: c_dtpprefix(1)     TYPE c VALUE ‘D’.

  IF p_dso IS NOT INITIAL.                    ” Check box to delete PSA request
    LOOP AT gt_parent_rnr INTO lwa_parent_rnr.
** Delete PSA Request
      CLEAR lwa_s_rsseldone.
      CALL FUNCTION ‘RSSM_RSSELDONE_READ’
        EXPORTING
          i_rnr           = lwa_parent_rnr
          i_single_select = ‘X’
        IMPORTING
          e_s_rsseldone   = lwa_s_rsseldone.

      IF lwa_s_rsseldonetyp = ‘I’.
        CALL FUNCTION ‘RSDS_DATASOURCE_OLDNEW’
          EXPORTING
            i_datasource = lwa_s_rsseldoneoltpsource
            i_logsys     = lwa_s_rsseldonelogsys
          IMPORTING
            e_new_isused = lv_new_ds.
        IF lv_new_ds IS INITIAL.
          IF NOT lwa_s_rsseldonesource IS INITIAL.
            SELECT SINGLE * FROM rsis INTO lwa_s_rsis WHERE
                   isource = lwa_s_rsseldonesource.
            lv_applnm = lwa_s_rsisapplnm.
          ELSE.
            lv_new_ds = ‘X’.
          ENDIF.
        ENDIF.
      ELSEIF lwa_s_rsseldonetyp = ‘O’.
        CALL FUNCTION ‘RSDS_DATASOURCE_OLDNEW’
          EXPORTING
            i_datasource = lwa_s_rsseldoneoltpsource
            i_logsys     = lwa_s_rsseldonelogsys
          IMPORTING
            e_new_isused = lv_new_ds.

        IF lv_new_ds IS INITIAL.
          IF NOT lwa_s_rsseldonesource IS INITIAL.
            SELECT SINGLE * FROM rsdchabas INTO lwa_s_rsdchabas WHERE
                   chabasnm = lwa_s_rsseldonesource.
            lv_applnm = lwa_s_rsdchabasapplnm.
          ELSE.
            lv_new_ds = ‘X’.
          ENDIF.
        ENDIF.
      ELSE.
        IF lwa_parent_rnr(1) = c_dtpprefix.
          CALL FUNCTION ‘RSS2_DTP_REQ_MAP_TO_SELDONE’
            EXPORTING
              i_rnr       = lwa_parent_rnr
            IMPORTING
              e_s_seldone = lwa_s_rsseldone.
          lv_new_ds = ‘X’.
        ENDIF.
      ENDIF.

      CALL FUNCTION ‘RSAR_ODS_API_DEL’
        EXPORTING
          i_request         = lwa_parent_rnr
          i_date            = lwa_s_rsseldoneseldate
          i_new_psa         = lv_new_ds
        EXCEPTIONS
          no_ods_found      = 3
          parameter_failure = 1
          OTHERS            = 2.
      IF sysubrc <> 0.             “Delete sy-subrc
        CLEAR lv_msg.

        IF NOT symsgid IS INITIAL AND NOT symsgno IS INITIAL.   ” Error message
          CALL FUNCTION ‘FORMAT_MESSAGE’
            EXPORTING
              id        = symsgid
              lang      = ‘-D’
              no        = symsgno
              v1        = symsgv1
              v2        = symsgv2
              v3        = symsgv3
              v4        = symsgv4
            IMPORTING
              msg       = lv_msg
            EXCEPTIONS
              not_found = 1
              OTHERS    = 2.
          IF sysubrc = 0.
            WRITE:/ lv_msg.
          ENDIF.
        ELSE.                 ” Error message
          CALL FUNCTION ‘FORMAT_MESSAGE’
            EXPORTING
              id        = ‘RSM1’
              lang     = ‘-D’
              no        = ‘206’
              v1        = lwa_parent_rnr
              v2        = symsgv2
              v3        = symsgv3
              v4        = symsgv4
            IMPORTING
              msg       = lv_msg
            EXCEPTIONS
              not_found = 1
              OTHERS    = 2.
          IF sysubrc = 0.
            WRITE:/ lv_msg.
          ENDIF.
        ENDIF.                ” Error message
      ENDIF.                  “Delete sy-subrc
    ENDLOOP.
  ENDIF.                    ” Check box to delete PSA request

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Matthew Billingham

    I’d advise getting an expert ABAPper to look at your code. Long, unencapsulated programs are expensive to maintain.

    Also – use SELECT SINGLE, rather than SELECT UP TO 1 ROWS. They do exactly the same thing, and the former is much easier to read than the latter.

    (0) 

Leave a Reply