In the specification type class, functions are implemented for generating the PP-specific structures for BOMs and routings. Examples of some functions are shown below that consider the specification types WORKORDER and PRODUCTION_VERSION. It should be noted that a customized implementation tailored to the respective requirements may differ.
1. The initial creation of VART-class
The initial creation of a specification class (P)
2. Implementation Interface /SCT/QP_IF_PP and master data method GET_PP_MASTER_DATA
This method is used to build the bill of materials and routing data of the specification
Usage /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.This method is needed for both specification types WORKORDER and PRODUCTION_VERSION.
3. Implementation of SYNC methods SYNC_ORDER_TO_QPPD and SYNC_QPPD_TO_ORDER
The following two methods must be implemented for the WORKORDER specification type via the /SCT/QP/IF/PP interface. These are required to create the synchronization between the QPPD object for the production order and the standard SAP.
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: generation of nodes
The specification type PRODUCTION_VERSION has a structure with recursive assemblies:

The Builder methods build this structure. The SAP standard bills of material and routings serve as the basis.
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.*********************************************************************** Creation of the QPPD hierarchy based on the SAP production version*********************************************************************** determine kmat* Use PP_SERVICE and obtain the routing and bill of materials* build nodes on this basis 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.********************************************************************** *Creates a QPPD hierarchy based on the selected production version********************************************************************** 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.*********************************************************************** Creates a QPPD node matching the current operation* and assigns the appropriate BOM component********************************************************************** 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.*********************************************************************** Expands QPPD data for the operation with the appropriate* BOM component********************************************************************** 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.Individual determination of the generation sequence
To enable an individual generation sequence, global generation is activated, and "Individual (VART class)" is selected in the "Assignment of object types" screen of the specification type customizing:

With these settings /SCT/QP_IF_VART~SET_GENER_FLAG will be called.
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.