Quantcast
Channel: Tweaks
Viewing all articles
Browse latest Browse all 66

How to Get Accurate Pricing in SD for Customer and Material?

$
0
0

Custom Function Module to retrieve accurate Pricing in SD for Customer and Material.

Of late, we have been focussing on HANA, UI5, Fiori and all the related new jargons. But in reality, a major percentage of clients are still in the classical database and they still have simple requirements of getting the right data. They might complain a little about performance or/and look and feel of their current ERP, but at the end of the day, they cannot be pissed off more than with the wrong report, output or data. So still today, our age old clients have the same age old secret desire to play with correct data only. 🙂 

There are many situations where we need to find out the correct price of an Item(i.e. Material) for a Customer. The below custom Function Module, which we created, can be used as an API or as a utility FM to get the pricing details of a material; and can be called from any report program or enhancement as per the requirement.

The beauty here is, this FM takes only few information like the customer, material, and sales area details as input, but during the process of retrieval of pricing, we need much more information for which we have to fetch data from more than 20 tables, which is handled systematically inside this FM. Our idea is not to teach you how to create a custom FM, but to provide you a ready reference, in case you have a similar requirement in Pricing. Believe us, Pricing is a must in every SAP Project.

Even if you might not need this FM exactly, but we are positive, you would need many of the tables and standard function modules while working in some customization and in those instances, this article might help as a use case scenario for those tables and FMs.

Scope of the development

  • Create a Function Module with the import and table parameters (shown below).
  • Inside the FM use the detailed logic given below to fill the communication structure (Header structure KOMK and Item structure KOMP) which is very much important to get the accurate pricing from the FM PRICING.
  • Call the standard FM ‘PRICING’ with the proper input. In the table parameter TKOMV of the FM PRICING, we can get all the condition type and their values
  • After getting the output from the FM PRICING then prepare the output table for the custom FM to display them in the output.

Import parameter:

IM_KUNNR - Customer (KUNNR)

IM_MATNR - Material (MATNR)

IM_VKORG - Sales Organization (VKORG)

IM_VTWEG - Distribution Channel (VTWEG)

IM_SPART - Division (SPART)

IM_KALVG - Document procedure (for determining pricing procedure) (KALVG)

IM_MGLME - Quantity (MGLME)

IM_VRKME - Sales unit (VRKME)

IM_PRICING_DAT - Condition pricing date

IM_RETURN_FLAG – Return flag

IM_CDM - General Flag

SAP ABAP Training

Table parameter:

T_OUTTAB            - Output table

T_ERROR_MSG   - Error message

SAP HANA

MM Pricing

Also Read: PO re-Price issue in BAPI_PO_CHANGE

Detailed Logic for the Function Module

  • Create one Function Module with the above Import and Table parameters.
  • Write the below logic inside the function module.

Call FM ‘PRICING_REFRESH’ to refresh the previous pricing if exist.

DATA : i_tkomk TYPE STANDARD TABLE OF komk,

i_tkomv TYPE STANDARD TABLE OF komv INITIAL SIZE 0.

CALL FUNCTION 'PRICING_REFRESH'
TABLES
tkomk = i_tkomk
tkomv = i_tkomv.

Fill the Communication structure (Header structure KOMK and Item structure KOMP) which is very much important to get the accurate pricing from the FM PRICING.

Fill the Header Communication structure KOMK

Select all the fields from tables KNVV, MARA, MVKE and KNA1 and pass to the corresponding field of the header communication structure.

* Local data declaration

DATA: lk_komk TYPE KOMK,

           lk_komp TYPE KOMP.

  MOVE-CORRESPONDING: MVKE TO lk_komk, (local structure type of KOMK)                                                          

                      MARA TO lk_komk,

                      KNVV TO lk_komk,           
                      KNA1 TO lk_komk.           

  lk_komk-vkorg     = im_vkorg.  " Sales Org from Import parameter 
  lk_komk-vkorgau   = im_vkorg.  " Sales Org from Import parameter 
  lk_komk-vtweg     = im_vtweg.  " Distribution channel from Imp
  lk_komk-spart     = im_spart.  " Division from Import parameter

  lk_komk-kalvg     = im_kalvg.          " Document procedure

Select Pricing procedure

  SELECT SINGLE kalsm                     " Pricing procedure
  INTO v_t683v_kalsm
  FROM t683v                     " Pricing Determination in Sales Docs.
  WHERE vkorg = p_im_vkorg       " Sales Organisation
    AND vtweg = p_im_vtweg       " Distribution Channel
    AND spart = p_im_spart       " division
    AND kalvg = p_im_kalvg       " customer’s document Pricing Procedure
    AND kalks = p_k_knvv-kalks.  " customer’s Pricing Procedure

  lk_komk-kalsm     = v_t683v_kalsm.     " proper pricing procedure

Move the required fields from KNVV to the header structure

  lk_komk-waerk     = knvv-waers.      " Currency
  lk_komk-hwaer     = knvv-waers.      " Currency

* Get the company code
  SELECT SINGLE
         bukrs                  " Company code
         INTO v_bukrs
         FROM tvko              " Organizational Unit: Sales Org
    WHERE vkorg = im_vkorg .
  lk_komk-bukrs     = v_bukrs.         " Company code

Move the required fields from KNA1 to the header structure

  lk_komk-land1     = kna1-land1.      " Country key
  lk_komk-aland     = kna1-land1.      " Country key
  lk_komk-regio     = kna1-regio.      " Region(State,country)
  lk_komk-land1_we  = kna1-land1.
  lk_komk-aland_werk = kna1-land1.
  lk_komk-auart     = ‘ZSOR’.

Select the region from table T001W

SELECT SINGLE region counc cityc
    INTO k_t001w
    FROM t001w
    WHERE werks = KNVV-werks.   “ Plant from KNVV table

  lk_komk-wkreg     = t001w-regio.

  lk_komk-wkcou      = k_t001w-counc.
  lk_komk-wkcty      = k_t001w-cityc.

Pass customer from Import parameter

  lk_komk-kunnr     = im_kunnr.          " Customer Number
  lk_komk-kunwe     = im_kunnr.          " Ship-to party
  lk_komk-kunre     = im_kunnr.          " Bill-to party

Get the Head office A/C number from KNB1 table

  SELECT SINGLE knrze
      FROM knb1
      INTO v_knb1_knrze
  WHERE kunnr EQ im_kunnr
    AND bukrs EQ v_bukrs.

  IF v_knb1_knrze IS NOT INITIAL.
    lk_komk-knrze = v_knb1_knrze.        " Head office A/C number
  ELSE.
    lk_komk-knrze = im_kunnr.          " Head office A/C number
  ENDIF.
lk_komk-kappl      = ‘V’.           " Application for SD Pricing

* If Pricing date is Provided in the Input screen, then use that one

IF im_pricing_dat IS NOT INITIAL.

  lk_komk-prsdt =  im_pricing_dat. " pricing and exchange Date
  lk_komk-fbuda =  im_pricing_dat. " Services rendered Date
  lk_komk-fkdat =  im_pricing_dat. " Billing index & printout dt
  lk_komk-erdat =  im_pricing_dat. " Record Created date
  lk_komk-audat =  im_pricing_dat. " Doc Date(Received/Sent)

* If Pricing date is not Provided , then use the Current date for Pricing

  ELSE.

  lk_komk-prsdt     = sy-datum.       “Pricing and exchange Date
  lk_komk-fbuda     = sy-datum.       “Services rendered Date
  lk_komk-fkdat     = sy-datum.       “Billing index & printout date
  lk_komk-erdat     = sy-datum.       “Record Created date
  lk_komk-audat     = sy-datum.       " Doc Date(Received/Sent)

ENDIF.

lk_komk-vbtyp      = ‘C’.           " SD document category
lk_komk-werks      = v_werks.           " Plant
lk_komk-zzp_caltyp = ‘P’.
lk_komk-hityp_pr   = ‘Z’.
lk_komk-auart_sd   = ‘ZSOR’.
lk_komk-trtyp      = ‘H’.
lk_komk-kokrs      = XYZ.   “this is Controlling Area of the Client

lk_komk-taxk1      = 1.

Also Check: Do all ABAPers know Fixed Point Arithmetic?

Get the Customer hierarchy Number

Data: li_cust_hierarchy TYPE STANDARD TABLE OF vbpavb INITIAL SIZE 0,

CALL FUNCTION 'SD_CUSTOMER_HIERARCHY_PATH'
    EXPORTING
      customer        = im_kunnr
      date            = sy-datum
      htype           = ‘Z’
      sales_channel   = im_vtweg
      sales_division  = im_spart
      sales_org       = im_vkorg
    TABLES
      hpath           = li_cust_hierarchy

 * Read the table to get the customer hierrarchy 1
  READ TABLE li_cust_hierarchy INTO lk_cust_hierarchy
                               WITH KEY histunr  = 1.
  IF  sy-subrc EQ 0.
    Lk_komk-hienr01 = lk_cust_hierarchy-kunnr.
  ENDIF.

* Read the table to get the customer hierrarchy 2
  READ TABLE li_cust_hierarchy INTO lk_cust_hierarchy
                               WITH KEY histunr  = 2.
  IF  sy-subrc EQ 0.
    lk_komk-hienr02 = lk_cust_hierarchy-kunnr.

* Read the table to get the customer hierrarchy 3
  READ TABLE li_cust_hierarchy INTO lk_cust_hierarchy
                               WITH KEY  histunr  = 3.
  IF  sy-subrc EQ 0.
    lk_komk-hienr03 = lk_cust_hierarchy-kunnr.
  ENDIF.

* Read the table to get the customer hierarchy 4
  READ TABLE li_cust_hierarchy INTO lk_cust_hierarchy
                               WITH KEY histunr  = 4.
  IF  sy-subrc EQ 0.
    lk_komk-hienr04 = lk_cust_hierarchy-kunnr.
  ENDIF.

If the customer is supposed to receive retail pricing, check condition ZS22 to see if C2, CC and/or RX items should also be Retail Priced.

  IF lk_komk-kalks = 'A' OR
     lk_komk-kalks = 'C' .

*  Check to see if the Customer is supposed to get Retail Pricing
    SELECT * FROM a904 INTO TABLE li_a904
       WHERE  kappl =  c_kappl " Value 'V'
          AND kschl =  c_kschlzs22
          AND vkorg =  lk_komk-vkorg
          AND vtweg =  lk_komk-vtweg
          AND kunnr =  lk_komk-kunnr
          AND kondm IN (c_cc, c_c2, c_rx )
          AND datbi GE lk_komk-prsdt
          AND datab LE lk_komk-prsdt .

    IF sy-subrc = 0 .
      LOOP AT li_a904 INTO lk_a904 .
*  Check to make sure the conditions are not deleted
        SELECT SINGLE * FROM konp INTO lk_konp
                                  WHERE knumh    = lk_a904-knumh
                                  AND   loevm_ko = ' ' .
        IF sy-subrc EQ 0.
*  Set an 'X' if retail pricing should be executed.
          CASE lk_a904-kondm .
            WHEN c_c2 .
              MOVE c_charx TO lk_komk-zz_c2_retail .
            WHEN c_cc .
              MOVE c_charx TO lk_komk-zz_cc_retail .
            WHEN c_rx .
              MOVE c_charx TO lk_komk-zz_rx_retail .
            WHEN OTHERS.
          ENDCASE.
        ENDIF.
      ENDLOOP .
    ENDIF.

    CLEAR lk_konp.

*  Check the Chain for any MPGs not found at the Customer.
    IF lk_komk-zz_c2_retail IS INITIAL OR
       lk_komk-zz_cc_retail IS INITIAL OR
       lk_komk-zz_rx_retail IS INITIAL .

      SELECT * FROM a931 INTO TABLE li_a931
         WHERE    kappl =  c_kappl   " Value 'V'
            AND kschl   =  c_kschlzs22
            AND vkorg   =  lk_komk-vkorg
            AND vtweg   =  lk_komk-vtweg
            AND hienr02 =  lk_komk-hienr02
            AND kondm IN (c_cc, c_c2, c_rx )
            AND datbi GE lk_komk-prsdt
            AND datab LE lk_komk-prsdt .

      IF sy-subrc = 0 .

        LOOP AT li_a931 INTO lk_a931 .
*  Check to make sure the conditions are not deleted
          SELECT SINGLE * FROM konp INTO lk_konp
                                    WHERE knumh    = lk_a931-knumh
                                    AND   loevm_ko = ' ' .

          IF sy-subrc EQ 0.
*  Set an 'X' if retail pricing should be executed.
            CASE lk_a931-kondm .
              WHEN c_c2 .
                MOVE c_charx TO lk_komk-zz_c2_retail .
              WHEN c_cc .
                MOVE c_charx TO lk_komk-zz_cc_retail .
              WHEN c_rx .
                MOVE c_charx TO lk_komk-zz_rx_retail .
              WHEN OTHERS.
            ENDCASE.
          ENDIF.
        ENDLOOP .
      ENDIF.
    ENDIF.
  ENDIF.

* Check to see if the Zero Percent Flag should not apply to this customer Check the Sold-to.

  CLEAR lk_konp.

  SELECT SINGLE * FROM a918 INTO lk_a918
      WHERE kappl =  c_kappl
        AND kschl =  c_kschlzszp
        AND vkorg =  lk_komk-vkorg
        AND vtweg =  lk_komk-vtweg
        AND kunnr =  lk_komk-kunnr
        AND datbi GE lk_komk-prsdt
        AND datab LE lk_komk-prsdt .

  IF sy-subrc = 0 .

*  Check to make sure the conditions are not deleted
    SELECT SINGLE * FROM konp INTO lk_konp
                              WHERE knumh    = lk_a918-knumh
                              AND   loevm_ko = ' ' .
    IF sy-subrc EQ 0.
      lk_komk-zzzero_perc_flx = c_charx.
    ENDIF.
  ENDIF.

*  If the flag is not set, check the Chain
  IF lk_komk-zzzero_perc_flx = ' ' .

*  Check the Chain
    SELECT SINGLE *  FROM a935 INTO lk_a935
        WHERE kappl   =  c_kappl
          AND kschl   =  c_kschlzszp
          AND vkorg   =  lk_komk-vkorg
          AND vtweg   =  lk_komk-vtweg
          AND hienr02 =  lk_komk-hienr02
          AND datbi   GE lk_komk-prsdt
          AND datab   LE lk_komk-prsdt .

    IF sy-subrc = 0 .

*  Check to make sure the conditions are not deleted
      SELECT SINGLE * FROM konp INTO lk_konp
                                WHERE knumh    = lk_a935-knumh
                                AND   loevm_ko = ' ' .
      IF sy-subrc EQ 0.
        lk_komk-zzzero_perc_flx = c_charx.
      ENDIF.
    ENDIF.
  ENDIF.

*  Check the Customer Group if the zero percent flag is not filled
  IF lk_komk-zzzero_perc_flx = ' ' .

*  Check the Customer Group
    SELECT SINGLE *
      FROM a906
      INTO lk_a906
      WHERE kappl   =  c_kappl
        AND kschl   =  c_kschlzszp
        AND vkorg   =  lk_komk-vkorg
        AND vtweg   =  lk_komk-vtweg
        AND kdgrp   =  lk_komk-kdgrp
        AND datbi   GE lk_komk-prsdt
        AND datab   LE lk_komk-prsdt.

    IF sy-subrc = 0 .

      CLEAR lk_konp.
*  Check to make sure the conditions are not deleted
      SELECT SINGLE * FROM konp INTO lk_konp
                                WHERE knumh    = lk_a906-knumh
                                AND   loevm_ko = ' ' .
      IF sy-subrc EQ 0.
        lk_komk-zzzero_perc_flx = c_charx.
      ENDIF.
    ENDIF.
  ENDIF.

Fill the Item Communication structure KOMP

Move the corresponding field of MVKE and MARA to the item communication structure.

MOVE-CORRESPONDING:  MVKE TO lk_komp,
MARA TO lk_komp.
IF im_vrkme IS NOT INITIAL.   “ From Import parameter
lk_komp-meins      = im_vrkme.
lk_komp-lagme      = im_vrkme.
lk_komp-vrkme      = im_vrkme.
lk_komp-kmein      = im_vrkme.
ELSE.
lk_komp-vrkme      = mara-meins.
lk_komp-meins      = mara-meins.
lk_komp-lagme      = mara-meins.
lk_komp-kmein      = mara-meins.
ENDIF.

lk_komp-mglme        = im_mglme.    " Quantity From Import parameter
lk_komp-kpein        = im_mglme.    " Quantity
lk_komp-werks        = v_werks.     " Plant
lk_komp-bwkey        = knvv-vwerk. " Plant

* Get the vendor from theSource List
SELECT lifnr        " Vendor Number
FROM eord           " Purchasing Source List
INTO lv_lifnr
UP TO 1 ROWS
WHERE matnr = p_p_im_matnr
AND werks = p_v_werks
AND flifn = c_flag
AND vdatu LE sy-datum
AND bdatu GE sy-datum.
ENDSELECT
lk_komp-zzvendor     = lv_lifnr.      " Vendor

lk_komp-kposn        = '000010’.       " Condition item number
lk_komp-matnr        = im_matnr.    " Material Number
lk_komp-pmatn        = im_matnr.    " Material Number
lk_komp-zzdemand_matnr = im_matnr.
lk_komp-mgame        = im_mglme.    " Quantity
lk_komp-prsok        = ’X’.         " Pricing is OK
lk_komp-umvkz        = 1.           " Numerator for conversion
lk_komp-umvkn        = 1.           " Denominator for Conversion
lk_komp-taxm1        = 1.           " Tax classification material
lk_komp-use_multival_attr = ‘X’.   " Use Multivalue Attributes
lk_komp-zzbismt  = mara-bismt.
lk_komp-zzmtpos  = mvke-mtpos.
lk_komp-wkreg    = t001w-regio.   " Region
lk_komp-kursk    = 1.
lk_komp-prsfd    = ’X’.             " Carry out pricing
lk_komp-evrwr    = ’X’.             " Determine cost
lk_komp-prodh1   = mvke-prodh+0(4). " Product Hierarchy1
lk_komp-prodh2   = mvke-prodh+4(4). " Product Hierarchy2
lk_komp-prodh3   = mvke-prodh+8(4). " Product Hierarchy3
lk_komp-zzprodh2 = mvke-prodh+8(3).
lk_komp-zzprodh2+3(1) = 0.
lk_komp-zzprodh3 = mvke-prodh+8(4).
lk_komp-zzvkorg  = im_vkorg.        “ From import parameter

lk_komp-zzmmsta = marc-mmsta.    " Material Status

lk_komp-prctr   = marc-prctr.    " profit centre
lk_komp-zzndc10 = mean-ean11.

* Get the Default item category for the document

CALL FUNCTION 'RV_VBAP_PSTYV_DETERMINE'
EXPORTING
t184_auart          = ‘ZSOR’  " ZSOR value
t184_mtpos          = mvke-mtpos
t184_uepst          = ' '
t184_vwpos          = ' '
vbap_pstyv_i        = ' '
IMPORTING
vbap_pstyv          = lv_pstyv
EXCEPTIONS
eintrag_nicht_da    = 1
pstyv_nicht_erlaubt = 2
OTHERS              = 3.

IF sy-subrc EQ 0.

* Sales document item category
lk_komp-pstyv = lv_pstyv.

* Get the Schedule line item number
SELECT ettyp
INTO lv_ettyp
FROM tvepz
UP TO 1 ROWS
WHERE pstyv = lv_pstyv.
ENDSELECT.

IF sy-subrc EQ 0 .
* Get the Purchase Order type
SELECT SINGLE bsart
FROM tvep
INTO lv_bsart
WHERE ettyp = lv_ettyp.

IF sy-subrc EQ 0.
*  Set the indicator showing a dropship item
IF NOT lv_bsart IS INITIAL.
lk_komp-zzdscdisc = c_charx.     " Value 'X'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.

* Clear active price methods, net indicator, program and super net each time those are moved during MOVE CORRESPONDING.

CLEAR: lk_komp-zzkschl     ,
lk_komp-zznetbill   ,
lk_komp-zzsupernet  ,
lk_komp-zzprog_cd   ,
lk_komp-zzkschl_ret ,
lk_komp-vabme       ,
lk_komp-tragr       .

* Finally pass the Communication structure to call the Standard FM PRICING and get the accurate Pricing Values

CALL FUNCTION 'PRICING'
EXPORTING
calculation_type = ‘C’            " Carry out new Pricing
comm_head_i      = lk_komk
comm_item_i      = lk_komp
IMPORTING
comm_head_e      = lk_komk
comm_item_e      = lk_komp  “ change value will be returned
TABLES
tkomv            = i_tkomv
EXCEPTIONS
OTHERS           = 0.

After execution of the standard FM PRICING.

PRICING Function Module

All the condition type and their corresponding values will be populated in the table parameter of the PRICING FM.

FM Pricing

Output from standard Order

VA01 Sales Order

Sample output of the FM after execution.

Enhance Pricing

The output which is prepared from the table parameter TKOMV of the standard FM PRICING.

Do not miss this: Ready Reckoner for SAP Developers. SD, MM, FI flow and tables for ABAPers.

Function Modules and Tables to Remember that are used in this Z function Module

Function Modules:

  1. ‘PRICING_REFRESH’ called before calling the FM ‘PRICING’ to refresh the Pricing values if anything exists.
  2. KNVV_SINGLE_READ  to get the Customer Master Sales Data
  3. MARA_SINGLE_READ  to get the Material master data
  4. MVKE_SINGLE_READ to get the Sales Data for Material
  5. RV_VBAP_PSTYV_DETERMINE to get the item category
  6. SD_CUSTOMER_HIERARCHY_PATH to get the customer hierarchy
  7. PRICING to get the customer and material Pricing
  8. SD_CONDTAB_SELECT to get the start date and end date of the condition record number to populate in the output.

Table used to get the Accurate Pricing of Customer and material:

KONH T001W MVKE A935
KNVV MARM KONP A906
MARA T683V A904 TVEP
MARC KNA1 A931 TVEPZ
MEAN KNB1 A918 LFA1

Point to remember

Either we have to populate all the fields of the communication structure (Header and Item) manually that are populated in the standard USER Exits or some how we have to call the below USER Exits to get the accurate pricing of the Customer and material.

  • USEREXIT_PRICING_PREPARE_TKOMK
  • USEREXIT_PRICING_PREPARE_TKOMP.

We know you do not want to see 100 of lines of codes on our blog. But being a technical blog, sometimes we take the liberty to flood you with ABAP codes and syntax. 🙂 . Please bear with us. This FM is an outcome of a request from a genuine reader. Since one of our readers was getting benefitted offline, therefore we thought of publishing it so that, few other ABAPers in need might get some lead and help at the time of distress.

The custom FM might look simple and straight forward, but while trying to figure out the logic and build them, it took quite some time for us. Hope, you would not have to spend that many hours if you have a similar requirement.

So…What Do You Think?

Now we want to hear from you.

Do you think, this article explaining some custom logic for Pricing in helpful?

Whether you feel it is helpful or not, in either case, please leave a quick comment below.

Are you Fiori Ready? Check this end to end Fiori Implementation.

 


Viewing all articles
Browse latest Browse all 66

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>