In der Vorschriften Klasse werden Funktionen für die Generierung der PP spezifischen Strukturen für Stücklisten und Arbeitsplan implementiert. Nachfolgend sind Beispiele für speziell die Vorschriftenarten WORKORDER und PRODUCTION_VERSION dargestellt. Zu beachten ist, dass eine kundenindividuelle Implementierung zugeschnitten an die jeweiligen Anforderungen Unterschiede aufweisen kann.

1. Initiales Anlegen der VART-Klasse

Initiales Anlegen einer Klasse zur Vorschriftenart (P)

2. Implementierung Interface /SCT/QP_IF_PP und Stammdaten Methode GET_PP_MASTER_DATA

Mit dieser Methode werden die Stücklisten und Arbeitsplandaten der Vorschriftenarten aufgebaut:

Verwendung /SCT/QP_IF

PUBLIC SECTION.
INTERFACES /sct/qp_if_pp .
 
METHOD /sct/qp_if_pp~get_pp_master_data.
* Call of PP-service-method. Converting specification structur into structture MKAL, STPO and PLPO
rt_dispo = mo_pp_service->/sct/qp_if_pp_service~map_instance_to_masterdata(
is_origin = is_origin
io_vart = me ).
ENDMETHOD.

Die Methode wird sowohl für die Vorschriftenart WORKORDER als auch PRODUCTION_VERSION benötigt.

3. Implementierung SYNC Methoden SYNC_ORDER_TO_QPPD und SYNC_QPPD_TO_ORDER

Für die Vorschriftenart WORKORDER sind die folgenden beiden Methoden zu implementieren über das Interface /SCT/QP/IF/PP. Diese werden benötigt, um die Synchronisierung zwischen dem QPPD-Objekt zum Fertigungsauftrag zum Standard SAP herzustellen:

Verwendung /SCT/QP_IF

METHOD /sct/qp_if_pp~sync_order_to_qppd.
TRY.
mo_pp_service->workorder_to_qppd(
EXPORTING
ir_header = ir_header
ir_operations = ir_operations
ir_bom = ir_bom
io_vart = me
iv_syncmodel = c_mapping_workorder
).
CATCH /sct/qp_cx_error INTO DATA(lo_error).
ENDTRY.
ENDMETHOD.
 
METHOD /sct/qp_if_pp~sync_qppd_to_order.
TRY.
mo_pp_service->qppd_to_workorder(
EXPORTING
ir_header = ir_header
ir_operations = ir_operations
ir_bom = ir_bom
io_vart = me
iv_syncmodel = c_mapping_workorder
CATCH /sct/qp_cx_error INTO DATA(lo_error).
ENDTRY.
ENDMETHOD.

4. Builder: Generierung von Knoten

Die Vorschriftenart besitzt eine Struktur mit rekursiven Baugruppen: 

image-20240604-115952.png

Die Builder Methoden bauen diese Struktur auf. Als Grundlage dienen die SAP Standard Stücklisten und Arbeitspläne.

Builder

* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method /SCT/MT_CL_PRODUCTION_VERSION->BUILD
* +-------------------------------------------------------------------------------------------------+
* | [!CX!] /SCT/QP_CX_ERROR
* | [!CX!] /SCT/MT_CX_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD build.
/sct/mt_if_production_version~mo_production ?=
/sct/mt_cl_production=>/sct/mt_if_production~get_instance(
iv_material = /sct/qp_if_vart~mrs_node_data->matnr
iv_plant = /sct/qp_if_vart~mrs_node_data->werks ).
 
CLEAR /sct/mt_if_production_version~mo_production.
 
IF mo_ecc IS NOT BOUND.
mo_ecc = /sct/mt_cl_ecc=>/sct/mt_if_ecc~get_instance( iv_link_guid = /sct/qp_if_vart~mrs_node_data->guid ).
IF mo_ecc IS NOT BOUND.
mo_ecc = /sct/mt_cl_ecc=>/sct/mt_if_ecc~get_instance( iv_doctype = mc->doctype_marc iv_link_guid = /sct/qp_if_vart~mrs_node_data->guid ).
ENDIF.
ENDIF.
 
IF mo_ecc IS BOUND.
/sct/mt_if_production_version~mo_production ?= mo_ecc->get_production( ).
ENDIF.
 
 
IF /sct/qp_if_vart~mrs_node_data->noderel IS INITIAL.
build_init( ).
RETURN.
ENDIF.
 
build_key_set( ).
 
DATA(lr_assembly) = get_base( iv_vtyp = 'ASSEMBLY' ).
 
DATA(lt_itembase) = mt_itembase.
 
LOOP AT lt_itembase REFERENCE INTO DATA(lr_itembase).
lr_itembase->val = build_key_get( it_element = lr_itembase->val ).
 
build_delete_items( ir_itembase = lr_itembase ).
 
IF is_item_existing( ir_itembase = lr_itembase ) = abap_false.
CASE lr_itembase->vtyp.
WHEN const-operation-vtyp.
build_operation( is_itembase = lr_itembase->* ir_parent = lr_assembly ).
WHEN const-testing-vtyp.
build_testing( is_itembase = lr_itembase->* ir_parent = lr_assembly ).
WHEN OTHERS.
ENDCASE.
ENDIF.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method /SCT/MT_CL_PRODUCTION_VERSION->BUILD_INIT
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
 
METHOD build_init.
**********************************************************************
* Erzeugung der QPPD-Hierarchie anhand der SAP-Fertigungsversion
**********************************************************************
 
* KMAT ermitteln
* PP_SERVICE bemühen und Abeitsplan und Stückliste besorgen
* Dementsprechend Knoten aufbauen.
 
DATA(lv_kmat) = /sct/mt_if_production_version~mo_production->/sct/qp_if_vart~get_value( 'MT_MATNR_CONF' ).
 
IF lv_kmat IS INITIAL.
lv_kmat = 'SLAB'.
ENDIF.
 
DATA : lo_mm_service TYPE REF TO /sct/qp_if_mm_service.
 
/sct/qp_cl_factory=>get_instance( CHANGING co_instance = lo_mm_service ).
 
DATA(lr_fvers) = lo_mm_service->get_prodversion(
EXPORTING
iv_matnr = lv_kmat
iv_werks = CONV #( /sct/qp_if_vart~get_value( 'MT_PLANT' ) )
iv_verid = CONV #( /sct/qp_if_vart~get_value( 'MT_VERSION' ) )
).
 
do_map_from_masterdata( lr_fvers ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method /SCT/MT_CL_PRODUCTION_VERSION->BUILD_OPERATION
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_ITEMBASE TYPE TY_ITEMBASE
* | [--->] IR_PARENT TYPE REF TO /SCT/QP_S_BASE
* | [<-()] RS_ITEMBASE TYPE REF TO /SCT/QP_S_BASE
* | [!CX!] /SCT/QP_CX_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD build_operation.
 
DATA(ls_node) = CORRESPONDING /sct/qp_s_qvc_data_sort( is_itembase ).
ls_node-vname = 'OPERATION'.
 
build_create_item( is_base_parent = ir_parent->*
iv_posnr = CONV #( 9999 - is_itembase-posnr )
is_node_target = ls_node ).
ENDMETHOD.
 
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method /SCT/MT_CL_PRODUCTION_VERSION->DO_MAP_FROM_MASTERDATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IR_PRODVERS TYPE REF TO /SCT/QP_IF_MM_SERVICE=>TY_PRODVERSION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD do_map_from_masterdata.
**********************************************************************
* Erzeugt eine QPPD Hierarchie anhand der gewählte Fertigungsversion
**********************************************************************
 
DATA(ls_node) = VALUE /sct/qp_s_qvc_data_sort( vtyp = const-assembly-vtyp
hiera = const-assembly-hiera
ovart = const-vart
vname = 'Assembly'
matnr = mrs_node_data->matnr
werks = mrs_node_data->werks
).
 
DATA(lr_assembly) = build_create_item( is_base_parent = ms_base
is_node_target = ls_node ).
 
DATA(lt_stpo) = ir_prodvers->t_stpo->
DATA(lt_plpo) = ir_prodvers->t_plpo->
SORT lt_plpo BY vornr DESCENDING.
 
DATA(lv_first) = lines( lt_plpo ).
 
LOOP AT lt_plpo REFERENCE INTO DATA(lr_plpo).
 
DATA(lv_line) = sy-tabix.
do_map_from_plpo( EXPORTING ir_plpo = lr_plpo
ir_parent = lr_assembly
ir_prodvers = ir_prodvers
iv_first_op = xsdbool( lv_line = lv_first )
CHANGING ct_stpo = lt_stpo ).
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method /SCT/MT_CL_PRODUCTION_VERSION->DO_MAP_FROM_PLPO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IR_PLPO TYPE REF TO /SCT/QP_IF_MM_SERVICE=>TY_PLPO
* | [--->] IR_PRODVERS TYPE REF TO /SCT/QP_IF_MM_SERVICE=>TY_PRODVERSION(optional)
* | [--->] IV_FIRST_OP TYPE BOOLEAN
* | [--->] IR_PARENT TYPE REF TO /SCT/QP_S_BASE
* | [<-->] CT_STPO TYPE /SCT/QP_IF_MM_SERVICE=>TTY_STPO
* +--------------------------------------------------------------------------------------</SIGNATURE>
 
METHOD do_map_from_plpo.
**********************************************************************
* Erzeugt einen QPPD Knoten passend zum aktuellen Vorgang
* und ordnet die passenden Stücklistenkomponente zu
**********************************************************************
 
FIELD-SYMBOLS: <field> TYPE any,
<value> TYPE any.
 
READ TABLE mt_itembase INTO DATA(ls_data)
WITH KEY vtyp = const-operation-vtyp.
CHECK sy-subrc = 0.
DATA : ls_val LIKE LINE OF ls_data-val.
 
DATA(lt_comp) = mo_tools->get_struct_comp( io_data = ir_plpo ).
 
LOOP AT lt_comp ASSIGNING FIELD-SYMBOL(<comp>).
UNASSIGN <field>.
ASSIGN COMPONENT <comp>-name OF STRUCTURE ir_plpo->* TO <field>.
CHECK <field> IS ASSIGNED AND <field> IS NOT INITIAL.
 
IF <comp>-name = 'VORNR'.
ls_data-posnr = CONV #( <field> ).
ENDIF.
mo_pp_service->map_tablefield_to_element(
EXPORTING
iv_syncmodel = c_mapping_prodversion
iv_tabname = mo_pp_service->c_table-masterdata-operation
iv_fieldname = CONV #( <comp>-name )
IMPORTING
es_map = DATA(ls_map)
).
 
IF ls_map-element IS NOT INITIAL.
CLEAR ls_val.
ls_val-element = ls_map-element.
IF ls_map-objekttyp IS NOT INITIAL.
ls_val-objekttyp = ls_map-objekttyp.
ELSE.
ls_val-objekttyp = 'OPER_ACTIVITY'.
ENDIF.
 
READ TABLE ls_data-val ASSIGNING FIELD-SYMBOL(<val>)
WITH KEY element = ls_val-element
objekttyp = ls_val-objekttyp.
IF sy-subrc NE 0.
INSERT ls_val INTO TABLE ls_data-val ASSIGNING <val>.
ENDIF.
IF <val> IS ASSIGNED.
UNASSIGN <value>.
ASSIGN COMPONENT ls_map-valfield OF STRUCTURE <val> TO <value>.
IF <value> IS ASSIGNED.
<value> = CONV #( <field> ).
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
 
LOOP AT ir_prodvers->t_plmz->* REFERENCE INTO DATA(lr_plmz)
WHERE plnty = ir_prodvers->plko->plnty
AND plnnr = ir_prodvers->plko->plnnr
AND plnal = ir_prodvers->plko->plnal
AND stlty = ir_prodvers->cstmat->stlty
AND stlnr = ir_prodvers->cstmat->stlnr
AND stlal = ir_prodvers->cstmat->stlal.
 
READ TABLE ct_stpo REFERENCE INTO DATA(lr_stpo)
WITH KEY stlkn = lr_plmz->stlkn.
IF sy-subrc = 0.
DATA(lv_index) = sy-tabix.
do_map_from_stpo( EXPORTING ir_stpo = lr_stpo CHANGING cs_data = ls_data ).
DELETE ct_stpo INDEX lv_index.
ENDIF.
ENDLOOP.
 
IF iv_first_op = abap_true.
LOOP AT ct_stpo REFERENCE INTO lr_stpo.
do_map_from_stpo( EXPORTING ir_stpo = lr_stpo CHANGING cs_data = ls_data ).
ENDLOOP.
ENDIF.
 
mo_cust->get_node_hiera_elements(
EXPORTING
iv_vart = mrs_node_data->vart
iv_vtyp = ls_data-vtyp
iv_hiera = ls_data-hiera
IMPORTING
et_element_usage = DATA(lt_usage)
 
DATA(lt_element) = VALUE /sct/qp_th_element( FOR GROUPS OF <wa> IN lt_usage GROUP BY <wa>-element ( <wa>-element ) ).
 
ls_data-val = FILTER #( ls_data-val IN lt_element WHERE element = table_line ).
 
DATA(lr_op) = build_operation( is_itembase = ls_data ir_parent = ir_parent ).
 
ENDMETHOD.
 
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method /SCT/MT_CL_PRODUCTION_VERSION->DO_MAP_FROM_STPO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IR_STPO TYPE REF TO /SCT/QP_IF_MM_SERVICE=>TY_STPO
* | [<-->] CS_DATA TYPE TY_ITEMBASE
* +--------------------------------------------------------------------------------------</SIGNATURE>
 
METHOD do_map_from_stpo.
**********************************************************************
* Erweitert QPPD Daten zum Vorgang mit den passenden
* Stücklistenkomponente
**********************************************************************
 
FIELD-SYMBOLS: <field> TYPE any,
<value> TYPE any.
DATA : ls_val LIKE LINE OF cs_data-val.
 
DATA(lt_comp) = mo_tools->get_struct_comp( io_data = ir_stpo ).
 
DATA(lv_rowgrp) = CONV /sct/qp_rowgrp( ir_stpo->posnr ).
 
LOOP AT lt_comp ASSIGNING FIELD-SYMBOL(<comp>).
UNASSIGN <field>.
ASSIGN COMPONENT <comp>-name OF STRUCTURE ir_stpo->* TO <field>.
CHECK <field> IS ASSIGNED AND <field> IS NOT INITIAL.
 
mo_pp_service->map_tablefield_to_element(
EXPORTING
iv_syncmodel = c_mapping_prodversion
iv_tabname = mo_pp_service->c_table-masterdata-component
iv_fieldname = CONV #( <comp>-name )
IMPORTING
es_map = DATA(ls_map)
).
 
IF ls_map-element IS NOT INITIAL.
CLEAR ls_val.
ls_val-element = ls_map-element.
IF ls_map-objekttyp IS NOT INITIAL.
ls_val-objekttyp = ls_map-objekttyp.
ELSE.
ls_val-objekttyp = 'COMPONENTS'.
ENDIF.
ls_val-rowgrp = lv_rowgrp.
 
READ TABLE cs_data-val ASSIGNING FIELD-SYMBOL(<val>)
WITH KEY element = ls_val-element
objekttyp = ls_val-objekttyp
rowgrp = ls_val-rowgrp.
IF sy-subrc NE 0.
INSERT ls_val INTO TABLE cs_data-val ASSIGNING <val>.
<val>-sortnr = ir_stpo->posnr. "Sortierung
ENDIF.
IF <val> IS ASSIGNED.
UNASSIGN <value>.
ASSIGN COMPONENT ls_map-valfield OF STRUCTURE <val> TO <value>.
IF <value> IS ASSIGNED.
<value> = CONV #( <field> ).
CASE <comp>-type->get_data_type_kind( <field> ).
WHEN cl_abap_typedescr=>typekind_float
OR cl_abap_typedescr=>typekind_packed
OR cl_abap_typedescr=>typekind_int
OR cl_abap_typedescr=>typekind_int2
OR cl_abap_typedescr=>typekind_int8.
IF <field> < 0.
SHIFT <value> LEFT DELETING LEADING space.
DATA(length) = strlen( <value> ) - 1.
<value> = '-' && <value>(length).
ENDIF.
ENDCASE.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.

5. Individuelle Bestimmung der Generierungsreihenfolge

Um eine individuelle Generierungsreihenfolge zu ermöglichen wird die globale Generierung aktiviert und im "Zuordnung Objekttypen"-Bild des Vorschriftenarten Customizings "Individuell (VART-Klasse)" gewählt:

image-20240604-120008.png

mit diesen Einstellungen wird /SCT/QP_IF_VART~SET_GENER_FLAG aufgerufen.

SET_GENER_FLAG

PUBLIC SECTION.
METHODS /sct/qp_if_vart~set_gener_flag REDEFINITION .
 
METHOD /sct/qp_if_vart~set_gener_flag.
CASE ir_source_base->vtyp.
*---------------- ASSEMBLY ---------------------------------------------
WHEN 'ASSEMBLY'.
IF io_source_object->ms_node_object-objekttyp = 'TECHDATA'.
 
*Mark all operations linked to the assembly
rtr_base = /sct/qp_if_vart~get_base_tab( iv_vtyp = 'OPERATION'
is_hint = VALUE #( base = ir_source_base children = abap_true ) ).
ENDIF.
 
*---------------- OPERATION ---------------------------------------------
WHEN 'OPERATION'.
DATA(lr_assembly) = zif_qp_prodweg~get_parent( ir_source_base ).
 
IF io_source_object->ms_node_object-objekttyp = 'COMPONENT'.
rtr_base = VALUE #( ( lr_assembly ) ).
ENDIF.
 
"if it is the last operation mark den next assembly
DATA(lr_last_operation) = /sct/qp_if_vart~get_base( is_hint = value #( ir_base = ir_source position = 'LAST' ).
IF lr_last_operatioon = ir_source_base.
rtr_base = VALUE #( BASE rtr_base ( /sct/qp_if_vart~get_base( is_hint = value #( ir_base = ir_source vtypposition = 'LAST' ). ) ).
ENDIF.
"Gerierungsreiehnfolge setzen. Beim erneuten Ändern besteht die bereits vom Builder generierte Sortierreihenfolge nicht mehr.
ENDCASE.
 
* Sorting for generation beginning at the end
LOOP AT rtr_base INTO DATA(rs_base).
rs_base->gensort = c_max_gensort - rs_base->posnr.
ENDLOOP.
ENDMETHOD.