CRM and CX Blogs by Members
Find insights on SAP customer relationship management and customer experience products in blog posts from community members. Post your own perspective today!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

Introduction

During order taking process the Sales Representative can choose the product which constitutes the order.

The price of the products will be displayed along with the product in standard REX application. The price determination can be –

  • Only offline price - REX will reflect the indicative price prior to sync. This information is updated in the latest sync.
  • For transfer orders - as there will be no additional pricing conditions in the back-end the offline price is the actual price.
  • For Transfer orders offline pricing available in REX would be same as pricing available in CRM backend at the time of last sync with CRM. Pricing would be the same unless there is recent change in the prices from previous sync

The offline pricing happens in the following way-

The Sales Representative will log into their mobile device and create Transfer Orders. The Pricing for orders is maintained in CRM back end and pushed to front end using a standard REX functionality called Offline pricing.

Customizing multiple offline pricing in CRM


The offline prices are downloaded from CRM to REX. Standard REX add-on configuration in CRM allows only one condition table download to REX. However this may not meet the business requirement to have flexible offline pricing to consider multiple pricing condition tables. The custom configuration table is defined in CRM and BAPI to download the offline pricing and is enhanced to call the custom table in place of the standard configuration table.

The custom logic be built to determine the offline prices in the following sequence –

  1. Check the customer specific price
  2. If there is no record found in the above step then check the is customer group specific price
  3. If there is no record found in above steps then get the product general price

The below customization is done to enable the offline pricing determination logic in CRM Add on

Custom table

A custom table is created with key fields and access sequence for each Sales Organization.

The custom table with below fields is created.

  • Sales Organization
  • Access sequence
  • Value
  • Key field
  • Condition Type (ZPR0)

Sold –To – Party ( customer) , customer group, product & sales area are passed to the CRM BAPI from front end to get the pricing. The BAPI fetches prices for a given customer and product from the condition tables (which are configured  as mentioned in Step 1 ) in the order of access sequence. The prices are sent to the front end for the combination of sold to party and product.  In addition the combination of the customer group product is  picked in front end so that all the customers belonging to that group will be charged with that price.


Technical Flow Description

Implement the BADI of the BAPI “/MAC/RSFM_GET_CONDTABLE” with below logic

  • Enhance the method /MAC/RS_BADI_GET_CONDTABLE_BEF of the BADI implementation of /MAC/RS_BADI_DEF_PRICING
  • Fetch the value from the table ZACCESS_SEQ (Ref 6.5.4.4) for the sales org of the SR into the table IT_ACCESS_SEQ.

  Sort the table by the field KOZGF 

  • Loop IT_ACCESS_SEQ
    • If KEY_FIELD =’CUST_GROUP’
      • Fetch the value from the condition table(IT_ACCESS_SEQ-COND_TABLE) for the customer groups of given BPs & products
    • If KEY_FIELD =’SOLD_TO_PARTY’
      • Fetch the value from the condition table(IT_ACCESS_SEQ-COND_TABLE) for the given BPs & products
    • If KEY_FIELD =’PRODUCT’
      • Fetch the value from the condition table(IT_ACCESS_SEQ-COND_TABLE) for the given products.
  • ENDLOOP
  • Set the flag CV_SKIP as ‘X’ to ignore the standard BAPI flow.

ABAP Development

  Implement the BADI of the BAPI “/MAC/RSFM_GET_CONDTABLE” with below logic  

  • Enhance the method /MAC/RS_BADI_GET_CONDTABLE_BEF of the BADI implementation of /MAC/RS_BADI_DEF_PRICING
  • Fetch the value from the table ZACCESS_SEQ for the sales org of the SR into the table IT_ACCESS_SEQ.

  Sort the table by the field KOZGF 

  • Loop IT_ACCESS_SEQ
    • If KEY_FIELD =’CUST_GROUP’
      • Fetch the value from the condition table (IT_ACCESS_SEQ-COND_TABLE) for the customer groups of given BPs, products & condition type(ZACCESS_SEQ-KSCHL)

  Copy the customer group level product price to corresponding BPs. 

    • If KEY_FIELD =’SOLD_TO_PARTY’
      • Fetch the value from the condition table (IT_ACCESS_SEQ-COND_TABLE) for the given BPs, products & condition type.
    • If KEY_FIELD =’PRODUCT’
      • Fetch the value from the condition table (IT_ACCESS_SEQ-COND_TABLE) for the given products & condition type.
  • Check the export parameter does not contain the prices for each BP & Product combination
    • Update prices in the export parameter for product & BP combination.
  • ENDLOOP
  • Set the flag CV_SKIP as ‘X’ to ignore the standard BAPI flow.

Source code


METHOD /mac/rs_badi_if_pricing~/mac/rs_badi_get_condtable_bef.

CONSTANTS: c_sign_i        TYPE c LENGTH 1 VALUE 'I',
c_option_eq     TYPE c LENGTH 2 VALUE 'EQ'.


TYPES: BEGIN OF t_bp_cust_grp,
partner_id TYPE bu_partner,
bp_guid  TYPE bu_partner_guid,
cust_grp TYPE crmt_cust_group,
END OF t_bp_cust_grp.

DATA: v_selection_fields   TYPE string,
v_condtable_name     TYPE /sapcnd/cond_table_name,
v_cond_tab           TYPE /sapcnd/cond_table_id,
v_timestamp          TYPE timestamp,
v_timestamp_t          TYPE timestamp,
v_cust_grp           TYPE crmt_cust_group,
v_timezone           TYPE timezone,
v_business_unit      TYPE zbusinessunit,
v_datum TYPE sy-datum.

DATA: r_products_ranges   TYPE RANGE OF comt_product_guid,
r_cust_grp_ranges   TYPE RANGE OF crmt_cust_group,
r_bp_ranges         TYPE RANGE OF comt_product_guid.

DATA: wa_products_range    LIKE LINE OF r_products_ranges,
wa_cust_grp_ranges   LIKE LINE OF r_cust_grp_ranges,
wa_bp_ranges         LIKE LINE OF r_bp_ranges.

DATA: r_data               TYPE REF TO data.

DATA: it_bp_guids_ids      TYPE /mac/rst_bp_id_guid,
it_cond_id           TYPE STANDARD TABLE OF zacc_seq,
it_access_seq        TYPE STANDARD TABLE OF zacc_seq,
it_bp_cust_grp       TYPE STANDARD TABLE OF t_bp_cust_grp,
it_condtable         TYPE SORTED TABLE OF /mac/rss_condtable WITH NON-UNIQUE KEY product_guid product_id partner.

DATA: wa_bp_guids_ids      TYPE LINE OF /mac/rst_bp_id_guid,
wa_condtable_out     TYPE /mac/rss_condtable,
wa_condtable         TYPE /mac/rss_condtable,
wa_selected_data     TYPE /sapcnd/t681_s,
wa_bus_sarea         TYPE crmt_bus_sales_area,
wa_cond_id           TYPE zacc_seq,
wa_access_seq        TYPE zacc_seq,
wa_data              TYPE crmt_bus_set0030,
wa_bp_cust_grp       TYPE t_bp_cust_grp.

FIELD-SYMBOLS: <fs_bp_id>               LIKE LINE OF it_bp_ids,
<fs_product>             LIKE LINE OF it_products,
  <fs_condtable_tab>       TYPE ANY TABLE,
  <fs_condtable_struc>     TYPE any,
  <fs_condtable_value>     TYPE any,
  <fs_condtable_curr>      TYPE any.

" Clear the variables and tables for processing
CLEAR: ct_condtable[], it_condtable[], ct_return[].

" Get the access sequence for determiing offline prices from ZACC_SEQ for given sales org.
SELECT  *
INTO CORRESPONDING FIELDS OF TABLE it_cond_id
FROM zacc_seq
WHERE sales_org EQ is_sales_area-sales_org .

" Sort by access sequence
DELETE ADJACENT DUPLICATES FROM it_cond_id.
SORT it_cond_id BY kozgf.

" Get the database table name for the condition table
LOOP AT it_cond_id INTO wa_cond_id.

CLEAR v_cond_tab.
v_cond_tab = wa_cond_id-cond_table.

CALL FUNCTION '/SAPCND/CUS_T681_SEL'
EXPORTING
i_application   = 'CRM'
i_usage         = 'PR'
i_cond_table_id = v_cond_tab
i_state         = 'A'
IMPORTING
e_selected_data = wa_selected_data.

CLEAR wa_access_seq.
wa_access_seq = wa_cond_id.
wa_access_seq-cond_table = wa_selected_data-kotab.
APPEND wa_access_seq TO it_access_seq.

ENDLOOP.

IF it_access_seq IS INITIAL.
RETURN.
ENDIF.

wa_bp_ranges-sign   = c_sign_i.
wa_bp_ranges-option = c_option_eq.

" Get the BP GUIDs for given BPs
LOOP AT it_bp_ids ASSIGNING <fs_bp_id>.

wa_bp_guids_ids-partner_id = <fs_bp_id>-partner_id.

CALL FUNCTION 'BUPA_NUMBERS_GET'
EXPORTING
iv_partner      = wa_bp_guids_ids-partner_id
IMPORTING
ev_partner_guid = wa_bp_guids_ids-partner_guid.

APPEND wa_bp_guids_ids TO it_bp_guids_ids.

wa_bp_ranges-low = wa_bp_guids_ids-partner_guid.
APPEND wa_bp_ranges TO r_bp_ranges.

ENDLOOP.

" Populate products range table
wa_products_range-sign   = c_sign_i.
wa_products_range-option = c_option_eq.

LOOP AT it_products ASSIGNING <fs_product>.
wa_products_range-low = <fs_product>-product_guid.
APPEND wa_products_range TO r_products_ranges.
ENDLOOP.

CLEAR v_timestamp.
" v_timezone is initial coz time zone is UTC
CONVERT DATE sy-datum INTO TIME STAMP v_timestamp TIME ZONE v_timezone.
v_datum = sy-datum + 1.
CONVERT DATE v_datum INTO TIME STAMP v_timestamp_t TIME ZONE v_timezone.
wa_cust_grp_ranges-sign = c_sign_i.
wa_cust_grp_ranges-option = c_option_eq.

LOOP AT it_access_seq INTO wa_access_seq.

v_condtable_name = wa_access_seq-cond_table.

" IF offline prices to be determied in customer grp specific way
IF wa_access_seq-key_field EQ 'CUST_GROUP'.

" Populate customer group table

LOOP AT it_bp_guids_ids INTO wa_bp_guids_ids .

CLEAR wa_bus_sarea.
wa_bus_sarea-sales_org = is_sales_area-sales_org.
wa_bus_sarea-channel   = is_sales_area-dis_channel.
wa_bus_sarea-division  = is_sales_area-division.

CALL FUNCTION 'CRM_BUPA_FRG0030_GET_DETAIL'
EXPORTING
iv_partner_guid = wa_bp_guids_ids-partner_guid
is_sales_area   = wa_bus_sarea
IMPORTING
es_data         = wa_data.

CLEAR wa_bp_cust_grp.
wa_bp_cust_grp-partner_id = wa_bp_guids_ids-partner_id.
wa_bp_cust_grp-bp_guid  = wa_bp_guids_ids-partner_guid. "wa_bp_ranges-low.
wa_bp_cust_grp-cust_grp = wa_data-customer_group .

APPEND wa_bp_cust_grp TO it_bp_cust_grp.

" Populate customer group range table.
CLEAR wa_cust_grp_ranges-low.
wa_cust_grp_ranges-low = wa_data-customer_group.
APPEND wa_cust_grp_ranges TO r_cust_grp_ranges.

ENDLOOP.

SORT r_cust_grp_ranges BY low.
DELETE ADJACENT DUPLICATES FROM r_cust_grp_ranges COMPARING low" lt_cust_grp COMPARING cust_grp.

CLEAR v_selection_fields.
CONCATENATE 'CUST_GROUP PRODUCT TIMESTAMP_TO TIMESTAMP_FROM KBETR KPEIN KMEIN KONWA' v_selection_fields INTO v_selection_fields RESPECTING BLANKS.

CREATE DATA r_data TYPE STANDARD TABLE OF (v_condtable_name).
ASSIGN r_data->* TO <fs_condtable_tab>.

SELECT (v_selection_fields)
FROM (v_condtable_name) INTO CORRESPONDING FIELDS OF TABLE <fs_condtable_tab>
WHERE sales_org EQ is_sales_area-sales_org_o
AND dis_channel EQ is_sales_area-dis_channel
AND cust_group IN r_cust_grp_ranges
AND product IN r_products_ranges
AND kschl EQ wa_access_seq-kschl
AND ( timestamp_from <= v_timestamp or timestamp_from = v_timestamp_t )
AND timestamp_to >= v_timestamp
AND release_status EQ ' '.

" IF offline prices to be determied in customer specific way
ELSEIF wa_access_seq-key_field EQ 'SOLD_TO_PARTY'.

CLEAR v_selection_fields.
CONCATENATE 'SOLD_TO_PARTY PRODUCT TIMESTAMP_TO TIMESTAMP_FROM KBETR KPEIN KMEIN KONWA' v_selection_fields INTO v_selection_fields RESPECTING BLANKS.

CREATE DATA r_data TYPE STANDARD TABLE OF (v_condtable_name).
ASSIGN r_data->* TO <fs_condtable_tab>.

SELECT (v_selection_fields)
FROM (v_condtable_name) INTO CORRESPONDING FIELDS OF TABLE <fs_condtable_tab>
WHERE sales_org EQ is_sales_area-sales_org_o
AND dis_channel EQ is_sales_area-dis_channel
AND sold_to_party IN r_bp_ranges
AND product IN r_products_ranges
AND kschl EQ wa_access_seq-kschl
AND ( timestamp_from <= v_timestamp or timestamp_from = v_timestamp_t )
AND timestamp_to >= v_timestamp
AND release_status EQ ' '.

" IF offline prices to be determied as general price (product specific)
ELSEIF wa_access_seq-key_field EQ 'PRODUCT'.

CLEAR v_selection_fields.
CONCATENATE 'PRODUCT TIMESTAMP_TO TIMESTAMP_FROM KBETR KPEIN KMEIN KONWA' v_selection_fields INTO v_selection_fields RESPECTING BLANKS.

CREATE DATA r_data TYPE STANDARD TABLE OF (v_condtable_name).
ASSIGN r_data->* TO <fs_condtable_tab>.

SELECT (v_selection_fields)
FROM (v_condtable_name) INTO CORRESPONDING FIELDS OF TABLE <fs_condtable_tab>
WHERE sales_org EQ is_sales_area-sales_org_o
AND dis_channel EQ is_sales_area-dis_channel
AND product IN r_products_ranges
AND kschl EQ wa_access_seq-kschl
AND ( timestamp_from <= v_timestamp or timestamp_from = v_timestamp_t )
AND timestamp_to >= v_timestamp
AND release_status EQ ' '.

ENDIF.

UNASSIGN <fs_condtable_value>.
IF <fs_condtable_tab> IS  NOT INITIAL.

CLEAR wa_condtable_out.
"Fill output condition table
LOOP AT <fs_condtable_tab> ASSIGNING <fs_condtable_struc>.

ASSIGN COMPONENT 'PRODUCT' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
wa_condtable_out-product_guid = <fs_condtable_value>.

READ TABLE it_products ASSIGNING <fs_product> WITH KEY product_guid = <fs_condtable_value>.
IF sy-subrc EQ 0.
wa_condtable_out-product_id = <fs_product>-product_id.
ENDIF.
UNASSIGN <fs_condtable_value>.
ELSE.
CONTINUE.
ENDIF.

ASSIGN COMPONENT 'TIMESTAMP_FROM' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
wa_condtable_out-timestamp_from = <fs_condtable_value>.
UNASSIGN <fs_condtable_value>.
ENDIF.

ASSIGN COMPONENT 'TIMESTAMP_TO' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
wa_condtable_out-timestamp_to = <fs_condtable_value>.
UNASSIGN <fs_condtable_value>.
ENDIF.

ASSIGN COMPONENT 'KPEIN' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
wa_condtable_out-quantity = <fs_condtable_value>.
UNASSIGN <fs_condtable_value>.
ENDIF.

ASSIGN COMPONENT 'KMEIN' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
wa_condtable_out-qty_unit = <fs_condtable_value>.
UNASSIGN <fs_condtable_value>.

IF NOT wa_condtable_out-qty_unit IS INITIAL.
CALL FUNCTION 'UNIT_OF_MEASURE_SAP_TO_ISO'
EXPORTING
sap_code    = wa_condtable_out-qty_unit
IMPORTING
iso_code    = wa_condtable_out-isocodunit
EXCEPTIONS
not_found   = 1
no_iso_code = 2
OTHERS      = 3.
IF sy-subrc <> 0.
CLEAR wa_condtable_out-isocodunit.
ENDIF.
ELSE.
CLEAR wa_condtable_out-isocodunit.
ENDIF.

ENDIF.

ASSIGN COMPONENT 'KONWA' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_curr>.
IF <fs_condtable_curr> IS ASSIGNED.

CALL FUNCTION 'CURRENCY_CODE_SAP_TO_ISO'
EXPORTING
sap_code = <fs_condtable_curr>
IMPORTING
iso_code = wa_condtable_out-currency
EXCEPTIONS
OTHERS   = 4.

IF sy-subrc NE 0 OR wa_condtable_out-currency IS INITIAL.
wa_condtable_out-currency = <fs_condtable_curr>.
ENDIF.
ENDIF.

ASSIGN COMPONENT 'KBETR' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED AND <fs_condtable_curr> IS ASSIGNED.

CALL FUNCTION 'BAPI_CURRENCY_CONV_TO_EXTERN_9'
EXPORTING
currency        = <fs_condtable_curr>
amount_internal = <fs_condtable_value>
IMPORTING
amount_external = wa_condtable_out-net_value.

UNASSIGN <fs_condtable_value>.
UNASSIGN <fs_condtable_curr>.
ENDIF.

ASSIGN COMPONENT 'SOLD_TO_PARTY' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
READ TABLE it_bp_guids_ids INTO wa_bp_guids_ids WITH KEY partner_guid = <fs_condtable_value>.
IF sy-subrc EQ 0.
wa_condtable_out-partner = wa_bp_guids_ids-partner_id.
*              READ TABLE it_condtable INTO wa_condtable WITH KEY product_guid = wa_condtable_out-product_guid
* product_id   = wa_condtable_out-product_id
*                                                                 partner      = wa_condtable_out-partner.
*              IF sy-subrc NE 0.
INSERT wa_condtable_out INTO TABLE it_condtable.
*              ENDIF.
ENDIF.
UNASSIGN <fs_condtable_value>.
ENDIF.
ASSIGN COMPONENT 'CUST_GROUP' OF STRUCTURE <fs_condtable_struc> TO <fs_condtable_value>.
IF <fs_condtable_value> IS ASSIGNED.
v_cust_grp = <fs_condtable_value>.
wa_condtable_out-partner = v_cust_grp.
INSERT wa_condtable_out INTO TABLE it_condtable.
UNASSIGN <fs_condtable_value>.
ENDIF.
IF wa_access_seq-key_field EQ 'PRODUCT'.
INSERT wa_condtable_out INTO TABLE it_condtable.
ENDIF.
ENDLOOP.
ENDIF.
ENDLOOP.

ct_condtable[] = it_condtable[].

" Set skip flag to X in order to ignore the standard BAPI flow
cv_skip = 'X'.

ENDIF.

ENDMETHOD.


********Above document was co authored by my fellow colleagues Karthi Dhayalan and Samatha  ThammaReddy . *********