Scenario: In standard SAP, SM30 is used to maintain data through a Table Maintenance Generator (TMG). However, it only allows us to assign access to a limited number of users—typically one at a time using authorization objects. This becomes a bottleneck when multiple users need to maintain data but should not be given broad access to SM30.
To overcome this limitation, I’ve developed a custom report program that acts as a gateway to perform CRUD (Create, Read, Update, Delete) operations on TMG, but only for authorized users of the report.
Business Requirement:
Allow only authorized users to maintain table data via TMG.
Eliminate the need to provide direct SM30 access.
Improve security, flexibility, and usability in maintaining table data.
Security and authorization handling.
Instead of giving access to SM30:
Assign a custom role to the report program
Let users maintain only the specific table via this report
This restricts access to other tables or SM30 entirely
*&---------------------------------------------------------------------*
*& Report ZPD_RP_TMG_CUSTOM
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZPD_RP_TMG_CUSTOM.
INCLUDE zpd_tmg_top_dec.
include zpd_tmg_logic_forms.
START-OF-SELECTION .
PERFORM get_data.
PERFORM prepare_field_catalog.
PERFORM disp_alv.
FORM prepare_field_catalog .
CLEAR : gt_fieldcat .
gt_fieldcat = VALUE #( ( fieldname = 'MANDT' col_pos = 1 seltext_l = 'MANDT' checkbox = '' outputlen = 15 )
( fieldname = 'SERIAL_NO' col_pos = 2 seltext_l = 'SERIAL_NO' checkbox = '' outputlen = 20 )
( fieldname = 'NAME' col_pos = 3 seltext_l = 'NAME' checkbox = '' outputlen = 30 )
( fieldname = 'USER_ID' col_pos = 4 seltext_l = 'USER_ID' checkbox = '' outputlen = 15 )
( fieldname = 'PASSWORD' col_pos = 5 seltext_l = 'PASSWORD' checkbox = '' outputlen = 30 )
( fieldname = 'COMPANY_CODE' col_pos = 6 seltext_l = 'COMPANY_CODE' checkbox = '' outputlen = 15 ) ).
ENDFORM.
FORM disp_alv .
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = sy-repid
i_callback_pf_status_set = 'MY_SCREEN'
i_callback_user_command = 'USER_COMMAND'
it_fieldcat = gt_fieldcat
TABLES
t_outtab = gt_alv
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form get_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM get_data .
SELECT mandt
serial_no
name
user_id
password
company_code
FROM zpd_t_tmg INTO TABLE gt_zpd_t_tmg.
IF sy-subrc = 0.
PERFORM zpd_t_tmg_to_gt_alv .
ENDIF.
ENDFORM.
FORM my_screen USING rx_extab TYPE slis_t_extab .
SET PF-STATUS 'MY_SCREEN'.
ENDFORM.
"form user command"
FORM user_command USING ucomm LIKE sy-ucomm
p_selfld TYPE slis_selfield.
DATA: gd_repid LIKE sy-repid,
ref_grid TYPE REF TO cl_gui_alv_grid.
DATA: l_valid TYPE c.
" to get modified alv op
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = ref_grid.
IF NOT ref_grid IS INITIAL.
CALL METHOD ref_grid->check_changed_data
IMPORTING
e_valid = l_valid. " Entries are Consistent
ENDIF.
CASE ucomm.
WHEN '&DISP'.
CLEAR : gv_flag .
gv_flag = abap_true .
PERFORM change_fieldcat1.
WHEN '&SAVE' .
IF gv_flag = abap_true .
PERFORM modify_changes .
PERFORM prepare_field_catalog .
ELSE.
MESSAGE 'No change was made' TYPE 'E'.
ENDIF .
WHEN '&CR_NEW'.
REFRESH gt_alv1 .
PERFORM get_data1 .
PERFORM prepare_field_catalog1 .
PERFORM display_alv1 .
WHEN '&DATA_SAVE'.
PERFORM save_data.
WHEN '>_DT'.
PERFORM dynamic_output .
WHEN '&F03' OR '&F15'.
RETURN.
WHEN '&F12 '.
LEAVE PROGRAM .
ENDCASE .
p_selfld-refresh = 'X'.
IF ucomm = '&DISP'.
p_selfld-exit = 'X'.
PERFORM disp_alv.
ENDIF.
IF ucomm = '&SAVE'.
p_selfld-exit = 'X'.
PERFORM prepare_field_catalog.
PERFORM disp_alv.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form prepare_field_catalog1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM prepare_field_catalog1 .
CLEAR : gt_fieldcat1 .
gt_fieldcat = VALUE #( ( fieldname = 'MANDT' edit = 'X' col_pos = 1 seltext_l = 'MANDT' ref_fieldname = 'MANDT' checkbox = '' outputlen = 15 )
( fieldname = 'SERIAL_NO' edit = 'X' col_pos = 2 seltext_l = 'SERIAL_NO' ref_fieldname = 'SERIAL_NO' checkbox = '' outputlen = 20 )
( fieldname = 'NAME' edit = 'X' col_pos = 3 seltext_l = 'NAME' ref_fieldname = 'NAME' checkbox = '' outputlen = 30 )
( fieldname = 'USER_ID' edit = 'X' col_pos = 4 seltext_l = 'USER_ID' ref_fieldname = 'USER_ID' checkbox = '' outputlen = 15 )
( fieldname = 'PASSWORD' edit = 'X' col_pos = 5 seltext_l = 'PASSWORD' ref_fieldname = 'PASSWORD' checkbox = '' outputlen = 30 )
( fieldname = 'COMPANY_CODE' edit = 'X' col_pos = 6 seltext_l = 'COMPANY_CODE' ref_fieldname = 'PASSWORD' checkbox = '' outputlen = 15 ) ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form display_alv1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM display_alv1 .
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = sy-repid
i_callback_pf_status_set = 'MY_SCREEN1 '
i_callback_user_command = 'USER_COMMAND'
it_fieldcat = gt_fieldcat
TABLES
t_outtab = gt_alv1
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
FORM my_screen1 USING rx_extab TYPE slis_t_extab .
SET PF-STATUS 'MY_SCREEN1'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form get_data1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM get_data1 .
DO 150 TIMES.
APPEND gs_alv1 TO gt_alv1.
ENDDO.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form save_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM save_data .
REFRESH : gt_alv2 , gt_alv3.
gt_alv3[] = gt_alv1.
IF gt_alv3 IS NOT INITIAL .
DELETE gt_alv3 WHERE serial_no IS INITIAL.
ENDIF.
IF gt_alv3 IS NOT INITIAL .
LOOP AT gt_alv3 INTO gs_alv3.
IF gs_alv3 IS NOT INITIAL .
IF gs_alv3-company_code IS NOT INITIAL.
CLEAR gs_alv.
READ TABLE gt_alv INTO gs_alv WITH KEY serial_no = gs_alv3-serial_no .
IF sy-subrc NE 0.
gs_alv2-serial_no = gs_alv3-serial_no.
gs_alv2-name = gs_alv3-name.
gs_alv2-password = gs_alv3-password.
gs_alv2-user_id = gs_alv3-user_id.
gs_alv2-company_code = gs_alv3-company_code.
APPEND gs_alv2 TO gt_alv2.
CLEAR : gs_alv3, gs_alv2 , gs_alv.
ELSE .
MESSAGE : ' Data already exists' TYPE 'E'.
CLEAR gs_alv.
ENDIF.
ELSE.
MESSAGE : 'Fill the required fied(Company code)' TYPE 'E'.
ENDIF.
ENDIF.
ENDLOOP.
MODIFY zpd_t_tmg FROM TABLE gt_alv2.
IF sy-subrc = 0.
MESSAGE 'Data transacted successfully' TYPE 'S'.
LOOP AT gt_alv2 INTO gs_alv2.
gs_alv-name = gs_alv2-name.
gs_alv-user_id = gs_alv2-user_id.
gs_alv-password = gs_alv2-password.
gs_alv-serial_no = gs_alv2-serial_no.
gs_alv-company_code = gs_alv2-company_code.
APPEND gs_alv TO gt_alv.
CLEAR : gs_alv , gt_alv2.
ENDLOOP.
REFRESH: gt_alv2 , gt_alv1.
PERFORM get_data1.
ENDIF.
ELSE.
MESSAGE 'Please enter the data' TYPE 'E'.
ENDIF.
ENDFORM.
FORM dynamic_output .
CLEAR : gs_serno , gs_ccode.
REFRESH gt_alv4.
gt_alv4[] = gt_alv1[].
IF gt_alv4 IS NOT INITIAL .
DELETE gt_alv4 WHERE serial_no IS INITIAL.
DELETE gt_alv4 WHERE company_code IS INITIAL .
ENDIF.
PERFORM get_data2.
CLEAR : gs_serno , gs_ccode.
IF gt_alv4 IS NOT INITIAL.
LOOP AT gt_alv1 ASSIGNING FIELD-SYMBOL(<lfs_data>)
WHERE serial_no IS INITIAL AND
company_code IS INITIAL.
READ TABLE gt_serno INTO gs_serno WITH KEY serial_no = <lfs_data>-serial_no.
IF sy-subrc = 0.
<lfs_data>-user_id = gs_serno-user_id.
<lfs_data>-company_code = gs_serno-company_code.
ENDIF.
ENDLOOP.
ELSE.
MESSAGE 'fill out required entry fields' TYPE 'E'.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form get_data2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM get_data2 .
REFRESH : gt_serno , gt_ccode.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form change_fieldcat1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM change_fieldcat1 .
LOOP AT gt_fieldcat ASSIGNING FIELD-SYMBOL(<lfs_fieldcat>)
WHERE ( fieldname = 'serial_no' OR fieldname = 'company_code' OR fieldname = 'user_id' OR fieldname = 'password'
OR fieldname = 'name').
<lfs_fieldcat>-edit = 'X'.
ENDLOOP.
ENDFORM.
FORM modify_changes .
REFRESH gt_alv5 .
IF gt_alv IS NOT INITIAL.
PERFORM alv_to_alv5.
PERFORM get_changed_data.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form get_changed_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM get_changed_data .
IF gt_alv5[] IS NOT INITIAL .
LOOP AT gt_alv5 INTO DATA(gs_alv5) .
READ TABLE gt_zpd_t_tmg INTO DATA(gs_zpd_t_tmg) WITH KEY serial_no = gs_alv5-serial_no.
IF sy-subrc = 0 AND ( gs_alv5 EQ gs_zpd_t_tmg ) .
DELETE gt_alv5 FROM gs_alv5.
CLEAR : gs_alv5 , gs_zpd_t_tmg .
ENDIF.
CLEAR : gs_alv5 , gs_zpd_t_tmg .
ENDLOOP.
IF gt_alv5 IS INITIAL .
MESSAGE 'No changes was made' TYPE 'E'.
ELSE.
DELETE gt_alv5[] WHERE company_code IS INITIAL.
IF sy-subrc NE 0 AND gt_alv5 IS NOT INITIAL .
MODIFY zpd_t_tmg FROM gt_alv5.
IF sy-subrc = 0.
MESSAGE 'Data saved successfully' TYPE 'S'.
gv_flag = abap_false.
ENDIF.
ELSE.
MESSAGE 'Fill the required field(Company code)' TYPE 'E'.
ENDIF .
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form alv_to_alv5
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM alv_to_alv5 .
LOOP AT gt_alv INTO gs_alv.
gs_alv5-mandt = sy-mandt.
gs_alv5-company_code = gs_alv-company_code.
gs_alv5-name = gs_alv-name.
gs_alv5-password = gs_alv-password.
gs_alv5-serial_no = gs_alv-serial_no.
gs_alv5-user_id = gs_alv-user_id.
APPEND gs_alv5 TO gt_alv.
CLEAR : gs_alv , gs_alv5.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form zpd_t_tmg_to_gt_alv
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM zpd_t_tmg_to_gt_alv .
AUTHORITY-CHECK OBJECT 'ZAUTHTMG'
ID 'ACTVT' FIELD '01'.
IF sy-subrc <> 0 .
MESSAGE e006(zmsg_auth).
ENDIF.
LOOP AT gt_zpd_t_tmg INTO gs_zpd_t_tmg.
gs_alv-serial_no = gs_zpd_t_tmg-serial_no.
gs_alv-company_code = gs_zpd_t_tmg-company_code.
gs_alv-name = gs_zpd_t_tmg-name.
gs_alv-password = gs_zpd_t_tmg-password.
gs_alv-user_id = gs_zpd_t_tmg-user_id.
APPEND gs_alv TO gt_alv.
CLEAR : gs_alv , gs_zpd_t_tmg .
ENDLOOP.
ENDFORM.
OUTPUT:
When we click on new entries button and click on save :
Data will be saved to Database :
Thanks and regards:
Pradeep Ishwar Devadiga
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
13 | |
9 | |
9 | |
7 | |
7 | |
6 | |
6 | |
6 | |
6 | |
5 |