SAP BW BEST PRACTISE #2. Ограничиваем выбор переменных на селекционном экране через F4.

Создаем класс ZCL_F4_MAIN

Переходим на вкладку “Interfaces” и добавляем два интерфейса:

  • IF_BADI_INTERFACE
  • IF_RSR_VARIABLE_F4_RESTRICT

Переопределяем методы

IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_FLAT

  METHOD if_rsr_variable_f4_restrict~get_restriction_flat.
    DATA: BEGIN OF wt_cfodel,
            low TYPE rschavl,
          END OF wt_cfodel.
    DATA:
      l_v_classname   TYPE seoclsname,
      l_o_object      TYPE REF TO object,
      l_f4_method     TYPE string VALUE `IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_FLAT`,
      l_method_exists TYPE rs_bool,
      l_s_range       LIKE LINE OF c_t_range,
      l_common_logic  TYPE rs_bool VALUE rs_c_false,
      lt_auth         TYPE rsdd_t_range,
      lt_del          LIKE SORTED TABLE OF wt_cfodel WITH UNIQUE KEY low,
      lt_buffer       LIKE SORTED TABLE OF wt_cfodel WITH UNIQUE KEY low,
      ls_del          LIKE LINE OF lt_del,
      ls_buffer       LIKE LINE OF lt_buffer,
      ls_auth         TYPE rrrangesid.

*   Собираем имя класса по маске ZCL_F4_[Имя переменной]
    CONCATENATE   `ZCL_F4_` i_vnam INTO l_v_classname.

*   Проверяем есть ли метод для обработки переменной в полученном классе
    CALL FUNCTION 'Z_FM_CHECK_METHOD'
      EXPORTING
        i_class_name    = l_v_classname
        i_method_name   = l_f4_method
      IMPORTING
        e_method_exists = l_method_exists.

    IF l_method_exists = rs_c_true.
*     Если такой метод есть, то вызываем его
      CREATE OBJECT l_o_object TYPE (l_v_classname).
      CALL METHOD l_o_object->(l_f4_method)
        EXPORTING
          i_vnam        = i_vnam
          i_iobjnm      = i_iobjnm
          i_t_var_range = i_t_var_range
          i_t_compid    = i_t_compid
          i_req_data    = i_req_data
        CHANGING
          c_infoprov    = c_infoprov
          c_f4_mode     = c_f4_mode
          c_key_date    = c_key_date
          c_t_range     = c_t_range.

      IF c_t_range IS INITIAL.
*       Если переменная не вернула ничего, то выводим пустой список значений
        CLEAR l_s_range.
        l_s_range-sign = 'I'.
        l_s_range-option = 'EQ'.
        l_s_range-iobjnm = i_iobjnm.
        l_s_range-low = ''.
        APPEND l_s_range TO c_t_range.
        l_s_range-sign = 'E'.
        APPEND l_s_range TO c_t_range.
      ELSE.
*       Если переменная что-то вернула, то проверяем, что это не значение n_c_use_common_logic, которое говорит, что не надо применять логику, описанную в классе для запроса.
*       В этом случае выполняем общую логику
        READ TABLE c_t_range WITH KEY low = me->n_c_use_common_logic TRANSPORTING NO FIELDS.
        IF sy-subrc = 0.
          l_common_logic = rs_c_true.
        ENDIF.

      ENDIF.
    ELSE.
*     Если такого метода нет, то выполняем общую логику
      l_common_logic = rs_c_true.
    ENDIF.

*   Общая логика для переменных, для которых не создана отдельная реализация
    IF l_common_logic = rs_c_true.
*     Исключаем # из доступных для выбора значений
      CLEAR c_t_range.
      l_s_range-sign = 'E'.
      l_s_range-option = 'EQ'.
      l_s_range-iobjnm = i_iobjnm.
      l_s_range-low = ''.
      APPEND l_s_range TO c_t_range.
    ENDIF.

  ENDMETHOD.

IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_NODE

METHOD IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_NODE.
    DATA:
      l_v_classname   TYPE seoclsname,
      l_o_object      TYPE REF TO object,
      l_f4_method     TYPE string VALUE `IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_NODE`,
      l_method_exists TYPE rs_bool.

*   Собираем имя класса по маске ZCL_F4_[Имя переменной]
    CONCATENATE   `ZCL_F4_` i_vnam INTO l_v_classname.

*   Проверяем есть ли метод для обработки переменной в полученном классе
    CALL FUNCTION 'Z_FM_CHECK_METHOD'
      EXPORTING
        i_class_name    = l_v_classname
        i_method_name   = l_f4_method
      IMPORTING
        e_method_exists = l_method_exists.

*   Если такой метод есть, то вызываем его
    IF l_method_exists = rs_c_true.
      CREATE OBJECT l_o_object TYPE (l_v_classname).
      CALL METHOD l_o_object->(l_f4_method)
        EXPORTING
          i_vnam        = i_vnam
          i_iobjnm      = i_iobjnm
          i_t_var_range = i_t_var_range
          i_t_compid    = i_t_compid
          i_req_data    = i_req_data
        CHANGING
          c_t_hierarchy = c_t_hierarchy
          c_t_node      = c_t_node
          c_infoprov    = c_infoprov
          c_f4_mode     = c_f4_mode.
    ENDIF.
  ENDMETHOD.

IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_HIER

METHOD IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_HIER.
    DATA:
      l_v_classname   TYPE seoclsname,
      l_o_object      TYPE REF TO object,
      l_f4_method     TYPE string VALUE `IF_RSR_VARIABLE_F4_RESTRICT~GET_RESTRICTION_HIER`,
      l_method_exists TYPE rs_bool.

*   Собираем имя класса по маске ZCL_F4_[Имя переменной]
    CONCATENATE   `ZCL_F4_` i_vnam INTO l_v_classname.

*   Проверяем есть ли метод для обработки переменной в полученном классе
    CALL FUNCTION 'Z_FM_CHECK_METHOD'
      EXPORTING
        i_class_name    = l_v_classname
        i_method_name   = l_f4_method
      IMPORTING
        e_method_exists = l_method_exists.

*   Если такой метод есть, то вызываем его
    IF l_method_exists = rs_c_true.
      CREATE OBJECT l_o_object TYPE (l_v_classname).
      CALL METHOD l_o_object->(l_f4_method)
        EXPORTING
          i_vnam               = i_vnam
          i_iobjnm             = i_iobjnm
          i_t_var_range        = i_t_var_range
          i_t_compid           = i_t_compid
          i_req_data           = i_req_data
        CHANGING
          c_version            = c_version
          c_dateto             = c_dateto
          c_version_restricted = c_version_restricted
          c_dateto_restricted  = c_dateto_restricted.
    ENDIF.
  ENDMETHOD.

IF_RSR_VARIABLE_F4_RESTRICT~HIER_NEEDED_FOR_NODE_RSTR

method IF_RSR_VARIABLE_F4_RESTRICT~HIER_NEEDED_FOR_NODE_RSTR.
endmethod.

Z_FM_CHECK_METHOD

FUNCTION Z_FM_CHECK_METHOD.
*"--------------------------------------------------------------------
*"*"Локальный интерфейс:
*"  IMPORTING
*"     REFERENCE(I_CLASS_NAME) TYPE  SEOCLSNAME
*"     REFERENCE(I_METHOD_NAME) TYPE  STRING
*"  EXPORTING
*"     REFERENCE(E_METHOD_EXISTS) TYPE  RS_BOOL
*"--------------------------------------------------------------------

  DATA:
    l_o_class            TYPE REF TO cl_oo_class,
    l_t_methods          TYPE seo_methods,
    l_v_clsname          TYPE seoclsname,
    l_v_cmpname          TYPE seocmpname,
    l_t_method_name      TYPE STANDARD TABLE OF string,
    l_v_lines            TYPE i,
    l_v_check_interface  TYPE rs_bool,
    l_o_intf_description TYPE REF TO cl_abap_intfdescr.

* Проверяем существует ли заданный на вход в ФМ класс
  TRY.
      CREATE OBJECT l_o_class
        EXPORTING
          clsname                   = i_class_name
          with_inherited_components = seox_true
          with_interface_components = seox_true.
    CATCH cx_class_not_existent .
      RETURN.
  ENDTRY.

* Если соответствущий класс существует, получаем его методы
  CLEAR l_t_methods.
  IF l_o_class IS NOT INITIAL.
    CALL METHOD l_o_class->get_methods
      RECEIVING
        result = l_t_methods.
  ENDIF.

* Проверяем есть ли среди методов класса метод, поданный на вход в ФМ
  l_v_check_interface = rs_c_false.
  SPLIT i_method_name AT `~` INTO TABLE l_t_method_name.
  DESCRIBE TABLE l_t_method_name LINES l_v_lines.
  IF l_v_lines > 1.
    l_v_clsname = l_t_method_name[ 1 ].
    l_v_cmpname = l_t_method_name[ 2 ].
    l_v_check_interface = rs_c_true.
  ELSE.
    l_v_clsname = i_class_name.
    l_v_cmpname = l_t_method_name[ 1 ].
  ENDIF.
  READ TABLE l_t_methods WITH KEY clsname = l_v_clsname cmpname = l_v_cmpname TRANSPORTING NO FIELDS.

  IF sy-subrc = 0.
*   Метод существует
    IF l_v_check_interface = rs_c_true.
*     Если это реализация интерфейса, проверяем внедрена ли она
*      l_o_intf_description ?= cl_abap_intfdescr=>describe_by_name( i_method_name ).
*      IF l_o_intf_description->applies_to_class( i_class_name ) = rs_c_true.
      e_method_exists = rs_c_true.
*      ENDIF.
    ELSE.
*     Если это просто метод класса, то дополнительной проверки не надо
      e_method_exists = rs_c_true.
    ENDIF.
  ENDIF.




ENDFUNCTION.

Заходим в транзакцию SE19 и создаем ZBI_RSR_VARIABLE_F4_RESTRICT

ZBI_RSR_VARIABLE_F4_RESTRICT

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *