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