*&---------------------------------------------------------------------*
*& Report  Z_USR_AUDIT                                                 *
*& Audit oprvnn uivatel                                           *
*&---------------------------------------------------------------------*
*& Lukas Nyklicek, EPCOS s.r.o.                                        *
*& 9.10.2011                                                           *
*&---------------------------------------------------------------------*

REPORT z_usr_audit LINE-SIZE 108 NO STANDARD PAGE HEADING LINE-COUNT 90.

TYPE-POOLS icon.

TYPES:
* List of users
  BEGIN OF ty_user,
    bname TYPE usr02-bname,
  END   OF ty_user,
  ty_t_user TYPE TABLE OF ty_user,
  tv_c1       TYPE c LENGTH 1,
  BEGIN OF ts_1fld_obj,
    objct TYPE xuobject,
  END OF ts_1fld_obj,
  tt_1fld_obj TYPE STANDARD TABLE OF ts_1fld_obj,
  BEGIN OF ty_ust12_data,
        auth  TYPE ust12-auth,
        field TYPE ust12-field,
        von   TYPE ust12-von,
        bis   TYPE ust12-bis,
  END OF ty_ust12_data,
  tyt_ust12_data TYPE SORTED TABLE OF ty_ust12_data
                      WITH UNIQUE KEY auth field von bis,
  BEGIN OF ty_ust12_tab,
        objct TYPE ust12-objct,
        auth_data TYPE tyt_ust12_data,
  END OF  ty_ust12_tab,
  tyt_ust12_tab TYPE SORTED TABLE OF ty_ust12_tab
                      WITH UNIQUE KEY objct,
  BEGIN OF ts_user_ref,
    refuser TYPE xubname,
    bname   TYPE xubname,
  END OF ts_user_ref,
  tt_user_ref TYPE STANDARD TABLE OF ts_user_ref,
  BEGIN OF ts_usclass,
    bname TYPE xubname,
    class TYPE xuclass,
  END OF ts_usclass,
  tt_class TYPE TABLE OF ts_usclass,
  BEGIN OF ts_user,
    bname TYPE xubname,
  END OF ts_user,
  tt_user TYPE TABLE OF ts_user,
  BEGIN OF ts_prof,
    profn  TYPE xuprofile,
  END OF  ts_prof,
  tt_prof TYPE TABLE OF ts_prof,
  BEGIN OF ts_prf_lst,
     profn   TYPE xuprofile,
     subprof TYPE xuprofile,
     typ     TYPE xutyp,
  END OF ts_prf_lst,
  tt_prf_lst TYPE TABLE OF ts_prf_lst,
  BEGIN OF ts_auth,
    objct TYPE xuobject,
    auth  TYPE xuauth,
  END OF ts_auth,
  tt_auths TYPE TABLE OF ts_auth,
  BEGIN OF ts_auth_fld_type ,
    object     TYPE xuobject,
    auth       TYPE xuauth,
    field      TYPE xufield,
    low        TYPE xuval,
    high       TYPE xuval,
    merge_flag TYPE c LENGTH 1,
  END OF ts_auth_fld_type,
  tt_auth_fld_type   TYPE TABLE OF ts_auth_fld_type,
  tt_crit_val TYPE TABLE OF usref,
  BEGIN OF type_auth,
         auth LIKE ust12-auth,
  END OF type_auth,
  type_auth_table TYPE STANDARD TABLE OF type_auth.
*  types:
*     begin of ts_authx_spec,
*       fieldname type fieldname ,
*       rollname  type rollname,
*       domname   type domname,
*       valexi    type c,
*       entitytab type entitytab,
*     end of ts_authx_spec.
*   types: tt_authx_spec type table of ts_authx_spec.

CONSTANTS:
  gc_max_range_sel TYPE i VALUE 500,  "note 978447
  c_searchtype_and TYPE xandor VALUE 'AND',
  c_searchtype_or  TYPE xandor VALUE 'OR',
  gc_in              TYPE c LENGTH 1 VALUE 'I',
  gc_opt_eq          TYPE c LENGTH 2 VALUE 'EQ',
  gc_act_03(2)       TYPE c        VALUE '03', "auth check actvt 03
  gc_aktps_a         TYPE xuaktpas VALUE 'A',  "object status: active
  gc_ptype_c         TYPE c        VALUE 'C',
  gc_ptype_s         TYPE c        VALUE 'S',
  gc_true           TYPE c     VALUE 'X',
  gc_false          TYPE tv_c1 VALUE ''.
*  gc_max_range_sel type i value 500 .

FIELD-SYMBOLS: <ust12_tab>  TYPE LINE OF tyt_ust12_tab,
               <ust12_data> TYPE LINE OF tyt_ust12_data.

TABLES: usr02, usr03, usgrp_user, usr21, adrp, adcp, adr6,
        agr_flags, agr_users, agr_texts,
        tstct, usr11, usrefus,
        usrvarid, uscrauthid, uscrauidt.

SELECTION-SCREEN BEGIN OF BLOCK variant WITH FRAME TITLE text-s01.
PARAMETERS p_varn LIKE usrvar-varname OBLIGATORY.
SELECTION-SCREEN END OF BLOCK variant.
SELECTION-SCREEN BEGIN OF BLOCK user WITH FRAME TITLE text-s02.
SELECT-OPTIONS:
  p_user FOR usr02-bname NO INTERVALS,
  p_class FOR usr02-class NO INTERVALS,
  p_group FOR usgrp_user-usergroup NO INTERVALS,
  p_kostl FOR usr03-kostl NO INTERVALS.
SELECTION-SCREEN END OF BLOCK user.
PARAMETERS:
  p_datum LIKE sy-datum NO-DISPLAY,
  p_locked AS CHECKBOX,
  p_delet AS CHECKBOX.

INCLUDE zms01cw10.

DATA:
  BEGIN OF i_user OCCURS 0,
    bname LIKE usr02-bname,
    name_text LIKE adrp-name_text,
    function LIKE adcp-function,
    pernr LIKE pa0002-pernr,
    department LIKE adcp-department,
    tel_number LIKE adcp-tel_number,
    tel_extens LIKE adcp-tel_extens,
    smtp_addr LIKE adr6-smtp_addr,
    sysid LIKE sy-sysid,
    mandt LIKE sy-mandt,
    ustyp LIKE usr02-ustyp,
    ustypt TYPE val_text, "usr02-ustyp
    uflag LIKE usr02-uflag,
    uflagt TYPE val_text, "usr02-uflag
    kostl LIKE usr03-kostl,
    utypt LIKE tutyp-utyptext, "USR06-LIC_TYPE
    gltgb LIKE usr02-gltgb,
  END OF i_user,
  BEGIN OF i_role OCCURS 0,
    bname LIKE usr02-bname,
    agr_name LIKE agr_users-agr_name,
    typ(4),
    text LIKE agr_texts-text,
  END OF i_role,
  BEGIN OF i_tran OCCURS 0,
    bname LIKE usr02-bname,
    tcode LIKE tstct-tcode,
    ttext LIKE tstct-ttext,
  END OF i_tran,
  BEGIN OF i_prof OCCURS 0,
    bname LIKE usr02-bname,
    profile LIKE ust04-profile,
    ptext LIKE usr11-ptext,
  END OF i_prof,
  BEGIN OF authlist OCCURS 30,
     object    LIKE usr12-objct,
     auth      LIKE usr12-auth,
     cpf       LIKE usr10-profn,
     profile   LIKE usr10-profn,
     cauth     LIKE usr12-auth,
  END OF authlist,
  BEGIN OF proflist OCCURS 30,    "Int. Tab. fuer User
     profile LIKE usr10-profn,
     samprof(1),
     ptext   LIKE usr11-ptext,
  END OF proflist,
  i_tstct LIKE tstct OCCURS 0 WITH HEADER LINE,
  auths LIKE usref OCCURS 0 WITH HEADER LINE,
  tcodes LIKE ussel OCCURS 0 WITH HEADER LINE,
  profile TYPE xuprofname,
  poc_stran TYPE i VALUE 999,
  i_uscrauidt LIKE uscrauidt OCCURS 0 WITH HEADER LINE,
  BEGIN OF i_uscrauth OCCURS 0,
    auth_id    LIKE uscrauth-auth_id,
    cr_auth    LIKE uscrauth-cr_auth,
    objct      LIKE uscrauth-objct,
    field      LIKE uscrauth-field,
    low        LIKE uscrauth-low,
    high       LIKE uscrauth-high,
    searchtype LIKE uscrauth-searchtype,
  END OF i_uscrauth,
  BEGIN OF i_cr_auth OCCURS 0,
    auth_id    LIKE uscrauthid-auth_id,
    auth_color LIKE uscrauthid-auth_color,
    text       LIKE uscrauidt-text,
  END OF i_cr_auth,
  BEGIN OF lt_auth_id OCCURS 10,
    auth_id  LIKE uscrauthid-auth_id,
  END OF lt_auth_id,
*  p_datum LIKE sy-datum,
  uflagc TYPE domvalue_l,
  entries_in_result            TYPE i,
  gt_1fld_obj TYPE tt_1fld_obj,
  ust12_tab TYPE tyt_ust12_tab,
  ust12_data TYPE tyt_ust12_data,
  full_authorization_flag(1)   TYPE c,
  missng_authorization_flag(1) TYPE c,
  BEGIN OF profiles OCCURS 0.
        INCLUDE STRUCTURE uslst.
DATA: END OF profiles.
DATA: BEGIN OF deleted_auths OCCURS 100.
        INCLUDE STRUCTURE usref.
DATA: END OF deleted_auths.
DATA: BEGIN OF user_crauth OCCURS 0,
      auth_id    LIKE uscrauth-auth_id,
      bname      LIKE usr02-bname,
      auth_color LIKE vuscrauthi-auth_color,
  END OF user_crauth.
DATA:  BEGIN OF crit_val OCCURS 20.
        INCLUDE STRUCTURE usref.
DATA:  END OF crit_val,
  BEGIN OF user_crcomb OCCURS 0,
        comb_id   LIKE uscrcomb-comb_id,
        bname     LIKE uscrcomb-bname,
        comb_col  LIKE uscrcomb-comb_col,
  END OF user_crcomb,
  gt_prf_lst          TYPE tt_prf_lst,
  bers               TYPE tt_auths WITH HEADER LINE,
  merged_it_auth_fld TYPE tt_auth_fld_type WITH HEADER LINE,
  gt_user_i           TYPE tt_user,
  n_val TYPE STANDARD TABLE OF tpr01 WITH HEADER LINE,
  i_val LIKE n_val OCCURS 0 WITH HEADER LINE,
  gt_refuser          TYPE tt_user_ref,
  pattern_high(4) TYPE c,
  pattern_low(4)  TYPE c,
  gv_log_return       TYPE bal_s_excm,
  gt_c_prfn           TYPE tt_prof,
  gv_ret              TYPE x,
  gs_return  TYPE bapiret2,
  gv_mode             TYPE c LENGTH 8.

INCLUDE rsusr008_009_c01.

*CLASS lcl_progress DEFINITION DEFERRED.
DATA go_progress  TYPE REF TO lcl_progress.

INITIALIZATION.
*  CONCATENATE sy-datum(6) '01' INTO p_datum.
  p_datum = sy-datum.

AT SELECTION-SCREEN.
  IF p_kostl[] IS NOT INITIAL AND p_delet IS NOT INITIAL.
    MESSAGE 'Nelze souasn zadat stedisko a zahrnut vymazanch uivatel.'
       TYPE 'E'.
  ENDIF.

START-OF-SELECTION.
  SELECT * FROM tstct INTO TABLE i_tstct WHERE sprsl EQ 'E' OR sprsl EQ 'C'.
* Naten kritickch oprvnn
  SELECT * FROM uscrauidt INTO TABLE i_uscrauidt WHERE langu EQ 'E'.
  SORT i_uscrauidt.
  SELECT * FROM usrvarid WHERE varname EQ p_varn.
    lt_auth_id-auth_id = usrvarid-auth_id.
    APPEND lt_auth_id.
  ENDSELECT.
*    CHECK sy-subrc = 0.
* Global list of CA inside VCA
  CLEAR: i_cr_auth, i_cr_auth[].
  SELECT * FROM uscrauthid FOR ALL ENTRIES IN lt_auth_id
    WHERE auth_id = lt_auth_id-auth_id.
    i_cr_auth-auth_id    = uscrauthid-auth_id.
    i_cr_auth-auth_color = uscrauthid-auth_color.
    i_cr_auth-text       = uscrauthid-auth_id.
    APPEND i_cr_auth.
  ENDSELECT.
* CHECK sy-subrc = 0.
* Get authorization data of CA
  CLEAR: i_uscrauth, i_uscrauth[].
  SELECT * FROM uscrauth INTO CORRESPONDING FIELDS OF TABLE i_uscrauth
    FOR ALL ENTRIES IN i_cr_auth
    WHERE auth_id = i_cr_auth-auth_id.
  PERFORM prepare_of_selection.
  PERFORM start_of_selection.
  SORT user_crauth.
  DELETE ADJACENT DUPLICATES FROM user_crauth.

*************************************************************
  SELECT bname ustyp uflag gltgb FROM usr02
     INTO CORRESPONDING FIELDS OF TABLE i_user
     WHERE bname IN p_user
       AND class IN p_class.

  IF p_locked IS INITIAL.
    DELETE i_user WHERE uflag NE 0.
  ENDIF.
  LOOP AT i_user.
    SELECT SINGLE * FROM usgrp_user
       WHERE bname EQ i_user-bname
         AND usergroup IN p_group.
    IF sy-subrc IS NOT INITIAL AND p_group[] IS NOT INITIAL.
      DELETE i_user.
      CONTINUE.
    ENDIF.
    CLEAR usr21.
    SELECT SINGLE * FROM usr21 WHERE bname EQ i_user-bname.
    IF usr21-kostl NOT IN p_kostl.
      DELETE i_user.
      CONTINUE.
    ENDIF.
    IF p_delet IS INITIAL AND usr21-kostl EQ 'DELETED'.
      DELETE i_user.
      CONTINUE.
    ENDIF.
    i_user-kostl = usr21-kostl.
    IF i_user-gltgb IS INITIAL.
      i_user-gltgb = '99991231'.
    ENDIF.
    CLEAR usrefus.
    SELECT SINGLE * FROM usrefus WHERE bname EQ i_user-bname.
    IF usrefus-useralias+2(1) CA '0123456789'.
      CONCATENATE '250' usrefus-useralias+2(5) INTO i_user-pernr.
    ENDIF.
    SELECT SINGLE name_text FROM adrp INTO i_user-name_text
       WHERE persnumber EQ usr21-persnumber
         AND date_from LE p_datum
         AND date_to GE p_datum.
    SELECT SINGLE * FROM adcp INTO CORRESPONDING FIELDS OF i_user
       WHERE addrnumber EQ usr21-addrnumber
         AND persnumber EQ usr21-persnumber
         AND date_from LE p_datum
         AND date_to GE p_datum.
    SELECT SINGLE smtp_addr FROM adr6 INTO i_user-smtp_addr
       WHERE addrnumber EQ usr21-addrnumber
         AND persnumber EQ usr21-persnumber.
    i_user-sysid = sy-sysid.
    i_user-mandt = sy-mandt.
    SELECT SINGLE utyptext FROM tutyp JOIN usr06 ON usr06~lic_type EQ tutyp~usertyp
       INTO i_user-utypt
       WHERE usr06~bname EQ i_user-bname
         AND tutyp~langu EQ 'E'.
    SELECT SINGLE ddtext FROM dd07t INTO i_user-ustypt
       WHERE domname EQ 'XUUSTYP'
         AND ddlanguage EQ 'E'
         AND as4local EQ 'A'
         AND domvalue_l EQ i_user-ustyp.
    WRITE i_user-uflag TO uflagc LEFT-JUSTIFIED.
    SELECT SINGLE ddtext FROM dd07t INTO i_user-uflagt
       WHERE domname EQ 'XUUFLAG'
         AND ddlanguage EQ 'E'
         AND as4local EQ 'A'
         AND domvalue_l EQ uflagc.
    MODIFY i_user.
* ROLE
    CLEAR i_role.
    i_role-bname = i_user-bname.
    SELECT agr_name FROM agr_users INTO i_role-agr_name
       WHERE uname EQ i_user-bname
         AND from_dat LE p_datum
         AND to_dat GE p_datum
         AND col_flag EQ ' '.
      APPEND i_role.
    ENDSELECT.
    LOOP AT i_role WHERE bname EQ i_user-bname.
      SELECT SINGLE * FROM agr_flags WHERE agr_name = i_role-agr_name
                                       AND flag_type = 'COLL_AGR'.
      IF agr_flags-flag_value EQ 'X'.
        i_role-typ = icon_composite_activitygroup.
      ELSE.
        i_role-typ = icon_activity_group.
      ENDIF.
      SELECT SINGLE text FROM agr_texts INTO i_role-text
         WHERE agr_name EQ i_role-agr_name
           AND spras EQ 'E'
           AND LINE EQ '00000'.
      IF sy-subrc IS NOT INITIAL.
        SELECT SINGLE text FROM agr_texts INTO i_role-text
                WHERE agr_name EQ i_role-agr_name
                  AND LINE EQ '00000'.
      ENDIF.
      MODIFY i_role.
    ENDLOOP.
* Profily
    CLEAR i_prof.
    i_prof-bname = i_user-bname.
    SELECT profile FROM ust04 INTO i_prof-profile
       WHERE bname = i_user-bname.
      SELECT SINGLE profile FROM agr_1016
         JOIN agr_users ON agr_1016~agr_name EQ agr_users~agr_name
         INTO profile
         WHERE uname EQ i_user-bname
           AND profile EQ i_prof-profile
           AND from_dat LE p_datum
           AND to_dat GE p_datum
           AND generated EQ 'X'
           AND pstate EQ 'A'.
      CHECK sy-subrc IS NOT INITIAL.
      CLEAR i_prof-ptext.
      SELECT SINGLE ptext FROM usr11 INTO i_prof-ptext
         WHERE langu EQ 'E' AND profn EQ i_prof-profile AND aktps EQ 'A'.
      IF sy-subrc IS NOT INITIAL.
        SELECT SINGLE ptext FROM usr11 INTO i_prof-ptext
           WHERE profn EQ i_prof-profile AND aktps EQ 'A'.
      ENDIF.
      APPEND i_prof.
    ENDSELECT.
* Transakce
    REFRESH: auths, tcodes, authlist.
    SELECT SINGLE profile FROM ust04 INTO profile
         WHERE bname = i_user-bname AND ( profile LIKE '%SAP_ALL%'
            OR profile LIKE 'SAP_NEW%' OR profile EQ 'S_A.ADMIN'
            OR profile EQ 'S_A.CUSTOMIZ' OR profile EQ 'S_A.SYSTEM' ).
    IF sy-subrc IS INITIAL.
      i_tran-bname = i_user-bname.
      i_tran-tcode = '*'.
      i_tran-ttext = 'All transactions'.
      APPEND i_tran.
    ELSE.
      SELECT profile FROM ust04 INTO profile
           WHERE bname = i_user-bname.
        REFRESH: authlist, proflist.
        CALL FUNCTION 'PROFIL_AUFLOESEN'
          EXPORTING
            obj1              = 'S_TCODE'
            profile           = profile
          TABLES
            authlist          = authlist
            proflist          = proflist
          EXCEPTIONS
            profile_not_found = 1
            OTHERS            = 2.
        IF sy-subrc <> 0.
          MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                  WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
        ENDIF.
        LOOP AT authlist.
          auths-object = authlist-object.
          auths-auth = authlist-auth.
          APPEND auths.
        ENDLOOP.
      ENDSELECT.
      SORT auths.
      DELETE ADJACENT DUPLICATES FROM auths.
      CALL FUNCTION 'SUSR_GET_TCODES_AUTH_S_TCODE'
        TABLES
          auths  = auths
          tcodes = tcodes.
      i_tran-bname = i_user-bname.
      LOOP AT tcodes.
        i_tran-tcode = tcodes-low.
        CLEAR i_tstct-ttext.
        READ TABLE i_tstct WITH KEY tcode = i_tran-tcode sprsl = 'E'.
        IF sy-subrc IS NOT INITIAL.
          READ TABLE i_tstct WITH KEY tcode = i_tran-tcode.
        ENDIF.
        i_tran-ttext = i_tstct-ttext.
        APPEND i_tran.
      ENDLOOP.
    ENDIF.
  ENDLOOP.

END-OF-SELECTION.
  FORMAT RESET.
  LOOP AT i_user.
    NEW-PAGE.
* role
    READ TABLE i_role WITH KEY bname = i_user-bname.
    IF sy-subrc IS INITIAL.
      WRITE:/ 'AVAILABLE ROLES (ACTIVITY GROUPS) for the user' INTENSIFIED.
      ULINE /1(108).
      FORMAT COLOR COL_HEADING.
      WRITE:/ '|Role                          |Type|Name        ', (56) space, '|'.
      FORMAT COLOR COL_NORMAL.
      ULINE /1(108).
      LOOP AT i_role WHERE bname EQ i_user-bname.
        WRITE:/
           '|' NO-GAP, i_role-agr_name COLOR COL_KEY NO-GAP,
           '|' NO-GAP, (3) i_role-typ AS ICON,
           '|' NO-GAP, (69) i_role-text, '|' NO-GAP.
      ENDLOOP.
      FORMAT RESET.
      ULINE /1(108).
      SKIP.
    ENDIF.
* Profily
    READ TABLE i_prof WITH KEY bname = i_user-bname.
    IF sy-subrc IS INITIAL.
      WRITE:/ 'AVAILABLE PROFILES (not part of roles) for the user' INTENSIFIED.
      ULINE /1(76).
      FORMAT COLOR COL_HEADING.
      WRITE:/ '|Profile     |Name', (55) space, '|'.
      FORMAT COLOR COL_NORMAL.
      ULINE /1(76).
      LOOP AT i_prof WHERE bname EQ i_user-bname.
        WRITE:/
           '|' NO-GAP, i_prof-profile COLOR COL_KEY NO-GAP,
           '|' NO-GAP, i_prof-ptext, '|' NO-GAP.
      ENDLOOP.
      FORMAT RESET.
      ULINE /1(76).
      SKIP.
    ENDIF.
* transakce
    READ TABLE i_tran WITH KEY bname = i_user-bname.
    IF sy-subrc IS INITIAL.
      WRITE:/ 'AVAILABLE TRANSACTIONS (PROGRAMS) for the user' INTENSIFIED.
      ULINE /1(59).
      FORMAT COLOR COL_HEADING.
      WRITE:/ '|Transaction code    |Text                                |'.
      FORMAT COLOR COL_NORMAL.
      ULINE /1(59).
      LOOP AT i_tran WHERE bname EQ i_user-bname.
        WRITE:/
           '|' NO-GAP, i_tran-tcode COLOR COL_KEY NO-GAP,
           '|' NO-GAP, i_tran-ttext NO-GAP, '|' NO-GAP.
      ENDLOOP.
      FORMAT RESET.
      ULINE /1(59).
      SKIP.
    ENDIF.
* Kritick oprvnn
    READ TABLE user_crauth WITH KEY bname = i_user-bname.
    IF sy-subrc IS INITIAL.
      WRITE:/ 'CRITICAL AUTHORIZATIONS for the user' INTENSIFIED.
      ULINE /1(83).
      FORMAT COLOR COL_HEADING.
      WRITE:/ '|ID of CA            |Text of Critical Authorization                              |'.
      FORMAT COLOR COL_NORMAL.
      ULINE /1(83).
      LOOP AT user_crauth WHERE bname EQ i_user-bname.
        CLEAR i_uscrauidt.
        READ TABLE i_uscrauidt WITH KEY auth_id = user_crauth-auth_id
           BINARY SEARCH.
        CASE user_crauth-auth_color.
          WHEN '3'.
            FORMAT COLOR COL_TOTAL.
          WHEN '6'.
            FORMAT COLOR COL_NEGATIVE.
          WHEN OTHERS.
            FORMAT COLOR COL_NORMAL.
        ENDCASE.
        WRITE:/
           '|' NO-GAP, user_crauth-auth_id NO-GAP,
           '|' NO-GAP, i_uscrauidt-text NO-GAP, '|' NO-GAP.
      ENDLOOP.
      FORMAT RESET.
      ULINE /1(83).
      SKIP.
    ENDIF.
* Patika
    SKIP.
    FORMAT INTENSIFIED.
    IF sy-linno GT 77. NEW-PAGE. ENDIF.
*   IF sy-linno GT 80. NEW-PAGE. ENDIF. (puvodne bylo nastaveno 80).
    WRITE:/4 'All data is correct and I have checked the necessity of this roles',
            'and the lack of function segregation', /40 'is fulfilled by internal controls.'.
    FORMAT INTENSIFIED OFF.
    SKIP 4.
    WRITE: /17 '.......................                            ......................',
           /17 ' Boss of the employee                                       Date'.
    SKIP 4.
    WRITE: /17 '.......................                            ......................',
           /17 ' Head of the SMP BA OIT                                     Date'.
    SKIP.
    WRITE:/10 'Please send the filled form back to your local authorization administrator - SMP BA OIT.'.

  ENDLOOP.

  CLEAR poc_stran.
  DO.
    READ LINE sy-index FIELD VALUE poc_stran.
    IF NOT sy-subrc IS INITIAL.
      EXIT.
    ENDIF.
    IF NOT poc_stran IS INITIAL.
      MODIFY LINE sy-index FIELD VALUE poc_stran FROM sy-pagno.
      CLEAR poc_stran.
    ENDIF.
  ENDDO.

TOP-OF-PAGE.
  FORMAT COLOR COL_KEY INTENSIFIED.
  WRITE:/ 'Page:', (4) sy-pagno NO-GAP, '/' NO-GAP, (4) poc_stran,
        40 'EPCOS SAP R/3 USER INVENTORY', 98 sy-datum.
  HIDE poc_stran.
  FORMAT RESET.
  SKIP.
  CONCATENATE i_user-tel_number i_user-tel_extens INTO i_user-tel_number
         SEPARATED BY space.
  WRITE:
    / 'USER        :', i_user-name_text,
   53 'SYSTEM NAME  :', i_user-sysid,
    / 'USER ID     :', i_user-bname,
   53 'CLIENT       :', i_user-mandt,
    / 'FUNCTION    :', i_user-function,
   53 'USER TYPE    :', (40) i_user-ustypt,
    / 'PERS. NUMBER:', i_user-pernr,
   53 'STATUS       :', (40) i_user-uflagt,
    / 'DEPARTMENT  :', i_user-department,
   53 'COST CENTER  :', i_user-kostl,
    / 'TELEPHONE   :', i_user-tel_number,
   53 'LICENSE      :', i_user-utypt,
    / 'E-MAIL      :', (40) i_user-smtp_addr,
   53 'VALID THROUGH:', i_user-gltgb.
  ULINE.
  SKIP.
*&---------------------------------------------------------------------*
*&      Form  prepare_of_selection
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM prepare_of_selection .
* get objects with only one field
  PERFORM get_1field_objects USING gt_1fld_obj.

* get references user
  PERFORM read_refuser TABLES gt_refuser.

* fill global composite profile reuse table
* (basis for buffered profile resolve w/o db-access)
  PERFORM resolve_all_composite_profs.

* Set pattern for interval comparison                       "note 978447
  PERFORM set_pattern CHANGING pattern_low
                               pattern_high .

* Set pattern for interval comparison                       "note 978447
  PERFORM set_pattern CHANGING pattern_low
                               pattern_high .

* Load & check selected variant for critical authorizations
*  PERFORM check_critical_variant .

* Handle error/warning log
*  perform suim_alv_error_log tables gt_log_alv
*                             using 'Error log'(012).        "#EC *
* Check for errors before analysis
  IF sy-batch IS INITIAL.

*   Dialog job: no fatal messages allowed
*    READ TABLE gt_log_alv WITH KEY type = 'A' TRANSPORTING NO FIELDS .
*    IF sy-subrc IS INITIAL.
*      gv_log_return-cancel = 'X' .
*      RETURN. "fatal errors in log - stop further process
*    ENDIF.
*    CLEAR gt_log_alv[].
*   get selected option from error log
    CALL FUNCTION 'PRGN_FUNCTION_EXIST'
      EXPORTING
        name   = 'SUSR_GET_LOG_EXIT_COMMAND'
      EXCEPTIONS
        OTHERS = 1.
    IF sy-subrc = 0.
      CALL FUNCTION 'SUSR_GET_LOG_EXIT_COMMAND'
        IMPORTING
          es_s_excm = gv_log_return.
    ENDIF.

  ELSE.

*   Background job: no messages allowed
*    IF NOT gt_log_alv[] IS INITIAL.
*      MESSAGE e883(01) WITH p_varn.
*      EXIT.
*    ENDIF.

  ENDIF.

ENDFORM.                    " prepare_of_selection
*&---------------------------------------------------------------------*
*&      Form  start_of_selection
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM start_of_selection.

  DATA: exception TYPE i,
        fieldtext TYPE dfies-fieldtext,
        fieldname TYPE tobj-fiel1.

* Process selected variant
  CREATE OBJECT go_progress.
  PERFORM get_users_for_vca USING exception.

* >>> note 1259329
* Display result
  IF exception IS NOT INITIAL.

    CASE exception.

      WHEN 1.
*        MESSAGE i002(ue) WITH crit_val-field crit_val-object.

      WHEN 2.
*        MESSAGE i003(ue) WITH crit_val-field crit_val-object.

    ENDCASE.
* <<< note 1259329

  ELSE.

*        IF NOT val_usrs IS INITIAL.
**   Only valid users should be displayed
*          PERFORM restrict_result USING comb.
*        ENDIF.

  ENDIF.

ENDFORM.                    "start_of_selection
*&---------------------------------------------------------------------*
*&      Form  get_users_for_vca
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_EXCEPTION  text
*----------------------------------------------------------------------*
FORM get_users_for_vca USING p_exception TYPE i.

  DATA:
    lo_users_for_ca TYPE REF TO lcl_user,
    ld_number       TYPE i,
    lv_txt          TYPE string.
*-----------------------------------------------------------------------
  CLEAR i_uscrauth.
  SORT  i_uscrauth BY auth_id cr_auth objct.

  DESCRIBE TABLE i_cr_auth LINES ld_number.
  CALL METHOD go_progress->reset
    EXPORTING
      id_text  = 'Data being analysed...'(010)              "#EC *
      id_total = ld_number
      id_step  = 1.
  CREATE OBJECT lo_users_for_ca.

  LOOP AT i_cr_auth.
    CALL METHOD go_progress->next
      EXPORTING
        id_number = sy-tabix.
*   Resolve single critical authorization (specified AUTH_ID)
    PERFORM get_users_for_ca USING    i_cr_auth-auth_id
                                      p_exception
                             CHANGING lo_users_for_ca.

*   Fill in the table for input the result list
    PERFORM fill_in_result_tables_auth TABLES lo_users_for_ca->t_user[]
        USING  i_cr_auth-auth_id
               'AU'.
  ENDLOOP.

* How many entries in the table to be displayed
  DESCRIBE TABLE user_crauth LINES entries_in_result.

ENDFORM.                    " get_users_for_vca
*&---------------------------------------------------------------------*
*&      Form  get_users_for_ca
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_AUTH_ID        text
*      -->P_EXCEPTION      text
*      -->PO_USERS_FOR_CA  text
*----------------------------------------------------------------------*
FORM get_users_for_ca
  USING
    p_auth_id       TYPE uscrauth-auth_id
    p_exception     TYPE i
  CHANGING
    po_users_for_ca TYPE REF TO lcl_user.

  DATA:
    ld_users_for_objct   TYPE i,                            "#EC NEEDED
    ld_users_for_group   TYPE i,                            "#EC NEEDED
    ld_users_for_ca      TYPE i,                            "#EC NEEDED
    loop_status          TYPE i,
    auth_id_tabix        TYPE sy-tabix,
    current_cr_auth      TYPE uscrauth-cr_auth,
    current_searchtype   TYPE uscrauth-searchtype,
    current_object       TYPE uscrauth-objct,
    lo_users_for_objct   TYPE REF TO lcl_user,
    lo_users_for_group   TYPE REF TO lcl_user.

  CONSTANTS:
    c_continue           TYPE i VALUE 0,
    c_end_object         TYPE i VALUE 1,
    c_end_cr_auth        TYPE i VALUE 2,
    c_end_auth_id        TYPE i VALUE 3.

* Main loop preparation
  CALL METHOD po_users_for_ca->reset.
  READ TABLE i_uscrauth WITH KEY auth_id = p_auth_id BINARY SEARCH.
  IF sy-subrc = 0.
    auth_id_tabix = sy-tabix.
  ELSE.
*   There is no users for the value P_AUTH_ID
    EXIT.
  ENDIF.
  CREATE OBJECT: lo_users_for_objct, lo_users_for_group.

* Main loop
  DO.

*   Fill in data for current AUTH_ID + CR_AUTH + OBJCT
    crit_val-object = i_uscrauth-objct.
    crit_val-aktps  = 'A'.
    crit_val-field  = i_uscrauth-field.
    IF i_uscrauth-low IS INITIAL.
      crit_val-von  = ''' '''.
    ELSE.
      crit_val-von  = i_uscrauth-low.
    ENDIF.
    crit_val-bis    = i_uscrauth-high.
    APPEND crit_val.

* >>> note 1259329
*   Im Fall crit_val-von = '#**', prfen, ob eine Suche nach Gesamtmenge
*aller mglichen Werten mglich ist. Wenn nicht, schon hier abbrechen.
    IF i_uscrauth-low = '#**'.
      PERFORM check_for_total_volume USING p_exception.

      IF p_exception IS NOT INITIAL.
        EXIT.
      ENDIF.
    ENDIF.
* <<< note 1259329

*   Save current values
    current_cr_auth    = i_uscrauth-cr_auth.
    current_object     = i_uscrauth-objct.
    current_searchtype = i_uscrauth-searchtype.

*   Loop control
    loop_status = c_continue.
    ADD 1 TO auth_id_tabix.
    READ TABLE i_uscrauth INDEX auth_id_tabix.
    IF sy-subrc <> 0.
      loop_status = c_end_auth_id.
    ELSE.
*     Sequential escalation of LOOP_STATUS

*     next object?
      IF i_uscrauth-objct <> current_object.
        loop_status = c_end_object.
      ENDIF.
*     special handling for AND-combined 1-field-objects inside
*     one cr_auth name                                        "# 1084012
      IF current_searchtype = c_searchtype_and.
        READ TABLE gt_1fld_obj
            WITH KEY objct = current_object
            BINARY SEARCH TRANSPORTING NO FIELDS.
        IF sy-subrc IS INITIAL.
          loop_status = c_end_object.
        ENDIF.
      ENDIF.
*     next cr_auth/group ?
      IF i_uscrauth-cr_auth <> current_cr_auth.
        loop_status = c_end_cr_auth.
      ENDIF.
*     end of auth_id?
      IF i_uscrauth-auth_id <> p_auth_id.
        loop_status = c_end_auth_id.
      ENDIF.
    ENDIF.

    IF loop_status >= c_end_object.
*     Old OBJCT is finishing:
      CALL METHOD lo_users_for_objct->reset.
      PERFORM get_users_for_or_and USING current_searchtype
          lo_users_for_objct->t_user[]
          ld_users_for_objct.
      CALL METHOD lo_users_for_group->append_class
        EXPORTING
          search  = current_searchtype
        IMPORTING
          r_addon = lo_users_for_objct
          number  = ld_users_for_group.
*     New OBJCT is starting:
      CLEAR:
        ust12_tab, ust12_tab[],
        crit_val,  crit_val[].
    ENDIF.

    IF loop_status >= c_end_cr_auth.
*     Old CR_AUTH within P_AUTH_ID is finishing:
      CALL METHOD po_users_for_ca->append_class
        EXPORTING
          search  = c_searchtype_and
        IMPORTING
          r_addon = lo_users_for_group
          number  = ld_users_for_ca.
*     Further CR_AUTH must not be checked (performance)
      IF ld_users_for_ca = 0.
*       Processing of P_AUTH_ID is terminated
        EXIT.
      ENDIF.
*     New CR_AUTH is starting:
      CALL METHOD lo_users_for_group->reset.
    ENDIF.

    IF loop_status = c_end_auth_id.
*     Processing of P_AUTH_ID is completed
      EXIT.
    ENDIF.

  ENDDO.

ENDFORM.                    " get_users_for_ca
*&---------------------------------------------------------------------*
*&      Form  check_for_total_volume
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_EXCEPTION  text
*----------------------------------------------------------------------*
FORM check_for_total_volume USING p_exception TYPE i.

  DATA:
     lt_authx_spec TYPE tt_authx_spec,
     field_tab LIKE dfies OCCURS 0 WITH HEADER LINE,
     st_return_tab LIKE ddshretval OCCURS 0 WITH HEADER LINE,
     return_overflow.

  FIELD-SYMBOLS:
     <authx>   TYPE ts_authx_spec,
     <lp_values> TYPE usr_values.

  PERFORM get_domain_data TABLES lt_authx_spec.

  READ TABLE lt_authx_spec ASSIGNING <authx>
     WITH KEY fieldname = i_uscrauth-field
     BINARY SEARCH.

  IF sy-subrc = 0.

    IF <authx>-valexi IS INITIAL    AND
       <authx>-entitytab IS INITIAL.

*MESSAGE i002(ue) WITH crit_val-field crit_val-object <authx>-valexi.
      p_exception = 1.
      EXIT.
    ELSE.

*     Liste der DDIC-Felder fr Wertetabelle
      CALL FUNCTION 'DDIF_NAMETAB_GET'
        EXPORTING
          tabname   = <authx>-entitytab
          all_types = ' '
        TABLES
          dfies_tab = field_tab
        EXCEPTIONS
          not_found = 1
          OTHERS    = 2.
      IF sy-subrc <> 0.
*       es gibt keine Wertetabelle/Prftabelle fr dieses Feld
*       Vergleich nach Gesamtmenge alle mglichen Werten nicht mglich
      ELSE.

*       es wurde eine Wertetabelle gefunden
        PERFORM get_values_of_searchhelp TABLES field_tab st_return_tab
                                         USING <authx>
                                         CHANGING return_overflow.

        IF return_overflow IS NOT INITIAL.
*MESSAGE i003(ue) WITH crit_val-field crit_val-object <authx>-valexi.
          p_exception = 2.
          EXIT.
        ENDIF.

      ENDIF.

    ENDIF.

  ELSE.
*    MESSAGE i002(ue) WITH crit_val-field.
    p_exception = 1.
    EXIT.
  ENDIF.

ENDFORM.                    " CHECK_FOR_TOTAL_VOLUME
*&---------------------------------------------------------------------*
*&      Form  fill_in_result_tables_auth
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_USER      text
*      -->PV_AUTH_ID   text
*      -->P_VIEW_TYPE  text
*----------------------------------------------------------------------*
FORM fill_in_result_tables_auth TABLES pt_user     TYPE ty_t_user
                                USING  pv_auth_id  TYPE auth_id
                                       p_view_type TYPE c.

  DATA:
    lv_lin_cnt   TYPE i,
    lv_class_buf TYPE xuclass,
    lv_astat_buf TYPE x,
    lt_usr02     TYPE tt_class,
    lr_usr02     TYPE RANGE OF xubname,
    ls_r_usr02   LIKE LINE OF lr_usr02.

  FIELD-SYMBOLS:
    <fs_usclass> TYPE ts_usclass,
    <fs_user>    TYPE ts_user.
*----------------------------------------------------------------------*

  IF pt_user[] IS INITIAL.
    CLEAR user_crauth.
    user_crauth-auth_id = pv_auth_id.
    READ TABLE i_cr_auth WITH KEY auth_id = pv_auth_id.
    IF sy-subrc = 0.
      user_crauth-auth_color = i_cr_auth-auth_color.
    ENDIF.
    APPEND user_crauth.
    EXIT.
  ENDIF.

  CLEAR: missng_authorization_flag.
  SORT pt_user.

  IF p_view_type EQ 'AU'.

    user_crauth-auth_id = pv_auth_id.
    READ TABLE i_cr_auth WITH KEY auth_id = pv_auth_id.
    user_crauth-auth_color = i_cr_auth-auth_color.

    IF full_authorization_flag IS INITIAL.
*     prepare SELECT ... IN instead of FOR ALL ENTRIES
      IF lv_lin_cnt < 10000 .
*      select bname + usergroup from database
        ls_r_usr02-sign  = gc_in.
        ls_r_usr02-option = gc_opt_eq .
        LOOP AT pt_user INTO ls_r_usr02-low.
          APPEND ls_r_usr02 TO lr_usr02.
        ENDLOOP.

        TRY.
            SELECT bname class FROM usr02 INTO TABLE lt_usr02
               FOR ALL ENTRIES IN pt_user
               WHERE bname = pt_user-bname .          "#EC CI_SGLSELECT
          CATCH cx_sy_open_sql_db.
            SELECT bname class FROM usr02 INTO TABLE lt_usr02
               FOR ALL ENTRIES IN pt_user
               WHERE bname = pt_user-bname .          "#EC CI_SGLSELECT
        ENDTRY.
      ELSE.
        SELECT bname class FROM usr02 INTO TABLE lt_usr02
           FOR ALL ENTRIES IN pt_user
           WHERE bname = pt_user-bname .              "#EC CI_SGLSELECT
      ENDIF.

      IF lt_usr02[] IS INITIAL .
        MESSAGE e723(01). "Error opening/reading a data record
      ENDIF.
*   partly buffered authority check against S_USER_GRP
      CLEAR: lv_class_buf,
             lv_astat_buf .
      SORT lt_usr02 BY class.
      LOOP AT lt_usr02 ASSIGNING <fs_usclass> .

        IF sy-tabix = 1. "1st record must be handled every time
          lv_class_buf = <fs_usclass>-class.
          AUTHORITY-CHECK OBJECT 'S_USER_GRP'
                ID 'CLASS' FIELD <fs_usclass>-class
                ID 'ACTVT' FIELD gc_act_03.
          IF sy-subrc IS INITIAL.
            user_crauth-bname = <fs_usclass>-bname.
            APPEND user_crcomb .
          ELSE.
            lv_astat_buf = 1.
            missng_authorization_flag = 'X' .
          ENDIF.

        ELSE.

          IF lv_class_buf EQ <fs_usclass>-class .

            IF lv_astat_buf IS INITIAL .
              user_crauth-bname = <fs_usclass>-bname.
              APPEND user_crauth .
            ENDIF.

          ELSE. "next auth check must be done

            lv_class_buf = <fs_usclass>-class.
            AUTHORITY-CHECK OBJECT 'S_USER_GRP'
                  ID 'CLASS' FIELD <fs_usclass>-class
                  ID 'ACTVT' FIELD gc_act_03.
            IF sy-subrc IS INITIAL.
              CLEAR lv_astat_buf.
              user_crauth-bname = <fs_usclass>-bname.
              APPEND user_crauth .
            ELSE.
              lv_astat_buf = 1.
              missng_authorization_flag = 'X' .
            ENDIF.

          ENDIF.
        ENDIF.
      ENDLOOP.   "AT lt_usr02

      IF missng_authorization_flag IS NOT INITIAL.
*      The result list is incomplete because of missing authorizations
        MESSAGE i878(01).
      ENDIF.

    ELSE. "full authorization - no usr02-selection needed

      LOOP AT pt_user ASSIGNING <fs_user>.
        user_crauth-bname = <fs_user>-bname .
        APPEND user_crauth.
      ENDLOOP.

    ENDIF.  "  IF full_authorization_flag IS INITIAL

    SORT user_crauth.
    DELETE ADJACENT DUPLICATES FROM user_crauth.

  ENDIF.  "  IF p_view_type EQ 'AU'.

ENDFORM.                    " FILL_IN_RESULT_TABLES_AUTH
*&---------------------------------------------------------------------*
*&      Form  get_domain_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_AUTHX_SPEC  text
*----------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*&      Form  get_users_for_or_and
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_SRCHTYPE     text
*      -->P_USERS_OR_AND  text
*      -->PV_CNT_USER     text
*----------------------------------------------------------------------*
FORM get_users_for_or_and USING pv_srchtype       TYPE xandor
                                p_users_or_and    TYPE ty_t_user
                                pv_cnt_user       TYPE i.
  DATA:
    lv_cnt_auths TYPE i VALUE 0,
    lv_cnt_profs TYPE i VALUE 0.
*-----------------------------------------------------------------------

  CLEAR: auths, auths[], profiles, profiles[],
         deleted_auths, deleted_auths[].
* Get authorizations
* The subroutine SUSR_GET_AUTHS_WITH_SPEC_VALS is used instead of
* the function module SUSR_GET_AUTHS_WITH_SPEC_VALS because:
* 1) the possibility to improve performance. The table USR12 can be read
* only once and then the data can be buffered.
* 2) The table LOCFOUND and all operetions with it are unnecessary.
  IF crit_val-field IS INITIAL.
    PERFORM susr_get_auths_of_object USING crit_val-object
                                           lv_cnt_auths
                                           auths[].
*   Go further if only there is a result
    IF lv_cnt_auths EQ 0.
      EXIT.
    ENDIF.
  ELSE.
    PERFORM susr_get_auths_with_spec_vals USING crit_val-object
                                                pv_srchtype
                                                lv_cnt_auths
                                                crit_val[]
                                                auths[] .
*   Go further if only there is a result
    IF lv_cnt_auths EQ 0.
      EXIT.
    ENDIF.
  ENDIF.

* For getting profiles corresponding to the authorizations we can use
* the function module SUSR_GET_PROFS_WITH_SPEC_AUTHS. But in this case
* the performance is not optimal bacause:
*    the synchronization can be done for all USR and UST tables at ones
*    and not in the cycle.
  CLEAR: lv_cnt_profs, profiles[].
* Get profiles related to authorizations
  PERFORM susr_get_profs_with_spec_auths TABLES profiles
                                                auths
                                          USING lv_cnt_profs.
  IF lv_cnt_profs EQ 0.
    CLEAR pv_cnt_user.
    EXIT.
  ENDIF.

* Get users related to profiles
  PERFORM susr_get_users_with_spec_profs USING profiles[]
                                               p_users_or_and[]
                                               pv_cnt_user.
  IF pv_cnt_user EQ 0.
    EXIT.
  ELSE.

* All inconsistencies should be deleted in other special report.
  ENDIF.
* Check if selected users match selection options
* for user id, user group, user group(general), reference user,
* alias, role
  PERFORM match_user_list USING p_users_or_and[]
                                pv_cnt_user .

* Add users that have critical data distributed between several
* authorizations (may be even in several profiles)
  IF deleted_auths[] IS NOT INITIAL.
    IF crit_val-field IS NOT INITIAL.
      PERFORM add_matching_users_val TABLES p_users_or_and
                                            deleted_auths
                                            crit_val
                                      USING crit_val-object
                                            pv_srchtype
                                            pv_cnt_user.
    ENDIF.
  ENDIF.

ENDFORM.                    " GET_USERS_FOR_OR
*&---------------------------------------------------------------------*
*&      Form  add_matching_users_val
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_USER       text
*      -->PT_DEL_AUTHS  text
*      -->PT_CRIT_VAL   text
*      -->PV_OBJECT     text
*      -->PV_SRCHTYPE   text
*      -->PV_CNT_USER   text
*----------------------------------------------------------------------*
FORM add_matching_users_val TABLES   pt_user      TYPE ty_t_user
                                     pt_del_auths LIKE deleted_auths[]
                                     pt_crit_val  LIKE crit_val[]
                            USING    pv_object    TYPE xuobject
                                     pv_srchtype  TYPE xandor
                                     pv_cnt_user  TYPE i.
  DATA:
    lt_add_user     TYPE ty_t_user WITH HEADER LINE,
    lv_cnt_add_user TYPE i,
    rc        TYPE i,
    lt_profs  TYPE tt_prof,
    lt_return TYPE tt_prof,
    lt_profc  TYPE tt_prof,
    lr_auth   TYPE RANGE OF xuauth,
    ls_r_auth LIKE LINE OF lr_auth .

  FIELD-SYMBOLS:
    <fs_auths> TYPE usref,
    <fs_profn> TYPE ts_prof.
*----------------------------------------------------------------------*

* prepare the fast selection on database
  ls_r_auth-sign   = gc_in .
  ls_r_auth-option = gc_opt_eq .
  LOOP AT pt_del_auths ASSIGNING <fs_auths> .
    ls_r_auth-low = <fs_auths>-auth .
    APPEND ls_r_auth TO lr_auth.
  ENDLOOP.

  TRY.

      SELECT profn FROM ust10s INTO TABLE lt_profs
        WHERE aktps =  gc_aktps_a
          AND objct =  pv_object
          AND auth  IN lr_auth .                        "#EC CI_GENBUFF

    CATCH cx_sy_open_sql_db.

      SELECT profn FROM ust10s INTO TABLE lt_profs
        FOR ALL ENTRIES IN pt_del_auths
        WHERE aktps =  gc_aktps_a
          AND objct =  pv_object
          AND auth  =  pt_del_auths-auth .              "#EC CI_GENBUFF

  ENDTRY.

  IF lt_profs IS NOT INITIAL.
    EXIT.  "Error situation ??
  ENDIF.
  SORT lt_profs.
  DELETE ADJACENT DUPLICATES FROM lt_profs.

*   PERFORM CHECK_PROF USING IT_PROFILES-PROFILE
*                             RC.

* add father profiles (composite profiles)
  LOOP AT lt_profs ASSIGNING <fs_profn> .
    PERFORM get_father_profs USING  <fs_profn>-profn
                                    gt_prf_lst
                                    lt_return.
    APPEND LINES OF lt_return TO lt_profc.
  ENDLOOP.
  APPEND LINES OF lt_profc TO lt_profs.
  SORT lt_profs.
  DELETE ADJACENT DUPLICATES FROM lt_profs.

* handle restrictions from selection screen for perf. improvement
* in correction part II
*  PERFORM match_profile_list USING lt_profs.

  PERFORM get_users_with_profiles USING lt_profs[]
                                        lt_add_user[].

  IF lt_add_user[] IS INITIAL.
    EXIT.
  ELSE.
* Delete duplicated users
    LOOP AT lt_add_user.
      READ TABLE pt_user WITH KEY bname = lt_add_user-bname
                         TRANSPORTING NO FIELDS BINARY SEARCH.
      IF sy-subrc IS INITIAL.
        DELETE lt_add_user.
      ENDIF.
    ENDLOOP.

*  Check if selected users match selection options for user-id,
*  user group, user group(general), reference user, alias, role
    PERFORM match_user_list USING lt_add_user[]
                                  lv_cnt_add_user .
    IF lv_cnt_add_user IS INITIAL.
      EXIT.
    ELSE.
* Analyse the auth. data
      LOOP AT lt_add_user.
        rc = 1.
* Merge user's auth. data and compare with critical one.
        PERFORM check_auth_data USING pt_crit_val[]
                                      pv_srchtype
                                      lt_add_user-bname
                                      pv_object
                                      rc.
        IF rc NE 0.
          DELETE lt_add_user.
        ENDIF.
      ENDLOOP.
    ENDIF.
  ENDIF.

* Merge lists of users
  APPEND LINES OF lt_add_user TO pt_user.
  SORT pt_user.
  DELETE ADJACENT DUPLICATES FROM pt_user.
  DESCRIBE TABLE pt_user LINES pv_cnt_user.

ENDFORM.                    " ADD_MATCHING_USERS_VAL
*&---------------------------------------------------------------------*
*&      Form  check_auth_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_CRIT_VAL  text
*      -->PV_SRCHTYPE  text
*      -->PV_ADD_USER  text
*      -->PV_OBJECT    text
*      -->PV_RC        text
*----------------------------------------------------------------------*
FORM check_auth_data USING pt_crit_val  LIKE crit_val[]
                            pv_srchtype  TYPE xandor
                            pv_add_user  TYPE xubname
                            pv_object    TYPE xuobject
                            pv_rc        TYPE i.

  DATA:
    lv_flag       TYPE c,
    lt_auths      TYPE tt_auths WITH HEADER LINE,
    lt_auths_fld  TYPE tt_auth_fld_type,
    lt_prof       TYPE tt_prof,
    lr_prof       TYPE RANGE OF xuprofile.
*----------------------------------------------------------------------*
  pv_rc = 1.
* Get user profiles
  PERFORM get_users_single_profs USING pv_add_user
                                       gt_prf_lst[]
                                       lt_prof[] .

* Get user authorizations as JOIN between UST10s

  SELECT objct auth FROM ust10s INTO TABLE lt_auths
     WHERE profn IN lr_prof                                 "ca 100
       AND aktps EQ gc_aktps_a .                        "#EC CI_GENBUFF

  CHECK lt_auths[] IS NOT INITIAL.

  SELECT objct auth field von bis FROM ust12
    INTO TABLE lt_auths_fld FOR ALL ENTRIES IN lt_auths
    WHERE objct = lt_auths-objct
      AND auth  = lt_auths-auth
      AND aktps = gc_aktps_a .

  CHECK lt_auths_fld[] IS NOT INITIAL.

* Merge authorizations
  SORT lt_auths.
  SORT lt_auths_fld.

  CLEAR: bers[],
         merged_it_auth_fld[],
         lv_flag.

  PERFORM merge_auth USING lt_auths[]
                           lt_auths_fld[]
                           pv_object
                           lv_flag.
  IF lv_flag IS NOT INITIAL.
*  Merging is done. Compare merged authorizations with critical data
    PERFORM compare_merged_data USING bers[]
                                      merged_it_auth_fld[]
                                      pt_crit_val[]
                                      pv_srchtype
                                      pv_rc.
  ENDIF.
ENDFORM.                    " CHECK_AUTH_DATA
*&---------------------------------------------------------------------*
*&      Form  compare_merged_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_BERS            text
*      -->PT_MERGE_AUTH_FLD  text
*      -->PT_CRIT_VAL        text
*      -->PV_SRCHTYPE        text
*      -->PV_RC              text
*----------------------------------------------------------------------*
FORM compare_merged_data  USING  pt_bers           TYPE tt_auths
                                 pt_merge_auth_fld TYPE tt_auth_fld_type
                                 pt_crit_val       TYPE tt_crit_val
                                 pv_srchtype       TYPE xandor
                                 pv_rc             TYPE i.

  DATA:
     lt_ust12_merged TYPE TABLE OF ust12,
     ls_ust12        TYPE ust12,
     lv_found        TYPE x.

  FIELD-SYMBOLS: <fs_auth>     TYPE ts_auth,
                 <fs_auth_fld> TYPE ts_auth_fld_type.
*----------------------------------------------------------------------*
* Compare data
  LOOP AT pt_bers ASSIGNING <fs_auth>.

    READ TABLE pt_merge_auth_fld ASSIGNING <fs_auth_fld>
        WITH KEY auth = <fs_auth>-auth
                 merge_flag = 'X'.
    IF sy-subrc NE 0.
      CONTINUE.
    ENDIF.

    CLEAR: ls_ust12, lt_ust12_merged[].

    LOOP AT pt_merge_auth_fld ASSIGNING <fs_auth_fld>
      WHERE auth = <fs_auth>-auth .
      MOVE: <fs_auth>-auth      TO ls_ust12-auth ,
            <fs_auth_fld>-field TO ls_ust12-field ,
            <fs_auth_fld>-low   TO ls_ust12-von ,
            <fs_auth_fld>-high  TO ls_ust12-bis .
      APPEND ls_ust12 TO lt_ust12_merged .

    ENDLOOP.

    PERFORM check_value TABLES pt_crit_val
                               lt_ust12_merged
                        USING  pv_srchtype
                               lv_found.
    IF lv_found = 1.
*    There is at least matching merged authorizations
      CLEAR pv_rc.
      EXIT.
    ENDIF.

  ENDLOOP.  "AT pt_bers
ENDFORM.                    " COMPARE_MERGED_DATA
*&---------------------------------------------------------------------*
*&      Form  check_value
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_CRIT_VAL       text
*      -->PT_UST12          text
*      -->PV_SRCHTYPE       text
*      -->PV_AUTH_IS_FOUND  text
*----------------------------------------------------------------------*
FORM check_value TABLES pt_crit_val STRUCTURE crit_val
                        pt_ust12    STRUCTURE ust12
                 USING  pv_srchtype  TYPE xandor
                        pv_auth_is_found TYPE x.

  CONSTANTS:
      lc_space(3)  TYPE c VALUE ''' ''' ,
      lc_star(1)   TYPE c VALUE '*',
      lc_starxx(3) TYPE c VALUE '#**' .

*  DATA SHIFT_POSITIONS TYPE I.
  DATA fixed_val_flag TYPE c.
  DATA: rc        TYPE i,
        exception TYPE i.

  FIELD-SYMBOLS:
    <fs_ust12>    TYPE ust12,
    <fs_crit_val> TYPE usref.
*----------------------------------------------------------------------*
* Set intervals according to the character set pattern
  LOOP AT pt_ust12 ASSIGNING <fs_ust12>.
    IF <fs_ust12>-von NE lc_star .
      PERFORM set_interval_auth_ust12 USING <fs_ust12>-von
                                            <fs_ust12>-bis.
    ENDIF.
  ENDLOOP.

* This OR-related code concerns interval values of a particular
* authorization field. So it can be used for cases when auth. fields
* values of an object have relationship either AND or OR.
  IF pv_srchtype = 'OR'.

    LOOP AT pt_ust12 ASSIGNING <fs_ust12>.
      CLEAR: pv_auth_is_found.
      LOOP AT pt_crit_val ASSIGNING <fs_crit_val>
                          WHERE field = <fs_ust12>-field .
*       1st. handle special cases
*       - search for unmaintained auth-fields
        IF <fs_crit_val>-von = lc_space.
          CLEAR pv_auth_is_found.
          IF <fs_ust12>-von = lc_space .
            pv_auth_is_found = 1.
            EXIT.
          ELSE.
            CONTINUE.
          ENDIF.
        ENDIF.
*- if the auth-field contains a star all further question are fullfilled
        IF <fs_ust12>-von = lc_star . "*-value covers all definitions
          pv_auth_is_found = 1.
          EXIT.
        ENDIF.
*       - search for full authorization with fixed values fields
        IF <fs_crit_val>-von EQ lc_starxx.
*         Check if the field is activity one or its domain has
*         fixed values so that check if user has all possible values
*         that means implicit star.
          PERFORM check_field_type TABLES pt_ust12
                                   USING  <fs_crit_val>-field
                                          <fs_crit_val>-object
                                          fixed_val_flag
                                          rc
                                          exception.
          IF NOT rc IS INITIAL.
            pv_auth_is_found = 1.
            EXIT.
          ELSE.
            pv_auth_is_found = 0.
            EXIT.
          ENDIF.
        ENDIF.     "  <fs_crit_val>-von ...

*       and now check for matching intervals
        PERFORM value_in_intervall_or USING <fs_crit_val>-von
                                            <fs_crit_val>-bis
                                            <fs_ust12>-von
                                            <fs_ust12>-bis
                                            pv_auth_is_found .
        IF pv_auth_is_found = 1.
          EXIT.
        ENDIF.

      ENDLOOP.  " AT pt_crit_val
      IF pv_auth_is_found = 1.
        EXIT.
      ENDIF.
    ENDLOOP.  " AT pt_ust12

  ELSE.   "AND condition

    LOOP AT crit_val ASSIGNING <fs_crit_val>.

      pv_auth_is_found = 0.
      LOOP AT pt_ust12 ASSIGNING <fs_ust12>
                       WHERE field = <fs_crit_val>-field.

*     1st. handle special cases
*     - search for unmaintained auth-fields
        IF <fs_crit_val>-von = lc_space.
          IF <fs_ust12>-von = lc_space .
            pv_auth_is_found = 1.
            EXIT.
          ELSE.
            CONTINUE.
          ENDIF.
        ENDIF.
*- if the auth-field contains a star all further question are fullfilled
        IF <fs_ust12>-von = lc_star . "*-value covers all definitions
          pv_auth_is_found = 1.
          EXIT.
        ENDIF.

*     -  search for full authorization
        IF <fs_crit_val>-von EQ lc_starxx.
*       Check if the field is activity one or its domain has
*       fixed values so that check if user has all possible values
*       that means implicit star.
          PERFORM check_field_type TABLES pt_ust12
                                   USING  <fs_crit_val>-field
                                          <fs_crit_val>-object
                                          fixed_val_flag
                                          rc
                                          exception.
          IF NOT rc IS INITIAL.
*         All user's activities/values cover '*'.
            pv_auth_is_found = 1.
            EXIT.
          ELSE.
            IF NOT fixed_val_flag IS INITIAL.
*           AND condition is broken - go out of the routine.
              pv_auth_is_found = 0.
              EXIT.
            ENDIF.
          ENDIF. " NOT rc .
        ENDIF. " <fs_crit_val>-von EQ

*     and now check for matching intervals
        PERFORM value_in_intervall_and USING <fs_crit_val>-von
                                             <fs_crit_val>-bis
                                             <fs_ust12>-von
                                             <fs_ust12>-bis
                                             pv_auth_is_found .
        IF pv_auth_is_found = 1.
          EXIT.
        ENDIF.
      ENDLOOP.   " AT pt_ust12

      IF pv_auth_is_found = 0.
        EXIT.
      ENDIF.
    ENDLOOP.  " AT crit_val
  ENDIF.
ENDFORM.                    " CHECK_VALUE
*
*&---------------------------------------------------------------------*
*&      Form  get_father_profs
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_PROF    text
*      -->PT_PROF    text
*      -->PT_RETURN  text
*----------------------------------------------------------------------*
FORM get_father_profs  USING  pv_prof    TYPE xuprofile
                            pt_prof    TYPE tt_prf_lst
                            pt_return  TYPE tt_prof.
  DATA:
    ls_prof TYPE ts_prof.

  FIELD-SYMBOLS:
    <fs_prf_lst> TYPE ts_prf_lst.
*----------------------------------------------------------------------*
  CLEAR: pt_return[].

  LOOP AT pt_prof ASSIGNING <fs_prf_lst> WHERE subprof = pv_prof.
    ls_prof-profn = <fs_prf_lst>-profn.
    APPEND ls_prof TO pt_return.
  ENDLOOP.
  SORT pt_return.
  DELETE ADJACENT DUPLICATES FROM pt_return.

ENDFORM.                    " get_father_profs
*&---------------------------------------------------------------------*
*&      Form  get_users_single_profs
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_USER    text
*      -->PT_PROF    text
*      -->PT_RETURN  text
*----------------------------------------------------------------------*
FORM get_users_single_profs  USING pv_user   TYPE xubname
                                   pt_prof   TYPE tt_prf_lst
                                   pt_return TYPE tt_prof.
  DATA:
   lt_ust04 TYPE tt_prof,
   lt_return TYPE tt_prof.

  FIELD-SYMBOLS:
   <fs_profn> TYPE ts_prof.
*----------------------------------------------------------------------*
* 1st get direct assigned profiles
  SELECT profile FROM ust04 INTO TABLE lt_ust04
    WHERE bname = pv_user.

* 2nd resolve composite profile to get all single profs
  LOOP AT lt_ust04 ASSIGNING <fs_profn> .
    READ TABLE pt_prof
         WITH KEY profn = <fs_profn>-profn
         TRANSPORTING NO FIELDS BINARY SEARCH.
    IF sy-subrc IS INITIAL. "it's a composite profile
      PERFORM resolve_buffered_cprof USING <fs_profn>-profn
                                           lt_return.
      APPEND LINES OF lt_return TO pt_return .
    ELSE.
      APPEND <fs_profn> TO pt_return.
    ENDIF.
  ENDLOOP.
  SORT pt_return.
  DELETE ADJACENT DUPLICATES FROM pt_return .
ENDFORM.                    " get_users_single_profs
*&---------------------------------------------------------------------*
*&      Form  get_users_with_profiles
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_PROF    text
*      -->PT_USER    text
*----------------------------------------------------------------------*
FORM get_users_with_profiles  USING   pt_prof    TYPE tt_prof
                                      pt_user    TYPE tt_user.
  DATA:
     lr_profile TYPE RANGE OF xuprofile,
     ls_profile LIKE LINE OF lr_profile.
  FIELD-SYMBOLS:
    <fs_prof> TYPE ts_prof .
*----------------------------------------------------------------------*

  IF pt_prof[] IS INITIAL.
    CLEAR: pt_user[].
    RETURN.
  ENDIF.

  ls_profile-sign   = gc_in .
  ls_profile-option = gc_opt_eq .
  LOOP AT pt_prof ASSIGNING <fs_prof> .
    ls_profile-low = <fs_prof>-profn.
    APPEND ls_profile TO lr_profile.
  ENDLOOP.
* select user wich are assigned to pt_prof
  TRY.

      SELECT bname FROM ust04
          INTO TABLE pt_user
          WHERE profile IN lr_profile.                  "#EC CI_GENBUFF

    CATCH cx_sy_open_sql_db.

      SELECT bname FROM ust04
         INTO TABLE pt_user
         FOR ALL ENTRIES IN pt_prof
         WHERE profile = pt_prof-profn .                "#EC CI_GENBUFF

  ENDTRY.
* Some users can have several profiles. Such users are duplicated
  SORT pt_user .
  DELETE ADJACENT DUPLICATES FROM pt_user.

ENDFORM.                    " get_users_with_profiles
*&---------------------------------------------------------------------*
*&      Form  match_user_list
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_USER    text
*      -->PV_USR_CNT text
*----------------------------------------------------------------------*
FORM match_user_list USING  pt_user    TYPE ty_t_user
                            pv_usr_cnt TYPE i.

  FIELD-SYMBOLS: <fs_user> TYPE ty_user .
*----------------------------------------------------------------------*

  IF gt_user_i[] IS INITIAL.
*   there are no restrictions regarding user attributes on selscr
    DESCRIBE TABLE pt_user LINES pv_usr_cnt .
    RETURN.
  ENDIF.

* and now compare and handle the table pt_user
* it's not allowed to change gt_user_i  !!!
  SORT pt_user.
  LOOP AT pt_user ASSIGNING <fs_user> .
    READ TABLE gt_user_i WITH KEY bname = <fs_user>-bname
            TRANSPORTING NO FIELDS BINARY SEARCH.
    IF sy-subrc IS NOT INITIAL.
      DELETE pt_user.
    ENDIF.
  ENDLOOP.
  DESCRIBE TABLE pt_user LINES pv_usr_cnt .

ENDFORM.                    " match_user_list
*&---------------------------------------------------------------------*
*&      Form  merge_auth
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_AUTHS     text
*      -->PT_AUTH_FLD  text
*      -->PV_OBJECT    text
*      -->P_FLAG       text
*----------------------------------------------------------------------*
FORM merge_auth USING pt_auths      TYPE tt_auths
                      pt_auth_fld   TYPE tt_auth_fld_type
                      pv_object     TYPE xuobject
                      p_flag            TYPE c.

* Buffer of authorization objects TOBJ ( Note 907822 )
  STATICS:
    BEGIN OF lt_object OCCURS 100,
        name   LIKE usobt-object,
        count  TYPE i,
        tobj   TYPE tobj,
    END OF lt_object.

  DATA: c_count TYPE i,
        f_count TYPE i,
        erg TYPE c,
        merge_field TYPE tobj-fiel1,
        ls_tobj     TYPE tobj.

  FIELD-SYMBOLS: <fs_auth>      TYPE ts_auth,
                 <it_auth_fld>  TYPE ts_auth_fld_type,
                 <it_auth_bers> TYPE ts_auth.

  FIELD-SYMBOLS: <field> TYPE xufield.

  DATA: su_index TYPE sy-index,
        merging_flag TYPE c.
*----------------------------------------------------------------------*

  CLEAR: n_val, n_val[],
         i_val, i_val[].
* Define number of fields in object
  READ TABLE lt_object WITH KEY name = pv_object.
  IF sy-subrc NE 0.
    SELECT SINGLE * FROM tobj INTO ls_tobj WHERE objct = pv_object.
    IF sy-subrc NE 0.
      EXIT.
    ENDIF.
    lt_object-name = pv_object.
    DO 10 TIMES.
      ASSIGN COMPONENT sy-index OF STRUCTURE ls_tobj TO <field>.
      IF <field> IS INITIAL.
        lt_object-count = sy-index - 2.
        EXIT.
      ENDIF.
    ENDDO.
    MOVE ls_tobj TO lt_object-tobj.
    APPEND lt_object.
  ELSE.
    MOVE lt_object-tobj TO ls_tobj.              " Note 907822
  ENDIF.

* Number of fields that should be equal for merging
  f_count = lt_object-count - 1.
* Get first authorization
  READ TABLE pt_auths INDEX 1 ASSIGNING <fs_auth>.
  APPEND <fs_auth> TO bers.
* Get auth.data of first authorization

  LOOP AT pt_auth_fld ASSIGNING <it_auth_fld>
                    WHERE object =  <fs_auth>-objct
                      AND auth   =  <fs_auth>-auth.

    APPEND <it_auth_fld> TO merged_it_auth_fld.
  ENDLOOP.
* Start from second authorization
  LOOP AT pt_auths ASSIGNING <fs_auth> FROM 2.
    CLEAR merging_flag.
* Already merged
    LOOP AT bers ASSIGNING <it_auth_bers>.
      CLEAR: c_count, merge_field.
*     Compare data for every field
      DO lt_object-count TIMES.
        su_index = sy-index + 1.
        ASSIGN COMPONENT su_index OF STRUCTURE ls_tobj TO <field>.
*       Get new values
        PERFORM get_field_values TABLES n_val
                                 USING  <fs_auth>
                                        pt_auth_fld
                                        pv_object
                                        <field>.
*       Get old values
        PERFORM get_field_values TABLES i_val
                                 USING  <it_auth_bers>
                                        pt_auth_fld
                                        pv_object
                                        <field>.
*       Compare fields values
        PERFORM fill_compare_fields IN PROGRAM saplsuprn
                TABLES i_val n_val USING '0' erg.
        IF erg = 'E'.
          c_count = c_count + 1.
        ELSE.
          merge_field = <field>.
*         ERG_FIELD = ERG.
        ENDIF.
      ENDDO.
      IF c_count = lt_object-count.
* All fields are equal
        merging_flag = 'X'.
        EXIT.
      ELSEIF c_count = f_count.
* N-1 fields are equal. So merging is possible
        CLEAR: n_val, n_val[], i_val, i_val[].
* Get new values for field to be merged
        PERFORM get_field_values TABLES n_val
                                 USING  <fs_auth>
                                        pt_auth_fld
                                        pv_object
                                        merge_field.
* Get old values for field to be merged
        PERFORM get_field_values TABLES i_val
                                 USING  <it_auth_bers>
                                         pt_auth_fld
                                         pv_object
                                         merge_field.
* Merge old and new values for field to be merged
        PERFORM fill_field_merge IN PROGRAM saplsuprn TABLES n_val i_val
.
* Merge authorizations
        PERFORM fill_set_field_st_new TABLES i_val
                                              merged_it_auth_fld
                                       USING  pv_object
                                             <it_auth_bers>
                                             merge_field.
        p_flag = 'X'.
        merging_flag = 'X'.
        EXIT.
      ENDIF.
    ENDLOOP.  " AT bers

    IF merging_flag IS INITIAL.
*    No merging can be done. Add authorization to BERS
*    Add authorization to BERS
      READ TABLE bers WITH KEY objct = <fs_auth>-objct
                               auth  = <fs_auth>-auth
                      TRANSPORTING NO FIELDS
                      BINARY SEARCH.
      IF sy-subrc IS NOT INITIAL.
        INSERT <fs_auth> INTO bers INDEX sy-tabix.
*       Add authorization data to MERGED_IT_AUTH_FLD.
        LOOP AT pt_auth_fld ASSIGNING <it_auth_fld>
                            WHERE object = <fs_auth>-objct
                              AND auth   = <fs_auth>-auth.
          APPEND <it_auth_fld> TO merged_it_auth_fld.
        ENDLOOP.  " AT pt_auth_fld
      ENDIF.
    ENDIF.

  ENDLOOP.   " AT pt_auth_fld

ENDFORM.                    " MERGE_AUTH
*&---------------------------------------------------------------------*
*&      Form  fill_set_field_st_new
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_VAL              text
*      -->PT_MERGED_AUTH_FLD  text
*      -->PV_OBJECT           text
*      -->PS_BERS             text
*      -->PV_MERGE_FLD        text
*----------------------------------------------------------------------*
FORM fill_set_field_st_new TABLES pt_val        LIKE i_val[]
                                pt_merged_auth_fld TYPE tt_auth_fld_type
                           USING  pv_object     TYPE xuobject
                                  ps_bers       TYPE ts_auth
                                  pv_merge_fld  TYPE xufield.

  DATA:
    ls_auth_fldx  TYPE ts_auth_fld_type,
    ls_auth_fld   TYPE ts_auth_fld_type,
    lv_index      TYPE sytabix.

  FIELD-SYMBOLS:
     <fs_auth_fld> TYPE ts_auth_fld_type.
*----------------------------------------------------------------------*
  ls_auth_fldx-object = pv_object.
  ls_auth_fldx-auth   = ps_bers-auth.
  ls_auth_fldx-field  = pv_merge_fld.

  READ TABLE pt_merged_auth_fld INTO ls_auth_fld
       WITH KEY object = pv_object
                auth   = ps_bers-auth
                field  = pv_merge_fld.

  lv_index  = sy-tabix.
  WHILE    ls_auth_fld-object = pv_object
       AND ls_auth_fld-auth   = ps_bers-auth
       AND ls_auth_fld-field  = pv_merge_fld
       AND sy-subrc = 0.

    DELETE pt_merged_auth_fld INDEX lv_index.
    READ TABLE pt_merged_auth_fld INTO ls_auth_fld INDEX lv_index.
  ENDWHILE.

  CLEAR: ls_auth_fldx-low,
         ls_auth_fldx-high,
         ls_auth_fld.

  LOOP AT pt_val.
    MOVE-CORRESPONDING ls_auth_fldx TO ls_auth_fld.
    ls_auth_fld-merge_flag = 'X'.
    ls_auth_fld-low  = pt_val-low.
    ls_auth_fld-high = pt_val-high.
    READ TABLE pt_merged_auth_fld
         WITH KEY object = ls_auth_fld-object
                  auth   = ls_auth_fld-auth
                  field  = ls_auth_fld-field
                  low    = ls_auth_fld-low
                  high   = ls_auth_fld-high
         ASSIGNING <fs_auth_fld> BINARY SEARCH.
    IF sy-subrc IS NOT INITIAL.
      INSERT ls_auth_fld INTO pt_merged_auth_fld INDEX sy-tabix.
    ENDIF.
  ENDLOOP.

ENDFORM.                    " FILL_SET_FIELD_ST_NEW
*&---------------------------------------------------------------------*
*&      Form  get_field_values
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_VAL       text
*      -->PT_AUTH      text
*      -->PT_AUTH_FLD  text
*      -->PV_OBJECT    text
*      -->PV_FIELD     text
*----------------------------------------------------------------------*
FORM get_field_values  TABLES   pt_val       LIKE n_val[]
                       USING    pt_auth      TYPE ts_auth
                                pt_auth_fld  TYPE tt_auth_fld_type
                                pv_object    TYPE xuobject
                                pv_field     TYPE xufield.
  DATA:
    ls_auth_fld TYPE ts_auth_fld_type,
    lv_cnt      TYPE i.
*----------------------------------------------------------------------*

  REFRESH pt_val.
  READ TABLE pt_auth_fld INTO ls_auth_fld WITH KEY object = pv_object
                                                   auth   = pt_auth-auth
                                                   field  = pv_field
                                                   BINARY SEARCH.
  lv_cnt = sy-tabix.

  WHILE     ls_auth_fld-object = pv_object
        AND ls_auth_fld-auth   = pt_auth-auth
        AND ls_auth_fld-field  = pv_field
        AND sy-subrc = 0.

    READ TABLE pt_val WITH KEY low  = ls_auth_fld-low
                               high = ls_auth_fld-high
                      TRANSPORTING NO FIELDS
                      BINARY SEARCH.
    IF sy-subrc IS NOT INITIAL.
      INSERT ls_auth_fld INTO pt_val INDEX sy-tabix.
    ENDIF.

    lv_cnt = lv_cnt + 1.
    READ TABLE pt_auth_fld INTO ls_auth_fld INDEX lv_cnt.

  ENDWHILE.

ENDFORM.                    " GET_FIELD_VALUES
*&---------------------------------------------------------------------*
*&      Form  resolve_buffered_cprof
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_CPROF   text
*      -->PT_SPROFS  text
*----------------------------------------------------------------------*
FORM resolve_buffered_cprof USING pv_cprof  TYPE xuprofile
                                  pt_sprofs TYPE tt_prof.
  FIELD-SYMBOLS:
    <fs_cprof_lin> TYPE ts_prf_lst.
*----------------------------------------------------------------------*
  LOOP AT gt_prf_lst ASSIGNING <fs_cprof_lin> WHERE profn = pv_cprof
                                                AND typ   = gc_ptype_s.
    APPEND <fs_cprof_lin>-subprof TO pt_sprofs.
  ENDLOOP.

ENDFORM.                    " resolve_buffered_cprof
*&---------------------------------------------------------------------*
*&      Form  susr_get_auths_of_object
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_OBJECT     text
*      -->PV_CNT_AUTHS  text
*      -->PT_AUTHS      text
*----------------------------------------------------------------------*
FORM susr_get_auths_of_object USING  pv_object    TYPE xuobject
                                     pv_cnt_auths TYPE i
                                     pt_auths     LIKE auths[].
  DATA:
    ls_auths TYPE usref.
*----------------------------------------------------------------------*

  CLEAR: ust12_data, ust12_data[].

  PERFORM get_data_from_ust12buffer USING pv_object
                                          ust12_data[].
* Only authorizations names are required
  ls_auths-object = pv_object.
  LOOP AT ust12_data ASSIGNING <ust12_data>.
    IF sy-tabix EQ 1.
      ls_auths-auth = <ust12_data>-auth.
      APPEND ls_auths TO pt_auths.
    ELSE.
      IF ls_auths-auth EQ <ust12_data>-auth.
        CONTINUE.
      ELSE.
        ls_auths-auth = <ust12_data>-auth.
        APPEND ls_auths TO pt_auths.
      ENDIF.
    ENDIF.
  ENDLOOP.

  DESCRIBE TABLE pt_auths LINES pv_cnt_auths.

ENDFORM.                    " SUSR_GET_AUTHS_OF_OBJECT
*&---------------------------------------------------------------------*
*&      Form  get_data_from_ust12buffer
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_CRIT_VAL_OBJECT  text
*      -->PT_UST12_DATA       text
*----------------------------------------------------------------------*
FORM get_data_from_ust12buffer USING
                                 pv_crit_val_object TYPE xuobject
                                 pt_ust12_data      TYPE tyt_ust12_data.

  DATA: ls_ust12_tab TYPE ty_ust12_tab.
*-----------------------------------------------------------------------

* To be thought off how to return the values
  READ TABLE ust12_tab ASSIGNING <ust12_tab>
    WITH KEY objct = pv_crit_val_object BINARY SEARCH.
  IF sy-subrc EQ 0.
    pt_ust12_data = <ust12_tab>-auth_data[].
  ELSE.
* Authorization data for the particular object
    SELECT auth field von bis FROM ust12
      INTO TABLE ls_ust12_tab-auth_data
      WHERE objct = pv_crit_val_object
        AND aktps = gc_aktps_a.                         "#EC CI_GENBUFF
* Fill in the table with complex structure
    ls_ust12_tab-objct = pv_crit_val_object.
    INSERT ls_ust12_tab INTO TABLE ust12_tab.
    pt_ust12_data[] = ls_ust12_tab-auth_data.
  ENDIF.

ENDFORM.                    " GET_DATA_FROM_UST12BUFFER
*&---------------------------------------------------------------------*
*&      Form  susr_get_auths_with_spec_vals
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_CRIT_OBJECT  text
*      -->PV_SRCHTYPE     text
*      -->PV_CNT_AUTHS    text
*      -->PT_CRIT_VAL     text
*      -->PT_AUTHS        text
*----------------------------------------------------------------------*
FORM susr_get_auths_with_spec_vals USING  pv_crit_object TYPE xuobject
                                          pv_srchtype    TYPE xandor
                                          pv_cnt_auths   TYPE i
                                          pt_crit_val    LIKE crit_val[]
                                          pt_auths       LIKE auths[].

* Logic of this subroutine is similar to logic of
* the function module SUSR_GET_AUTHS_WITH_SPEC_VALS but only
  PERFORM matching_auths_new TABLES pt_crit_val
                                    pt_auths
                             USING  pv_crit_object
                                    pv_cnt_auths
                                    pv_srchtype .

ENDFORM.                    " SUSR_GET_AUTHS_WITH_SPEC_VALS
*&---------------------------------------------------------------------*
*&      Form  matching_auths_new
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_CRIT_VAL   text
*      -->PT_AUTHS      text
*      -->PV_OBJECT     text
*      -->PV_CNT_AUTHS  text
*      -->PV_SRCH_TYPE  text
*----------------------------------------------------------------------*
FORM matching_auths_new TABLES   pt_crit_val STRUCTURE crit_val
                                 pt_auths     STRUCTURE auths
                        USING    pv_object    TYPE xuobject
                                 pv_cnt_auths TYPE i
                                 pv_srch_type TYPE xandor .
* Structure and logic of this subroutine is similar to
* structure and logic of subroutine MATCHING_AUTHS but performance is
* improved.
  DATA:
       lv_obj_1field   TYPE x,
       lv_field2       TYPE xufield,
    lv_auth_is_found   TYPE x,
*       SHIFT_POSITIONS TYPE I,
       ust12_one_auth LIKE ust12 OCCURS 0 WITH HEADER LINE,
       current_auth LIKE ust12-auth.

  FIELD-SYMBOLS <crit_val> LIKE crit_val.
*----------------------------------------------------------------------
  CLEAR: pt_auths, pt_auths[], pv_cnt_auths.

* 1st create intervals for critical values
  LOOP AT pt_crit_val ASSIGNING <crit_val> .             "note 978447
    PERFORM set_interval_auth_input USING <crit_val>-von
                                          <crit_val>-bis .
  ENDLOOP.

* 2nd check if it is an one-field object                - note 1036693
  SELECT SINGLE fiel2 FROM tobj INTO lv_field2
    WHERE objct EQ pv_object.

  IF lv_field2 IS INITIAL .
    lv_obj_1field = 1 .               "the object contains only 1 field
  ELSE.
    CLEAR: lv_obj_1field.
  ENDIF.

* Get data from the buffer UST12BUFFER
  CLEAR: ust12_data, ust12_data[].

  PERFORM get_data_from_ust12buffer USING pv_object
                                          ust12_data[].

  READ TABLE ust12_data ASSIGNING <ust12_data> INDEX 1.
  IF sy-subrc EQ 0.
    current_auth = <ust12_data>-auth.
  ENDIF.

  LOOP AT ust12_data ASSIGNING <ust12_data>.
    IF <ust12_data>-auth EQ current_auth.
      MOVE-CORRESPONDING <ust12_data> TO ust12_one_auth.
      APPEND ust12_one_auth.
    ELSE.
      PERFORM check_value TABLES pt_crit_val
                                 ust12_one_auth
                           USING pv_srch_type
                                 lv_auth_is_found.

      IF lv_auth_is_found = 1.
        pt_auths-object = pv_object.
        pt_auths-auth   = current_auth.
        APPEND pt_auths.
        pv_cnt_auths = pv_cnt_auths + 1.
      ELSE.                                            "note 1036693
        IF pv_srch_type = c_searchtype_and AND lv_obj_1field = 1 .
          deleted_auths-object = pv_object.
          deleted_auths-auth   = current_auth.
          APPEND deleted_auths.
        ENDIF.
      ENDIF.

      CLEAR: ust12_one_auth, ust12_one_auth[].
      current_auth = <ust12_data>-auth.
      MOVE-CORRESPONDING <ust12_data> TO ust12_one_auth.
      APPEND ust12_one_auth.
    ENDIF.
  ENDLOOP.
* For last object name
  PERFORM check_value TABLES pt_crit_val
                             ust12_one_auth
                       USING pv_srch_type
                             lv_auth_is_found.
  IF lv_auth_is_found = 1.
    pt_auths-object = pv_object.
    pt_auths-auth   = current_auth.
    APPEND pt_auths.
    pv_cnt_auths = pv_cnt_auths + 1.
  ENDIF.

ENDFORM.                    " MATCHING_AUTHS_NEW
*&---------------------------------------------------------------------*
*&      Form  susr_get_profs_with_spec_auths
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_PROFS   text
*      -->PT_AUTHS   text
*      -->PV_LIN_CNT text
*----------------------------------------------------------------------*
FORM susr_get_profs_with_spec_auths
          TABLES pt_profs  STRUCTURE profiles
                 pt_auths  STRUCTURE usref
          USING  pv_lin_cnt TYPE i.

  DATA:
    lt_sprofs TYPE tt_prof,
    lr_auths  TYPE RANGE OF xuauth,
    ls_auths  LIKE LINE OF lr_auths,
    ls_uslst  TYPE uslst,
    lv_object TYPE xuobject ,
    lt_return TYPE tt_prof,
    lt_cprofs TYPE tt_prof.

  FIELD-SYMBOLS:
    <fs_usref> TYPE usref,
    <fs_profn> TYPE ts_prof.
*----------------------------------------------------------------------*
* prepare range table for selection at UST10S
  ls_auths-sign   = gc_in .
  ls_auths-option = gc_opt_eq .
  LOOP AT pt_auths ASSIGNING <fs_usref> .
    ls_auths-low = <fs_usref>-auth.
    APPEND ls_auths TO lr_auths .
  ENDLOOP.

  IF <fs_usref> IS ASSIGNED .
    lv_object = <fs_usref>-object.
  ELSE.
    EXIT. "no selection table -> no result.
  ENDIF.
* now get data from UST10S (try it fast, if it fails go the classic way)
  TRY.

      SELECT profn FROM ust10s INTO TABLE lt_sprofs
        WHERE aktps  EQ gc_aktps_a
          AND objct  EQ lv_object
          AND auth   IN lr_auths.                       "#EC CI_GENBUFF

    CATCH cx_sy_open_sql_db.

      SELECT profn FROM ust10s INTO TABLE lt_sprofs
        FOR ALL ENTRIES IN pt_auths
        WHERE aktps  EQ gc_aktps_a
          AND objct  EQ lv_object
          AND auth   EQ pt_auths-auth.                  "#EC CI_GENBUFF

  ENDTRY.

  SORT lt_sprofs.
  DELETE ADJACENT DUPLICATES FROM lt_sprofs .

* add father profiles (composite profiles) to the result list
  LOOP AT lt_sprofs ASSIGNING <fs_profn> .
    PERFORM get_father_profs USING  <fs_profn>-profn
                                    gt_prf_lst
                                    lt_return.
    APPEND LINES OF lt_return TO lt_cprofs.
  ENDLOOP.

  SORT lt_cprofs.
  DELETE ADJACENT DUPLICATES FROM lt_cprofs .
  CLEAR: ls_uslst.
  ls_uslst-aktps = gc_aktps_a.
  ls_uslst-type  = gc_ptype_c.
  LOOP AT lt_cprofs ASSIGNING <fs_profn> .
    ls_uslst-profile = <fs_profn>-profn.
    APPEND ls_uslst TO pt_profs.
  ENDLOOP.

* transfer the result to the classic transfer format
  CLEAR: ls_uslst.
  ls_uslst-aktps = gc_aktps_a.
  ls_uslst-type  = gc_ptype_s.
  LOOP AT lt_sprofs ASSIGNING <fs_profn> .
    ls_uslst-profile = <fs_profn>-profn.
    APPEND ls_uslst TO pt_profs.
  ENDLOOP.

* restrict profs like select screen input for perf. optimization
* in correction part II

* return also a line counter
  DESCRIBE TABLE pt_profs LINES pv_lin_cnt .

ENDFORM.                    " SUSR_GET_PROFS_WITH_SPEC_AUTHS
*&---------------------------------------------------------------------*
*&      Form  susr_get_users_with_spec_profs
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_PROFILES  text
*      -->PT_USERS     text
*      -->PV_USER_CNT  text
*----------------------------------------------------------------------*
FORM susr_get_users_with_spec_profs USING  pt_profiles LIKE profiles[]
                                           pt_users    TYPE ty_t_user
                                           pv_user_cnt TYPE i.
  DATA:
    lr_profile    TYPE RANGE OF xuprofile,
    ls_profile    LIKE LINE OF lr_profile,
    ls_refusers   TYPE LINE OF tt_user_ref,
    lt_users_copy TYPE ty_t_user,
    lt_refuser    TYPE tt_user_ref.

  DATA:
    sy_subrc.

  FIELD-SYMBOLS:
    <fs_prof>  TYPE uslst,
    <fs_users_copy> TYPE ty_user.
*----------------------------------------------------------------------*

  ls_profile-sign   = gc_in .
  ls_profile-option = gc_opt_eq .
  LOOP AT pt_profiles ASSIGNING <fs_prof> .
    ls_profile-low = <fs_prof>-profile.
    APPEND ls_profile TO lr_profile.
  ENDLOOP.
* select user wich are assigned to p_profiles
  TRY.

      SELECT bname FROM ust04
          APPENDING TABLE pt_users
          WHERE profile IN lr_profile.                  "#EC CI_GENBUFF

    CATCH cx_sy_open_sql_db.

      SELECT bname FROM ust04
         APPENDING TABLE pt_users
         FOR ALL ENTRIES IN pt_profiles
         WHERE profile = pt_profiles-profile .          "#EC CI_GENBUFF

  ENDTRY.

* Some users can have several profiles. Such users are duplicated
  SORT pt_users.
  DELETE ADJACENT DUPLICATES FROM pt_users.
  lt_users_copy[] = pt_users[].
  lt_refuser[] = gt_refuser[].
  CLEAR pt_users.

  SORT gt_refuser.
* select users with reference user
  LOOP AT lt_users_copy ASSIGNING <fs_users_copy>.

    APPEND <fs_users_copy> TO pt_users.
    CLEAR sy_subrc.

    WHILE sy_subrc = 0.

      READ TABLE lt_refuser INTO ls_refusers
         WITH KEY refuser = <fs_users_copy>-bname
         BINARY SEARCH.
      sy_subrc = sy-subrc.

      IF sy-subrc = 0.
        DELETE lt_refuser INDEX sy-tabix.

        READ TABLE pt_users
             WITH KEY bname = ls_refusers-bname
             TRANSPORTING NO FIELDS
             BINARY SEARCH.
        IF sy-subrc <> 0.
          INSERT ls_refusers-bname INTO pt_users INDEX sy-tabix.
        ENDIF.
      ENDIF.

    ENDWHILE.
  ENDLOOP.

  DESCRIBE TABLE pt_users LINES pv_user_cnt .

ENDFORM.                    " SUSR_GET_USERS_WITH_SPEC_PROFS
*&---------------------------------------------------------------------*
*&      Form  value_in_intervall_and
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->VVON       text
*      -->VBIS       text
*      -->TVON       text
*      -->TBIS       text
*      -->FOUND      text
*----------------------------------------------------------------------*
FORM  value_in_intervall_and USING vvon   TYPE xuval
                                   vbis   TYPE xuval
                                   tvon   TYPE xuval
                                   tbis   TYPE xuval
                                   found  TYPE x.

  IF NOT ( tbis < vvon  OR tvon > vbis ).                 "#EC PORTABLE
    found = 1.
  ELSEIF vvon CA pattern_low(1) .

    IF sy-fdpos IS NOT INITIAL .
      MOVE vvon(sy-fdpos) TO vvon .
    ENDIF.
*   it's also a hit: vvon is member of vvon*
    IF vvon EQ tvon .
      found = 1.
    ENDIF.

  ELSEIF tvon CA pattern_low(1) .

    IF sy-fdpos IS NOT INITIAL .
      MOVE tvon(sy-fdpos) TO tvon .
    ENDIF.
*   it's also a hit: tvon is a member of tvon*
    IF vvon EQ tvon .
      found = 1.
    ENDIF.

  ELSE.
    found = 0.
  ENDIF. " vvon <= tvon AND  tbis <= vbis

ENDFORM.                               " VALUE_IN_INTERVALL_AND
*&---------------------------------------------------------------------*
*&      Form  value_in_intervall_or
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->VVON       text
*      -->VBIS       text
*      -->TVON       text
*      -->TBIS       text
*      -->FOUND      text
*----------------------------------------------------------------------*
FORM value_in_intervall_or USING vvon   TYPE xuval
                                 vbis   TYPE xuval
                                 tvon   TYPE xuval
                                 tbis   TYPE xuval
                                 found  TYPE x.

  found = 1 .
  IF tbis < vvon  OR  vbis < tvon .                       "#EC PORTABLE
    found = 0 .              "intervals are not overlapping
    IF vvon CA pattern_low(1) .

      IF sy-fdpos IS NOT INITIAL .
        MOVE vvon(sy-fdpos) TO vvon .
      ENDIF.
*      it's also a hit: vvon is member of vvon*
      IF vvon EQ tvon .
        found = 1.
      ENDIF.

    ELSEIF tvon CA pattern_low(1) .

      IF sy-fdpos IS NOT INITIAL .
        MOVE tvon(sy-fdpos) TO tvon .
      ENDIF.
*      it's also a hit: tvon is a member of tvon*
      IF vvon EQ tvon .
        found = 1.
      ENDIF.

    ENDIF. " vvon CA patt ...
  ENDIF.  " tbis < vvon ...

ENDFORM.                               " VALUE_IN_INTERVALL_OR
*&---------------------------------------------------------------------*
*&      Form  get_1field_objects
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_OBJECTS text
*----------------------------------------------------------------------*
FORM get_1field_objects USING pt_objects TYPE tt_1fld_obj.

  SELECT objct FROM tobj INTO TABLE pt_objects
    WHERE fiel2 = space.

  SORT pt_objects.

ENDFORM.                    " get_1field_objects
*&---------------------------------------------------------------------*
*&      Form  read_refuser
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PT_REFUSER text
*----------------------------------------------------------------------*
FORM read_refuser  TABLES pt_refuser.

  SELECT bname refuser FROM usrefus
    INTO CORRESPONDING FIELDS OF TABLE pt_refuser
    WHERE refuser <> space.                             "#EC CI_GENBUFF

  SORT pt_refuser.

ENDFORM.                    " READ_REFUSER
*&---------------------------------------------------------------------*
*&      Form  resolve_all_composite_profs
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM resolve_all_composite_profs .
  DATA:
    lv_msg1    TYPE symsgv,
    lv_msg2    TYPE symsgv,
    lv_msg3    TYPE symsgv,
    lt_return  TYPE tt_prf_lst,
    lt_rec_chk TYPE tt_prof,
    lv_txt     TYPE string.

  FIELD-SYMBOLS:
    <fs_one_prof> TYPE ts_prof.
*----------------------------------------------------------------------*
  IF gt_c_prfn[] IS NOT INITIAL.
    RETURN.
  ENDIF.
* set actual status output
  lv_txt = 'Select all profiles'(t02).                      "#EC *
  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      percentage = 10
      text       = lv_txt.

  PERFORM write_joblog_status USING 'SELPRF'
                                     lv_txt .

* get all c-profiles in a simple list
  SELECT profn FROM usr10 INTO TABLE gt_c_prfn
    WHERE aktps = gc_aktps_a
      AND typ   = gc_ptype_c.                         "#EC CI_SGLSELECT

  SORT gt_c_prfn.
* now we have to resolve all c-profiles and have now to resolve them
  LOOP AT gt_c_prfn ASSIGNING <fs_one_prof>.
    CLEAR: lt_return[],
           lt_rec_chk[],
           gv_ret.

    PERFORM resolve_one_prof USING <fs_one_prof>-profn
                                   lt_return[]
                                   lt_rec_chk
                                   gv_ret.
    IF gv_ret IS INITIAL.
      APPEND LINES OF lt_return TO gt_prf_lst.
    ELSE.
      lv_msg1 = 'Inconsistent composite profile'(e01).      "#EC *
      lv_msg2 = 'is excluded from selection'(e02).          "#EC *
      lv_msg3 = '(profile contains cycles).'(e03) .         "#EC *
      CONCATENATE lv_msg1 <fs_one_prof>-profn
             INTO lv_msg1
             SEPARATED BY space.

      IF sy-batch IS INITIAL .

        CALL FUNCTION 'BALW_BAPIRETURN_GET2'
          EXPORTING
            type   = 'W'
            cl     = '01'
            number = '319'
            par1   = lv_msg1
            par2   = lv_msg2
            par3   = lv_msg3
          IMPORTING
            return = gs_return.
*        append gs_return to gt_log_alv.
      ELSE.

        MESSAGE ID '01' TYPE 'I'  NUMBER '319'
                WITH lv_msg1
                     lv_msg2
                     lv_msg3.
      ENDIF.
    ENDIF.
  ENDLOOP.

ENDFORM.                    " resolve_all_composite_profs
*&---------------------------------------------------------------------*
*&      Form  resolve_one_prof
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->VALUE(PV_PROF)  text
*      -->PT_PROF         text
*      -->PT_REC_CHK      text
*      -->PV_RET          text
*----------------------------------------------------------------------*
FORM resolve_one_prof USING  value(pv_prof)     TYPE xuprofile
                             pt_prof            TYPE tt_prf_lst
                             pt_rec_chk         TYPE tt_prof
                             pv_ret             TYPE x.
  DATA:
    lt_return     TYPE tt_prf_lst,
    lt_profs      TYPE tt_prof,
    lt_rec_chk    TYPE tt_prof,
    lt_prf_lst    TYPE tt_prf_lst,
    ls_prf_lst    TYPE ts_prf_lst.

  FIELD-SYMBOLS:
    <fs_prof>     TYPE ts_prof,
    <fs_prof_lst> TYPE ts_prf_lst.
*----------------------------------------------------------------------*
  ls_prf_lst-profn = pv_prof.
* 1a. get subprofiles for pv_prof including prof-type
  SELECT subprof FROM ust10c INTO TABLE lt_profs
    WHERE  profn EQ pv_prof
      AND  aktps EQ 'A'.


* 1b. prepare the list for appending into global list,
*     resolve the actual level
  LOOP AT lt_profs ASSIGNING <fs_prof> .

    READ TABLE gt_c_prfn  WITH KEY profn = <fs_prof>-profn
         TRANSPORTING NO FIELDS.

    IF sy-subrc IS INITIAL .
*     it's an active c-profile - get resolved content of this profile
*     - 1st check it against cycles
      READ TABLE pt_rec_chk WITH KEY profn = <fs_prof>-profn
           TRANSPORTING NO FIELDS.
      IF sy-subrc IS INITIAL.
        pv_ret = 1.
        RETURN.
      ENDIF.
*     - 2nd resolve this composite profile
      lt_rec_chk[] = pt_rec_chk[].
      APPEND <fs_prof>-profn TO lt_rec_chk[].

      PERFORM resolve_one_prof USING <fs_prof>-profn
                                     lt_return[]
                                     lt_rec_chk
                                     gv_ret.
      IF gv_ret IS INITIAL.
*       add results to the result list on this resolution level
        ls_prf_lst-subprof = <fs_prof>-profn.
        ls_prf_lst-typ     = gc_ptype_c.
        APPEND ls_prf_lst TO lt_prf_lst.

        LOOP AT lt_return ASSIGNING <fs_prof_lst> .
          <fs_prof_lst>-profn = pv_prof.
          APPEND <fs_prof_lst> TO lt_prf_lst .
        ENDLOOP.
        CLEAR: lt_return[].
      ENDIF.
    ELSE.
*     it's a single profile ... append to return list
      ls_prf_lst-subprof = <fs_prof>-profn.
      ls_prf_lst-typ     = gc_ptype_s.
      APPEND ls_prf_lst TO lt_prf_lst.

    ENDIF.

  ENDLOOP.

  APPEND LINES OF lt_prf_lst TO pt_prof. "respect recursiv call
  SORT pt_prof BY typ subprof.
  DELETE ADJACENT DUPLICATES FROM pt_prof.
ENDFORM.                    " resolve_one_prof
*&---------------------------------------------------------------------*
*&      Form  write_joblog_status
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_MODE    text
*      -->PT_TXT     text
*----------------------------------------------------------------------*
FORM write_joblog_status USING pv_mode LIKE gv_mode
                               pt_txt  TYPE string.

  DATA: lv_txt TYPE string.

  IF sy-batch IS INITIAL AND sy-binpt IS INITIAL .
    RETURN.
  ENDIF.

  CASE pv_mode.
    WHEN 'SELPRF' .
      lv_txt = 'Select and check all profiles'(s01).        "#EC *
      MESSAGE ID 'S#' TYPE 'I' NUMBER '408' WITH lv_txt .

    WHEN 'SELSCR' .
      lv_txt = 'Analyze selection criteria for user'(s02).  "#EC *
      MESSAGE ID 'S#' TYPE 'I' NUMBER '408' WITH lv_txt .

    WHEN 'ANALY' .
      lv_txt = 'Analyze user data'(s03).                    "#EC *
      MESSAGE ID 'S#' TYPE 'I' NUMBER '408' WITH lv_txt .

    WHEN 'OUTPUT' .
      lv_txt = 'Prepare list output'(s04).                  "#EC *
      MESSAGE ID 'S#' TYPE 'I' NUMBER '408' WITH lv_txt .

    WHEN 'SELVCA' .
      lv_txt = ' Analyze Critical Authorization:'(s05).     "#EC *
      MESSAGE ID 'S#' TYPE 'I' NUMBER '252' WITH lv_txt pt_txt .

    WHEN 'SELVCC' .
      lv_txt =  ' Analyze Critical Combination:'(s06).      "#EC *
      MESSAGE ID 'S#' TYPE 'I' NUMBER '252' WITH lv_txt pt_txt .

    WHEN OTHERS.
      MESSAGE ID 'S#' TYPE 'I' NUMBER '408' WITH lv_txt .

  ENDCASE.

ENDFORM.                    " write_joblog_status