Object dependency execution is done by coding from SAP_APPL. Therefore it’s not available in non-ERP
systems (exception: Low Level Configuration).
There are two types of object dependencies:
- Classic object dependencies: Preconditions, Selection conditions, Procedures, Actions
- Constraints (not executed in Classification and Low Level Configuration; can be assigned to Configuration Profiles only)
Classic object dependencies can be linked to a large number of objects. To do so, internal pointer KNOBJ is stored within
application table of objects (e.g. STPO-KNOBJ for BOM items).
What are the different object dependencies types used for?
- Precondition:
Determine whether an object (e.g. char or char value) should be displayed. - Selection Condition:
Determine whether an object (e.g. BOM item) is valid and should be used. If assigned to a characteristic, the
char is required, if SelCond is fulfilled - Action & Procedure:
Are used to calculate values.
(Actions are obsolete and should not be used anymore. Nevertheless they are still supported.)
KNOBJ is a reference to CUOB-KNOBJ to create a link to the internal object dependecy key KNNUM. KNNUM is assigned to
external name, status etc. by table CUKB.
In object dependencies it’s important where a value comes from, cause different authors are not allowed to overwrite existing values.
Different valuation by different authors will result in char valuation conflicts (inconsistencies). Field name normally is ATAUT or KNTYPE.
Database and ABAP-Runtime use different ‘codes’.
Database | Runtime | Author |
---|---|---|
SPACE | DE | Set by User |
8 | SF | Default Can be overwritten by any author; Default can be set in master data or in object dependency using function $SET_DEFAULT |
2 | AC | Action |
3 | SC | Selection condition |
4 | CL | Classification |
5 | CS | Constraint |
6 | DD | DDB management Intersection build for restrictable chars |
7 | PR | Procedure |
Classic object dependency execution is triggered by events, like the user pressing <enter> key. At one time only the object dependency linked
to a single object is executed. Sequence of object dependencies and objects is well-defined.
When a configurable item is configured, sequence of object dependencies is as follows:
- Withdraw values set by Action or Procedure
- Actions are executed up to 25 times
- Actions assigned to configuration profile
- Actions assigned to characteristics
- Actions assigned to char values
- Procedures assigned to configuration profile
- Procedures assigned to characteristics
- Procedures assigned to char values
- Actions again are executed up to 25 times (profile, char and char value)
- Selection conditions assigned to the object (e.g. BOM item)
- Actions assigned to the object, if SelCond is fulfilled
- Procedures assigned to the object, if SelCond is fulfilled
- Preconditions assigned to characteristics
- Preconditions assigned to char values
When a non-configurable item is configured, sequence of object dependecies is as follows:
- Selection conditions assigned to the object (e.g. BOM item)
- Actions assigned to the object, if SelCond is fulfilled
- Procedures assigned to the object, if SelCond is fulfilled
Classification data can be used instead of Selection conditions.
The sequence of actions assigned to a single object is undefined. Sequence of procedures can be defined by user (column
in assignment screen).
Remark: Constraints are executed whenever an ‘input’ characteristic is changed. Constraint execution is not linked to
events or instances.
Business Overview
The ERP variant configurator is used to create and check characteristic value assignments for configurable objects, to calculate
condition keys for value based surcharges and to perform value based structure determinations (BOM explosions). There are
different types of configurable objects like e.g. materials (KMAT), standard nets (projects), routings.
Fig 1: Typical scenario: Sales of configurable Material
The typical use case is the configuration of materials in scenario 'sales of configurable materials' in ERP-SD:
- A sales person creates an SD order with an item holding a configurable material.
- The interactive (high level) variant configurator is invoked and the user specifies the configuration of this item in terms of characteristic
value assignments in the configurator UI. - The configuration is checked for completeness and consistency against the configuration model of the KMAT to ensure that the ordered
item is buildable: this includes evaluation of dependencies to check validity of assigned values and to calculate additional (dependent) values. - The configurator can determine dynamic pricing condition keys (variant conditions) for feature based pricing.
- If the configuration is consistent and complete and matches the customer's requirements the user returns to the sales order screen and
saves the configuration along with the configurable item - The configuration data created in this interactive ('high level') configuration are later used for planning and manufacturing of the configured
material. These subsequent steps involve non-interactive ('low level') configuration, e .g. for manufacturing BOM explosion and routings.
Dependencies
Types of Dependencies
Dependencies are used to check consistency of the configuration and to calculate dependent elements in the configuration. The variant configurator
supports different types of dependencies:
Type | Purpose | High Level Only | Declarative |
---|---|---|---|
Selection Condition | Define an element as 'mandatory' based on other input to the configuration. | No | No |
Precondition | Define an element as 'forbidden' based on other input | No | No |
Procedure | Calculate dependent elements | No | No |
Action | Similar to procedures (obsolete) | No | ('kind of'' - see below) |
Constraints | Check consistency of a combination of objects and | Yes | Yes |
'High Level Only' indicates that the type of dependencies can only be used in 'high level' configuration (KMAT).
'Declarative' indicates that dependencies bring their own implicit control logic: no sequence numbers or ordering by the calling application is required;
the result of applying the dependencies is independent of the sort order in which they are evaluated.
Dependencies marked in light grey are called 'classic dependencies'; these are all dependency types with the exception of constraints.
The evaluation of constraints differs significantly from the evaluation of 'classic dependencies' and is not covered in this document.
Actions are classified as 'kind of declarative' because they are evaluated up to 25 times in a loop: in this way output of an action can serve as input to
another action regardless of their detailed evaluation sequence. Running all actions 25 times is, of course, an arbitrary limitation and generally
not too efficient.
Object dependency execution is triggered by (SAPLCEI0)EVALUATE_DEPENDENCY_KNOWLEDGE.
High Level Configuration
While executing object dependencies characteristic valuation is stored in function group CUDB. (CUDB is often called DynamicDataBase, DDB).
Some important breakpoints:
Function Module | Description |
---|---|
CUDB_INIT | Initialize char valuation buffer |
CUDB_SAVE_TMP | Buffer current char valuation |
CUDB_LOAD_TMP | Restore current valuation from buffer |
CUDB_SET_VAL | Set single char value |
CUDB_DEL_VAL | Delete single value |
CUDB_RESTRICT_DOM | Restrict values of restrictable char |
Important global variables are:
Function Module | Description |
---|---|
CUDBD_TO_FACT_I | List of instances in multi-level configuration |
CUDBD_AW_FACT_I | urrent values (non-restrictable chars) More than one value for the same char means either a multi-value char or a conflict |
CUDBD_AZW_FACT_I | Restrictable chars. Field F points to DOM_IDX |
CUDBI_SYM_DOMS | List of char values (ref by CUDBD_AZW_FACT_I) |
CUDBI_NUM_DOMS | List of num values (ref by CUDBD_AZW_FACT_I) (SAPLCUTM) |
CUTMD_JUSTIFICATION | Author of values in CUDB (CUDBD_A(z)W_FACT_I -F -> CUTMD_JUSTIFICATION-FACT) |
Execution of classic OD is done in function group CUOV:
Function Module | Description |
---|---|
CUOV_DO_PROCEDURE | Execute procedure |
CUOV_DO_ACTION | Execute action |
CUOV_EVAL_PRECONDITIONS | Evaluate precondition |
CUOV_EVAL_SEL_CONDITIONS | Evaluate selection condition |
Important global variables are:
Global variable | Description |
---|---|
CUOVD_KNNUM | KNNUM of current OD |
CUOVD_SELF | Pointer to current SELF instance in CUDB |
CUOVD_PARENT | Pointer to current PARENT instance in CUDB |
CUOVD_ROOT | Pointer to current ROOT instance in CUDB |
Low Level Configuration
Low Level Configuration is used for MRP, calculation, routing etc.
In Low Level an object dependency assigned to the configuration profile is not executed. In Low Level char values can be calculated
for $SELF instance only. Execution is done in function group CULL. (CUDB and CUOV are not used.) CULL_INIT Initialize new
Low Level configuration and set configuration date.
CULL_MAKE_INSTANCE Define instance. ITYPE provides class type and object (material) PROPERTIES is a list of char values
CULL_CONFIGURE_ITEM Configure single item. First selection condition is evaluated. If the item has classification data, this can
be used as selection condition instead. If selection condition is fulfilled, procedures are executed. If values are calculate by
dependency, those inferred values are returned.
Variant functions
Variant functions are called from CUFC_FUNCTION_CALL in High- and Low-Level Configuration.
If call is done by PFUNCTION statement GLOBALS parameter is filled and access to CUPR functions is allowed to set characteristic
values. If call is done by FUNCTION statement GLOBALS parameter is not filled. Access to CUPR functions is not permitted.
In both cases results may be returned for characteristics defined in CU65, CU66, CU67 by table MATCH. Access to QUERY and MATCH
table is done by CUOV_GET_FUNCTION_ARGUMENT and CUOV_SET_FUNCTION_ARGUMENT.
Maintenance of Dependencies
VC dependencies are written in a special dependency syntax using the VC dependency editor (cu01-cu03). The syntax allows
the modeller to refer to other VC master data like characteristics, values, classes/materials.
Screenshot: Dependency Editor with a simple selection condition
For classic dependencies, the system stores the following data:
Table | Content |
---|---|
CUKB | Basic data (depdency type KNART, admin info etc) |
CUKBT | Language dependent descriptions |
CUKN | Source code |
CUEX | Runtime code format |
CUOB | Allocation of dependency to a 'carrier' object: the 'carrier' object can be a configuration profile, BOM item, characteristic, value etc. |
CUXREF | Cross references (master data objects referenced in a dependency) |
Details about VC dependency maintenance are described in a different handover document.
Generally, VC master data are maintained in separate transactions per object. As of ERP 5.0, the PME VC integrated modelling environment with an
improved dependency editor is available to create VC master data from a model view. Replication of VC master data between different ERP systems
is usually done via ALE (IDocs). A detailed overview of VC data is given in the corresponding VC training classes (LOVC990) and in the SAP Online
Help Portal.
The following tables is meant as a short overview and reminder:
Object | Transaction code | Main DB tables |
---|---|---|
Bill of Materials | cs01-03 | MAST, STPO |
Characteristic | ct04 | CABN, CABNT, CAWN, CAWNT |
Class | cl01-03, cl22n | KLAH, KSSK, KMSL |
Configuration Profile | cu41-43 | CUCO |
Constraint Net | cu21-23 | CURSVAR, CURSPAT, CURSSPN, CURSDNN, CURSCOD |
Dependency | cu01-03 | CUKB, CUKBT, CUKN, CUOB, CUEX |
Material | mm01-03 | MARA |
UI Design (Cstic groups) | cu50 | CECUSD, CECUSDT, CECUFM |
Value specific pricing surcharge | cu50 | MACOND |
Variant Function | cu65-67 | CUVFUN |
Variant Table | cu61-63, cu60 | CUVTAB |
Runtime Evaluation of Dependencies
Runtime evaluation of classic dependencies is based on interpretation of the runtime code format. For high level configuration interpretation
is done in function group CUOV - which is the topic of this document - and for low level configuration interpretation is done in function group CULL.
Architecture
- The variant configurator accesses configuration master data of the configurable object to retrieve the following information:
- Configuration profiles
- Classes, characteristics and their values (domains, defaults, facets)
- BOM structure
- Dependencies attached to config.profile, characteristics, values, BOM items etc
- Variant tables used in dependencies
- A configuration consists of instances, characteristics and values
- Instances correspond to items in the sales order
- A 'single level' configuration contains exactly one (root) instance
- A multi-level configuration contains a tree of instances
- The configuration can hold additional transient data like e.g. dynamic domain restrictions (for F4 help) or information about visibility and
availability for input of characteristics - The configuration is represented in a two-tiered fashion:
- External layer (CEI0): this is used to communicate with the user interface and with external APIs
- Internal layer (CUDB): this serves as the 'working memory' for dependency evaluation
- Both layers are kept in sync via a pull mechanism: in this way, inferences and status information (conflicts) calculated from dependencies
are made known to the external problem solver / User Interface.
- The configuration is built-up from
- Static model data (defaults, fixed BOM components)
- User selections
- Dynamic model inferences (values calculated from dependencies, BOM items with selection conditions)
- The configuration is checked at certain points in time - e.g. after each user input:
- As part of the check function, classical dependencies are evaluated and inferences and consistency status are re-calculated.
Design
Interpretation of classic dependencies in high level configuration is performed in function group CUOV. The interpreter is designed
in 'old style' (non-OO) ABAP using function modules and formroutines.
Function Modules
The main function modules in function group CUOV are the following:
Function Module | Description | Callers |
---|---|---|
CUOV_CHECK_CONDITION | Check a list of conditions | CLKNE_CONFIGURE_OBJECT, |
CUOV_DO_PROCEDURE | Evaluate a list of procedures | CLKNE_CONFIGURE_OBJECT, |
CUOV_DO_ACTION | Evaluate a list of actions | CLKNE_CONFIGURE_OBJECT, |
CUOV_SET_OVARS | Assign DDB instance numbers to instance variables $ROOT, $PARENT and $SELF | CE_I_CONFIGURE, |
Note: Functions CUOV_EVAL_* are similar to these function modules but are currently not used (no static reference found). They accept the dependency
identifiers (KNNUM) instead of the code tables as input.
The following auxiliary function modules exist for tracing dependency evaluation:
Function Module | Description | Callers |
---|---|---|
CUOV_TRC_INIT | Initialize trace | Invoked dynamically from SAPLCUTC |
CUOV_TRC_DETAIL | Display trace detail | Depreceated |
CUOV_ACT_TRC_DETAIL | Display trace details for actions | Invoked dynamically from SAPLCUTC |
CUOV_PCND_TRC_DETAIL | Display trace details for preconditions | Invoked dynamically from SAPLCUTC |
CUOV_SCND_TRC_DETAIL | Display trace details for selection conditions | Invoked dynamically from SAPLCUTC |
CUOV_PROC_TRC_DETAIL | Display trace details for procedures | Invoked dynamically from SAPLCUTC |
The following utility function modules exist:
Function Module | Description | Callers |
---|---|---|
CUOV_GET_CURRENT_DEPENDENCY | Return basic data (CUKB) of the currently processed dependency |
|
CUOV_GET_FUNCTION_ARGUMENT | Read or write actual parameters in a variant function interface | Customer specific code implementing variant functions |
CUOV_GET_VARS | Extract variables from dependency code | Explanation (SAPLCUXP) |
Data Structures
Classic dependency evaluation is based on two kinds of input data:
- Dependency code to be interpreted
- Working memory (Dynamic Database = DDB) against which dependencies are evaluated
CUOV dependency evaluation functions expect an an input parameter (table) with dependency code. In addition, CUOV has a global memory
with DDB instance numbers for instance variables $ROOT, $PARENT, $SELF to read or write data in the dynamic database during evaluation.
The DDB is managed in function group CUDB which provides access functions to read and write entries in the DDB.
Additional global memory variables in CUOV are the following (see include lcuovtop):
Data | Description | Comments |
---|---|---|
CUOVD_KNNUM | Internal ID of currently processed dependency |
|
CUOVD_RETCODE | Error return code of dependency processing |
|
CUOVD*_TRC* | Trace settings and trace content recorded in the current session |
|
CUOVD*_MTRC* | New Trace settings and trace content recorded in the current session | New trace introduced with OSS note 800863 |
Note: all data in the global memory of CUOV are transient, i.e. they are not saved together with the configuration.
Only trace settings can be saved in the trace modules (CUTC).
Code Format of Classic Dependencies
The code format of classic dependencies is a binary tree consisting of one or several nodes: each node represents a term.
Example: code tree for condition <variable_1> EQ 'XYZ' OR <variable 2> EQ 'UVW
In ABAP, the tree is represented as an internal table of lines with structure KBD_TREE:
Component | Datatype | Comments |
---|---|---|
TYPE | CHAR4 | Type of term |
OP | CHAR32 | Extended operator |
ARG1 | CHAR6 (storing an integer with sign) | Reference to a child term in KBD_TREE |
ARG2 | CHAR6 (storing an integer with sign) | Reference to a child term in KBD_TREE |
Note: The reference to the child term is stored as a table line 'offset': if the current term is in table line idx, the left child term is found in table line
idx + arg1 and the right child term is found in table line idx + arg2. A tree node can be re-used as child term in different parent terms (code compression).
The sort order of KBD_TREE lines must not be changed !
Example: Code table KBD_TREE for selection condition ak_color = 'RAL4711' OR ak_fabric = '001'
The code tree can be viewed by selecting the detailed view of a dependency in transaction cu04 and by clicking the 'Compilation' button.
Explanation of code table entries:
Line No | TYPE | OP | ARG1 | ARG2 | Comment |
---|---|---|---|---|---|
000001 | blog | OR | 1 | 5 | Binary logical operator term (OR) |
000002 | sxpr | EQ | 1 | 3 | Term representing the symbolic comparison expression |
000003 | avar | 0000006028 | 1 | 0 | Term representing variable $root.ak_color; |
000004 | sym | $ROOT | 5 | 0 | Symbol identifying the instance variable (one of $root, $parent, $self). |
000005 | qlit | RAL4711 | 7 | 0 | Quoted literal (constant) representing the right hand side of the symbolic comparison expression |
000006 | sxpr | EQ | 1 | 2 | Term representing the symbolic comparison expression |
000007 | avar | 0000006029 | 3- | 0 | Term representing variable $root.ak_fabric. |
000008 | qlit | 001 | 3 | 0 | Quoted literal (constant) representing the right hand side of the symbolic comparison expression |
In the appendix you can find more examples of code trees including also other syntax elements.
Term types, operators and arguments in classic dependencies:
Type | Description | Operator | Left Child | Right Child |
---|---|---|---|---|
Logical Terms | ||||
blog | Binary logical operator term | AND, OR | <condition 1> | <condition 2> |
ulog | Unary logical operator term | NOT | empty (0) | <condition> |
sxpr | Symbolic comparison expression | EQ, NE, GT, LT, GE, LE | <operand 1> | <operand 2> |
nxpr | Numeric comparison expression | EQ, NE, GT, LT, GE, LE | <operand 1> | <operand 2> |
oxpr | Object comparison expression | EQ, NE, GT, LT, GE, LE | <operand 1> | <operand 2> |
Numeric Terms | ||||
bnum | Binary numeric operator term | +, -, *, /, ** | <operand 1> | <operand 2> |
unum | Unary numeric operator term | - (minus) | empty (0) | <operand> |
fnum | Builtin numeric function term | See table in CUPP_FUNCTION_OP | empty (0) | <operand> |
num | Single number | Number in float format | empty (0) | empty (0) |
intv | Interval | SPACE | <left bound> | <right bound> |
intb | Interval bound | Number in float format | Type of bound (integer) | empty (0) |
Symbolic Terms | ||||
sym | Unquoted literal | Character string | length of string | <continuation string> |
qlit | Quoted literal | Character string without quotes (max 32) | length of string | <continuation string> |
c | Continuation string | String (segment) | length of string | <continuation string> |
Variables | ||||
var | Symbol used as a variable | Name of variable | empty (0) | empty (0) |
avar | Characteristic variable | Internal identifier of characteristic (ATINN) | <instance variable> | Flag (RFLAG) for characteristic kind: |
fvar | Facet variable | Internal identifier of characteristic (ATINN) | <instance variable> | Facet identifier: |
prd2 | Characteristic variable | Avar | <Internal identifier of characteristic> (ATINN) stored as sym | <instance variable> |
Type Specification | ||||
obj | Type specification | Object type + class type | <object key> stored as sym | empty (0) |
Lists | ||||
cons | Head of list | Name of list item | <list element> | <tail of list> |
$nil | Empty list | SPACE | empty (0) | empty (0) |
Predicates | ||||
prd0 | Non-atomic predicate with arity zero | Name of predicate | empty (0) | empty (0) |
prd1 | Non-atomic predicate with arity one | Name of predicate | <argument> | empty (0) |
prd2 | Non-atomic predicate with arity two | Name of predicate | <argument_1> | <argument_2> |
pred | Non-atomic predicate with arity >= three | Name of predicate | <list of arguments> | empty (0) |
Tables | ||||
tab | Table call | Internal table identifier (CLINT) | <arguments> | empty (0) |
icol | Input argument | Internal identifier of formal argument (ATINN) | <actual argument> | <rest arguments> |
ocol | Output argument | Internal identifier of formal argument (ATINN) | <actual argument> | <rest arguments> |
dcol | Output argument | Internal identifier of formal argument (ATINN) | <actual argument> | <rest arguments> |
rcol | Changed argument | Internal identifier of formal argument (ATINN) | <actual argument> | <rest arguments> |
Functions | ||||
fun | Variant function call | Internal function identifier (CLINT) | <arguments> | empty (0) |
pfun | Variant function call | Internal function identifier (CLINT) | <arguments> | empty (0) |
Assignments | ||||
sass | Symbolic assignment expression (single valued target) | = | <target> | <source> |
nass | Numeric assignment expression (single valued target) | = | <target> | <source> |
smas | Symbolic assignment expression (multi valued target) | = | <target> | <source> |
mas | Numeric assignment expression (multi valued target) | = | <target> | <source> |
sres | Symbolic domain restriction (restrictable target) | = | <target> | <source> |
nres | Numeric domain restriction (restrictable target) | = | <target> | <source> |
bass | Boolean assignment expression (characteristic facet target) | = | <target_fvar> | <source> |
Control Statements | ||||
cond | Conditional action | IF | <condition> | <list of actions> |
Note: entries in brackets <..> denote references to other terms in the code tree.
Trace Settings
Data | Type | Comments |
---|---|---|
CUOVD_KBAU_TRC_ON | C | Boolean indicator for 'trace active' |
CUOVD_KBAU_MTRC_ON | C | Boolean indicator for 'NEW trace active' |
Trace Records
Data | Type | Comments |
---|---|---|
CUOVD_TRC | Table of CUOVT_TRC_LINE | Table with trace messages + optional detail infos for each message |
Type CUOVT_TRC_LINE
Field | Type | Description |
---|---|---|
HANDLE | I | Handle of trace message |
MODULE | CUOVT_MODULE Identifier of the module to which the trace message belongs (e.g. CSTR for constraints, DDB for Dynamic Database) | |
KEY | CUOVT_INT_KEY | Numeric key of trace entry |
MSGNR | T100-MSGNR | T100 Message number |
CURR_DATA | CUOVT_TRC_DATA | A table with detail info about input and output parameters to dependency processing in the current traced operation |
Error Handling
T100 message area: 28. Formroutine for error messages: CUOV_MSG. Global return code variable (CUOVD_RETCODE) is set and an 'S' message is issued.
The message includes the name of the currently processed dependency (KNNAM). Example (28-510): 'Error in dependency processing: division by zero in
dependency &1<KNNAM>'. Messages are also recorded in the application log. They can be displayed via transaction slg1 for object PPVA subobject CUOV.
Implementation Details
This section describes implementation details of the dependency processing functions.
Overview
Function group CUOV is written in 'old style' (non-Object Oriented) ABAP and can process dependencies against ONE configuration
represented in the Dynamic Database (function group CUDB).
Program SAPLCUOV has the following includes:
Include | Description |
---|---|
LCUOVTOP | Global Data |
LCUOVF01 | General formroutines for condition action / procedure |
LCUOVF02 | Evaluation of table/function call |
LCUOVF03 | Evaluation involving azw variables (restrictable characteristics) |
LCUOVF05 | Trace handling |
LCUOVO01 | Trace detail screen |
Object Identifiers
- Dependencies are identified via internal numbers (CUKB-KNNUM - NUMC10)
- Object Types (Classes/materials) are identified via a triple object type, class type, object key (DDB_ITP - CHAR10/3/50)
- Characteristics are identified via internal inumbers (CABN-ATINN - NUMC10)
- Characteristic values are either numeric (CAWN-ATFLV) or symbolic (CAWN-ATWRT)
- Instances in the configuration are identified via instance numbers (CUINST - NUMC8)
Basic Dependency Interpretation Algorithm
The interpreter starts with the root node of the code tree and evaluates it.
- For conditions, the root node is a condition term
- For actions and procedures, the root node is a list term with the list items representing simple assignment statements
Evaluating a term means:
- Calculating a boolean success/failure indicator
- Possibly calculating additional result fields like e.g. a symbolic value (ATWRT)
- Possibly generating side effects (value assignments) in the Dynamic Database (DDB)
Based on the term type, calculating these results requires evaluation of one or several child terms in the code tree. Evaluation functions are generally recursive.
For each term type, a specialized evaluation function exists (form routines with naming convention CUOV_EVAL*).
The following table shows evaluation steps for the condition example shown above (Fig. 3.2.1):
Stacklevel | Form routine | Description | Comments |
---|---|---|---|
1 | CUOV_EVAL_CND |
|
|
2 | CUOV_EVAL_BLOG |
|
|
3 | CUOV_EVAL_CND |
|
|
4 | CUOV_EVAL_SXPR |
|
|
5 | CUOV_EVAL_STERM |
| The result of this step depends on the content of the configuration (DDB). |
4 | CUOV_EVAL_SXPR |
|
|
5 | CUOV_EVAL_STERM |
|
|
4 | CUOV_EVAL_SXPR |
|
|
3 | CUOV_EVAL_CND |
|
|
2 | CUOV_EVAL_BLOG |
| If the first condition result was FALSE, the evaluation would proceed to evaluate the second OR condition. |
1 | CUOV_EVAL_CND |
|
|
Function Details: CUOV_CHECK_CONDITION
Abstract: evaluate a set of pre- or selection conditions.
Import:
- CNDTYPE: P = precondition, S = selection condition
- KEY_DATE: validity date for master data access
Export:
- RESULT: T = True, F = False
- KNNUM: internal number of dependency that determined the result
Tables:
- CODE: table with dependency code for one or several dependencies (readonly)
Step | Description | Comments |
---|---|---|
1 | Reset return error code and result dependency KNNUM |
|
2 | Loop at lines of import table CODE: for each dependency (CODE-KNNUM) copy the code lines to local terms table X_CODE |
|
3 | At each group change in CODE-KNNUM evaluate the current dependency code collected in X_CODE: | A difference between precondition and selection condition occurs if multiple conditions (KNNUMs) are passed in the CODE table:
|
3a | CUOV_EVAL_PRECND | Another difference between the two condition types is the way in which the dependency interpreter handles terms that evaluate to result 'UNKNOWN':
|
4 | Within CUOV_EVAL_PRECND/SELCND the following steps are executed: |
|
4a | basic health check on code | Code must be non-empty |
4b | Determine whether tracing is requested for the current dependency (CUOV_CHECK_KBAU_TRC). | Calls out to trace function modules like CUTC_MSG_NEEDED |
4c | Perform generic condition evaluation with ternary result logic including UNKNOWN (CUOV_EVAL_CND). | Formroutine recursively evaluates the code terms as described in Chapter 4.3. |
4d | Collect trace data and store them as trace message (possibly with details about variable bindings) in the trace module (CUOV_HANDLE_KBAU_TRC) | Calls out to trace function module CUTC_SET_MSGX_TXT |
Function Details: CUOV_DO_PROCEDURE
Abstract: evaluate a sequence of procedures. Import:
- KEY_DATE: validity date for master data access Tables:
- CODE: table with dependency code for one or several dependencies (readonly) Exceptions:
- ACTION_DONE: indicates that a change was made to the DDB
- INTERNAL_ERROR: an internal (hard) error occurred
- UNKNOWN_INSTANCE: an inference was attempted on an unknown DDB instance
Step | Description | Comments |
---|---|---|
1 | Reset return error code and flag for 'action done'. |
|
2 | Prepare global variable for justification used for procedure inferences in the DDB (CUOVD_JUSTIFICAND). | A justification identifies a 'reason' for a value assignment in the DDB and is used in the overwrite logic of the DDB and in the explanation functions. |
3 | Loop at lines of import table CODE: for each dependency (CODE-KNNUM) copy the code lines to local terms table X_CODE | It is crucial, that the given sort order of procedures is preserved. |
4 | At each group change in CODE-KNNUM evaluate the current dependency code collected in X_CODE: |
|
4 | Within CUOV_EVAL_ACTIONS the following steps are executed: |
|
4a | Determine whether tracing is requested for the current dependency (CUOV_CHECK_KBAU_TRC). | Calls out to trace function modules like CUTC_MSG_NEEDED |
4b | Perform generic procedure statement evaluation (CUOV_EVAL_ACTION_LIST). | Formroutine recursively evaluates the code terms as described in Chapter 4.3. |
4c | Each statement is evaluated in formroutine CUOV_EVAL_ACTION. | A procedure statement can be a simple assignment statement, a multiple assignment statement, a domain restriction, a facet assignment, an IF-THEN (conditional) statement, a variant table or variant function statement or a general builtin function statement (e.g. $set_default, $set_pricing_factor) . |
4d | Collect trace data and store them as trace message (possibly with details about variable bindings) in the trace module (CUOV_HANDLE_KBAU_TRC) | Calls out to trace function module CUTC_SET_MSGX_TXT |
5 | Check if a change was made on the DDB. If this is the case (CUOVD_ACTION_DONE = T), the exception ACTION_DONE is raised. | The exception seems like a slightly awkward mechanism to convey 'positive information' - a better approach might be to use a simple return code/flag as EXPORTING parameter.. |
Comment: A complete 're-evaluation' cycle for procedures includes the removal of all previously known procedure inferences BEFORE calling this function.
The removal step is done in high level configuration using function module CUDB_DEL_ATTRS_BY_KNTYPE (called e.g. in CEI0 formroutine TMS_PROCEDURE).
The removal step is necessary to guarantee reproducible results of the procedure evaluation in case a configuration is checked multiple times.
Function Details: CUOV_DO_ACTION
Abstract: evaluate a sequence of actions. Import:
- KEY_DATE: validity date for master data access Tables:
- CODE: table with dependency code for one or several dependencies (readonly) Exceptions:
- ACTION_DONE: indicates that a change was made to the DDB
- INTERNAL_ERROR: an internal (hard) error occurred
- UNKNOWN_INSTANCE: an inference was attempted on an unknown DDB instance
The steps executed in this function are very similar to the steps in CUOV_DO_PROCEDURE. The following differences exist:
2 | Prepare global variable for justification used for procedure inferences in the DDB (CUOVD_JUSTIFICAND). | The fields 'KNTYPE' (knowledge type) and SEGM ('knowledge segment') have the constant values for action inferences and are different from the corresponding values for procedures. |
4c | Each statement is evaluated in formroutine CUOV_EVAL_ACTION. | Inferences (value assignments) are immediately applied to the DDB using function modules in function group CUDB. |
Within CUOV_SET_VAL, a different DDB function is called for actions than for procedures:
- For procedures CUDB_REPL_VAL is called because procedures can overwrite each other
- For actions CUDB_SET_VAL is called because actions cannot overwrite each other (two different action inferences for the same characteristic
cause a value conflict)|
Comment: A complete 're-evaluation' cycle for actions includes the removal of all previously known action inferences BEFORE calling this function.
The removal step is done in high level configuration using function module CUDB_DEL_ATTRS_BY_KNTYPE (called e.g. in CEI0 formroutine TMS_ACTION).
The removal step is necessary to guarantee reproducible results of the action evaluation in case a configuration is checked multiple times..
Within a re-evaluation cycle, the same set of actions can be evaluated multiple times because the variant configurator attempts to calculate all
possible inferences from the actions independent of their sort order ('DO 25 TIMES').
Function Details: CUOV_SET_OVARS
Abstract: set runtime bindings for object variables $self, $parent, $root. Import:
- PARENT: identifier (NUMC8) of the parent instance of the currently configured DDB instance
- ROOT: identifier (NUMC8) of the root instance in the current configuration
- SELF: identifier (NUMC8) of the currently configured DDB instance Exceptions:
- INTERNAL_ERROR: an internal (hard) error occurred
Comment:
This function must be called before calling CUOV_DO_PROCEDURES/ACTIONS or CUOV_CHECK_CONDITION so that the dependency interpreter
knows against which DDB instances it should resolve syntax elements involving the object variables $self, $parent, $root ( e.g. $self.COLOR = 'RED').
- In a single level (one instance) configuration, $self = $root = $parent = 1.
- Note: $self = $parent is a rather arbitrary convention in this case
- In a multi-level configuration, the focus of dependency evaluation shifts from one instance to the next through the BOM parts hierarchy as the configuration
check proceeds. CUOV_SET_VARS is called whenever a focus shift happens.- It's an implicit convention that $root is always =1
- For evaluation of a BOM item selection condition, $self denotes the part instance that may or may not be created via the selection condition.
Strictly speaking, $self is undefined for BOM item selection conditions because the condition is evaluated BEFORE instantating the part.- Special master data references like MDATA $SELF.STPO_POSNR are nevertheless allowed in this case to allow for a 'generic' modelling
of selection conditions
- Special master data references like MDATA $SELF.STPO_POSNR are nevertheless allowed in this case to allow for a 'generic' modelling
Tips&Tricks for Debugging
Explanation
The variant configurator has an explanation function to provide details about the current state of the configuration. If you see a value that
was calculated by the configurator you can obtain an explanation for this value by clicking on the 'info' button behind the value:
Fig: CU50 Explanation of a calculated characteristic value
The system will show a popup with all 'reasons' or 'justification's of the value. You can also double click one the of the justifications to obtain
more detailed information like e.g. the documentation & source code of a dependency.
Trace
Evaluation of classic dependencies can be debugged with the help of the variant configurator trace function. In the configuration screen
(va01/cu50) go to menu 'Extras -> Trace -> Settings' and switch on the configurator trace for one or several of the following trace areas:
- Preconditions
- Selection conditions
- Actions
- Procedures
- Dynamic database
Fig: cu50 Define Trace Settings
Check the corresponding check boxes in column 1 and activate your selection. In the filter dialog you can specify a list of objects (dependencies)
to which tracing should be applied - this is useful to limit the size of trace outputs in large configuration models.
Perform the configuration steps you want to investigate and then goto menu 'Extras->Trace->Display' to view the trace messages recorded.
Fig: cu50 - Display recorded Trace Messages.
This figure shows a set of trace messages recorded at the 'more detailed' level: the list shows which dependencies have been evaluated and
includes information about input ('>') and output ('>') parameters of procedures. By double clicking on a trace message for a dependency you
can display its source code. Typical errors like missing inferences can be analyzed by looking e.g. at the input values to procedures and
actions in this list.
Logging
Messages about serious errors like corrupt code or zero divisions encountered during dependency evaluation are written to the application log
using function module CUTC_WRITE_APPL_LOG. These messages can be viewed in transaction slg1 for object 'PPVA' and subobject 'CUOV'.
Break-Points
Logical step | Code location |
---|---|
Create a logged message | Formroutine CUOV_MSG |
Evaluate procedures | Function CUOV_DO_PROCEDURE, first line, |
If you want to filter to a particular dependency, you can also switch on filtered trace for this dependency and place a break-point
in CUOV_CHECK_KBAU_TRC on the line with CUOVD_KBAU_TRC_ON = TRUE.
Evaluate a procedure/action statement | Formroutine CUOV_EVAL_ACTION |
Get a value from the Configuration | Formroutine CUOV_GET_VAL |
Set a value in the Configuration | Formroutine CUOV_SET_VAL |
Get a master data (MDATA) value | Formroutine CUOV_EVAL_MASTER_DATA |
Evaluate preconditions /selection conditions | Function CUOV_CHECK_CONDITION, first line, |
Evaluate variant table access | Formroutine CUOV_EVAL_TABLE |
Evaluate variant function call | Formroutine CUOV_EVAL_FUNCTION |
OSS Notes
The following table gives an overview of OSS notes about classic dependency evaluation. Main component for notes search: LO-VC-DEP. Keywords: SAPLCUOV
Priorities give the author's personal view of how important a note is (1=very high, 2=high, 3=medium). Prio = MOD indicates modification notes. OSS notes with
numbers <500000 are usually old and should be available in most customer systems.
Topic | Number | Title | Comment |
---|---|---|---|
General | |||
| 977372 | Dependencies corrupt after Unicode conversion | Maintenance issue |
| 917987 | General performance in variant configuration | Consulting |
| 670571 | Object dependencies are processed incorrectly | Fixed in 4.5B |
|
|
|
|
Pre/Selection Conditions | |||
| 961910 | Mandatory characteristics and preconditions | MOD, Pilot release |
| 544523 | LO-VC-DEP: Error with conditions with multi-value characteristics | Fixed in 4.6C SP36, 4.7 SP02 |
| 359733 | Rounding error in value check with intervals | Fixed in 4.6C SP13 |
| 307786 | Performance: MDATA and multi-value characteristics |
|
| 128247 | Ref MDATA $SELF.<Characteristic> in select conditn |
|
|
|
|
|
Procedure | |||
| 718257 | Error in dependency: negative value for characteristic |
|
| 398350 | Optional output parameters for variant functions |
|
| 183548 | Object dependencies: indicator 'Negative values allowed' |
|
| 173918 | Rounding error in requirements with IN operator | 'Requirements' should be called 'dependencies' |
| 166766 | Error in CEIL,TRUNC,FRAC functions in obj.dependncs | Consulting |
| 90417 | Default values in object dependencies | MOD |
Explanation & Trace | |||
| 567263 | CU50:Explanatn for dependency causes exceptn CONVT_OVERFLOW | Bug in pretty printer |
| 480738 | Trace output for configuration is lost | Fixed in 4.6C SP28 |
| 387703 | Detail trace for restrict. charact. in object dependencies |
|