If the current system already has dozens or even hundreds of NAST output types, one day must adapt all those forms if related to one group of specific criteria like sales organization, then how to identify which output type has been used by the sales organization?
It’s well known that general NAST output determination and configuration are maintained with various key combinations and stored at multiple condition record tables just like pricing determination processing.
1. List of the basic tables for NAST output processing
- TNAPR (Processing programs for output)
The easiest way to check the driver program and form name per output type.
- NACH (Detailed output data)
It has a relationship of condition record number with Condition Type. And it already contains all the values of key combinations but we don’t know their meanings exactly. Actually, we can use this field VAKEY for pattern searching if that value contains the criteria you want, but be aware that could be inaccurate as company code/sales org./ purchase org./plants, etc could share the same value.
Another important field is KOTABNR which is the condition table code. It can be used to search the real condition table in Table T681 mentioned below.
- T681 (Conditions: Structures)
It contains the relationship of the Condition table code with the Condition table. Take KOTABNR 902 as an example, its condition table is A902 for application ‘V’. That’s one of the tables we need to search where-used list per output type.
- Condition tables like A902
There’re hundreds of Condition tables like A902 with various key combinations per output type. For this example, the key combination is Sales org./Cust.grp 1/Mat.pr.grp/ZZPRODH2. If we need where-used for sales org/ customer group/material pricing group, that’s the table we need to search.
2. Sample program to fetch all related outputs/forms for the sales organization
- 1) Fetch all the form names/driver programs per output type;
- 2) Fetch all output condition records per application/ output type;
- 3) Fetch all condition tables with condition table codes fetched from step 2;
- 4) Create dynamic selection based on condition tables fetched in step 3;
- 5) Loop structure of the dynamic table, search sales organization field name VKORG;
- 6) Loop output type and collect sales org./form names/driver programs per output type.
*&---------------------------------------------------------------------*
*& Report ZSD_FORMS_VKORG_LIST
*&
*-----------------------------------------------------------------------
* Program Information
*-----------------------------------------------------------------------
* Program Name: ZSD_FORMS_VKORG_LIST
REPORT zsd_forms_vkorg_list.
TABLES: nach, tnapr, t681, dd03l, zpolarisorgmap.
*-----------------------------------------------------------------------
* Types& Data Definition
*-----------------------------------------------------------------------
TYPES: BEGIN OF t_key,
kappl TYPE kappl,
kschl TYPE na_kschl,
vkorg TYPE vkorg,
END OF t_key,
BEGIN OF t_out,
fonam(36),
kappl TYPE kappl,
kschl TYPE na_kschl,
vkorg TYPE vkorg,
pgnam TYPE na_pgnam,
sfp_flag(16),
END OF t_out.
DATA: gt_tnapr TYPE TABLE OF tnapr,
gr_table TYPE REF TO cl_salv_table,
gs_tnapr LIKE LINE OF gt_tnapr,
gt_out TYPE TABLE OF t_out,
gs_out LIKE LINE OF gt_out,
gt_vkorg TYPE TABLE OF zpolarisorgmap,
gs_vkorg LIKE LINE OF gt_vkorg,
gt_t681 TYPE TABLE OF t681,
gs_t681 LIKE LINE OF gt_t681,
gt_key TYPE TABLE OF t_key,
gs_key LIKE LINE OF gt_key,
gt_nach TYPE TABLE OF nach,
gs_nach LIKE LINE OF gt_nach.
DATA:
o_ref TYPE REF TO data.
FIELD-SYMBOLS:
<lt_table> TYPE STANDARD TABLE,
<fs> TYPE any,
<field> TYPE any,
<field1> TYPE any.
*-----------------------------------------------------------------------
* Selection Parameters
*-----------------------------------------------------------------------
SELECTION-SCREEN: BEGIN OF BLOCK a2 WITH FRAME TITLE text-001.
SELECT-OPTIONS: s_kschl FOR tnapr-kschl.
SELECT-OPTIONS: s_fonam FOR tnapr-fonam.
SELECTION-SCREEN: END OF BLOCK a2.
PARAMETERS:
p_tab TYPE tabname NO-DISPLAY, " Table name
p_field(20) TYPE c NO-DISPLAY, " Field name
p_polar AS CHECKBOX DEFAULT '', " Polaris only
p_script AS CHECKBOX DEFAULT '', "script only
p_skip AS CHECKBOX DEFAULT ''. " no form find
*-----------------------------------------------------------------------
* START-OF-SELECTION
*-----------------------------------------------------------------------
START-OF-SELECTION.
PERFORM get_data.
PERFORM data_output.
*&---------------------------------------------------------------------*
*& Form get_data
*&---------------------------------------------------------------------*
FORM get_data.
REFRESH gt_vkorg.
SELECT *
FROM zpolarisorgmap
INTO TABLE gt_vkorg.
REFRESH gt_tnapr.
SELECT *
INTO TABLE gt_tnapr
FROM tnapr
WHERE kschl IN s_kschl
AND ( fonam IN s_fonam OR fonam2 IN s_fonam OR
fonam3 IN s_fonam OR fonam4 IN s_fonam OR
sform IN s_fonam ).
LOOP AT gt_tnapr INTO gs_tnapr.
IF gs_tnapr-fonam IN s_fonam OR gs_tnapr-fonam2 IN s_fonam
OR gs_tnapr-fonam3 IN s_fonam OR gs_tnapr-fonam4 IN s_fonam
OR gs_tnapr-sform IN s_fonam.
ELSE.
DELETE TABLE gt_tnapr FROM gs_tnapr.
ENDIF.
ENDLOOP.
IF gt_tnapr[] IS INITIAL.
MESSAGE 'No Data found!' TYPE 'E' DISPLAY LIKE 'E'.
ENDIF.
REFRESH gt_nach.
SELECT *
FROM nach
INTO TABLE gt_nach
FOR ALL ENTRIES IN gt_tnapr
WHERE kappl = gt_tnapr-kappl
AND kschl = gt_tnapr-kschl.
IF gt_nach[] IS INITIAL.
LOOP AT gt_tnapr INTO gs_tnapr.
CLEAR gs_out.
gs_out-fonam = gs_tnapr-fonam.
gs_out-kschl = gs_tnapr-kschl.
gs_out-pgnam = gs_tnapr-pgnam.
gs_out-vkorg = 'N/A'.
APPEND gs_out TO gt_out.
ENDLOOP.
ENDIF.
IF gt_nach[] IS NOT INITIAL.
REFRESH gt_t681.
SELECT *
FROM t681
INTO TABLE gt_t681
FOR ALL ENTRIES IN gt_nach
WHERE kotabnr EQ gt_nach-kotabnr
AND kappl EQ gt_nach-kappl.
ENDIF.
LOOP AT gt_nach INTO gs_nach WHERE kotabnr IS NOT INITIAL.
CLEAR gs_tnapr.
READ TABLE gt_tnapr INTO gs_tnapr
WITH KEY kschl = gs_nach-kschl
kappl = gs_nach-kappl.
* Get condition table name
CLEAR gs_t681.
READ TABLE gt_t681 INTO gs_t681 WITH KEY
kotabnr = gs_nach-kotabnr
kappl = gs_nach-kappl.
IF sy-subrc EQ 0.
p_tab = gs_t681-kotab.
ELSE.
CONTINUE.
ENDIF.
*---to newly created object.
CREATE DATA o_ref TYPE TABLE OF (p_tab).
*--Asssign the reference to field-symbol
p_field = 'VKORG'.
ASSIGN p_field TO <field1>.
ASSIGN o_ref->* TO <lt_table>.
SELECT *
INTO TABLE <lt_table>
FROM (p_tab)
WHERE kappl = gs_nach-kappl
AND kschl = gs_nach-kschl
AND knumh = gs_nach-knumh.
LOOP AT <lt_table> ASSIGNING <fs>.
CLEAR gs_out.
ASSIGN COMPONENT <field1> OF STRUCTURE <fs>
TO <field>.
IF sy-subrc = 0.
gs_out-vkorg = <field>.
p_field = 'KAPPL'.
ASSIGN p_field TO <field1>.
ASSIGN COMPONENT <field1> OF STRUCTURE <fs>
TO <field>.
IF sy-subrc = 0.
gs_out-kappl = <field>.
ENDIF.
p_field = 'KSCHL'.
ASSIGN p_field TO <field1>.
ASSIGN COMPONENT <field1> OF STRUCTURE <fs>
TO <field>.
IF sy-subrc = 0.
gs_out-kschl = <field>.
ENDIF.
gs_out-pgnam = gs_tnapr-pgnam.
IF gs_tnapr-fonam IS NOT INITIAL.
gs_out-fonam = gs_tnapr-fonam.
ELSEIF gs_tnapr-fonam2 IS NOT INITIAL.
gs_out-fonam = gs_tnapr-fonam2.
ELSEIF gs_tnapr-fonam3 IS NOT INITIAL.
gs_out-fonam = gs_tnapr-fonam3.
ELSEIF gs_tnapr-fonam4 IS NOT INITIAL.
gs_out-fonam = gs_tnapr-fonam4.
ELSEIF gs_tnapr-sform IS NOT INITIAL.
gs_out-fonam = gs_tnapr-sform.
gs_out-sfp_flag = 'X'.
ENDIF.
IF p_script = 'X' AND gs_out-sfp_flag = 'X'.
CONTINUE.
ENDIF.
IF p_skip = 'X'.
IF gs_out-fonam IS INITIAL.
CONTINUE.
ENDIF.
ENDIF.
IF p_polar = 'X'.
CLEAR gs_vkorg.
READ TABLE gt_vkorg INTO gs_vkorg WITH KEY
pvkorg = gs_out-vkorg.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
ENDIF.
APPEND gs_out TO gt_out.
CLEAR gs_out.
ELSE.
CONTINUE.
ENDIF.
ENDLOOP.
ENDLOOP.
SORT gt_out BY fonam kappl kschl vkorg.
DELETE ADJACENT DUPLICATES FROM gt_out.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DATA_OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM data_output.
* Functions
DATA: lr_functions TYPE REF TO cl_salv_functions,
lr_columns TYPE REF TO cl_salv_columns_table,
lo_column TYPE REF TO cl_salv_column_table,
lr_column TYPE REF TO cl_salv_column,
lr_events TYPE REF TO cl_salv_events_table,
ls_color TYPE lvc_s_colo,
lr_sorts TYPE REF TO cl_salv_sorts,
lr_layout TYPE REF TO cl_salv_layout,
lr_optimize TYPE REF TO cl_salv_columns_table,
lf_variant TYPE slis_vari,
* ld_email TYPE adr6-smtp_addr,
ls_key TYPE salv_s_layout_key,
l_msg TYPE string.
DATA: lv_sub TYPE sood-objdes.
CLEAR lv_sub.
DATA: lv_xml_type TYPE salv_bs_constant,
lv_xml TYPE xstring.
TRY.
CALL METHOD cl_salv_table=>factory
EXPORTING
list_display = if_salv_c_bool_sap=>false
* r_container =
* container_name =
IMPORTING
r_salv_table = gr_table
CHANGING
t_table = gt_out.
CATCH cx_salv_msg.
ENDTRY.
* Set Screen status.
TRY.
CALL METHOD gr_table->set_screen_status
EXPORTING
report = sy-repid
pfstatus = 'ZSALV_STANDARD'
set_functions = 0.
ENDTRY.
CALL METHOD gr_table->get_functions
RECEIVING
value = lr_functions.
* Activate all Standard tool bar functions.
CALL METHOD lr_functions->set_all
EXPORTING
value = if_salv_c_bool_sap=>true.
lr_layout = gr_table->get_layout( ).
lr_layout->set_default( abap_true ).
lr_layout->set_save_restriction( if_salv_c_layout=>restrict_none ).
* Get Output table columns.
CALL METHOD gr_table->get_columns
RECEIVING
value = lr_columns.
* Set column width optimize
lr_columns->set_optimize( abap_true ).
* Set sorts.
TRY.
lr_sorts = gr_table->get_sorts( ).
CATCH cx_salv_not_found.
ENDTRY.
"Column
TRY.
lr_column = lr_columns->get_column( 'FONAM' ).
lr_column->set_long_text( 'FORM Name' ).
lr_column->set_medium_text( 'FORM Name' ).
lr_column->set_output_length( '36' ).
CATCH cx_salv_not_found .
ENDTRY.
TRY.
lr_column = lr_columns->get_column( 'SFP_FLAG' ).
lr_column->set_long_text( 'Adobe or SF?' ).
lr_column->set_medium_text( 'Adobe or SF?' ).
lr_column->set_output_length( '16' ).
CATCH cx_salv_not_found .
ENDTRY.
TRY.
* Apply Color
lo_column ?= lr_columns->get_column( 'KSCHL' ).
ls_color-col = 5.
ls_color-int = 1.
CALL METHOD lo_column->set_color
EXPORTING
value = ls_color.
CATCH cx_salv_not_found .
ENDTRY.
TRY.
* Apply Color
lo_column ?= lr_columns->get_column( 'VKORG' ).
ls_color-col = 5.
ls_color-int = 1.
CALL METHOD lo_column->set_color
EXPORTING
value = ls_color.
CATCH cx_salv_not_found .
ENDTRY.
IF gt_out[] IS NOT INITIAL.
* Display Data.
CALL METHOD gr_table->display.
ELSE.
WRITE: / 'DATA not found!'.
ENDIF.
ENDFORM.
By looping dynamic table field lists fetched from NACH with condition table code from T681, replacing sales org. field VKORG with other key combinations, we can get all the where-used lists we are interested in. But be aware of this approach to fetch sales org. list based on NACH entry and those condition tables(with key combinations including VKORG) may not cover all scenarios cause:
- Some output type doesn’t have condition records (NACH entry);
- Some output entries at NAST may create manually without NACH entry as well;
- Some output may be triggered by the customized programs without NAST processing, etc.
To be more accurate maybe need a sum of the result fetched from this approach plus entries from NAST at the production system like for the last 2 years. For example, fetch sales org. from VBAK for V1 application by VBELN equal to object key get from NAST. Please kindly let me know if any better ideas, thanks in advance