Устав от простыней в стиле:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
LOOP AT SCREEN. IF screen-name = 'ZSS-PERID'. screen-input = 0. ENDIF. IF zss-pernr IS NOT INITIAL. IF screen-name = 'ZSS-PERNR' OR screen-name = 'ZSS-LNAME' OR screen-name = 'ZSS-FNAME'. screen-input = 0. ENDIF. ENDIF. IF screen-name = 'ZSS-STELL'. screen-input = 0. ENDIF. ... IF screen-name = 'ZSS-TAXNM'. IF ... . screen-required = 0. ELSE. screen-required = 1. ENDIF. ENDIF. MODIFY SCREEN. ENDLOOP. ... LOOP AT SCREEN. IF screen-group1 = 'M1'. IF ... screen-input = 0. ELSE. screen-input = 1. ENDIF. MODIFY SCREEN. ENDIF. ENDLOOP. ... |
я решил обкатать новый подход.
Первым делом декларативное определение, например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
mt_profile_readonly = VALUE #( ( mask = '*' action = zcl_screen=>readonly ) ). mt_profile_employee = VALUE #( ( mask = '*' action = zcl_screen=>readonly ) ( mask = '*QKTGR*' action = zcl_screen=>obligatory ) ( mask = '*POSID*' action = zcl_screen=>input ) ). mt_profile_contractor = VALUE #( ( mask = '*' action = zcl_screen=>readonly ) ( mask = '*QKTGR*' action = zcl_screen=>input ) ( mask = '*TAXNM*' action = zcl_screen=>obligatory ) ( mask = '*TDATE*' action = zcl_screen=>input ) ). mt_profile_visitor = VALUE #( ( mask = '*' action = zcl_screen=>input ) ( mask = '*PERID*' action = zcl_screen=>invisible ) ( mask = '*PERNR*' action = zcl_screen=>invisible ) ( mask = '*STELL*' action = zcl_screen=>invisible ) ). |
Применение на практике сводится к следующему:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
MODULE screen_3000 OUTPUT. go_person_controller->process_screen( ). ENDMODULE. ... METHOD process_screen. IF m_mode = mc_display. zcl_screen=>apply_profile( mt_profile_readonly ). ELSE. IF m_data-pernr IS NOT INITIAL. IF is_employee( EXPORTING iv_pernr = m_data-perid ). zcl_screen=>apply_profile( mt_profile_employee ). ELSE. zcl_screen=>apply_profile( mt_profile_contractor ). ENDIF. ELSE. zcl_screen=>apply_profile( mt_profile_visitor ). ENDIF. ENDIF. ENDMETHOD. |
Пробую пока покатать-проверить, насколько такой подход применим в условиях, приближенным к боевым. Нужно больше мест применения, чтобы определить какой подход даст лучшую читаемость, компактность и проверяемость. И потихотньку можно добавить мяса.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
class ZCL_SCREEN definition public final create public . public section. types: BEGIN OF ty_profile, mask TYPE string, action TYPE char1, END OF ty_profile . types: tt_profile TYPE STANDARD TABLE OF ty_profile WITH DEFAULT KEY . constants INVISIBLE type CHAR1 value '-' ##NO_TEXT. constants READONLY type CHAR1 value 'R' ##NO_TEXT. constants DEFAULT type CHAR1 value ' ' ##NO_TEXT. constants INPUT type CHAR1 value '+' ##NO_TEXT. constants OBLIGATORY type CHAR1 value '!' ##NO_TEXT. methods CONSTRUCTOR . class-methods APPLY_PROFILE importing !PROFILE type TT_PROFILE . methods APPLY importing !PROFILE type TT_PROFILE . methods DONE . protected section. data MT_SCREEN type ISH_T_SCREEN . private section. ENDCLASS. CLASS ZCL_SCREEN IMPLEMENTATION. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_SCREEN->APPLY * +-------------------------------------------------------------------------------------------------+ * | [--->] PROFILE TYPE TT_PROFILE * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD apply. LOOP AT profile INTO DATA(ls_profile). LOOP AT mt_screen ASSIGNING FIELD-SYMBOL(<screen>). IF ls_profile-mask CA '*'. IF NOT ( <screen>-name CP ls_profile-mask ). CONTINUE. ENDIF. ELSE. IF NOT ( <screen>-name = ls_profile-mask ). CONTINUE. ENDIF. ENDIF. CASE ls_profile-action. WHEN invisible. <screen>-active = 0. <screen>-invisible = 1. <screen>-input = 0. <screen>-output = 0. <screen>-required = 0. WHEN readonly. <screen>-active = 1. <screen>-invisible = 0. <screen>-input = 0. <screen>-output = 1. <screen>-required = 0. WHEN default. WHEN input. <screen>-active = 1. <screen>-invisible = 0. <screen>-input = 1. <screen>-output = 1. <screen>-required = 0. WHEN obligatory. <screen>-active = 1. <screen>-invisible = 0. <screen>-input = 1. <screen>-output = 1. <screen>-required = 1. ENDCASE. ENDLOOP. ENDLOOP. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_SCREEN=>APPLY_PROFILE * +-------------------------------------------------------------------------------------------------+ * | [--->] PROFILE TYPE TT_PROFILE * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD apply_profile. DATA(lo_screen) = NEW zcl_screen( ). lo_screen->apply( profile ). lo_screen->done( ). ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_SCREEN->CONSTRUCTOR * +-------------------------------------------------------------------------------------------------+ * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD constructor. LOOP AT SCREEN. APPEND screen TO mt_screen. ENDLOOP. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_SCREEN->DONE * +-------------------------------------------------------------------------------------------------+ * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD done. LOOP AT SCREEN. READ TABLE mt_screen INTO DATA(ls_screen) WITH KEY name = screen-name. MOVE-CORRESPONDING ls_screen TO screen. MODIFY SCREEN. ENDLOOP. ENDMETHOD. ENDCLASS. |
Довольно интересный подход
Подумал, что в дополнение
Кроме задания маски с * для SCREEN-NAME хотелось бы использовать REGEX
Указывать SCREEN-GROUP1
Задавать непоредственно флаги SCREEN
Код может выглядить вот так
METHOD pbo.
DATA(lv_for_f641) = COND #( WHEN p_rtype = mc_r_type-f641 THEN ‘1’ ELSE ‘0’ ).
DATA(lv_not_for_f641) = COND #( WHEN p_rtype = mc_r_type-f641 THEN ‘0’ ELSE ‘1’ ).
» Change ready for input flag
process_screen( VALUE t_screen_group(
» Enabled and required for 641 GROUP
( group1 = ‘641’
input = lv_for_f641
required = lv_for_f641 )
» Reporting Period (always = ‘I’ other)
( name = ‘PNPTIMED’
input = ‘0’ )
» Payroll area
* ( name = ‘PNPABKRS-LOW’ required = ‘1’ )
» pn-begda & pn-endda enabled if NOT F641
( name = ‘\bPNPBEGDA|\bPNPENDDA’
input = lv_not_for_f641 )
) ).
ENDMETHOD.
process_screen
IMPORTING
it_screen TYPE t_screen_group.
METHOD process_screen.
» Check fields of SCREEN with type CHAR1 (Flags as INPUT, ACTIVE …)
DATA(lt_screen_field) = VALUE tttext255(
FOR ls_comp IN CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( ‘SCREEN’ ) )->components
WHERE ( type_kind = cl_abap_typedescr=>typekind_char AND length = 2 ) » <- char1
( ls_comp—name ) ).
LOOP AT SCREEN INTO DATA(ls_scr_dest).
» Have rule or not
DATA(lv_changed) = CONV abap_bool( abap_false ).
LOOP AT it_screen ASSIGNING FIELD—SYMBOL(<ls_screen_src>).
» Name by mask
IF <ls_screen_src>—name IS NOT INITIAL.
FIND REGEX ls_scr_dest—name IN <ls_screen_src>—name.
CHECK sy—subrc = 0.
lv_changed = lv_changed.
» Check group1
ELSEIF <ls_screen_src>—group1 IS NOT INITIAL.
CHECK ls_scr_dest—group1 = <ls_screen_src>—group1.
» Specify NAME or GROUP1
ELSE.
CONTINUE.
ENDIF.
» Copy fields from source to dest
LOOP AT lt_screen_field ASSIGNING FIELD—SYMBOL(<lv_field>).
ASSIGN COMPONENT <lv_field> OF STRUCTURE:
<ls_screen_src> TO FIELD—SYMBOL(<lv_src>),
ls_scr_dest TO FIELD—SYMBOL(<lv_dest>).
» ‘0’ Or ‘1’
CHECK sy—subrc = 0 AND <lv_src> IS NOT INITIAL.
<lv_dest> = <lv_src>.
lv_changed = abap_true.
ENDLOOP.
ENDLOOP.
» And change screen
CHECK lv_changed = abap_true.
MODIFY SCREEN FROM ls_scr_dest.
ENDLOOP.
ENDMETHOD.
Спасибо за блог!