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.