Skip to main content

QPPD

QPPD serves as a data modeling tool for master data and can also function as a central data hub hosting complex objects based on configuration values, such as the "technical order" for order dressing. This page explains how to link QPPD elements to characteristics and/or link QPPD objects to a configuration instance (both ways). Enhance your configuration logic and behavior with QPPD to elevate it to the next level.

When using QPPD to maintain master data, both elements and their values are typically managed directly within QPPD.
Product Form values

In the AVC context, a characteristic must exist beforehand to be included in a configuration model. For example, the characteristic PRODUCT_FORM needs to be created and added to the model.

Maintaining characteristic values in both AVC and QPPD is inefficient and error-prone. Therefore, QPPD should act as the single source of truth.

To support this, mdVC includes a pre-delivered implementation of the BADI vch_hl_es_core-vch_hl_md_domain_modify, which uses the class /mxp/vcha_cl_qppd_domain_modif. This implementation checks whether a matching QPPD element exists for a given characteristic and, if so, supplies the QPPD-defined values for configuration use at runtime.
Make sure to define suitable filter values when setting up the BADI.

BADI implementation

With this setup, there is no need to duplicate value maintenance in the characteristic itself — QPPD remains authoritative. However, the characteristic still needs to exist in the system to be added to the configuration model.

For complex calculations such as order dressing, calculating production alternatives, or other computations, it is beneficial to integrate and mirror some AVC values into QPPD in a separate Specification usually called a "Technical Order." This integration enables seamless, bidirectional synchronization of characteristic values between AVC and QPPD while ensuring configuration logic remains consistent and centrally governed in mdVC by reusing QPPD logic.

Due to the stateless nature of AVC and to allow users to modify specification values in QPPD, sophisticated draft handling is necessary. The draft handling described here focuses on sales documents where it's mandatory (sales document processing in SAP is stateful, AVC is stateless).

Synchronization Process

The following sections focuses on the key steps related to QPPD synchronization.

Synchronization Trigger and Target

The initial synchronization is a task passed to the engine:

new /mxp/vcha_cl_qp_va_sync( )
tip

In the standard implementation, log messages are synchronized back to AVC. Consider the Best practice to derive status after QPPD synchronization completes.

The enhancement spot /mxp/vcha_es_qp_sync controls synchronization: configurations for QPPD specification types, synchronization object type definitions, and status definitions.

Document Configuration

To prevent issues like late numbering and manage "out-of-date" draft objects, two custom fields are required at the SAP sales order header level:

  • Header Id
    A "Character 22" field storing a unique header ID. It is filled immediately after sales order creation and never changed.

  • Activation Session Timestamp
    A timestamp field filled at the start of a sales order session. Internally used by the QPPD draft implementation to detect outdated drafts. Must be of type timestampl.

Best practice in S/4 systems is to use the "Custom Fields" app (#CustomField-manage). For older releases, extend via developer extensibility. Only the Custom Fields app is considered clean-core compliant here.
Custom fields

Recommended field names are ZZ1_HeaderId and ZZ1_ActivationSession. If these conflict with your naming conventions, implement the BADI /mxp/vcha_doc_link_config to configure custom fields.

BADI /mxp/vcha_doc_link_config

info

The logic for these fields is delivered with mdVC, but the fields themselves are not (to remain clean core compliant).

The method get_header_fields must be implemented:

method /mxp/vcha_if_doc_link_config~get_header_fields.
e_header_id = 'ZZ1_HeaderId' ##NO_TEXT.
e_activation_session_ts = 'ZZ1_ActivationSession' ##NO_TEXT.
endmethod.
Synchronization Configuration

The target QPPD object must be defined. The BADI /mxp/vcha_qp_sync_vart_config configures the specification type, target object type, and follow-up actions on the QPPD object after synchronization. The method get_configuration must be implemented; configuration can be plant-specific.
get_configuration()

Specification Type Contract

  • No Specification Group should be assigned in Specification Type Customizing.
    Specification Group
  • An Object Type at header level must be assigned, listing all elements whose characteristics need synchronization from AVC instance. The names must match.
    Object Type
    All configuration values synchronize first to this object type, triggering follow-up actions.
  • Builder, Generation, and Follow-Up functions can be freely defined in QPPD style and configured within the BADI. They execute whenever a relevant synchronization element changes.
  • The status schema must follow the Status Configuration described below.

Method Implementation

The implementation may be plant-specific. A default implementation is provided:

  • Specification Type:
    Defaults to the QPPD Technical Order looked up by abbreviation TO in Specification Type Customizing.

  • Object Type:
    Default implementation links to MDVC_CONFIG; keep this name if using the default.

  • Key Parts VC:
    The QPPD object is linked by its Name. The default derives the name from a characteristic MDVC_LINK_VNAME. This value must be determined by a task before the actual QPPD synchronization. This is where the configured header ID is used.

    • VBAK_Z_UUID (customizable name) holds the header ID defined in Document Configuration, made available to AVC since it only accesses configuration values.
      UUID Characteristic
      UUID Link

    • POSNR (customizable name) holds the sales order item number, also exposed to AVC.
      POSNR Link

    • MDVC_LINK_VNAME is calculated by a custom task.
      MDVC_LINK_VNAME

Example task configuration showing that lcl_calc_mdvc_link_vname runs before QPPD synchronization:

/mxp/vcha_cl_va_engine=>factory(
i_badi_implementation = me
i_explosion_date = ref #( explosion_date )
i_hierarchy = ref #( hierarchy )
i_characteristics = ref #( characteristics )
i_values = ref #( values )
i_bill_of_materials = ref #( bill_of_materials )
i_assign_by_value = ref #( assign_by_value )
i_assign_by_key = ref #( assign_by_key )
i_unassign = ref #( unassign )
)->process( new /mxp/vcha_cl_va_task_composite( value #(
( new lcl_calc_mdvc_link_vname( ) )
( new /mxp/vcha_cl_qp_va_sync( ) )
( new /mxp/vcha_cl_va_log_to_status( ) ) ) ) ).

Example implementation of lcl_calc_mdvc_link_vname:

class lcl_calc_mdvc_link_vname definition create public inheriting from /mxp/vcha_cl_va_task_simple.
public section.
methods /mxp/vcha_if_va_task~execute redefinition.
endclass.
class lcl_calc_mdvc_link_vname implementation.
method /mxp/vcha_if_va_task~execute.
data(l_z_uuid) = i_engine->m_container->get_assigned_value_for_cstic(
i_engine->m_container->get_characteristic_by_name( i_instance_id = i_engine->m_container->m_root_instance_id
i_cstic_name = 'VBAK_Z_UUID' )->key ).
data(l_posnr) = i_engine->m_container->get_assigned_value_for_cstic(
i_engine->m_container->get_characteristic_by_name( i_instance_id = i_engine->m_container->m_root_instance_id
i_cstic_name = 'POSNR' )->key ).
check l_z_uuid is bound and l_posnr is bound.

i_engine->m_container->assign_value( value #( base corresponding #( i_engine->m_container->get_characteristic_by_name( i_instance_id = i_engine->m_container->m_root_instance_id
i_cstic_name = 'MDVC_LINK_VNAME' )->key )
value_string = /mxp/vcha_cl_qp_sd_key_util=>instance->key_for_item(
i_header_id = l_z_uuid->value_string
i_item = conv #( l_posnr->value_int_min ) ) ) ).
endmethod.
endclass.
tip

You can skip calculating MDVC_LINK_VNAME and instead concatenate via BADI settings (simpler but less flexible). At least a separate characteristic is needed for the AVC UI extension which is why we decided to recommend this way.

  • Define follow-up actions executed after any relevant configuration value change (object created or modified):
    • Builder flag: whether to execute QPPD Builder
    • Generation flag: whether to suppress QPPD Global Generation
    • Action name: which specific VART function to execute (see QPPD docs)
Status Configuration

Multiple instances of a QPPD object for a configuration instance can exist. The objects are not versioned but are distinguished by their status. All share the same Name, as defined in Synchronization configuration. The BADI /mxp/vcha_qp_draft_status_conf is used to configure the different statuses.
BADI interface draft status config
A default implementation is provided by /mxp/vcha_cl_qp_draft_stat_cfg.

  • Draft object
    The draft object exists "within a configuration" and can be discarded or adapted on each change.
    The default implementation creates the object with status IZQER (in creation).

  • Draft object "to be released"
    A draft object moves to "to be released" after the "Done" button is pressed in AVC, meaning it will be saved when the sales order is saved.
    The default implementation configures activity ZQFB ("release requested") to be executed, setting status IZQFB according to status customizing.

  • Active object
    A draft object "to be released" is promoted to "active" after saving the sales order as a post-processing step.
    Sales Order change events are fired by SAP standard, triggering class /mxp/vcha_cl_qp_slo_evt_activ as standard BGPF.
    The default implementation configures activity ZQFR ("release") to be executed, setting status IZQFR according to status customizing.

  • Inactive object (previously active, but replaced)
    An active object is marked inactive if another draft object "to be released" becomes active.
    The default implementation configures activity ZQLO ("mark for deletion") to be executed, setting status IZQLO according to status customizing.

The default implementation must match the status schema of the configured Specification Type:

method /mxp/vcha_if_qp_draft_stat_cfg~get_configuration.
r_result = value #( draft = value #( status = /sct/qp_cl_const=>status-in_creation
pending = value #( status = /sct/qp_cl_const=>status-release_requested
activities-promote_to_active = /sct/qp_cl_const=>activity-release )
activities = value #( initialize = value #( )
promote_to_pending = /sct/qp_cl_const=>activity-request_release ) )
active = value #( status = /sct/qp_cl_const=>status-released
inactive = value #( status = /sct/qp_cl_const=>status-marked_for_deletion )
activities = value #( deactivate = /sct/qp_cl_const=>activity-delete ) ) ).
endmethod.

Synchronization Back

Because the structure of a source QPPD object may vary a lot between use cases, no BADI is provided currently for synchronization back. Instead, the method SYNCH_BACK_TO_VC in the task class /mxp/vcha_cl_qp_va_sync is available for redefinition according to custom use cases. Additionally, all error messages within the object hierarchy will be synchronized to the AVC log, influencing status in the default handling (task /mxp/vcha_cl_va_log_to_status).

Finish Configuration

Once the configuration is finished by clicking Done, the AVC BADI vch_hl_on_save is triggered. The class /mxp/vcha_cl_qp_on_save can be added for a BADI implementation. It handles promoting the draft to the status "to be released".
BADI vch_hl_on_save
This status serves as an intermediate state while processing the sales document.

Post-Processing: Release QPPD Draft

As a post processing after saving the sales documents, all linked objects in status "to be released" will be promoted to "released". The Activation Session Timestamp will be considered, so that only relevant ones will be promoted:

  • The Activation Session Timestamp will be calculated once an object in status "to be released" exists for the document, but the timestamp is the beginning of the editing session, not the current one.
  • On Save, all objects which "last update" timestamp is higher than the Activation Session Timestamp will be considered as "to be promoted".
info

Objects which have errors will not be promoted to released nor considered as obsolete. They wait for manual editing (as the configuration does).

  • The relevant objects will be changed to "released".

If any error occurs, the standard BGPF unit will fail. Details are available in the standard transaction SBGRFCMON. For more sophisticated logic, consider using an UBC interface instead.

Delete obsolete Objects

Scheduled as a regular job, the previously mentioned conditions will be checked and all drafts older than the specified lifetime will be deleted (e.g., incomplete configurations, cancelled editing sessions, etc.).

Application Job for QPPD draft cleanup

  • Open the Fiori App for Application Jobs (#ApplicationJob-show).
  • Create a new Application Job based on the template /mxp/vcha_qp_draft_cleanup.

Job Template /mxp/vcha_qp_draft_cleanup

  • Choose a recurrence pattern; our recommendation is to schedule it once a day, which is sufficient.
  • Choose a lifetime of drafts in seconds; our recommendation is about 86,400 (one day), meaning all obsolete drafts older than a day will be deleted.
  • The specification type will be defaulted with all your specification types according to the BADI implementation. From a default implementation perspective, this means "all Technical Orders".

UI Extension

AVC provides a powerful UI extension approach, enabling, for example, the display of linked QPPD objects as a dedicated tab "group" in AVC. For more information on AVC UI extensions, see SAP Help and GitHub.

UI Extension

In brief, to display information of the linked QPPD object, the following configuration/development steps are required:

  • Develop your UI extension app as linked in the GitHub Repository.
  • Register an AVC UI extension and assign a name with Fiori app #VarCnfUserInterfaceExtension-manage
  • Define the characteristic groups for your configuration model in Fiori app #VariantConfiguration-manageGroups and assign characteristics.
    • Make sure to add at least one characteristic; otherwise, the tab remains hidden.
    • It is recommended to calculate the linked specification name as a separate characteristic, as mentioned in Synchronization configuration, and add it to this group. The UI extension can then access this value and display the object's values by filtering on it.
  • Link the UI extension to this group by specifying your View Extension name in group header.
  • Assign the characteristic group to the configuration profile in Fiori app #VariantConfiguration-assignGroupsToProfile.

For implementing your AVC UI extension:

  • Best practice is to expose parts of the QPPD object with OData and use Fiori Elements for displaying it.
    Consider using GDD to generate semantic-rich CDS views as a basis for the custom Consumption View.

  • Be aware that draft objects must not be displayed in display mode, only in editing mode.

  • Unfortunately, it is not supported from the AVC UI Extension side to embed external UI5 libraries, thus it is currently not possible to offer a library for helper functions such as:

    • Jump to QPPD
    • Display QPPD objects inline: UI and draft handling
      Display QPPD object
    • ...

    Nevertheless, metalsXP has some content available "pre-packaged". The current suggestion is to copy it as a "quick start" to your custom Extension project. This may change in the future if libraries become supported.

💬 Please reach out to the team of metalsXP for further details.

Setup Summary