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

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.

 


How to Add and Change PO Service Line using BAPI BAPI_PO_CHANGE?

$
0
0

Services Tab in PO screen (ME23N) is one of the dreaded tabs by most ABAPers. Whenever there is a requirement to add, delete or modify the items of the PO Services, I found, most ABAPers take the safest path of BDC? But Why?

In one of the projects, I remember, I used BDC for PO Services, because I was not able to link the PO Pack No to the Service Items.

You might also like to read this: UnPack the Pack Numbers in SAP.

With experience, everyone grows. The same happened with me too. In my current project, when I got the requirement to modify the PO Service Item, I was determined to complete it using BAPI. As usual, I faced some hiccups, but at the end of the tunnel, I saw the light. 🙂

I had two requirements.

  1. Edit existing PO Service Item.
  2. Add a new item in the PO Service.

bapi_po_change

Actual Requirement: We need to look for all Services Line Items where the Quantity and Actual Quantity columns are NOT equal. In the image above, for Service Line 10, the Quantity is 12 while the Actual Quantity is 9.293. Since the Quantity and Actual Quantity are different, we need to split this line into two lines.

1. Modify Service Line 10:

Line 10 would have Quantity as 9.293 and Actual Quantity as 9.293 (i.e. the actual quantity is copied to the quantity column).

2. Add new Service Line say 80 (assuming already there are lines till 70)

New Service Line 80 would be added with the difference in Quantity and Actual Quantity i.e. 2.707. (12 – 9.293 = 2.707). Quantity Column will have value 2.707 while Actual Quantity would be set to 0.000.

Similarly, Line 20 would be modified to have Quantity and Actual Quantity as 9 and a corresponding new Service line say, 90 would be added with Quantity as 3 i.e (12 -9 = 3) and Actual Quantity as 0.000. And same logic has to be applied to all Service lines which have a difference in the Quantity and Actual Quantity.

Hopefully, the technical requirement is clear. Let’s get into work.

Step 1: Get the PO details using BAPI_PO_GETDETAIL1.

My requirement was only to get Services and Account Assignment Category for BAPI_PO_CHANGE.

  call function 'BAPI_PO_GETDETAIL1'
      exporting
        purchaseorder      = wa_ekko-ebeln
        account_assignment = 'X'
        item_text          = 'X'
        header_text        = 'X'
        services           = 'X'
      importing
        poheader           = poheader
      tables
        return             = it_return
        poitem             = it_poitem
        poschedule         = it_poschedule
        poaccount          = it_poaccount
        poservices         = it_poservices
        posrvaccessvalues  = it_posrvaccessvalues.

Step 2: Fill the data for PO Header.

perform fill_header_data.  "ekko data passing here

Step 3: Exclude the Deleted PO Items and prepare the item[ ] table for the PO.

delete: it_poitem where delete_ind = 'L',
        it_esll1  where del = 'X'.

    loop at it_poitem into wa_poitem .
      perform fill_item.  “filling the item details.
      read table it_esll into wa_esll with key packno = wa_poitem-pckg_no.

      if sy-subrc = 0.
        loop at it_esll1 into wa_esll1 where packno = wa_esll-sub_packno.         

         if wa_esll1-act_menge ne 0.
            if wa_esll1-menge gt wa_esll1-act_menge.
              val = wa_esll1-menge - wa_esll1-act_menge.
              perform fill_po_data_new_bapi .
            endif.
        endif.
          clear: wa_esll1,val.
        endloop.
        clear: wa_esll1, lv_introw,lv_extrow,wa_poitem.
      endif.
    endloop.

Step 4: Populate details about Services and Account Assignment Category tables.

perform fill_po_data_new_bapi.

The Trickiest part of the development was to find the Account Assignment Category for the Service line item and mapping that Account Assignment Category to POACCESSVALUES[ ] table of the BAPI.

This is the HEART of the development work. And therefore, this is the core of this article. If you falter on this mapping, your BAPI would never do what you are expecting. So do not doze. Keep your mind and eyes open. 😀

4.1 Pass the Sub Pack Number and Internal Line Number of the Sub Line Item to the table ESKL and pick the ZEKKN. (For linking, this part is very very important). We cannot stress more. 😀

linking package number in po

4.2 Pass the EBELP and ESKL-ZEKKN to the table EKKN(Account Assignment Category)

Account Assignment Category

You will get all the details of copied row so that you can pass the details and create a new sub line item.

How to edit Service Line Item

Also Read: Decode the Standard Service Catalog Item of Service Master (ASMD-STLVPOS)

Taking a deeper look at the HEART of the Program/Development:

PO_ITEMS[] :

ITEM    |   PACKAGE NO

10      |   10001  (Parent Package No)

PO_ACCOUNT[]:

ITEM | SERIAL | QUANTITY | GL         | COST CENTRE| PROFIT CEN……….

10   |    01  |   100    | 45245      |  1452      | ……

PO_SERVICES[]:

PCKG NO  |  LINE NO   | EXT LINE  |  OUT LINE | SUB PCKG NO

10001    |  0000001  |   0000000 |     0             |  10002   (child package no)

10002    |  0000002  |   0000010 |     0             |  00000  |

10002    |  0000006  |   0000070 |     0             |  00000  |

SAP ABAP Training Free

PO_SERVICE_ACES_VALUES[]:

Here we need to Link the Account Assignment Category (i.e. GL , Order id, etc info ) to the changing Service Line Items (Need to assign the line which is modified (Service Line 10) and the new Service Line 80 which is added)

Correct mapping is very crucial. If we map right, the GL related info will be attached to the new sub line items correctly.

GL related info will be attached to the new sub line items

PO_SERVICE_ACES_VALUES[]:

PCKG NO  |  LINE NO  |   SERNO_LINE  | PERCENTAGE | SERIAL  | QUAN   | ……….

00002    |  0000002  |   01          |   100      |  01 (already highlighted above)|

00002    |  0000006  |   01          |   100      |  01

If you map the above Heart of the development correctly, your Service Line Item would be changed and added seamlessly.

Before executing our Conversion Program.

What is ABAP?

After executing our Conversion Program.

BAPI_PO_CHANGE

I am confident, with the above hints, ABAPers would be able to get the mapping straight and can add, delete or modify any PO Service using the BAPI. Bye bye BDC. 🙂

We know you do not need to be spoon fed. But we are attaching a demo program which does exactly what we explained above. Please note, it is just a prototype program. It has not passed any quality review. So, you will find better ways to write the code, but in case you need to refer to how we have mapped and linked the packages, serial numbers, and G/L account, the attached code below might be useful.

Code Snippet: Download the complete code from here.

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

So…What Do You Think?

Now we want to hear from you.

Do you think, this article is helpful?

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

 

SAP CoPilot – SAP’s own Digital Assistant Introduction

$
0
0

SAP CoPilot – Inspired by the flood of articles and knowledge share, I thought of writing one article on a new topic which I recently experienced. It was a very interesting learning opportunity for me and it threw me to a completely new ball game. I am amazed by the progress and the impact technology has in every arena of life and work. I am really mesmerized with the SAP CoPilot concept.

Let me take the liberty to humbly introduce (although, there are many articles on this topic already) you all to the product launched by SAP which is christened as “SAP CoPilot”, an SAP Digital Assistant. If someone uses the jargon DA to show off, you now know DA stands for Digital Assistant. 😛

Disclaimer: I am not an expert in SAP CoPilot but just a beginner and an enthusiast.

SAP CoPilot is the first ever digital assistant for any Enterprise and not only for SAP. SAP CoPilot helps to collaborate, support issue resolution and follow-ups and helps in taking immediate preventing and/or corrective action efficiently.

As per SAP, the first version of SAP CoPilot 1705 has the below capabilities:

  • Take Notes: While working with the SAP Fiori Apps, users can take notes and SAP CoPilot would link  them to the App and show them if the user looks for the notes when they return to the App later
  • Capture Screen Prints: SAP CoPilot can help you take the screen shots of Fiori Apps (very helpful for documentation). 😀
  • Recognize Business Object: SAP CoPilot recognizes business objects referred to in or chats or notes.
  • Take Quick Action: If needed, SAP CoPilot can automate the process of creating business objects quickly.
  • In-Context Chat: Chat with your partners from the business application context you are working with and share screen captures, note and business objects.

I have not explored all the capabilities mentioned above but being an ABAPer one feature which I found very useful is, using SAP CoPilot, we can automatically execute any Fiori App in the background, without even opening that particular App.

Also Read: Some Famous Success and Failure SAP Implementation Stories.

You can correlate SAP CoPilot to Google Allo or Siri in iPhone or Amazon Alexa or the most recent Samsung’s Bixby, though it is not exactly same. But conceptually they are similar. Using SAP CoPilot, users can chat, ask questions and even give commands like a Boss would give to his/her Personal Assistant. 😛

So, the first question is Where is SAP CoPilot available?

Ans: It is available in the Fiori Launchpad (SAP Fiori 2.0), as a component.

Next question is What are the pre-requisites?

Ans: SAP CoPilot requires either S/4HANA or NetWeaver 7.51.

And now, How it works?

SAP CoPilot can run your Fiori Apps, through Voice Recognition Technique or by directly chatting with it.

For example, we can directly ask SAP CoPilot to create a Purchase Order or any other SAP business objects. And like the faithful genie, it obeys. As you wish my master. 🙂

Also Read: End to End Implementation of Fiori App.

Hope this short post is enough to introduce you to another wonder of technology and science. In the next article, I will tell you how to get CoPilot into the Fiori Launchpad along with some more interesting features. Please stay tuned.

Before we sign off today, I would like to show you a sample SAP CoPilot screen from my Prototype System. Have fun.. 🙂

SAP CoPilot Introduction

So…What Do You Think?

Now we want to hear from you.

Do you think SAP CoPilot would have a long flight or will it have to do an emergency landing?

Whether you feel positive or negative, in either case, please leave a quick comment below and see how other’s opinion on this topic.

How to Execute a Report Always in Background mode, even on Press of Function Key F8?

$
0
0

Always run the report in background mode even on the press of F8? You might feel, what’s the big deal?

Just schedule a background job and you are good. You do not need to handle it in your program. But sometimes clients have different plans. They know that scheduling the job in the background would be the smartest solution, but still, they would insist that they might run it in the foreground through the custom t-code but even then, the program should execute in background mode. Crazy clients sometimes. But, the Client is God, therefore we cannot argue much with God. 🙂

Our solution to this requirement is to create a custom report and all the option to run the program in foreground mode will be disabled. Even whenever the user would press the F8 function key or click on the execute button even then the program will show the option to run in background mode.

Layout design, Logic implemented and step by step process to produce the output

Create a report program using the Tcode SE38. Here the report created is ZR_BACKGROUNG_CHECK. To enable the execute button to work as background run, we have to write the code in the event AT SELECTION SCREEN.

We need to assign the value ‘SJOB’ which is the Function Code for the batch job to the SSCRFIELDS-UCOMM where the value is either ‘ONLI’ or ‘EXEC’.

System field SY-UCOMM will hold the value ‘ONLI’ when the user will either click on the execution button or press the function key F8.

Also Read: Write your first program in HANA ABAP.

The Function Code ‘EXEC’ is defined inside the custom PF-STATUS which is explained below.

SAP ABAP

In the INITIALIZATION event, we need to create a custom PF-STATUS. The idea behind creation of the PF-STATUS is to customize the PF-STATUS for Selection Screen.

Sample Code:

free sap training

Double click on the INITIALIZATION event and inside this create the custom PF-STATUS. Here the PF-STATUS created is ‘ZCUSTOM’.

Sample Code: PF Status

Double click on the PF-STATUS name and it will ask to create one like below screen, click on yes button.

abap program in background

Provide a short text and press enter.
GUI Status for Selection Screen

Then the below screen will appear, here we need to go to menu bar Extras->Adjust template.

Extras->Adjust template.

Choose the SelectionScreen radio button from the template list given below screen shot and then press enter.

Adjust Template Status

You can find to see the below screen shot where we need to keep only the required function codes and have to remove others.

sap application tool bar function codes

Keep only these Function Codes given in the below screen shot. Here we have changed the function code name ‘ONLI’ to ‘EXEC’ and have kept the function key same that is F8.

PF Status in SAP

Also Check: Problem faced by ABAPer while working on the first SAPUI5 Development.

Activate the PF-STATUS and the report, upon the execution of the report we can see the 3 buttons that we have given in PF-STATUS.

program in background mode

In the below screen shot you can see the from the program menu we have disabled the ‘Execute’ and ‘Execute and Print’ option.

program menu in sap

Sample code:

In the event AT SELECTION-SCREEN OUTPUT, we need to write the below logic to exclude these 2 function code from the program menu.

FORM f_disable_foreground_run.

* Local Type Declaration
TYPES: BEGIN OF lt_ucomm    ,
ucomm TYPE sy-ucomm,
END OF lt_ucomm      .

* Local Internal Table and WorkArea Declaration
DATA : li_ucomm TYPE STANDARD TABLE OF lt_ucomm INITIAL SIZE 0,
lk_ucomm TYPE lt_ucomm.

* ‘ONLI’ is the Function code of Execution from Program menu
    lk_ucomm = 'ONLI'.

APPEND lk_ucomm TO li_ucomm.

CLEAR lk_ucomm.

* ‘PRIN’ is the Function code of Execution from Program menu
lk_ucomm = 'PRIN'.

APPEND lk_ucomm TO li_ucomm.
CLEAR lk_ucomm.

* Call FM to exclude the function from PF Status
CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
EXPORTING
p_status  = 'ZCUSTOM'
TABLES
p_exclude = li_ucomm.
ENDFORM.                    " F_DISABLE_FOREGROUND_RUN

Activate the report, execute the report, and feed the selection criteria and then either press F8 or click on the execution button you can see the below screen that we get for background run.

Background mode in SAP

 Choose the schedule option from the below screen then press the save button.

 You can see the scheduled job and result using the Transaction code SM37.

 Point to remember: PF-STATUS must be activated before executing the report.

Also Read: Create your First OData Service in 5 minute.

You might be doing UI5 development or Fiori implementation or might be working in the in-memory database HANA. But, sometimes, the need of the customer only need plain vanilla ABAP. Those moments are special where you need to provide the innovative solution which is just right for the clients using the age old ABAP. And did anyone try to scare you, with all machine learnings(ML) and artificial intelligence(AI) and Automation, ABAPers would die?

But we at SAPYard feel, with all those automation, the need for ABAPers would grow more. Afterall, who is going to do those ML, AI and Automation programming. 🙂 . And who is going to support and sustain those crazy innovations? Long live the ABAPers. 😛

So…What Do You Think?

Now we want to hear from you.

What do you think? Are ABAPers going to be extinct in near future?

Whether you feel yes or no, in either case, please leave a quick comment below.

How to Print Vertical Bar Code in SAP Forms?

$
0
0

We all know, SAP is an ocean and we find hidden treasures every other day. A few days back, I got a requirement from my client to print Bar Code in the output form. I have worked in all printing technologies in SAP (SAP Script, Smartforms, and Adobe Forms), so I thought, this development should go to a beginner in SAP ABAP. Not to someone who has more than 12 years of SAP ABAP and CRM experience. I thought, what value would it add to my skill set?

Never the less, it was assigned to me. When I went through the requirement in details, they had mentioned in bold, the bar code should be printed Vertical. Oh man!! I was wrong. 12 years was not enough for me to learn everything in Forms in SAP. Probably, the whole life time would never be sufficient to completely swim over the SAP Ocean. Forget about diving deep. 😀

When I figured out that I have never done Vertical Bar Code, I sent out a note to few of my friends, if they have done Vertical Bar Code printing. As usual, all my contacts gave a negative help. :P. Last week Sunday, we celebrated Friendship day. What an irony? 🙂

Now I knew, my problem was my own and I needed to find the solution myself. And with a little research, I was able to deliver the product well ahead of time.

Before this, you can check Images, Graphics, and Logo in Adobe Forms.

This is what I did and how I printed the bar code vertically.

Transaction – SE73

Choose System Bar Codes and then Change button.

Bar Code in SAP

Create Bar Code using Create button.

Vertical Bar Code

It asks for New Bar Code Technology or Conventional System Barcode. Choose one as per your requirement.

Christen your Bar Code. I coined it as ZZVBC.

Use any of the Bar Code Symbologies, this will determine the type of Bar Codes.

Now choose Bar Code Alignment, this is the most important part as this will determine whether the Barcode will become Vertical or Horizontal.

“Rotated”, makes your bar code Vertical. This is the trick which I wanted to share in this article. 😛

By the way, did you check our Tutorial about JavaScript in SAP Adobe Form?

We at SAPYard always say solutions in SAP are not complex. But reaching to that simple solution, i.e. finding that solution is the difficult part and time-consuming part.

Now choose the height & width of the Bar Code.

If you did not believe my words that Rotate would create Vertical Bar Code, then this screen would confirm it.

Save it in some transport and use it wherever you need it.

I have used in one of my forms and it looks like below.

It is indeed Vertical Bar Code. 😀

This was a simple trick. Hope you would find it useful when you need it in some real project and no one in the team has ever worked in Vertical Bar Code.

Also Check: How I used SAP Adobe Form as my personal PDF editor?

Now, we want some tips from you. Do you have anything to share?

Nothing is small. Nothing is simple. Please email us your contribution at mail@sapyard.com and we would add you as a member and publish your articles in your name.

How to Add Customized Node in SPRO? 

$
0
0

Can we add our customized node in SPRO? 

You might love ABAPers or hate them. But you can never ignore them. Forget about imagining SAP World without ABAPers. Put all Artificial Intelligence you can. Or make everything 100 percent Automatic. But whenever the end user or business user or functional consultant need any custom enhancement, is there any alternative to the awesome SAP ABAP Developers? 🙂

In this post, we would talk about a simple yet very handy enhancement which makes the life of the Functional Experts easy by accommodating custom nodes in SPRO. (just a small proof of importance of ABAPers) 😛

Over the course of implementation, there would be many customized tables and I am sure most of the functional expert doesn’t want to remember the Customized Z table names which they need for master data maintenance.

So what is the alternative then?

Ans: Rather than finding their personal notes, documentations and searching for tables,  SPRO is one easy solution for them.

Here is a simple approach to Creating a Node in SPRO.

STEP1: Create a table ZTEST_SPRO in SE11.

Custom node in SPRO

Provide the Delivery Class C (customize table).

Maintain the fields and Technical settings.

Also Read: Configuring Adobe Forms in NACE, OPK8, and SPRO

STEP2: Create table Maintenance Generator.

SAP Tips

sap abap tutorial

STEP3: Maintain the entries in Table Go to T-code SM30.

spro customization
sap abap tutorial

Now we have one entry in table ZTEST_SPRO.

Did you notice, till now (step3), we have not done any enhancement yet? We just made the stage ready for us to play. 🙂

STEP4: Go to SPRO we will add our Node in Sales and Distribution node.

Sales and Distribution is just an example. You can choose any Node as per your requirement.

SPRO

STEP5: go to T-code SIMGH.

Mind it. It is not Singh of “Singh is King”. It is Simgh. 😛

T-CODE SIMGH

Click on F4 Help to find out our desire Node (Search by title as given below).

SPRO CONFIG

Select Sales and Distribution in search help.

Select SALES AND DISTRIBUTION in search help.

STEP6: Click on edit.

SPRO Customization

SPRO Enhancement

Click on English in pop up.

As you can see we have all nodes under sales and distribution.

Also Check: SAP Fiori – System Check, Installation, and Configuration

STEP7: Select Sales and distribution and click on insert structure node (circled on above image) as sub node and give the description.

SUB NODE In spro

So our node appeared here now let’s add our Customize table in this node.

STEP8: Select Test Node Workflow and click on “Activity” icon highlighted below.

STEP9: Maintain the details as given below and create the “documentation” by hitting create button.

SPRO Documentation

Enter some details in the document.

how to maintain documentation in SAP?

STEP10: In Maintain Object Tab. enter the below entries.

maintain object in SPRO

Maintain Type – “S” table with text table.

So finally we have our added node in Tree. Now save the changes.

For a change, let me ask you something. Are you HANA Ready?

Let’s test our scenario. Go to T-Code SPRO.

Follow the path Sales and Distribution–> Test Node Workflow–>Test Workflow User Details.

Enhancement in SPRO

So we have our table here to play with. No need to remember neither the t-code nor the table name. Isn’t it convenient? 🙂

This is the simple solution which we provided to our Happy Business Users and Functional Consultants.. 🙂 Hope you found it useful.

Have you provided any custom tool or trick to your Business Users?

We want to hear from you. Please leave your quick comment below. If you have any question for me, please feel free to mention it too.

Modify the Run-Time Value of Workflow Containers. Part-1

$
0
0

Do you know how to modify the content of workflow containers at run-time?

This means you can actually modify and manipulate the workflow runtime values after the workflow has triggered and the work items are created.

Got Confused?

Ignore the previous lines 🙂

Before learning about how to modify the run-time value of workflow containers, we need to first understand the business requirements that force any one to manipulate the workflow container value at run-time. The manipulation can have a number of uses, in our post, we will learn about two simple scenarios that will help us to understand the concept.

Note: We have divided this tutorial into two parts, for the ease of the readers.

Business Requirement :

For example, we have a workflow that contains a total of 3 steps.

Please have a look.

Now let’s imagine that some how step 2 went to error state that caused the workflow to not complete.

Now if you are new to workflow, your first Question will be why it went to an error state?

There could be various reasons for that and let me point out 2 reasons that are related to this post.

  • The Workflow was not able to get the desired data and it got terminated.
  • The Values in the Workflow containers were not populated at run-time or wrongly populated and it got terminated.

Also Read: Install your SAP System for Free on your Personal Computer.

We want to first show you the comparison between above two scenarios. Let’s discuss one by one both scenarios discussed above.

(A) The Workflow was not able to get the desired data and it got terminated.  

Let us imagine that the step number 2 was fetching some data from the database and if data is not found, Step 2 is configured to want to be in an error state.

A real time example for you guys :

Let us take a purchase order workflow that is fetching the agent list from a ZTABLE and it is configured to fail when there is no agent/id found.

You can see in the below picture how workflow was not able to fetch any agent from the database and it went to an error state.

How to Solve this issue?

Now if you want to solve the issue you need to maintain the data and again need to restart the workflow using t-code SWUS. Let’s maintain the missing data and restart the workflow.

Want to learn how to restart the workflow? Please visit  How To Restart a Workflow in SAP.

After restarting the workflow.

See for yourself, the workflow was restarted and it generated a new work item.

Note: When the workflow was restarted, it generated a new work item and the whole process restarted again from the beginning.

So, what if you want to restart the workflow that is in error status due to data issue and also you want that NO new work item should be generated ie. the workflow should restart from the point where it went in error.

Then you need to use the transaction SWPR.

Present Scenario :

Desired scenario :

Also Check: How to Debug any Work Item in SAP Workflow?

Conclusion :

What have we understood till now?

If the workflow went to error state due to some data issue then,

  • We can normally restart the workflow using transaction SWUS but doing so will generate a new work item and the whole process, Previous steps that were already completed will be again executed.

What if there are more than 10 steps in workflow and workflow went to error state at the 9th step?                 

Isn’t it frustrating that again the same users for step 1- 8 will receive the new work item for the same document and they will execute the same steps again to complete the same work and also  in future, the user will need to delete the old work item from his workflow inbox because it is of no use.

                                                                      Totally frustrating 🙁

  • Now let us assume that workflow was restarted from the transaction SWPR, then no new work item is generated and the workflow is restarted from the point where it went to error.

 Great 🙂

Now please visit the next part of the post where we will see the scenario when the workflow went to error state because the values in the workflow containers were not populated at run-time or wrongly populated.

Please visit TheSharpTurtles for more Workflow Tutorials.

Modify the Run-Time Value of Workflow Containers. Part-2

$
0
0

I hope our previous article “Modify the run-time value of workflow containers Part 1” helped you understand the pros and cons of restarting a workflow when it goes into an error state due to the data issue. But what if the workflow went to the error state due to missing container value or workflow behaved wrongly due to wrong container data

Before we start let us just try to understand what is a Container in terms of workflow.

Container: For now just imagine Container as a bucket that holds the data and at runtime, workflow gets the required/operational data from this bucket. Easy right? 🙂See for yourself how the workflow container holds the data.

Now just take a look at a real time example that will show you how a missing container value forced the workflow to go into the error state.

In the below image, you can see that the workflow went to error and the workflow log reveals that workflow container is missing some data due to which the workflow failed.

If we debug the error work item, we will come to know which element/data is missing in the container. For this example, after debugging the work item we came to know that the release code was missing in the workflow container

To know how to debug a work item in sap workflow click here: How to Debug a Workitem in SAP

Let’s have a look at Some of the debugging snapshots :

Note: These snapshots are just giving you a glimpse of a real time scenario. 

Now here comes the best part. Let’s restart the workflow just like we did in the first scenario when the workflow went to error state due to a data issue.

Also Read: Did you check our first SAP Yard-athon Contest?

How do I Restart?

Find out more: How to Restart a Workflow

The first method will be using transaction SWUS to restart the whole workflow from the starting.

  • Doing so will again execute the whole workflow steps from the starting and the previously completed task will again restart that needs to be completed by the agents of the respective workflow task.
  • Using SWUS, restarting the workflow will not give you the guarantee that this time the missing/wrong values will be present in the workflow container. It may be possible that container values are not getting populated due to some database issue. If you are lucky enough then restarting the workflow can work but there is no guarantee that restarting the workflow will solve the issue.

 You can not do any thing here 🙁

  • Restarting the workflow using SWUS will again generate a new work item in the user’s inbox. Previous step users will need to again perform the same work with the new work item. Previous step user can get frustrated doing the same job again and again. Believe me, I have seen how users get angry when they get the new work item for the same task. 😛 Creating a new ticket to delete the old work item from their inbox comes as additional job for them and what if restarting the workflow again not solved the issue and previous step user again gets the new work item to complete. 🙂

So, are you going to restart the workflow, again and again? Generating a new work item each time and what if the issue is not solved?

The second method will be Using transaction SWPR to restart the workflow from the point where it went to an error state.

       Thank God, Restarting the workflow using the transaction SWPR will not generate a new Workitem 🙂

Let us do that and see whether this method would populate the missing container value or not.

Steps: Run the transaction SWPR and enter the work item that needs to be restarted from the step where it got stuck and press restart.

Wait…What ? The SWPR transaction is not able to restart the workflow. 

But Why? 🙁

Because, this time too, the missing container value is not present in the workflow container. 🙂 

Now I guess you have understood the purpose of comparing both the scenarios where workflow went into error state due to data issue and workflow went to error due to missing /container value.

   I know you are curious to learn how to resolve this missing container value thing.

SAP has provided a standard function module named ” SWL_WI_CONTAINER_MANIPULATE”

This powerful function module allows you to pass the work item ID of the step whose container you want to modify. You can display and edit the containers. In our case, the work item ID is 123456 and the release code is not populated.

Steps for changing the container value :

  • Run the transaction SE37 and execute the function module SWL_WI_CONTAINER_MANIPULATE

  • Enter the work item number whose container value needs to be modified and remove the display constant value ‘X’ so that you will be able to modify the container value. Then Execute.

  • Now you will be able to see the work item container values. Double click the container values whose data needs to be manipulated and modify the value.

  • Once you are done. Restart the workflow using SWPR or SWUS based upon the business need.

Here we are restarting the workflow using SWPR transaction since we do not want to generate a new work item again.

You can see that now after restarting the workflow, it restarted perfectly without going into an error state.

Reason: Because this time the missing container value is present in the workflow container and the workflow has received the container value at run time.

Seeing is Believing…

 

Hope you enjoyed reading this post and understanding the basic difference between Restarting the workflow using transaction SWUS and SWPR and also you came to know how to modify the container values at run-time?

For more workflow related posts visit my blog The Sharp Turtles.


Fetching Data from Memory Stack Using New Tool (in Debugger)

$
0
0

Many times we receive a requirement to add validations for standard transactions wherein the field value is not directly accessible in user exit or BADI. So if you are also struggling with such requirement, your wait is over. Prapti is here to your rescue. 😉

In this article, we will be learning a short and simple trick to access screen values in standard transaction code.

Basically, we would exploit the Memory Stack at Run-Time using the New Tool in Debugger. If in any interview, someone asks you, do you know Memory Stack Programming? After going through this article, your answer should be a big confident affirmative. 😛

Following are the steps that need to be followed:

  1. Get the program name and field data from the screen (using F1)
  2. Add a breakpoint in the exit / BADI
  3. Execute the transaction and check the value at runtime using New Tool (Tools -> Special Tool -> Loaded Programs)
  4. Add code in the exit / BADI for fetching data from the screen field

Seeing is Believing. Let me take a very simple real time practical example. While creating a purchase order in SAP, there is a provision to add one-time vendor details. Our requirement is to add a Validation on PINCODE length.

We were using CHECK method of BADI ME_PROCESS_PO_CUST for validation in PO. But found that the address details were not accessible in the BADI.

We followed the 4 steps mentioned above. We found the program name and field data.

Added the debugger and executed the transaction. In the debugger tool, go to New Tool option.

new tool in debugger

Alert: If your debugger takes you to Standard Tab by default, then you would not find the “New Tool“. Do not panic. Just click Desktop 1 or Desktop 2 or Desktop 3 and New Tool would be right there for your service. 🙂

Also ReadA to Z of Integration of SAP Ariba with SAP ECC

Go to Loaded Programs option in Special Tools.

Loaded Program

Select Global Data tab where we will be able to see all the global variables of each program.

New Tool in SAP

Let us now find the program and field for Address data.

Yeah, we got the ADDR1_DATA values. So now we reached the last step – the code :).

  FIELD-SYMBOLS:<fs1> TYPE any.

* Make the system know from which Program we need the data
  DATA:post_code(40) TYPE c VALUE '(SAPLSZA1)ADDR1_DATA-POST_CODE1'.

* Assign the value to a field system
  ASSIGN (post_code) TO <fs1>.

  IF  <fs1> IS ASSIGNED.
* Do your validation
    IF strlen( <fs1> ) NE '6'.
          MESSAGE 'Postal Code should be of length 6.' TYPE 'E'.
    ENDIF.

  ENDIF.

Basically, we just dug deep into the memory stack at the run-time and looked for all programs that were loaded in the system for completion of the particular transaction. Using the New Tool, we found the Global Data. Once you have the Global Data, you can just fetch that data in your program using Field Symbol.

Hope you like this trick. This is a simple solution which we need to do in every project. If you are a beginner on SAP ABAP, bookmark this article. You would need this for your first Memory Stack Programming. 😛

You can implement this same trick to fetch any global data like table, structures, variables, objects etc.

Note: There is a limitation. If the variable, work area, table etc are NOT declared as Global on the loaded programs, then we CANNOT retrieve its value using the above method.

Also Check: How to write your first Program in HANA ABAP?

Now I want to hear from you. Do you have any Tip or Trick to share?

Please do not shy away from sharing your knowledge. Together we learn better. Please leave your quick feedback below. Please Like Us on Facebook and Share our Contents.

Compilers, Assembler and Machine Code. Are they same?

$
0
0

Programmers and Consultants very frequently use Compilers and Assemblers jargons. We even interchange the usage as per our convenience. Are compilers, assemblers and machine code synonymous to each other? Unfortunately, No.

Are you one of the culprits who use these words to impress others? 😛

Let us take a step back and look into the history of the development of Programming Language and computer. We all know there are some generations of Programming Language.

1. First Generation Language (Machine Code)

Machine Codes are the First Generation Language which the Computers use. The first computer developed in the USA in Feb 1946 was as big as a standard living room (actual image below) and could only perform the calculations which the present day pocket calculator does. The first computer which was christened as ENIAC (Electronic Numerical Integrator and Computer) was popularly called the “Great Brian” by the then media/press.

Electronic Numerical Integrator And Computer

The first computer could be programmed in only one language i.e. machine code.

With the advent of other programming languages, are machine codes extinct?

No. Computers of even this day understands only machine codes. So whatever programming language you use, at the end when it communicates with the computer, it only used machine codes. As Computers only understand Machine Codes.

001D4680, 70143048, 30FC95F9 are some example of machine codes. Terrifying codes. Isn’t it? Now do not ask me what does it mean. 😀 I am not a computer. 😛

Do all computers talk the same machine code?

No. Every machine has its own machine code. The machine code depends on the processor used in the machine. You can say machine code is processor dependent.

For your curiosity, machine codes only use registers and distances(offsets). They do not use names for the variables.

Ex: ‘D202 5022 7089’ in S/370 Assembler means 3 Bytes addressed through Register 7, offset 89 has to be moved into Register 5 offset 22.

Also Read: Back to Basic

2. Second Generation Language (Assembler)

The first generation language was not user-friendly They were not easy to remember and understand. To surpass the problem, someone proposed the idea of replacing the machine codes with symbolic names covering one instruction each. They are called ‘mnemonics’.

In the second generation language, it became possible to use Symbolic names for the variables along with the first generation Registers. Offsets, i.e. distances were still supported but the system was able to partially calculate these distance by itself.

This mixture of first generation language along with symbolic names and auto calculation makes the second generation of computer language i.e. Assembler.

As any invention, the primitive (first release) Assembly language was not that advanced. But it made a very important introduction i.e. the idea of translating one language into another (symbolic commands to machine code). This concept is still used till date in each and every single computer system.

In an assembler, the translation of one language into another is done in the relation 1:1 (one is to one). What is typed into the machine by the programmer is exactly what is executed later.

Now the code ‘D202 5022 7089’ and command ‘MVC AFELD,BFELD’ do the same thing of moving couple of bytes.

3. Third Generation Language (HHigh-LevelProgramming Language like BASIC, COBOL, FORTRAN, C, PASCAL, PL/1, Ada)

The second generation Assembler was user-friendly. Then somebody got the idea to collect few commands into one command and make up a whole new language. Few sharp brains implemented this philosophy and thus the birth of programming languages like Ada, BASIC, C, COBOL, FORTRAN, PASCAL and PL/1 happened.

Now we needed a Compiler. Please note, Compiler and Assembler are two different things. Assembler has 1:1 relation while Compiler has 1: N relation depending on the language.

Let us clarify it a little more.

By now, many programming languages were developed but the computer still understood the machine code only (even till date computers only understand machine codes). These programming languages now need to be translated i.e the command needs to be translated into more assembler commands or machine code instructions. So the new name was coined to this translator to separate it from the earlier translator (Assembler) which only did 1:1 translation. It was christened as Compiler.

Compiler – 1: N Translation

Assembler – 1:1 Translation

Compilers can translate multiple languages to machine codes.

Also Check: Interesting details of Application Server

4. Fourth Generation Language (4GL)

Although the third-generation language became user-friendly, we needed to instruct how to do a certain task the In the fourth generation, there was one step up. The idea was to tell only which task is to be done. This technique came to be known as ‘Non-Procedural Programming’. The popular 4GL are ABAP/4, AS, CSP, DataFlex, Natural, Oracle etc.

You guessed it right. All generations before 4GL were Procedural Programming Language.

Let us not confuse fourth generation languages with fourth generation SYSTEMs. Systems are much more powerful. Systems have data dictionary, program generator and also tools for knitting different applications to one single application.

5. Fifth Generation Language

The Artificial Intelligence Systems can be programmed in an easier way. The 5GL are AI Languages. LISP and Prolog are two most popular AI languages.

Summary:

1GL were machine codes.

2GL were machine codes in symbolic language. Assemblers (1:1).

3GL were Procedural Programming. Tell the system how to do (collection of commands to create a whole new command). Compilers (1:N). Example BASIC, FORTRAN, C etc.

4GL were Non-Procedural Programming. Tell the system what to do. Example ABAP, Oracle, DataFlex etc

With SAP giving stress on Machine Learning, Artificial Intelligence, and IoT (Internet of Things), we at SAPYard thought of doing some homework on basics of Programming Language History.

We are sure, you all already knew about it but still, we wanted to do a refresher for all.

Do you have anything to add?

Please feel free to comment, criticize, encourage and provide your feedback. If you have some stories to tell, please do not hesitate.

Please browse our page for FioriSAPUI5ODataHANA-ABAPOOPsWorkflowWeb Dynpro etc tutorials.

Please Subscribe, Like & Share our Page

Automatically Fill Test Data in FM & BAPIs for SE37 – The Lazy Way

$
0
0

We often come across many issues with the upload programs that we develop to facilitate mass upload. The most boring work that I feel is when I have to replicate the runtime data in SE37 BAPI fields to troubleshoot the issue. So here is a tip to avoid this manual work. J

Bill Gates loves Lazy Developers, as they always tend to find an Automatic, Quick and Easy way to get things done. This trick is from that one Lazy but Smart ABAPer. J

In this article, we will be learning a small but helpful trick of filling the BAPI fields while we debug the program.

Following are the steps that need to be followed:

  1. Set a break-point on Call Function Statement
  2. Execute the upload program
  3. Press F5
  4. Press Services Of The Tool button
  5. Press Save Parameters as Test Data
  6. Give test data name

Let us try with a simple example. We are having a material upload program using BAPI_MATERIAL_SAVEDATA. We have set the break-point and executed the transaction.

SE37 Test Data

Press F5 and click on Services of the Tool.

BAPI_MATERIAL_SAVEDATA

Also Read: Lazy and Smart ABAPers

Click on Save Parameters as Test Data (SE37) option.

ABAP Tricks

Give a name to the test data variant and click on continue button.

Tips and Tricks for SAP

Now let us check in SE37. Enter BAPI name and execute.

Lazy Developers

Open Test data directory.

Difference between BAPI and RFC

Select the variant created by us previously and see the tables filled with the values from upload program. J

BAPI test data

Bingo. I am sure, it is new for many of us. Such tricks and tips are the forte of SAPYard.com. Hope you liked this interesting revelation. The next time, you need to test a standalone FM/BAPI in SE37, you know how to populate the data automatically.

Do not forget to provide your feedback and leave comments for Prapti (the Author). She personally replies to each and every queries and doubt.

Do you have any tips, tricks, tutorial, concept, config, business case or anything related to SAP to share? Write articles at SAPYard and EARN up to 500 INR per article? Please contact us at mail@sapyard.com to know more.

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on facebook. It might seem insignificant, but it helps more than you might think.

Also, check our popular step by step tutorials on some of the important topics of SAP ABAP.

1. ABAP for SAP HANA Tutorials
2. ABAP Web Dynpro Tutorials
3. GOS Tutorial
4. OOPs ABAP Tutorial
5. HANA Tutorial
6. SAP Netweaver and OData Tutorial
7. SAP Adobe Form Tutorial
8. SAP Fiori Tutorial
9. SAPUI5 Tutorial
10. SAP Screen Personas Tutorials
11. SAP Workflow

SPTA Parallel Processing Framework in ABAP

$
0
0

Parallel Processing Technique in SAP ABAP using SPTA Framework 

With the advent of HANA and In-Memory processing, this topic might look mis-timed. But, there are many organizations, which still have no plan to move to HANA within couples of years. As they say, the show must go on and that motivated us to publish this long pending article here for those ABAPers, who still have to deal millions of rows in batch jobs and who feel the “Nights are getting too shorter to execute those batch jobs in SAP” (inspired from a friends blog).

Why parallel processing required?

Parallel processing is required mainly to improve the performance of any ABAP program. Using parallel processing framework we can significantly improve the processing time of any program, particularly where data volume is very high. The basic concept behind the parallel processing framework is to divide the large volume of data into several small work packets and process different work packets into different tasks. So each work process will be processed at the same time in parallels and it will significantly reduce time. Nowadays every distribution-related projects have a large volume of data so invoking parallel processing framework is very useful to reduce time.

Conventional Parallel Processing

We can use parallel processing framework by calling any RFC enabled function module in NEW TASK. In this way, after determining the number of work packets we can create different tasks for each work packets and process them in parallel.

Also Read: bgRFC in SAP

Why SPTA framework required?

SPTA framework is the most sophisticated and secured framework for parallel processing provided by SAP. If we want to handle multiple records and want to update/check multiple database tables in parallel, in that case, using conventional way to invoke parallel processing is difficult and there can be some ABAP memory issue. But in SPTA framework there are build in security for all the ABAP memory related issues so it is very secure. Also, SPTA framework is very easy to implement and all the parallel processing work is handled by SAP we do not need to bother how to handle it. In this way, it is also a very sophisticated framework.

SPTA Parallel Processing Framework

To invoke SPTA framework we need to call function module SPTA_PARA_PROCESS_START_2. This is a standard SAP provided function module. In this function module, we have to use three subroutines to build our own processing logic.

SPTA_PARA_PROCESS_START_2

  1. BEFORE_RFC_CALLBACK_FORM: This routine is called by the function module before calling the RFC function module. Here we have to build different work packets which we want to process in the RFC function module.
  2. IN_RFC_CALLBACK_FORM: This routine is called by the function module after work packets are created. In this routine, we can use our own RFC enabled function module or custom code to process each work packets.
  3. AFTER_RFC_CALLBACK_FORM: This routine is called at the end by the function module. After processing of all the work packets, we have to collect all the processed data.

We have mentioned server group also when calling the function module. The server group can be maintained in the RZ12 transaction. But this is BASIS activity.

In the changing parameter, we have to pass our total internal table which contains all the data. From this internal table, we will create different small work packets (i.e. Internal tables) for parallel processing.

In the call back program name, we have to pass the calling program name.

Hope you are not confusing Parallel Processing with Parallel Cursor Technique. Please read this Graphical and Statistical Analysis of Parallel Cursor Technique in LOOPs.

Now we will discuss the main three subroutines and how to call them in details.

  • BEFORE_RFC_CALLBACK_FORM: In this routine, we have to create small internal tables which we are referring as work packets for parallel processing in the IN RFC routine. Please refer the below screenshot.

BEFORE_RFC_CALLBACK_FORM

All the parameters which are passed in this subroutine are mandatory. Here first we have to create small work packets. In the above code, it is defined like one work packet will contain 10 records. After creating one work packet I have ENCODE the data for further downstream processing. Also, we have to inform task manager that one RFC can be started by passing ‘X’ in the START_RFC field.

Also Read: What is Passive bgRFC?

  • IN_RFC_CALLBACK_FORM: In this routine, we have to write own processing logic to process all the data. We can call a RFC enabled function module from this routine or we can write our own logic inside this routine also. For each work packets, different tasks will be created and each task will call this routine for processing of data. Please refer below screenshot.

IN_RFC_CALLBACK_FORM

In the above code, I have first decoded the encoded data which is coming from BEFORE_RFC_CALLBACK_FORM routine for each work packets. Then write your own logic or call RFC enabled function module for processing. In the above example, I just sorted the random data. Then again I have encoded data for the downstream processing in AFTER_RFC_CALLBACK_FORM routine.

  • AFTER_RFC_CALLBACK_FORM: In this routine after processing of all the data we have to collect data. In this routine basically, we have to prepare final internal table after all the data processing. Please refer the attached screenshot.

AFTER_RFC_CALLBACK_FORM

In the above example I have decoded the data again and then displayed all the record. Here if any unit fails during processing in IN_RFC_CALLBACK_FORM no data will be available to collect because if any unit fails we must not prepare final table with less number of valid records. We can catch the failed unit by using IF_RFCSUBRC and IF_RFCMSG.

So by using this function module, we can invoke parallel processing framework in a sophisticated and secure manner.

Please download the code used in the above demonstration from Here.

Please note: We can design our own parallel processing technique without using SPTA Framework. The concept remains the same in the custom design too i.e. Records get processed into multiple different tasks and that runs parallel. So the processing time is reduced manifold.

My friend Partha (whom I referred in the first paragraph) has explained the custom Parallel Processing using a Program. Please check here: Parallel Processing Technique in SAP ABAP and it’s Advantages

Also, check SCN Blog on Two Different Types of Parallel Processing Examples

Here Partha has explained the concept and debugging of SPTA framework in a very illustrative way. Please check the Post on Parallel Processing and Debugging.

Do you have any tips, tricks, tutorial, concept, config, business case or anything related to SAP to share? Write articles at SAPYard and EARN up to 500 INR per article? Please contact us at mail@sapyard.com to know more.

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on FacebookIt might seem insignificant, but it helps more than you might think.

We have organized all our SAP Tutorials on one page. Please visit the below link to find all materials at one convenient place.

All SAP Tutorials at One Page

Code Quality Control, Simplified!!

$
0
0

After Simple Logistics and Simple Finance, should we coin this as Simple Code Inspector? 🙂

We assume that by now all the SAP Technical Consultants are aware of “ABAP Test Cockpit” also abbreviated as ATC. If not, please check the below two articles:
ABAP Test Cockpit(ATC) – Introduction and Steps
ABAP on SAP HANA: Part XVII. ATC – ABAP Test Cockpit Setup & Exemption Process

Anyway, as a refresher, I would like to point out some key aspects of ATC.

  • It is a code quality assurance tool from SAP.
  • It is directly integrated with ABAP workbench and available in Eclipse too.
  • It is compatible with Code Inspector, which means that the variants created in SCI can be used in ATC.
  • It has more amazing features than SCI viz. filtering, navigation and re-check functionality.
  • It has an exemption approval process wrapped around the entire ATC framework, which allows controlling the code quality with 4-eye principle.
  • It is tightly integrated with the transport management. With this, you could configure the ATC framework to allow/disallow transport request release based on the ATC issues left behind in the technical objects of that transport. This way, you can control poor quality code getting crept into higher systems in the stack.
  • Last, but not the least, it is highly recommended code quality control tool for all the HANA projects. It can also be used for determining HANA impact assessment for any client who wishes to move to HANA.

Anyway, the blog is more to highlight the new functionality of “Baseline” that SAP has introduced as part of SAP NetWeaver AS for ABAP 7.51 innovation package.

Why did SAP come up with functionality?

Using ATC is a value-add for all new technical objects but if the same is applied to a code base which is being developed & maintained from past 1-2 decades, then you would come up with hundreds and thousands of ATC issues.

Resolving those is extremely time consuming and would require extensive functional testing. It is also quite possible that instead of resolving ATC issues, we might end up introducing a bug in the code which can go untested to production. This is a major risk and hence a blocking point for most of the customers from using it.

Also Read: Exceptional SAPUI5 Code Sample Explanation for ABAPers

What is Baselining?

With this functionality, you can exclude all the ATC issues of the old code so that they stop coming up again in the next ATC run as they would be treated as special kind of exempted issues.

This way, if you make a small change in the old code, and run the ATC again, the ATC result will contain only those issues pertaining to the change that you made. Fantastic, isn’t it?

How to Baseline the old code?

  • Using ATC transaction, you can schedule an initial RUN (Transaction ATC à Runs à Schedule Runs) with a specific object set, or a package or any chunk of technical objects for whom you want to baseline the old ATC issues.
  • The scheduled run can be monitored using “Monitor and Control Runs” within the ATC transaction.
  • Once the run is finished, you can see the results using “Manage Results” node. In SAP ABAP 7.51, you would be able to see a new button called “Baseline”. Choose the scheduled run record and click on “Baseline” button. It will further give the options of whether these results should be categorized as:
    • Suppressed findings
    • Low priority findings
    • Exempt findings.

With it, you have basically asked the ATC framework to stop showing them in the ATC results, if at all you re-run the ATC tool for those technical objects.

Now, since the old legacy issues are treated as special exemptions, you can have much better control over the old deployment in the higher stack systems.

Do we have any problem with Baselining?

Well, we do!

As I mentioned that old legacy code is treated as special exemptions, but only until the mapping between the issue and the code line is maintained. If at all you introduce additional code lines in between, then the code lines are shifted downwards and hence the mapping is disturbed. For all the disturbed mapping (code lines), the baselining is destroyed and the issues start coming up again in your ATC run results.

Nevertheless, we still have an extensively reduced set of ATC issues compared to what we had previously without baselining.

Also Read: How to Create your first OData Service in SAP

What if I am not yet on SAP ABAP 7.51?

Well, the concern for all the customers below SAP NetWeaver AS for ABAP 7.51 is still not resolved.

They still must deal with the long list of ATC issues that crop up in every ATC run. Based on the experience that I have with ATC tool, here is my suggestion for all those customers:

Create 2 SCI variants to be used in ATC tool.

One variant should be configured in such a way that contains only static code checks which are easier to fix and certainly should bring in more robustness. For example:

  • Check of SY-SUBRC Handling
  • Unsecure use of FOR ALL ENTRIES
  • Search for APPEND and INSERT … INDEX in SORTED Tables
  • Search problematic statements for result of SELECT/OPEN CURSOR without ORDER BY

This variant should be used for all the fixes/CR’s which are done in the old code.

The second variant should be configured more aggressively including all performance checks, naming conventions check and robust programming checks. This should be mandatorily used for all new developments and should be adhered religiously.

Lastly, based on my experience with ATC, I would like to mention that quality code delivery is a discipline which needs to be inculcated irrespective of how big or how small the change we are doing and ATC tool is the way to bring such a discipline in us. While using it extensively, you will get adapted to looking at quality code so much that any poor quality will catch your eye instantly 😊

Enjoy coding.

Please consider this and take the actions you deem appropriate to maintain the sanity of your technical developments.

Do you have any tips, tricks, tutorial, concept, config, business case or anything related to SAP to share? Write articles at SAPYard and EARN up to 500 INR per article? Please contact us at mail@sapyard.com to know more.

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on FacebookIt might seem insignificant, but it helps more than you might think.

We have organized all our SAP Tutorials on one page. Please visit the below link to find all materials at one convenient place.

All SAP Tutorials at One Page

ABAP Objects – Is INTERFACE the Leaky Bucket of OOPs Design?

$
0
0

Most of us know, Encapsulation, Abstraction, Inheritance, and Polymorphism are the Pillars of Object Oriented Design. There is also a fifth aspect called INTERFACE which helps to provide external access to object members.

In normal ABAP RICEF, we already have ‘I’ for INTERFACE which often is associated with data exchanges within sap or external systems. We can somewhat relate to the same INTERFACE in OOPs ABAP too.

Pillars of Object Oriented Architecture

Also, Read Just 4 Versions of the same program to understand OOPs ABAP

INTERFACE is not a class. It is an entity which CANNOT have an implementation. It can only have EMPTY method declaration and components. INTERFACE components are always PUBLIC. INTERFACE is a concept by which the same method names will behave differently in different classes.

Below is an example of an INTERFACE with a method GET_KEY. 

INTERFACE locker_key .

" This method GET_KEY will not have any implementation
" in INTERFACE
  METHODS get_key .

ENDINTERFACE .

INTERFACE would have method(s) and those method(s) will have different implementations in different classes which call that INTERFACE. The method names in all the different classes would be same as in INTERFACE but can be designed to behave differently.

Example of a Class using INTERFACE Method GET_KEY

CLASS lcl_snoop  DEFINITION .
  PUBLIC  SECTION .

    INTERFACES locker_key .

ENDCLASS .

CLASS lcl_snoop  IMPLEMENTATION .

  "METHOD GET_KEY is implemented here
  METHOD locker_key~get_key .

     WRITE:/ ‘my locker key is confidential’.

  ENDMETHOD .

Similarly example of another Class that uses the same INTERFACE and same method GET_KEY. But the method does something else.

CLASS lcl_history_logger  DEFINITION .
  PUBLIC  SECTION .

    INTERFACES locker_key .

ENDCLASS .

CLASS lcl_ history_logger    IMPLEMENTATION .

  "METHOD GET_KEY is implemented differently here
  METHOD locker_key~get_key .

    write:/ ‘Access Date – ‘ , sy-datum, ‘Access Time = ‘, sy-uzeit.

  ENDMETHOD .

In the above code snippet, Class LCL_SNOOP and Class LCL_HISTORY_LOGGER are independent classes. But both use the INTERFACE LOCKER_KEY and the method GET_KEY are implemented differently although they have the same NAME in two classes.

INTERFACE is one of the concepts in Object Oriented ABAP to achieve Polymorphism.

The point to be noted is, INTERFACE just contains methods WITHOUT any implementations. INTERFACE helps in re-usability and maintain standard project framework.

Also, ReadHow to convert an existing ABAP Report to OOPs ABAP?

INTERFACE act as the connecting link. Just like the neck of the bottle in the below figure.

Interface in OOPs

Now coming back to the point which we wanted to demonstrate today. Is INTERFACE the leaky bucket in OOPs ABAP? In other words, is INTERFACE the weakest link which makes the classes using it vulnerable?

Let’s explore.

We all know INTERFACE plays a vital role in large projects or developing a custom app which can be extended based on customer demand. This extension might be done by the same person or different person. To maintain the consistency in the entire project we use INTERFACES. Example BADI always gives INTERFACES which all over the world ABAPers use the same method signature to implement the INTERFACE. Inside BADI, its framework calls these INTERFACEs to show custom business implementations (eg: TAB Strip on ME21n etc).

But INTERFACE has one drawback which is like the leaky bucket in the sense that if your CLASS_1 becomes FRIEND of an INTERFACE then other classes which are NOT a friend of INTERFACE or CLASS_1 but just implements that INTERFACE, can access the PRIVATE data of CLASS_1.

Just a word of caution from SAPYard Team. Do take care while designing the class. Do not give a secret hole to expose your sensitive data.

Here goes the code to show how INTERFACE acts like the leaky bucket.

" An INTERFACE with a method
INTERFACE locker_key .
  METHODS get_key .
ENDINTERFACE .

" Class granting INTERFACE locker_key as Friend.
CLASS lcl_mybank  DEFINITION FRIENDS locker_key .

  " Public to all
  PUBLIC  SECTION .
    METHODS  : get_bank_balance .

    " Private to lcl_mybank
  PRIVATE  SECTION .
    DATA  : lv_bank_balance  TYPE  i  VALUE  '12000.00' .
ENDCLASS .

" Class implementing the INTERFACE for which INTERFACE is Friend
CLASS lcl_mybank  IMPLEMENTATION .

  " Get Bank Balance info
  METHOD get_bank_balance .
    WRITE  : /  'My Bank Balance' , lv_bank_balance .
  ENDMETHOD .

ENDCLASS .

" This class (lcl_snoop) will also implement INTERFACE (locker_key)
" but will have alleged access to lcl_myBank Private section data due to INTERFACE
CLASS lcl_snoop  DEFINITION .
  PUBLIC  SECTION .
    INTERFACES locker_key .
ENDCLASS .

CLASS lcl_snoop  IMPLEMENTATION .
  "Snooping lcl_myBank private variables where lcl_snoop is no where related to lcl_myBank
  METHOD locker_key~get_key .

    DATA : lo_mybank  TYPE  REF  TO lcl_mybank .
    lo_mybank  =  NEW lcl_mybank( ) .
    WRITE: /  'Snoop Successfull. Account Hacked :-)' COLOR COL_NEGATIVE.
    write:/  'Amount in this bank account is - ', lo_mybank->lv_bank_balance .

  ENDMETHOD .
ENDCLASS .

START-OF-SELECTION .

" A Hacker Class
  DATA  : lo_snoop  TYPE  REF  TO lcl_snoop.

" New Instance
  lo_snoop  =  NEW lcl_snoop( ) .

" Get Bank Balance of Class LCL_MYBANK (which is no where related to LO_SNOOP)
  lo_snoop->locker_key~get_key(  ) .

Now let’s run the program and see the output.

Difference between Interface and Class

Look, class LCL_SNOOP was able to access the Private variable (lv_bank_balance) of LCL_MYBANK. Isn’t it scary? LCL_SNOOP and LCL_MYBANK are nowhere related. So how did LCL_SNOOP access the Private Variable?

The culprit is the FRIENDSHIP of LCL_MYBANK with INTERFACE LOCKER_KEY.

For the above example, INTERFACE was indeed the MOLE in the team.

Let us remove the FRIENDS statement from LCL_MYBANK definition (commented in the above screenshot). Your program would outrightly give a syntax error. It would say, Access to Private Attribute NOT allowed.

So, did you see the influence of INTERFACE and it impacts TO data visibility and access?

Hope you liked this tricky post. Now it is your duty to judiciously use INTERFACE in your OOPs design.

Have you ever injected any code knowingly? Do you know how to inject codes? Do you have any other types of Hacks? Do share your experience. Don’t worry if we inject or hack, we would be White-Hat Hackers. Everything ethical. Always responsible. Only for the betterment. J

Are you SAP ABAP on HANA Ready? If not, go through these Step by Step Tutorials on HANA ABAP.

Do you have any tips, tricks, tutorial, concept, config, business case or anything related to SAP to share? Write articles at SAPYard and EARN up to 500 INR per article? Please contact us at mail@sapyard.com to know more.

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on FacebookIt might seem insignificant, but it helps more than you might think.

We have organized all our SAP Tutorials on one page. Please visit the below link to find all materials (ABAP, HANA, ABAP on HANA, Workflow, Fiori, SAPUI5, Adobe etc) at one convenient place.

All SAP Tutorials at One Page

SAP TMG – No Need to Delete & Regenrate After Change of Table Structure

$
0
0

No Need to Delete and Regenerate the Table Maintenance Generator after Addition or Deletion of New Key or Non-Key Fields in Tables.

Do you know how?

Whenever we need to add a new key field or non-key field to an existing table which already has a TMG (Table Maintenance Generator), most of the developers keep a copy of all the codes written in the Tables Events and related area like PBO/PAI. So that after the new fields are added, they can delete the TMG and regenerate. Once the TMG is regenerated, all the previous codes are lost and the ABAPer has to retrofit the code back to the events from his back up.

FYI – We delete and regenarate the TMG because if we do not do it, the new fields does not get reflected in SM30 T-Code.

But what if, a new developer is in the project. He does not know that there is some custom logic written in the events. And he adds new fields and deletes existing TMG and regenerates the TMG without taking the backup?

This has been a pain in the neck even for seasoned ABAPers with over decades of hands-on experience. Today, we would show how you can add new fields and also make the existing TMG work with some simple steps without deleting the existing TMG.

Let’s start.

This is how the table looks before we add new  fields:

(Assume we have some  Events created for this table, ex:  event 05, event 06 etc…)

Step 1:   I have created a custom table with maintenance with some fields.

tmg

(Maintenance screen before adding the additional fields)

SAP TABLE

(Maintenance table)

SAP TMG

After adding the new fields to the existing table, in general, most consultants (read ABAPers) follow one difficult path of refreshing the table maintenance generator in order to make the new fields visible.

Delete the existing  TMG  and creating a new one with newly added fields to the table. If we have no events, we are lucky, we do not have any issue. But if there were events, then deleting the TMG would fade off all the logic in seconds. Once you deleted you can’t get the code back (though, there are ways to get it back).

Have you been a victim of TMG deletion? Have you ever lost any code because of TMG regeneration? 

Team SAPYard has always tried to provide solutions for the everyday small niggles. So here I come up with the alternative solution. We can get the new fields information without deleting the existing TMG. This would save the valuable time of ABAPers which they can utilize in some other productive actions ( i.e. watching soccer, cricket, stock market or the new kid in town i.e BitCoin). J

Also Read: Save the data in Customizing table without using transport number

Step 1: Added new fields to that table

Events in Table Maintenance Generator ( TMG Events ) |

Step 2: Adjust the table after addition of new fields in T-Code SE14.

Chose Activate and adjust database button and Save data.

Adjust table

Step 3:  Go back to the table (in change mode)  and click on table maintenance generator from Utilities menu item.

What Is Full Form Of TMG In Sap Term

Step  4: You would be able to see the change icon on the maintenance screen.

Click it.

table maintenance generator for standard table

Step 5:  Popup will appear on clicking the change icon.

tmg in sap tables

Step 6:  Here comes the most important section, whether you want to change or delete the fields.

If you want to add additional fields to the TMG, then select New field/sec. table in structure.

Click continue.

You must have realized, if you want to delete the fields from a table, then you need to select Field/sec. table removed from the structure.

Click continue.

Step 7: For our exercise, continuing as adding new fields

So next screen would be:

Step 8:  Here too, you have a very important decision to make. You want to add a key field or normal field?

Whether it is single screen or overview screen?

Here our situation is normal filed, with overview screen.

Click continue.

Step 9: One more popup will appear after you press the continue button.

Simply click on Continue.

Note:  Some processing time will take to activate

Then click on SAVE.

Congratulations you regenerated the TMG successfully without any hassle of deleting the TMG.

What are you waiting for? Go and check your maintenance (SM30).

Here you can see the result. Newly added fields are smiling and waiting for you to populate them.J

Also Read: Automatic Population of Values during Table Maintenance

 Follow the same procedure when you want to:

  • Add new Key fields to the table
  • Delete the fields (key/non-key) from the table

Hope you liked this trick. It might look simple but trust us, many ABAPers do not know this. Next time you change the structure of a Table, you know how to regenerate TMG without any headache. 🙂

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on FacebookIt might seem insignificant, but it helps more than you might think.

Also Check our Step by Step Tutorials on SAP HANA-ABAP


Utility Program to Auto Format the Texts into Meaningful Sentence

$
0
0

PO Texts in the Material Master – Long Text Wrap up Issue and Resolution

Issue: When loading PO texts in the Material master from a flat file, the long text do not wrap up automatically into a meaningful sentence.

Business Need: Our Client’s master data team came up with the above issue and we were trying to find a solution as to how to make the text truncate at the right place so that the meaning of the sentence remains intact.

Out of curiosity, I started looking at various standard programs and debugged the standard programs, to figure out how the SAP does it so cleanly.

The solution was right under our nose. T-Code SO10 (standard text) does it very simple and straight.

The text upload from a flat file is perfectly wrapped and truncated at appropriate places to keep the words and the sentence as a whole meaningful.

Analysis: Started debugging SO10 t-code from this point, to figure out how the file is wrapped by SAP. Go to t-code SO10 and hit the create button.

Note – The input file is not formatted at all.

longtext truncate in sap

Hit the Upload from Text menu to import a text file.
Text Wrap in SAP

Choose ASCII.ASCII format upload by SAPThe default Code Page used by SAP is ‘4110’.

codepage in sap

All the Code Pages in SAP can be found in table TCP00 (SAP code page catalog).

Codepage table in sap

Look, SAP auto formats the imported texts into meaningful sentences without breaking the work in the middle.

Long text Formatting in SAP

Also ReadUnwanted ‘#’ in the file

The inference from the above Analysis:

1. Read the file using the below FM.

SAP uses FM ‘WS_FILENAME_GET’ to read the file.

CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
def_filename     = pa_file
mask             = ',*.txt.'
mode             = 'O'
title            = 'Upload File'(078)
IMPORTING
filename         = pa_file
EXCEPTIONS
inv_winsys       = 1
no_batch         = 2
selection_cancel = 3
selection_error  = 4
OTHERS           = 5.

Step 2: FM to read the file.

SAP uses FM ‘IMPORT_TEXT’ in ASCII format with code page 4110. The table itf_lines will automatically have the begin of the paragraph (indicator ‘/’). This is the key FM which formats the long text into a meaningful sentence.

* -- Import the file contents to the internal table !!! 
CALL FUNCTION 'IMPORT_TEXT'
EXPORTING
codepage        = c_codepage
file            = pa_file
format_type     = c_ascii
word_langu      = sy-langu
TABLES
itf_lines       = gt_lines[]
EXCEPTIONS
file_open_error = 1
file_read_error = 2
upload_error    = 3
no_contents     = 4
OTHERS          = 5.

Remember, our goal is to send the text to FM SAVE_TEXT. But LINES table of SAVE_TEXT has a length of 132 characters. If your longtext is greater than 132 character, then it would be difficult to break the sentence correctly. Therefore, using this FM IMPORT_TEXT is very helpful. It automatically breaks the input longtext from file to good sentence and it is ready to be passed to SAVE_TEXT to upload to our desired destination.

Note: Make sure the code page is  4110 and is ASCII format.

If you use GUI_UPLOAD instead of the above FM, then you need to write your own intelligent logic to break the word at the right place and keep it meaningful. Check this example screenshot below where a long text is in li_tab as a very long string and we do not know how to pass correct lines to SAVE_TEXT.

The problem with GUI_UPLOAD is that it is not easy to break the sentence correctly using some custom logic. We cannot truncate the word in between. So the above FM IMPORT_TEXT is very useful in breaking one long string into multiple rows of meaningful sentences.

GUI_UPLOAD issue

Q: How to Identify PO text for different material in the file.
Ans: SAP automatically puts ‘/’ for every new paragraph. So every material PO text is separated by ‘/’, i.e. tdformat = ‘/’ (in itf_lines of IMPORT_TEXT).

Also Read – Playing Sherlock Holmes to detect CONVT_CODEPAGE runtime error mystery

Sample Program Developed to simulate the SAP behavior

Selection screen:  

CONSTANTS : c_codepage TYPE tcp02-cpcodepage  VALUE '4110',
             c_ascii(5) TYPE c  VALUE 'ASCII'.
 * -- Types declaration
 TYPES : BEGIN OF gts_err,
           matnr TYPE matnr,
           error TYPE bapi_msg,
         END OF gts_err.
 
 * -- Data declarations !!!
 DATA : gt_lines TYPE TABLE OF tline,
        gs_line  LIKE LINE  OF gt_lines,
        gs_lines LIKE LINE  OF gt_lines.
 
 DATA : gs_header LIKE thead,
        gv_matnr  TYPE matnr_d,
        gv_name   TYPE tdobname.
 
 DATA:  gt_lines_save TYPE STANDARD TABLE OF tline,
        gs_lines_save LIKE LINE OF  gt_lines_save.
 
 DATA: gt_err     TYPE TABLE OF gts_err,
       gs_err     LIKE LINE  OF gt_err,
       gr_message TYPE REF   TO cx_salv_msg.
 
 *-- REFERENCE definitions                                                *
 DATA gx_alv TYPE REF TO cl_salv_table.
 
 * -- Selection screen.. !!!
 SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
 PARAMETERS: pa_file  LIKE rlgrap-filename OBLIGATORY .
 SELECTION-SCREEN END OF BLOCK b1.
 
 * -- At Selection screen
 AT SELECTION-SCREEN ON VALUE-REQUEST FOR pa_file.
   CALL FUNCTION 'WS_FILENAME_GET'
     EXPORTING
       def_filename     = pa_file
       mask             = ',*.txt.'
       mode             = 'O'
       title            = 'Upload File'(078)
     IMPORTING
       filename         = pa_file
     EXCEPTIONS
       inv_winsys       = 1
       no_batch         = 2
       selection_cancel = 3
       selection_error  = 4
       OTHERS           = 5.
 
 INITIALIZATION.
 *Program level Authorization check.
   CALL FUNCTION 'AUTHORITY_CHECK_TCODE'
     EXPORTING
       tcode  = 'ZMM_XXX'
     EXCEPTIONS
       ok     = 0
       not_ok = 2
       OTHERS = 3.
   IF sy-subrc NE 0.
     MESSAGE s000(zs) WITH text-014 DISPLAY LIKE 'E'.
     LEAVE PROGRAM.
   ENDIF.
 
 START-OF-SELECTION.
 * -- Read the file contents on the internal table !!!
   CALL FUNCTION 'IMPORT_TEXT'
     EXPORTING
       codepage        = c_codepage  " 4110
       file            = pa_file
       format_type     = c_ascii
       word_langu      = sy-langu
     TABLES
       itf_lines       = gt_lines[]
     EXCEPTIONS
       file_open_error = 1
       file_read_error = 2
       upload_error    = 3
       no_contents     = 4
       OTHERS          = 5.
   IF sy-subrc <> 0.
     MESSAGE e000(zm) WITH text-err DISPLAY LIKE 'I'.
   ENDIF.
 
   DATA lx_columns TYPE REF TO cl_salv_columns_table.
 * -- Process the data for final output.
   gs_header-tdobject = 'MATERIAL'.
   gs_header-tdid     = 'BEST'.
   gs_header-tdspras  = sy-langu.
 
   LOOP AT gt_lines INTO gs_lines.
 
     REPLACE ALL OCCURRENCES OF '"' IN gs_lines-tdline WITH space.
 
     READ TABLE gt_lines INTO gs_line INDEX sy-tabix + 1 .
 
     IF gs_lines-tdformat = '/' . " Begin of new record !!!
       CLEAR gv_matnr.
       SPLIT gs_lines-tdline AT '~~' INTO gv_matnr gs_lines-tdline.
       CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
         EXPORTING
           input  = gv_matnr
         IMPORTING
           output = gv_matnr
         EXCEPTIONS
           OTHERS = 1.
 
       CLEAR gv_name.
       gs_header-tdname   =  gv_matnr.
       gs_lines_save      =  gs_lines.
 
       APPEND gs_lines_save TO gt_lines_save.
       CLEAR gs_lines_save.
     ELSE.
       gs_lines_save = gs_lines.
       APPEND gs_lines_save TO gt_lines_save.
       CLEAR  gs_lines_save.
     ENDIF.
 
     IF gs_line-tdformat EQ '/'.
       CALL FUNCTION 'SAVE_TEXT'
         EXPORTING
           client          = sy-mandt
           header          = gs_header
           savemode_direct = 'X'
         IMPORTING
           newheader       = gs_header
         TABLES
           lines           = gt_lines_save[]
         EXCEPTIONS
           id              = 1
           language        = 2
           name            = 3
           object          = 4
           OTHERS          = 5.
       IF sy-subrc <> 0.
         gs_err-matnr = gv_matnr.
         gs_err-error = text-upr.
         APPEND gs_err TO gt_err.
       ELSE.
         gs_err-matnr = gv_matnr.
         gs_err-error = text-ups.
         APPEND gs_err TO gt_err.
       ENDIF.
       CLEAR gs_err.
       REFRESH gt_lines_save[].
     ENDIF.
    ENDLOOP.
 
 ** -- Do it for last record.
   CALL FUNCTION 'SAVE_TEXT'
     EXPORTING
       client          = sy-mandt
       header          = gs_header
       savemode_direct = 'X'
     IMPORTING
       newheader       = gs_header
     TABLES
       lines           = gt_lines_save[]
     EXCEPTIONS
       id              = 1
       language        = 2
       name            = 3
       object          = 4
       OTHERS          = 5.
 
   IF sy-subrc <> 0.
     gs_err-matnr = gv_matnr.
     gs_err-error = text-upr.
     APPEND gs_err TO gt_err.
   ELSE.
     gs_err-matnr = gv_matnr.
     gs_err-error = text-ups.
     APPEND gs_err TO gt_err.
   ENDIF.
   CLEAR gs_err.
   REFRESH gt_lines_save[]..
 
   IF gt_err[] IS NOT INITIAL.
     TRY.
         cl_salv_table=>factory(
         IMPORTING
         r_salv_table = gx_alv
         CHANGING
         t_table      = gt_err ).
       CATCH cx_salv_msg INTO gr_message.
     ENDTRY.
 
     lx_columns = gx_alv->get_columns( ).
     lx_columns->set_optimize( 'X' ).
   ENDIF.
   gx_alv->display( ).

The output of the report

Material PO Text

Note: For our case, the material number is the first word in the file and it is separated by ‘~~’.

Let us validate the PO Text in the Material Master. Go to MM03 -> Purchase Order Text -> Give the Plant -> Hit the Text Editor.

Look the texts move to the next line whenever there is space crunch. The meaning of the sentence is intact. And the words are not split in between two lines.

LongText good

This is just a simple observation. Many of you might already be using SAVE_TEXT and getting your text auto formatted. But if you are a first-time ABAPer, I wanted to show you what should be your approach to tackle any SAP issue. You need to look for the answer in the Standard SAP Solutions. SAP has everything. We just need to learn to debug at the right place and figure out how to use them in our custom program.

Write and Earn at SAPYardIf interested to Earn some extra incomecheck here.

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on Facebook. It might seem insignificant, but it helps more than you might think.

Please write your comments & feedback below.

Step by Step Tutorials on S/4 HANA

Step by Step Code Snippet for Reference.

41 Funny Acronyms of SAP

$
0
0

The other day one of my friends was really frustrated by the way a particular business worked for one of the clients. Ignorance of some so call functional consultants had complicated the process and the custom solution could have been easily avoided, had the functional guy done some homework. In his heated moment he said, we are not in SAP System but in a ZAP System. He believed the client had more Z Programs than needed. The word ZAP brought smiles in everyone’s face.

Then we Googled for funny acronyms of SAP and we were amazed, there were tons of acronyms for SAP. We have listed 41 funny ones, which we thought could change the gloomy mood of anyone. If you enjoy it, do not forget to share with your colleagues, friends and team members.

SAP – Salary Advancement Program
SAP – Save Accounting Position
SAP – Save Another Programmer
SAP – See Administrators Panic
SAP – See All Products
SAP – See America Plan
SAP – Select Another Product
SAP – Send Another Payment
SAP – Send Another Player
SAP – Seriously Annoying Process
SAP – Shoot A Programmer
SAP – Siphon Away Profits
SAP – Sit And Play
SAP – Slow And Painful
SAP – Slow And Problematic
SAP – Smile And Pay
SAP – Socially Awkard Programmers
SAP – Software (of) Andhra Pradesh
SAP – Software Against Professionals
SAP – Software Against Profit
SAP – Sold A Penny
SAP – Solution Against Progress
SAP – Solutions And Problems
SAP – Some Ambiguous Process
SAP – Some Another Process
SAP – Some Arrogance Policy
SAP – Some Arrogant Programmer
SAP – Soon As Possible
SAP – Sorry About Production
SAP – Sorry After Purchase
SAP – Stand And Panic
SAP – Stand And Pray
SAP – Start Applying Patches
SAP – Stop All Production
SAP – Stop All Progress
SAP – Streaming Audio Player
SAP – Submit And Pray
SAP – Suck All Profit
SAP – Suffer After Purchase
SAP – Suitcase And Passport
SAP – System Against People

We found Start Applying Patches really hilarious. Submit And Pray is also unique as many times in real production system, we have seen anxious developers (read ABAPers) praying for the fix to work. 🙂

SAP is not that bad. We found some good acronyms in support of SAP too. 😛

7 Good SAP acronyms are listed below.

SAP – Smooth And Powerful
SAP – Solves All Problems
SAP – Speed Agile Productive
SAP – Speed And Prompt
SAP – Stable And Perfect
SAP – Sweet Apple Pie
SAP – Swift Action Plan

When we are talking about SAP, how can we leave ABAP behind? How do you rate below acronym for ABAP?
ABAP – Always Better Alternatives Possible

In all this fun, hope we do not dilute what SAP actually stand for?

The original full form of SAP is “Systeme, Anwendungen, Produkte in der Datenverarbeitung” in German. When translated into English SAP becomes Systems, Applications, and Products for Data Processing. The acronym was little long and the think tanks smartly stated calling it as S-A-P. We don’t call S-A-P as SAP (tree trunk sap). If someone calls S-A-P as SAP, you be confident, that guy has never worked in S-A-P. 🙂

Also, Read What does SAP do?

Well ABAP actually stands for Advanced Business Application Programming. This is the programming language used in SAP.

Now we want to hear from you.

do you have any another acronym to share?

Please write something in the comments section below.

 

Free Step by Step Exercises on SAP ABAP for HANA

SAP ABAP Checkpoint Group – Chase the Mysterious SAP Issues with a Smile

$
0
0

T-Code SAAB for SAP ABAP Checkpoint Group

If changes are made to the code, then there is no guarantee that previous assumptions are satisfied. SAP ABAP checkpoints can be used for making sure that program correctness is maintained. Under checkpoints, we consider Assertions, Breakpoint, and Log points.

Assertions can be used for improving the quality of software. Breakpoint and Log point are used for investigating program behavior in case of problems. They help in understanding and maintaining the code.

The transaction SAAP has been there for quite some time but it is a pity not many ABAPers are aware of it. Therefore we thought our SAPYard family members should know about this useful tool. Better late than never. It is such a handy tool, which might even be useful in the real production environment.

Checkpoint Group
The activation state of all checkpoints which can be activated is controlled by the checkpoint group.

Assertion
Let us consider a scenario where money is transferred from one account to another. Here, the sum of both balances must be equal before and after transfer. Simple Finance. Right? 🙂 With the help of assertion, we can check this condition. It is a statement which we can put in the program describing a specific condition.

syntax 1 – ASSERT logical expression.

During program execution, if expression fails, execution can be stopped. Program execution can be stopped by raising ASSERTION_FAILED.

syntax 2 – ASSERT ID checkpoint group CONDITION logical expression.

If ID statement is used then assertion activation and its behavior is controlled from outside the program by checkpoint group otherwise it is always active.

How to create Checkpoint group?

Checkpoint group can be created using SAAB transaction.

SAAB

Enter Name and click on create. Save it.

Please note – By default Assertion is Inactive as shown below in the Assertions frame.

How to create checkpoint group?

Also Read – Lazy and Smart ABAPers

Let us write a very basic program and execute it in SE38.

REPORT ZSAPYardCheckPoint.

DATA : lv1 TYPE c VALUE 'A'.
DATA : lv2 TYPE c VALUE 'B'.

INITIALIZATION.

  LOG-POINT ID zcheck_pt FIELDS: lv1,lv2.

START-OF-SELECTION .

  lv1 = 'X'.
  lv2 = 'Y'.

  LOG-POINT ID zcheck_pt FIELDS: lv1,lv2.

  WRITE 'Run.. Done'.

 ASSERT ID zcheck_pt CONDITION lv1 EQ lv2.

 BREAK-POINT ID zcheck_pt.

Execute the program. It would run successfully and write the output “Run.. Done”.

Case 1 – Abort

Now, go to transaction SAAB. Select radio button Abort in Assertions frame and save the Checkpoint Group.

How to activate Assert

Now, execute the program again. You will get a dump describing the position where Assertion is violated.

Assertion is violated

Did you check? Playing Sherlock Holmes to detect CONVT_CODEPAGE runtime error mystery

You can no doubt see the dump in the regular t-code ST22. But our aim in this article is to see the Log in SAAB T-code where we created the Checkpoint.

Case 2 – Log

In order to start logging, we need let the SAAB T-Code know about our intention.  We need to choose the Log radio button (as shown below) in the Assertions (Foreground) section.

Log radio button

You can see the log details with Variable values, which would be very useful in cases where we can’t replicate the scenarios in Quality or Development box – to chase the mysterious missing values.

Assert log

PS: If you do not see the above log, choose the Log radio button in Assertions frame and re-run your program.

Case 3 – Break

When you select Break option you will get following pop up which is just an information.

What does the above information mean?

Ans: In the normal case, the program is interrupted and the debugger is started. In case of background processing, there are two choices. It will behave like Log mode or Abort mode depending on what is selected in the above pop up. By default it is Log, so in Background processing mode, the program would not go into debug mode, but checkpoint group would log the issues.

Just like Assertions; Breakpoints and Logpoints can be activated by selecting Break and Log respectively.

break and log

BREAK-POINT:
Break Point can be activated by writing following code in your program.

BREAK-POINT ID <Checkpoingroup>.

breakpoint activation

Active breakpoint behaves same as an Always Active breakpoint. In case of background processing, activatable breakpoints are simply ignored. Run the Program in the foreground, you can see the program stop by at line 30.

LOG-POINTS:
Log Point can be made active by writing following code in your program.

LOG-POINT ID <Checkpoingroup>

Logs can be used to identify or analyze the system behavior. Variable values can be logged so that the developers can analyze those values.

You can add in your program statement LOG-POINT ID ZCHEECK_PT. You can also use the following syntax.

Run the program and go to transaction SAAB. Go to tab ‘LOG’. You will see following details which will help you to analyze program’s behavior.

Above statement log the value of field ‘log’. We can log up to 32 fields.

You can use SUBKEY addition to prevent the production of a huge amount of data in the log. All log occurrences will produce one record for the same SUBKEY. Only last occurrence can be seen but the counter will be incremented.

LOG_POINT ID ZTRY SUBKEY ‘TEST’ FIELDS log.

Also Read – DELETING rows of the internal table within the LOOP. Is it a Taboo? A big NO NO?

Checkpoint group activation can be done with three levels

  1. Personal Activation – Checkpoint group will be active for current user only.

2. User Level activation – Checkpoint group will be active for all defined users.

User Level Activation of Log

3. Server level Activation – The Same way we can define servers for which it will be active.

This was my humble effort to bring your notice to this simple yet very powerful tool which every ABAPer should make use of. I know, this transaction SAAB should have been introduced years ago. But every day you find something new in SAP. Please start using it and let me know if you face any issue. I would try to answer your queries.

If there any other useful tool which you use in your project?

Please share with us if you have some smart way to tackle production issues or identify dumps. If you have some custom tools which can be shared, do send it to us. We would be happy to share it in our portal.

Now, we want to hear from you. Please leave your feedback and comments below.

We have a very active Telegram (App) SAP Technical Group with more than 1440+ SAP Technical Practitioners from 6 Continents of the SAP World. Please join it using below link.
Telegram SAP Technical Discuss Group. You need to install the Telegram App first on your mobile device. Once you have it on your mobile, you can join the group and also access it from the Web on your computer and laptop.

Check Step by Step Tutorials on SAP HANA-ABAP

Utility Program to Auto Format the Texts into Meaningful Sentence

$
0
0

PO Texts in the Material Master – Long Text Wrap up Issue and Resolution

Issue: When loading PO texts in the Material master from a flat file, the long text do not wrap up automatically into a meaningful sentence.

Business Need: Our Client’s master data team came up with the above issue and we were trying to find a solution as to how to make the text truncate at the right place so that the meaning of the sentence remains intact.

Out of curiosity, I started looking at various standard programs and debugged the standard programs, to figure out how the SAP does it so cleanly.

The solution was right under our nose. T-Code SO10 (standard text) does it very simple and straight.

The text upload from a flat file is perfectly wrapped and truncated at appropriate places to keep the words and the sentence as a whole meaningful.

Analysis: Started debugging SO10 t-code from this point, to figure out how the file is wrapped by SAP. Go to t-code SO10 and hit the create button.

Note – The input file is not formatted at all.

longtext truncate in sap

Hit the Upload from Text menu to import a text file.
Text Wrap in SAP

Choose ASCII.ASCII format upload by SAPThe default Code Page used by SAP is ‘4110’.

codepage in sap

All the Code Pages in SAP can be found in table TCP00 (SAP code page catalog).

Codepage table in sap

Look, SAP auto formats the imported texts into meaningful sentences without breaking the work in the middle.

Long text Formatting in SAP

Also ReadUnwanted ‘#’ in the file

The inference from the above Analysis:

1. Read the file using the below FM.

SAP uses FM ‘WS_FILENAME_GET’ to read the file.

CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
def_filename     = pa_file
mask             = ',*.txt.'
mode             = 'O'
title            = 'Upload File'(078)
IMPORTING
filename         = pa_file
EXCEPTIONS
inv_winsys       = 1
no_batch         = 2
selection_cancel = 3
selection_error  = 4
OTHERS           = 5.

Step 2: FM to read the file.

SAP uses FM ‘IMPORT_TEXT’ in ASCII format with code page 4110. The table itf_lines will automatically have the begin of the paragraph (indicator ‘/’). This is the key FM which formats the long text into a meaningful sentence.

* -- Import the file contents to the internal table !!! 
CALL FUNCTION 'IMPORT_TEXT'
EXPORTING
codepage        = c_codepage
file            = pa_file
format_type     = c_ascii
word_langu      = sy-langu
TABLES
itf_lines       = gt_lines[]
EXCEPTIONS
file_open_error = 1
file_read_error = 2
upload_error    = 3
no_contents     = 4
OTHERS          = 5.

Remember, our goal is to send the text to FM SAVE_TEXT. But LINES table of SAVE_TEXT has a length of 132 characters. If your longtext is greater than 132 character, then it would be difficult to break the sentence correctly. Therefore, using this FM IMPORT_TEXT is very helpful. It automatically breaks the input longtext from file to good sentence and it is ready to be passed to SAVE_TEXT to upload to our desired destination.

Note: Make sure the code page is  4110 and is ASCII format.

If you use GUI_UPLOAD instead of the above FM, then you need to write your own intelligent logic to break the word at the right place and keep it meaningful. Check this example screenshot below where a long text is in li_tab as a very long string and we do not know how to pass correct lines to SAVE_TEXT.

The problem with GUI_UPLOAD is that it is not easy to break the sentence correctly using some custom logic. We cannot truncate the word in between. So the above FM IMPORT_TEXT is very useful in breaking one long string into multiple rows of meaningful sentences.

GUI_UPLOAD issue

Q: How to Identify PO text for different material in the file.
Ans: SAP automatically puts ‘/’ for every new paragraph. So every material PO text is separated by ‘/’, i.e. tdformat = ‘/’ (in itf_lines of IMPORT_TEXT).

Also Read – Playing Sherlock Holmes to detect CONVT_CODEPAGE runtime error mystery

Sample Program Developed to simulate the SAP behavior

Selection screen:  

CONSTANTS : c_codepage TYPE tcp02-cpcodepage  VALUE '4110',
             c_ascii(5) TYPE c  VALUE 'ASCII'.
 * -- Types declaration
 TYPES : BEGIN OF gts_err,
           matnr TYPE matnr,
           error TYPE bapi_msg,
         END OF gts_err.
 
 * -- Data declarations !!!
 DATA : gt_lines TYPE TABLE OF tline,
        gs_line  LIKE LINE  OF gt_lines,
        gs_lines LIKE LINE  OF gt_lines.
 
 DATA : gs_header LIKE thead,
        gv_matnr  TYPE matnr_d,
        gv_name   TYPE tdobname.
 
 DATA:  gt_lines_save TYPE STANDARD TABLE OF tline,
        gs_lines_save LIKE LINE OF  gt_lines_save.
 
 DATA: gt_err     TYPE TABLE OF gts_err,
       gs_err     LIKE LINE  OF gt_err,
       gr_message TYPE REF   TO cx_salv_msg.
 
 *-- REFERENCE definitions                                                *
 DATA gx_alv TYPE REF TO cl_salv_table.
 
 * -- Selection screen.. !!!
 SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
 PARAMETERS: pa_file  LIKE rlgrap-filename OBLIGATORY .
 SELECTION-SCREEN END OF BLOCK b1.
 
 * -- At Selection screen
 AT SELECTION-SCREEN ON VALUE-REQUEST FOR pa_file.
   CALL FUNCTION 'WS_FILENAME_GET'
     EXPORTING
       def_filename     = pa_file
       mask             = ',*.txt.'
       mode             = 'O'
       title            = 'Upload File'(078)
     IMPORTING
       filename         = pa_file
     EXCEPTIONS
       inv_winsys       = 1
       no_batch         = 2
       selection_cancel = 3
       selection_error  = 4
       OTHERS           = 5.
 
 INITIALIZATION.
 *Program level Authorization check.
   CALL FUNCTION 'AUTHORITY_CHECK_TCODE'
     EXPORTING
       tcode  = 'ZMM_XXX'
     EXCEPTIONS
       ok     = 0
       not_ok = 2
       OTHERS = 3.
   IF sy-subrc NE 0.
     MESSAGE s000(zs) WITH text-014 DISPLAY LIKE 'E'.
     LEAVE PROGRAM.
   ENDIF.
 
 START-OF-SELECTION.
 * -- Read the file contents on the internal table !!!
   CALL FUNCTION 'IMPORT_TEXT'
     EXPORTING
       codepage        = c_codepage  " 4110
       file            = pa_file
       format_type     = c_ascii
       word_langu      = sy-langu
     TABLES
       itf_lines       = gt_lines[]
     EXCEPTIONS
       file_open_error = 1
       file_read_error = 2
       upload_error    = 3
       no_contents     = 4
       OTHERS          = 5.
   IF sy-subrc <> 0.
     MESSAGE e000(zm) WITH text-err DISPLAY LIKE 'I'.
   ENDIF.
 
   DATA lx_columns TYPE REF TO cl_salv_columns_table.
 * -- Process the data for final output.
   gs_header-tdobject = 'MATERIAL'.
   gs_header-tdid     = 'BEST'.
   gs_header-tdspras  = sy-langu.
 
   LOOP AT gt_lines INTO gs_lines.
 
     REPLACE ALL OCCURRENCES OF '"' IN gs_lines-tdline WITH space.
 
     READ TABLE gt_lines INTO gs_line INDEX sy-tabix + 1 .
 
     IF gs_lines-tdformat = '/' . " Begin of new record !!!
       CLEAR gv_matnr.
       SPLIT gs_lines-tdline AT '~~' INTO gv_matnr gs_lines-tdline.
       CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
         EXPORTING
           input  = gv_matnr
         IMPORTING
           output = gv_matnr
         EXCEPTIONS
           OTHERS = 1.
 
       CLEAR gv_name.
       gs_header-tdname   =  gv_matnr.
       gs_lines_save      =  gs_lines.
 
       APPEND gs_lines_save TO gt_lines_save.
       CLEAR gs_lines_save.
     ELSE.
       gs_lines_save = gs_lines.
       APPEND gs_lines_save TO gt_lines_save.
       CLEAR  gs_lines_save.
     ENDIF.
 
     IF gs_line-tdformat EQ '/'.
       CALL FUNCTION 'SAVE_TEXT'
         EXPORTING
           client          = sy-mandt
           header          = gs_header
           savemode_direct = 'X'
         IMPORTING
           newheader       = gs_header
         TABLES
           lines           = gt_lines_save[]
         EXCEPTIONS
           id              = 1
           language        = 2
           name            = 3
           object          = 4
           OTHERS          = 5.
       IF sy-subrc <> 0.
         gs_err-matnr = gv_matnr.
         gs_err-error = text-upr.
         APPEND gs_err TO gt_err.
       ELSE.
         gs_err-matnr = gv_matnr.
         gs_err-error = text-ups.
         APPEND gs_err TO gt_err.
       ENDIF.
       CLEAR gs_err.
       REFRESH gt_lines_save[].
     ENDIF.
    ENDLOOP.
 
 ** -- Do it for last record.
   CALL FUNCTION 'SAVE_TEXT'
     EXPORTING
       client          = sy-mandt
       header          = gs_header
       savemode_direct = 'X'
     IMPORTING
       newheader       = gs_header
     TABLES
       lines           = gt_lines_save[]
     EXCEPTIONS
       id              = 1
       language        = 2
       name            = 3
       object          = 4
       OTHERS          = 5.
 
   IF sy-subrc <> 0.
     gs_err-matnr = gv_matnr.
     gs_err-error = text-upr.
     APPEND gs_err TO gt_err.
   ELSE.
     gs_err-matnr = gv_matnr.
     gs_err-error = text-ups.
     APPEND gs_err TO gt_err.
   ENDIF.
   CLEAR gs_err.
   REFRESH gt_lines_save[]..
 
   IF gt_err[] IS NOT INITIAL.
     TRY.
         cl_salv_table=>factory(
         IMPORTING
         r_salv_table = gx_alv
         CHANGING
         t_table      = gt_err ).
       CATCH cx_salv_msg INTO gr_message.
     ENDTRY.
 
     lx_columns = gx_alv->get_columns( ).
     lx_columns->set_optimize( 'X' ).
   ENDIF.
   gx_alv->display( ).

The output of the report

Material PO Text

Note: For our case, the material number is the first word in the file and it is separated by ‘~~’.

Let us validate the PO Text in the Material Master. Go to MM03 -> Purchase Order Text -> Give the Plant -> Hit the Text Editor.

Look the texts move to the next line whenever there is space crunch. The meaning of the sentence is intact. And the words are not split in between two lines.

LongText good

This is just a simple observation. Many of you might already be using SAVE_TEXT and getting your text auto formatted. But if you are a first-time ABAPer, I wanted to show you what should be your approach to tackle any SAP issue. You need to look for the answer in the Standard SAP Solutions. SAP has everything. We just need to learn to debug at the right place and figure out how to use them in our custom program.

Write and Earn at SAPYardIf interested to Earn some extra incomecheck here.

If you GENUINELY like our articles then it would be a HUGE help if you shared, subscribed and liked us on Facebook. It might seem insignificant, but it helps more than you might think.

Please write your comments & feedback below.

Step by Step Tutorials on S/4 HANA

Step by Step Code Snippet for Reference.

41 Funny Acronyms of SAP

$
0
0

The other day one of my friends was really frustrated by the way a particular business worked for one of the clients. Ignorance of some so call functional consultants had complicated the process and the custom solution could have been easily avoided, had the functional guy done some homework. In his heated moment he said, we are not in SAP System but in a ZAP System. He believed the client had more Z Programs than needed. The word ZAP brought smiles in everyone’s face.

Then we Googled for funny acronyms of SAP and we were amazed, there were tons of acronyms for SAP. We have listed 41 funny ones, which we thought could change the gloomy mood of anyone. If you enjoy it, do not forget to share with your colleagues, friends and team members.

SAP – Salary Advancement Program
SAP – Save Accounting Position
SAP – Save Another Programmer
SAP – See Administrators Panic
SAP – See All Products
SAP – See America Plan
SAP – Select Another Product
SAP – Send Another Payment
SAP – Send Another Player
SAP – Seriously Annoying Process
SAP – Shoot A Programmer
SAP – Siphon Away Profits
SAP – Sit And Play
SAP – Slow And Painful
SAP – Slow And Problematic
SAP – Smile And Pay
SAP – Socially Awkard Programmers
SAP – Software (of) Andhra Pradesh
SAP – Software Against Professionals
SAP – Software Against Profit
SAP – Sold A Penny
SAP – Solution Against Progress
SAP – Solutions And Problems
SAP – Some Ambiguous Process
SAP – Some Another Process
SAP – Some Arrogance Policy
SAP – Some Arrogant Programmer
SAP – Soon As Possible
SAP – Sorry About Production
SAP – Sorry After Purchase
SAP – Stand And Panic
SAP – Stand And Pray
SAP – Start Applying Patches
SAP – Stop All Production
SAP – Stop All Progress
SAP – Streaming Audio Player
SAP – Submit And Pray
SAP – Suck All Profit
SAP – Suffer After Purchase
SAP – Suitcase And Passport
SAP – System Against People

We found Start Applying Patches really hilarious. Submit And Pray is also unique as many times in real production system, we have seen anxious developers (read ABAPers) praying for the fix to work. 🙂

SAP is not that bad. We found some good acronyms in support of SAP too. 😛

7 Good SAP acronyms are listed below.

SAP – Smooth And Powerful
SAP – Solves All Problems
SAP – Speed Agile Productive
SAP – Speed And Prompt
SAP – Stable And Perfect
SAP – Sweet Apple Pie
SAP – Swift Action Plan

When we are talking about SAP, how can we leave ABAP behind? How do you rate below acronym for ABAP?
ABAP – Always Better Alternatives Possible

In all this fun, hope we do not dilute what SAP actually stand for?

The original full form of SAP is “Systeme, Anwendungen, Produkte in der Datenverarbeitung” in German. When translated into English SAP becomes Systems, Applications, and Products for Data Processing. The acronym was little long and the think tanks smartly stated calling it as S-A-P. We don’t call S-A-P as SAP (tree trunk sap). If someone calls S-A-P as SAP, you be confident, that guy has never worked in S-A-P. 🙂

Also, Read What does SAP do?

Well ABAP actually stands for Advanced Business Application Programming. This is the programming language used in SAP.

Now we want to hear from you.

do you have any another acronym to share?

Please write something in the comments section below.

 

Free Step by Step Exercises on SAP ABAP for HANA

Viewing all 66 articles
Browse latest View live


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