Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
franois_henrotte
Active Contributor
It is not easy to get price conditions as they can be stored into different condition tables based on the needs of each customer. The condition tables are generated and the fields used inside the tables are not always the same.

Here is a solution to get the price linked to a condition LV_KSCHL. We assume that the usage and application (keys from table T685) are fixed into constants - respectively 'A' and 'V' for Sales.

Step 1 : get access sequence

This is needed in order to retrieve the list of condition tables linked to the condition type.
    SELECT SINGLE * FROM t685
INTO @gs_t685
WHERE kvewe EQ @gc_kvewe
AND kappl EQ @gc_kappl
AND kschl EQ @lv_kschl.
IF sy-subrc EQ 0.
lv_kozgf = gs_t685-kozgf.
ENDIF.

Step 2 : get the list of condition tables linked to the access sequence
    DATA: lt_t682ia TYPE TABLE OF t682ia.


CLEAR: gt_t681.

CALL FUNCTION 'COND_READ_ACCESSES'
EXPORTING
i_kvewe = gc_kvewe
i_kappl = gc_kappl
i_kozgf = lv_kozgf
TABLES
t682ia_tab = lt_t682ia
EXCEPTIONS
OTHERS = 1.

SELECT * FROM t681
INTO TABLE gt_t681
FOR ALL ENTRIES IN lt_t682ia
WHERE kvewe EQ gc_kvewe
AND kotabnr EQ lt_t682ia-kotabnr.

Step 3 : for each condition table, get the data of the condition type

We follow the access sequence, and if some data is found, then we exit the loop. We could also collect all the data from the different condition tables, if needed. The date PRSDT can be also defined externally to some other value than the current date.
LOOP AT gt_t681 INTO DATA(ls_t681).
"Retrieve data from condition tables
get_data_from_condition_table( is_t681 = ls_t681
iv_prsdt = sy-datum ).
IF gt_data IS NOT INITIAL.
EXIT.
ENDIF.
ENDLOOP.

Now let's look at the dynamical reading of the data. As we have the structures T685 and T681, we have almost all information needed to do so. The only missing part is about the fields to be used for the selection of the table. This will be easily retrieved using function module WCB_GET_CONDITION_TABLE_KEYS. So the coding to retrieve the data will be like this :
  METHOD GET_DATA_FROM_CONDITION_TABLE.
DATA: lt_t682z TYPE wcb_t682z_tab.

DATA: lv_datum TYPE datum,
ls_where TYPE string.

DATA: ls_data TYPE ty_data.

DATA: ob_rec TYPE REF TO data.

FIELD-SYMBOLS: <lt_rec> TYPE STANDARD TABLE,
<lv_field> TYPE any,
<lv_knumh> TYPE knumh.


CREATE DATA ob_rec TYPE STANDARD TABLE OF (is_t681-kotab) WITH NON-UNIQUE DEFAULT KEY.
ASSIGN ob_rec->* TO <lt_rec>.

* Pay attention to this:
* Method GET_ACCESS_SEQUENCE should be called first in order to fill structure GS_T685
CALL FUNCTION 'WCB_GET_CONDITION_TABLE_KEYS'
EXPORTING
i_use = gc_kvewe
i_application = gc_kappl
i_condition_type = gs_t685-kschl
i_con_tab = is_t681-kotabnr
i_access = gs_t685-kozgf
IMPORTING
et_t682z = lt_t682z
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
RETURN.
ENDIF.

LOOP AT lt_t682z INTO DATA(ls_t682z).
ASSIGN COMPONENT ls_t682z-zifna OF STRUCTURE gs_komg TO <lv_field>.
IF sy-subrc EQ 0.
IF ls_where IS INITIAL.
ls_where = |{ ls_t682z-zifna } EQ '{ <lv_field> }'|.
ELSE.
ls_where = ls_where && | AND { ls_t682z-zifna } EQ '{ <lv_field> }'|.
ENDIF.
ENDIF.
ENDLOOP.

IF is_t681-ksdat IS INITIAL.
SELECT * INTO TABLE <lt_rec>
FROM (is_t681-kotab)
WHERE kappl EQ gc_kappl
AND kschl EQ gs_t685-kschl
AND (ls_where).
ELSE.
IF iv_prsdt IS INITIAL.
lv_datum = sy-datum.
ELSE.
lv_datum = iv_prsdt.
ENDIF.
SELECT * INTO TABLE <lt_rec>
FROM (is_t681-kotab)
WHERE kappl EQ gc_kappl
AND kschl EQ gs_t685-kschl
AND datbi GE lv_datum
AND datab LE lv_datum
AND (ls_where).
ENDIF.

LOOP AT <lt_rec> ASSIGNING FIELD-SYMBOL(<ls_line>).
ASSIGN COMPONENT 'KNUMH' OF STRUCTURE <ls_line> TO <lv_knumh>.
SELECT konp~knumh
konp~kbetr AS kbetr_1
konp~konwa
konp~kpein
konp~kmein
konm~kstbm
konp~konms
konm~kbetr AS kbetr_2
INTO ls_data
FROM konp
LEFT OUTER JOIN konm ON konm~knumh = konp~knumh
WHERE konp~knumh EQ <lv_knumh>
AND konp~loevm_ko EQ ' '.

IF ls_data-konwa CA '%'.
ls_data-kbetr_1 = ls_data-kbetr_1 / 10 .
ls_data-kbetr_2 = ls_data-kbetr_2 / 10 . "BGO01
ENDIF.
APPEND ls_data TO gt_data.

ENDSELECT.
ENDLOOP.

SORT gt_data BY knumh kstbm.

ENDMETHOD.

Notes:

  1. the parameters are trivial : IS_T681 TYPE T681 and IV_PRSDT TYPE PRSDT.

  2. the field T681-KSDAT indicates if the condition table is time-dependent.

  3. depending on your needs you define the table GT_DATA to contain data from tables KONP / KONM

  4. those two tables are always read with the key KNUMH coming from the condition tables


Prerequisite :

Now you should have noticed that we compare the values of the condition tables with the values from segment GS_KOMG. This one is of type KOMG and contains all the possible fields to be used in the key fields of condition tables. Of course you have to fill this segment before starting to read the condition tables. Here is some sample code to do it quite easily for a Billing document.
    CALL FUNCTION 'RV_INVOICE_PRICING_PREPARE'
EXPORTING
vbrk_i = ls_vbrk
vbrp_i = ls_vbrp
IMPORTING
komk_e = ls_komk
komp_e = ls_komp
TABLES
xkomfk = lt_komfk
xvbfs = lt_vbfs
xvbpa = lt_xvbpa
xvbrk = lt_xvbrk
xvbrp = lt_xvbrp
EXCEPTIONS
OTHERS = 1.

"Fill source fields for condition tables
MOVE-CORRESPONDING ls_komk TO gs_komg.
MOVE-CORRESPONDING ls_komp TO gs_komg.

 

As you probably noticed, this was extracted from a class that I made to read the condition tables dynamically. I extracted the important parts of the code and removed the Z tables and such things that are not generic so that you can see how this works from a global point of view.
9 Comments