Quantcast
Channel: ABAP Development
Viewing all 948 articles
Browse latest View live

How To Open Purchase Order Document From Interactive Report

$
0
0

Dear Friends

     i will show you how to use to open Document from ALV  Interactive Report

We have 2 way To open Purchase Requisition

Note :here Ebeln  is Purchase Requisition Number


1. Using Dialog Code Parameter ID

   set parameter id 'BES' field wa_ekko_temp-ebeln.
        call transaction 'ME23N' and skip first screen.

2. Using Function Module

 

    call function 'ME_DISPLAY_PURCHASE_DOCUMENT'
           exporting
             i_ebeln                    = ebeln
*             i_ebelp                    = it_final-ebelp
          exceptions
            not_found                  = 1
            no_authority               = 2
            invalid_call               = 3
            preview_not_possible       = 4
                   .

 

 

Please Use One of this Code


call function 'REUSE_ALV_GRID_DISPLAY'
                     exporting
                       i_callback_program        = sy-repid
                        i_callback_user_command  = 'GETDAILY'

                       it_fieldcat                       = fieldtab[]

                      tables
                        t_outtab                          = it_final.
                              .
form getdaily using ucomm like sy-ucomm  selfield type slis_selfield.

read table it_final index selfield-tabindex.
   case selfield-fieldname.

     when 'EBELN' .

set parameter id 'BES' field wa_ekko_temp-ebeln.
        call transaction 'ME23N' and skip first screen.

or

call function 'ME_DISPLAY_PURCHASE_DOCUMENT'
           exporting
             i_ebeln                    = ebeln
*             i_ebelp                    = it_final-ebelp
          exceptions
            not_found                  = 1
            no_authority               = 2
            invalid_call               = 3
            preview_not_possible       = 4
.
endcase.


endform.

 


Useful SAP Notes for Reference

$
0
0

Below are some of the useful SAP Notes provided by SAP.......These notes are gathered based on my experience (in SD and MM area) and should ideally be helpful for Technical consultants. 

 

1. Adding custom fields to VBAP, VBAK or VBKD.

 

Solution:

Please refer note: Note 143580 - Information on SD BAPIs and customer enhancement concept

This note provides information on which structures are to be modified. How these custom fields can be filled using BAPI.

 

For adding custom fields to MARA..refer Note 44410 - Integrating cust.-specific fields in matl master

 

2. User Exits in Delivery Processing.

 

Solution:

Note 415716 - User exits in delivery processing

If you ever need to understand....on how to work with delivery user exits, this is the most useful note.

This note not only provides information on userexits.....but also on internal tables like XLIKP, YLIKP etc. Which internal table contains which data?

 

Note 209846 - Use of SY-TCODE in delivery processing

This Note provides information on how checks related to SY-TCODE can be avoided in Delivery userexits. (Extract from Note...given below)

In your user exits,use field T180-TRTYP instead of field SY-TCODE. This field has the following characteristics depending on the processing mode:

  • H  Creation of the delivery
  • V  Change of the delivery
  • A  Display of the delivery

    If a differentiation should be required whether the creation of the delivery is carried out online (Transaction VL01N) or is carried out in collective processing (Transaction VL10x), use the V50AGL-SAMMELGANG flag in addition:  

  • T180-TRTYP = 'H' and V50AGL-SAMMELGANG = 'X':
    Creation of the delivery is carried out in collective processing.
  • T180-TRTYP = 'H' and V50AGL-SAMMELGANG = SPACE:
    Creation of the delivery is carried out online.

The mentioned advice works for the new and the old delivery dialog and for inbound and outbound delivery in the same way.

 

 

3. User Exits in Sales Order Processing

 

Note 381348 - Using user exit, customer exit, VOFM in SD

This note provides information on "Exit Technologies" used in SAP. (This note does not tell you...how to implement them!)

 

Note 178328 - Problems due to incorrect user exits in SD

This note is useful because it contains "Basic information concerning the management of internal tables in Sales and Distribution" and "General recommendations for the use of user exists (include technique)"

 

Note 156230 - Requirements: What is permitted, what is not?

If you need to understand Requirement Routines (VOFM Transaction) for Condition Type in SD Pricing. This note is very helpful!

 

4. Performance Problem and Oracle Hints

 

Note 185530 - Performance: Customer developments in SD

Note 191492 - Performance: Customer developments in MM/WM

 

Both the notes, provide good information on how database tables related to respective modules are to be accessed. Worth a look! (Not necessarily helpful for everyone)

 

Note 334224 - Important notes for creating indexes

Note 912620 - FAQ: Oracle indexes

 

Above notes, provide useful information on creation of index and what it is!

 

Note 772497 - FAQ: Oracle Hints

Note 130480 - Database hints in Open SQL for Oracle

 

Both the notes, provide good information on what are Oracle Hints and how they can be used.

 

5. BAPI's and other topics

 

BAPI's to obtain next number in the number range for Customer, Vendor and Contact Person

BAPI_CUSTOMER_GETINTNUMBER
BAPI_VENDOR_GETINTNUMBER
BAPI_PARTNEREMPLOYEE_GETINTNUM

Note from which the above was obtained is Note - 1749700

 

Classes available in SAP for creation of Vendor or Customer is:

VMD_EI_API - Vendor
CMD_EI_API - Customer

Methods are MAINTAIN_BAPI, MAINTAIN

 

Note 582221 - FAQ: BAPIs for purchase orders

Note 1257033 - Cookbook: Modification/enhancement for standard SAP system

Note 623459 - Creating/ changing a search help in the ABAP Dictionary

Note 27 - Recommendations for the ABAP file interface

Note 1319507 - Overview: Analysis of ABAP Web Service Configuration

Dynamically request values from user

$
0
0

Today I’d like to introduce a tool to request a random number of values from user. For example, you’d like to ask and then store a template of some structure to use this pattern further.

I used it to determine sample values for structure of an HR infotype to create a flexible data download program.

Initial screen of this report looks very ascetic:

1.jpg

                    The bottom button is used to request data from user. If you push it you’ll get:

2.jpg

Here you can see a list of P0009 structure fields with their names described at ABAP repository. So any changes of this structure will change this screen with requesting values.

Probably, you’d like to know how many instructions I was to code. Well, lets see it:

 

The first part is to describe my requesting tool:

DATA: lr_request_values TYPE REF TO zcl_bas_dyn_request_values.
  lr_request_values
= zcl_bas_dyn_request_values=>factory( ).

 

 

The second is to get my structure filled with values by user:

DATA: default_p0009 TYPE p0009,
     lr_descr     
TYPE REF TO cl_abap_structdescr,
     lr_elemdescr 
TYPE REF TO cl_abap_elemdescr.
   
lr_descr ?= cl_abap_structdescr=>describe_by_data( default_p0009 ).
    CHECK lr_descr IS BOUND.
 
LOOP AT lr_descr->components ASSIGNING <component>.

      ASSIGN COMPONENT <component>-name OF STRUCTURE default_p0009 TO <field>.
  
CHECK sy-subrc = 0.
   lr_elemdescr ?= cl_abap_elemdescr
=>describe_by_data( <field> ).
   ls_field
= lr_elemdescr->get_ddic_field( ).
  
IF ls_field-scrtext_m IS INITIAL.
    ls_field
-scrtext_m = ls_field-scrtext_s.
  
ENDIF.
   lv_defaultc
= <field>.
   lv_paratype
= 'P0009-' && <component>-name.
  
IF ls_field-scrtext_m IS INITIAL.
    ls_field
-scrtext_m = lv_paratype.
  
ENDIF.
   lr_request_values
->add_parameter(
    
EXPORTING
      iv_parakind 
= 'P'
      iv_paratype 
= lv_paratype
      iv_label    
= ls_field-scrtext_m
      iv_def_value
= lv_defaultc
    
CHANGING
      cv_parameter
= <field> ).
 
ENDLOOP.


And at last request user:

    lr_request_values->request_values( ).

When the last call ends my structure default_p0009 is filled with values user just filled. As you may count it’s just about 20 lines of code to ask user for values of any flat structure from ABAP repository.

And now my code to get this functionality:

 

TXT files attached for class ZCL_BAS_DYN_REQUEST_VALUES and for class ZCL_BAS_DYN_PARAM.

Search inside Open XML documents

$
0
0

Hello.

since Open XML documents are based on OPC and  xml vocabulary,

It can be very helpful to search patterns in documents.

 

for example , if we look for a certain text ,  or version of a document

we can  use outer methods for handle it.

 

we can search for any type including mime types.

Open XML documents let us dive inside the data and handle

it explicitly.

 

there are some kind of  documents that are based on  an image

but in Open XML we can get direct to data, and that is a huge benefit!

Displaying a DMS PDF Document in Web Dynpro

$
0
0

Purpose

 

The plain technical requirement is that a PDF document is stored in SAP needs to be displayed as a Pop-up to the portal user.

 

Details

 

Earlier, I used to use SAP GUI for HTML and call the 'DOCUMENT_SHOW_DIRECT' in a wrapper program with submit.

 

But here is a better way.

 

Create a New method DISPLAY_DOCUMENT in your assitance class, generally the TYPE of document is static but you can keep all as parameterised.

 

Inside the method call the following code

 


 

  DATA : W_URL  type string,
 
          v_url type MCDOK-URL.


CALL FUNCTION 'CVAPI_DOC_VIEW'
 
EXPORTING
    PF_DOKAR              
= I_DOKAR
    PF_DOKNR              
= I_DOKNR
    PF_DOKVR              
= I_DOKVR
    PF_DOKTL              
= I_DOKTL
   PF_HOSTNAME           
= 'DEFAULT'
   PF_APPL_START         
= ' '
   PF_GET_URL            
= 'X'

IMPORTING

   PFX_URL                = v_URL

EXCEPTIONS
   ERROR                 
= 1
   NOT_FOUND             
= 2
   NO_AUTH               
= 3
   NO_ORIGINAL           
= 4
  
OTHERS                 = 5.

 

IF SY-SUBRC <> 0.

* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO

*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.

ENDIF.

 

W_URL = v_url.

 


  data lo_window_manager type ref to if_wd_window_manager.
 
data lo_api_component  type ref to if_wd_component.
 
data lo_window         type ref to if_wd_window.
 

  lo_api_component  = wd_comp_controller->wd_get_api( ).
  lo_window_manager
= lo_api_component->get_window_manager( ).
 

  CALL METHOD lo_window_manager->CREATE_EXTERNAL_WINDOW
   
EXPORTING
      URL           
= W_URL

      MODAL          = ABAP_FALSE
      HAS_MENUBAR   
= ABAP_TRUE
      IS_RESIZABLE  
= ABAP_TRUE
      HAS_SCROLLBARS
= ABAP_TRUE
      HAS_STATUSBAR 
= ABAP_TRUE
      HAS_TOOLBAR   
= ABAP_TRUE
      HAS_LOCATION  
= ABAP_TRUE
    RECEIVING
     
WINDOW         = lo_window.

 

  lo_window->open( ).

 

Output

 

Well, I have called this code on click of ALV on the DMS document number... and here is the result

 

Capture.PNG

Why develop ABAP in Eclipse?

$
0
0

Hello everybody, I've opened this post to discuss about the reasons or convenience for developing ABAP in Eclipse or keep doing it in SAP GUI.

 

I haven't begun yet any ABAP project in Eclipse, but at this point I've found some inconvenients of developing ABAP in Eclipse.

 

The first one is the complexity of installing all the plug-ins you need to start developing ABAP in Eclipse. It is not an easy issue, due to you must know the level of customer SAP release, the Eclipse version that you are using and find the correct plug-ins version.

 

The second one is that developing ABAP in Eclipse is not intuitive, you cannot develop as easy as you do un SAP GUI, there are a lot of steps more that you must carry out to begin your work.

 

What do you think? Bring me some feed back about your experience developing in Eclipse.

 

Regards,

David.

Automatic QA and release request

$
0
0

The motivation behind thisblogcame aftera visit toSAPLabsLatin America in SaoLeopoldo-Brazil. We hadcontact with the SAP expertHeinzLudwigwhointroduced us to theAbapTestCockpit. When askedifSAPwas alreadyusing theATCwasfunnyhis reaction...

We did not have alltheprerequisitesto install theATC (EHP6 and SP3 ABAP), w
e intend toupdate thelandscapein anear future. But we hadthe idea to createa similar routinetostaticcode verification. We addto this therequests automatic releasewhen nothingwasfound, in case of false positiveoccurred, the request forexemptionoccursvia email.

 

This solution is running in our environment about three months and during this period we noticed an improvement in code quality and especially the maturity of team programmers.

 

ATC is a wonderful tool for quality assurance and automatic verification, merging applications like extended check, code inspector and exemption authorization by workflow.

 

If your landscape supports ATC, you will not have problems to start using it.

Just take a look on some good blogs:

 

http://scn.sap.com/docs/DOC-32628

http://scn.sap.com/docs/DOC-32172

http://scn.sap.com/docs/DOC-31773

http://scn.sap.com/community/abap/testing-and-troubleshooting/blog/2012/12/03/teched-2012-the-brand-new-abap-test-cockpit-a-new-level-of-abap-quality-assurance

 

But if your company still waiting to upgrade to compatible version, do not wait anymore. Automatic quality assurance not is the future - but the present. You can start it with some abap code and little work. The hard work is change the process - and the people's mind!

Be careful:codequalitywithouttestingis abad code!

 

 

 

1st step.

Create a BADI for CTS_REQUEST_CHECK.

SE19 - CTS_REQUEST_CHECK.jpg

 

2nd step.

Create a implementation class. Activate the BADI created.

Implementation class.jpg

 

3rd step.

Configure code inspector variant: transaction code SCI. It is possible to create new checks too. And the bestnews: their struggle nowwill be usedlaterwhen thelandscapeiscompatible withATC!

http://wiki.sdn.sap.com/wiki/display/Snippets/Code+Inspector+Check

http://scn.sap.com/community/abap/blog/2006/11/02/code-inspector--how-to-create-a-new-check

 

SCI variant.jpg

 

4th step.

Code the method CHECK_BEFORE_RELEASE in the class that was created in the step 2.

 

How it works: It isinformedthattherequestto be evaluated; its objectsmust beextracted(programs, classes, functions and others) and the source codeof each objectas well,using thestandard functionSVRS_GET_REPS_FROM_OBJECT.
Tofind the differencebetween the current versionand thepreviousSVRS_COMPUTE_DELTA_REPSfunctioncan alsobe used.
With thesource codeextracted, just perform thevalidationsand present thecheckpoints founded.

 

The focusis notpresentthe codeitself, but to showhow simple it is, the following how to calltheextended checkandcodeinspector.

Manypossibilities andideaswere emerging, asdo the checkingonlythemodified version, ortheentire programwhen it issomething morecritical.

 

You can call code inspector like it was called in this thread:

 

Or you can do only extended check, if you want to do a "soft check".

{code}

  wa_flags-x_dat = 'X'.
  wa_flags-x_per = 'X'.
  wa_flags-x_txt = 'X'.
  wa_flags-x_bre = 'X'.

... "other extended check validations if you want, just use wa_flags strucutre.

   LOOP AT me->t_request_obj ASSIGNING <fs_obj>.

     o_checker = cl_slin_driver=>get_checker_group( wa_flags ).

     v_prog = <fs_obj>-obj_name.

     o_ref = cl_slin_driver=>io_result( progname    = v_prog
                          ignore_pseudo_comments = v_comment_flag
                          call_cntx              = v_call_cntx
                          checker                = o_checker
                          cache_use              = v_cache_use ).

     o_ref->old_get_result_tables( IMPORTING result = t_result result_stat = t_result_stat ).

...


   ENDLOOP.

{code}

 

This same logic is also performed in a transaction report and in the SE09/SE10 release button. We created authorization objects to secure that only approvers can release requests with points to check with inserting of a justificative.

 

SE09/SE10 screen asking an exemption on release

Critical errors.jpg

 

The transaction report: "points to do better"

Z_ATC.jpg

Errors_result.jpg

 

That is all folks!

Sales Flow (Sales Order->Delivery->Transfer Order->TO Confirmation->Shipment) in ECC

$
0
0

Sales Order Creation

 

Transaction VA01

Enter Order Type and Click Enter.

 

1.jpg

 

Enter below information and press enter

 

Ship-to-Party – 22266601

Sold-to-Party – 22266601

PO Number – 12345      

Material – 5260010

Quantity – 1 EA

2.jpg

Click Save

Sales Order Number – 44 is created

 

3.jpg

 

Delivery Creation

 

Transaction VL01N

Enter Shipping Point and Order Number – 44 and press Enter

 

4.jpg

4a.jpg

In transport tab enter, Route as 000001 and Click Save.

Delivery number – 8000052 is created

5.jpg

 

Transfer Orders Creation & Confirmation

 

Transaction LT03

6.jpg

Enter Warehouse Number, Delivery as 8000052, Press Enter and Click Save

 

7.jpg

Transfer Order – 27 is created

 

Transaction LT12

Enter TO Number and Warehouse

8.jpg

Press Enter

10.jpg

Click Save

Transfer Order Confirm

11.jpg

 

Shipment Creation

 

Transaction – VT01N

Enter TransportPlanningPt and Shipment Type

13.jpg

Press Enter

14.jpg

Click Save

Shipment Number – 1009 is created

 

11.jpg

 

Transaction VT02N

Enter Shipment Number 1009 and press Enter

 

16.jpg

Click Deliveries

17.jpg

Enter Outbound Delivery Number 8000052 and click Execute.

 

18.jpg

Click Save

 

So this is how Sales Order->Delivery->Transfer Order->TO Confirmation->Shipment


Creating Dynamic ALV

$
0
0

Requirement

Recently we had a requirement to create a dynamic ALV. The number of columns in the output would vary depending upon the number of unique records in another table say ZRECORD. If ZRECORD had 7 unique records, our ALV should have 7 columns with column name represented by the key field of ZRECORD. 

Solution
1. Define three field symbols.
<fs_dyntable> TYPE standard table
<fs_dyn_wa> TYPE any
<fs_dyn_field> TYPE any.

2. Create a table similar to fieldcatalogue of type lvc_t_fcat (t_fieldcat) by looping through ZRECORD and appending column names depending upon the key field of ZRECORD to t_fieldcat.

3. T_fieldcat is passed too cl_alv_table_create=>create_dynamic_table and the new imported table is assigned to <fs_dyntable>

4. <fs_dyn_wa> is created as line of <fs_dyntable> as shown below.
CREATE DATA wa_new_line LIKE LINE OF <fs_dyntable>.
ASSIGN wa_new_line->* TO <fs_dyn_wa> (wa_new_line is reference type of DATA)

5. Each row of this dynamic table now can be filled using
ASSIGN COMPONENT (n) (column number)
OF STRUCTURE <fs_dyn_wa> TO <fs_dyn_field>.

<fs_dyn_field> = (data need to input).

6. After filling each row append <fs_dyn_wa> to <fs_dyntable>

7. Pass <fs_dyntable> to REUSE_ALV_GRID_DISPLAY as t_outtab, along with the new fieldcatalogue and other desired parameters.

How to check the SAP-directories ( Application layer directory ) otherthan al11

$
0
0

Hi ,

 

    If you dont have access to the AL11 to view the SAP-directories , then

 

   GOTO TCODE SE38 -> Execute the RSWATCH0 Program

 

   

2013-07-02_182734.jpg

 

    After Execution

 

        2013-07-02_182734.jpg

 

 

Regards,,

 

Aditya.

RE-FX: How to assign a rental space to an object group in a real estate contract

$
0
0

I've had a problem assigning a newly created rental space (cut out of a poolspace) to an object group.

I solved it and want to blog it to prevent other real estate developers from running into this mess with assigning rental objects to an object group.

 

At first, I was trying my luck with CL_REBD_OBJ_ASSIGN_MNGR_BO. But due to the fact, that there is only a interface available with OBJASSTYPE = '10' (Contract=>Object Group),

 

Table TIVBDOBJASSTYPE:

OBJASSTYPE IMPLIFNAME                                            GUIFMPBO                                XOBJASSTYPE        

10                   IF_REBD_OBJ_ASSIGN_MNGR_BO     REBD_GUI_OBJASS_BO_PBO   Vertrag => Objekt(gruppe)
11                                                                                   REBD_GUI_OBJASS_BO_PBO   Objektgruppe => Objekt  (Object Group => Rental Object)

 

Later I discovered, that the GUI is using using the class CL_RECN_OBJ_ASSIGN_MNGR_CN to accomplish what I wanted to do.

 

At first, I was not able to apply a method to do just that with objasstype 11.

As you can see in the table,  type 11 can only be handled in the GUI PBO Module. That's why I wrote nearly a copy of the code I found there when I debugged the '+' Button to add an object to the object group in the GUI.

 

Surprisingly there's this simple insert_bus_object-method at the end of the code snippet that does the job.

 

Everything works fine in the insert_bus_object-method, it quits with sy-subrc = 0:

 

Code

   METHOD add_rental_space_to_objgroup.
* Fügt ein Mietobjekt in eine Objektgruppe ein
  DATA:
    lo_obj_assign_mngr_cn TYPE REF TO cl_recn_obj_assign_mngr_cn,
    lt_obj_assign_bo      TYPE re_t_obj_assign_bo,
    lt_object_objtype     TYPE re_t_reca_object_objtype_x,
    ls_obj_assign         TYPE rebd_obj_assign,
    ls_obj_assign_bo      LIKE LINE OF lt_obj_assign_bo,
    ls_object_objtype     LIKE LINE OF lt_object_objtype,
    ld_objnr              TYPE recaobjnr,
    ld_adjustnumber       TYPE rebd_obj_assign_bo_x-adjustnumber,
    lf_assignonlyinfo     TYPE recabool,
    lo_bo                 TYPE REF TO if_reca_bus_object,
    ld_ident              TYPE recaident.

* init
* Object Assign Manager Contract
  lo_obj_assign_mngr_cn = io_obj_assign_mngr_cn.
  CLEAR: lf_assignonlyinfo.

* I. Which object will be added?
  ld_objnr = iv_objnr.

* II. get allowed object information
  CLEAR: lt_object_objtype.
  lt_object_objtype = lo_obj_assign_mngr_cn->get_objtypes_allowed( ).
* {lo_obj_assign_mngr muss vom Typ \CLASS=CL_RECN_OBJ_ASSIGN_MNGR_CN sein!}

* set valid from and valid to of assignment
  ls_obj_assign-validfrom = md_sheet_date.
  ls_obj_assign-validto   = reca0_date-max.

*   III. check if object already is present
  CALL METHOD lo_obj_assign_mngr_cn->get_list_bo
    EXPORTING
      id_objnrtrg    = ld_objnr
      if_fix_periods = abap_false
    IMPORTING
      et_list        = lt_obj_assign_bo.

*--> no entries in this table!

* delete generated entries
  DELETE lt_obj_assign_bo WHERE ismultiassgen = abap_true.

*   if yes use current date for insertion...
  IF lo_obj_assign_mngr_cn->is_attribute_supported(
            id_attribute = rebd2_objass_attribute-period ) = abap_true.

 

* => it's not true in my case, scroll down!


    READ TABLE lt_obj_assign_bo INTO ls_obj_assign_bo
      WITH KEY objnrtrg  = ld_objnr
               validfrom = ls_obj_assign-validfrom.
    IF sy-subrc = 0.
      ls_obj_assign-validfrom = sy-datum.
      LOOP AT lt_obj_assign_bo INTO ls_obj_assign_bo
        WHERE objnrtrg  = ld_objnr.
        IF ls_obj_assign_bo-validto > ls_obj_assign-validfrom.
          IF ls_obj_assign_bo-validto <> reca0_date-max.
            ls_obj_assign-validfrom = ls_obj_assign_bo-validto + 1.
          ENDIF."ls_obj_assign_bo-validto <> reca0_date-max.
        ENDIF."ls_obj_assign_bo-validto > ls_obj_assign-validfrom.
      ENDLOOP."AT lt_obj_assign_bo INTO ls_obj_assign_bo
    ENDIF."READ TABLE lt_obj_assign_bo INTO ls_obj_assign_bo

  ELSE.
    READ TABLE lt_obj_assign_bo INTO ls_obj_assign_bo
      WITH KEY objnrtrg     = ld_objnr
               validfrom    = ls_obj_assign-validfrom
               adjustnumber = ld_adjustnumber.
    IF sy-subrc = 0.
      CALL METHOD cf_reca_bus_object=>find_by_objnr
        EXPORTING
          id_objnr    = ld_objnr
        RECEIVING
          ro_instance = lo_bo
        EXCEPTIONS
          error       = 1
          OTHERS      = 2.
      IF sy-subrc <> 0.
*        mac_symsg_send_as_type 'S'.
*        CONTINUE.
      ENDIF."find_by_objnr

* ?
      CALL METHOD lo_bo->get_ident
        IMPORTING
          ed_ident = ld_ident.
*      MESSAGE s028(rebdoa) WITH ld_ident.
*      CONTINUE.
    ENDIF."READ TABLE lt_obj_assign_bo INTO ls_obj_assign_bo
  ENDIF."go_obj_assign_mngr->is_attribute_supported

 

************************

* MAIN RUN STARTS HERE *

************************


  CLEAR ls_object_objtype.
  READ TABLE lt_object_objtype INTO ls_object_objtype
       WITH KEY objtype = ld_objnr(2). "IM

  lf_assignonlyinfo = abap_false.

 

* Insert Rental Space to Object Group
  CALL METHOD lo_obj_assign_mngr_cn->insert_bus_object
    EXPORTING
      id_objnr          = ld_objnr
      id_validfrom      = ls_obj_assign-validfrom
      id_validto        = ls_obj_assign-validto
      id_adjustnumber   = lc_adjustnr_10
      id_assignonlyinfo = lf_assignonlyinfo
    IMPORTING
      es_obj_assign     = ls_obj_assign
    EXCEPTIONS
      error             = 1
      OTHERS            = 2.
  IF sy-subrc <> 0.
*    mac_symsg_send_as_type 'S'.
*    CONTINUE.
  ENDIF.

 

 

Checking the resulting contract with this rental space delivers in tab Objects the wanted hierarchy Object Group -> Rental Space.

Don't forget to check_all, store and commit your data of the created contract object!

 

P.S.: I would have expected a method in the Object Group-Interface IF_REBD_OBJECT_GROUP or an Interface in TIVBDOBJASSTYPE like IF_REBD_OBJ_ASSIGN_MNGR_BO with OBJASSTYPE = 11 which does the job!

Open XML developer Blog

Create Global Class and Method for Application Log

$
0
0

The goal of the object is to create the Global Class and Method for Application Log so that it can be reused where necessary in any RICEF object.

 

Application Log provides an infrastructure for collecting messages and exceptions in a log, saving, reading and deleting logs in the database and displaying them.

 

Application Log provides multiple advantages:

  • System-wide uniform event logging
  • Accessible standardized UI based on ABAP List Viewer (ALV)
  • High capabilities for analysis of log data  

 

Application logging records the progress of the execution of an application. Whereas the system log records system events, you can use the application log to record application-specific events.

 

Application Log is designed to temporarily store messages. Logs should be deleted in intervals (e.g. weekly batch job for deleting logs) to avoid too high database load.

 

A typical use of the Application Log is within delivery processing. Negative results of a dangerous goods check are written to the Application Log. Application messages and reactions are collected based on a customer defined examination schema (reactions determine how the document will be handled further). This approach increases the transparency of the process for end users. Messages are collected temporarily and are not saved to the database.

 

Create Custom Application log objects

First create object and sub object, Go to transaction SLG0. Go to change mode and click on New entries button on the application tool bar.

1.jpg

Then define the sub object for the object: Select the object and double click on sub object:

2.jpg

 

Create Global Class and Method to define the Application log code:

3.jpg

Define that Class and method in the code wherever necessary:

4.jpg

The Method will create log with all the messages and generate log (Can also check in Transaction SLG1):

5.jpg

Processing Logic

 

Define the following Parameter in method

6.jpg

Define following Data in the Method

7.jpg

Populate the Header data with the following details

8.jpg

Create the log with FM BAL_LOG_CREATE

9.jpg

 

Add all the message in the log using FM BAL_LOG_MSG_ADD

10.jpg

Save the Log using FM BAL_DB_SAVE

11.jpg

Display the log using FM  BAL_DSP_LOG_DISPLAY

12.jpg

Coding

 

METHOD CALL_APPLICATION_LOG.

***********************************************************************
* Data declaration
***********************************************************************
* Workarea
  DATA:       lwa_s_log      TYPE bal_s_log,    "Appl Log:header data
                  lwa_balloghndl TYPE balloghndl,   "Appl Log: Log Handle
                  lt_balloghndl  TYPE bal_t_logh.

 

  CONSTANTS: lco_x TYPE char1 VALUE 'X'.


  FIELD-SYMBOLS: <lfs_msg> TYPE bal_s_msg.

 

  CLEAR lwa_s_log.
  lwa_s_log-object       = i_object.
  lwa_s_log-subobject    = i_subobject.
  lwa_s_log-aldate     = sy-datum.     "Date
  lwa_s_log-altime     = sy-uzeit.     "Time
  lwa_s_log-aluser     = sy-uname.     "user name
  lwa_s_log-altcode    = sy-tcode.     "Transaction code
  lwa_s_log-alprog     = sy-cprog.     "Program name

*- create log
  CALL FUNCTION 'BAL_LOG_CREATE'
    EXPORTING
      i_s_log                 = lwa_s_log
    IMPORTING
      e_log_handle            = lwa_balloghndl
    EXCEPTIONS
      log_header_inconsistent = 1
      OTHERS                  = 2.
  IF sy-subrc <> 0.
    CLEAR lwa_balloghndl.
  ELSE.
*- Add all error messages
    IF <lfs_msg> IS ASSIGNED.
      UNASSIGN <lfs_msg>.
    ENDIF.
    LOOP AT i_msg ASSIGNING <lfs_msg>.

      CALL FUNCTION 'BAL_LOG_MSG_ADD'
        EXPORTING
          i_log_handle     = lwa_balloghndl
          i_s_msg          = <lfs_msg>
        EXCEPTIONS
          log_not_found    = 1
          msg_inconsistent = 2
          log_is_full      = 3
          OTHERS           = 4.
      IF sy-subrc NE 0.
        REFRESH lt_balloghndl.
      ENDIF.
    ENDLOOP.
* Save the log
    CALL FUNCTION 'BAL_DB_SAVE'
      EXPORTING
        i_client         = sy-mandt
        i_save_all       = lco_x
      EXCEPTIONS
        log_not_found    = 1
        save_not_allowed = 2
        numbering_error  = 3
        OTHERS           = 4.
    IF sy-subrc EQ 0.
      REFRESH lt_balloghndl.
    ENDIF.
*-- Display Application Log
    APPEND lwa_balloghndl TO lt_balloghndl.
    CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
      EXPORTING
        i_t_log_handle       = lt_balloghndl
        i_amodal             = space
      EXCEPTIONS
        profile_inconsistent = 1
        internal_error       = 2
        no_data_available    = 3
        no_authority         = 4
        OTHERS               = 5.
    IF sy-subrc NE 0.
      REFRESH lt_balloghndl.
    ENDIF.
  ENDIF.

ENDMETHOD.

Configuration of Remittance Checks Adobeforms in SPRO

$
0
0

Type of Object – FORM

 

Description – Configuration of Remittance Checks Adobeforms in SPRO

 

Process – FI

 

Document Purpose

Generally we configure SAP Script for Remittance Checks in SPRO.

 

Below is the configuration of Remittance Checks for Adobe forms in SPRO.

 

Configuration Details

Transaction SPRO

Financial Accounting (New) -> Banking Accounting -> Business Transaction -> Check Deposit -> Define Form

1.jpg

Click Define Forms

2.jpg

 

Transaction Code – FF68

 

Enter Bank Key, Bank Account, Currency, Group, Username, Entry Date, Transaction, Posting Date, Value Date and Currency.

 

3.jpg

Click Individual List

4.jpg

Output Device- ZPDF and click Print Preview

 

Output will be as below:

5.jpg

Open XML documents on a Background Task

$
0
0

This is a screen cast showing  Word Open  XML documents generation

from  SAP  on a Background  Job  (SM37)

The screen cast also showing selection

of the files content controls  data back into  SAP.

 

 

http://www.youtube.com/watch?v=zNhcnDwK-88

 

 

Hope you'll like  it.   

 

            Ronen  Almog

 

OpenXML.jpg


Useful ABAP Packages for Demo programs

$
0
0

Hi everyone,

 

As a developer, whenever we have to work with a new object, to grab the new concept, we may:

- Read about it on http://help.sap.com/nw_platform#section6

- Browse through different blog posts/documents on SCN

- Simply Google it

 

Another way I tend to do is to find the demo programs for that object in SAP. This is very useful as we have chance to see how the object works in action, and at the same time follow standard development practices from SAP.

 

So in this blog post, I will share the packages that I found very useful for object demoing purposes. Hope it is useful to you and if you know of any packages, feel free to add it in the comment so that we all have more knowledge. You may want to browse through the package from SE80 to find the demo of the concept you want to know about.

 

PackageTitleCommentsExample Reports/Webdynpro Components
BC400

Training: BC400 - ABAP Workbench: Concepts and Tools.

Contain programs that show some fundamental concepts of ABAP


BC401Course: BC401 - ABAP Objects. Contain programs that demonstrate some OO concepts in ABAP.
BC405Training Course BC405: List Creation and QueryContain programs that demonstrate concepts in Report Programming (e.g. ALV, Report Event, Logical Database)
BC412Course BC412: ABAP Dialog Program with EnjoySAP ControlsContain programs that demonstrate concepts in Dialog Programming
BC417SAP Training: BC417Contain programs that demonstrate BAPI concept
BC427BC427 Training ObjectsContain programs that demonstrate Enhancement Framework concepts (Classic BADI, New BADI, etc.)
BC470Training Course: BC470 - SAP Smart FormsContain programs that demonstrate SmartformsSAPBC470_DEMO
SABAPDEMOSDemos for ABAP DocumentationMany programs that demonstrate ABAP language concepts from ABAP Documentation

My favorite:

DEMO_REGEX

DEMO_REGEX_TOY

DEMO_JAVA_SCRIPT_MINI_EDITOR

SDW4Packages for Demo Center from tCode DWDMPrograms that demonstrates objects in Control Framework (I havent had much opportunities to use it in Production)
SLISGeneric list types

Contains pretty much useful and detail example with using ALV (REUSE_ALV_* and CL_GUI_ALV_GRID)

My favorite: BCALV_GRID_*
SALV_OM_OBJECTSALV Object Model Basis ClassesContains pretty much useful and detail example with using SALV (CL_SALV_TABLE)

My favorite

SALV_DEMO_TABLE_EVENTS

SALV_DEMO_TABLE_*

SWDP_DEMOWebdynpro Demo ApplicationContains many useful Web Dynpro applications that illustrate essential UI elements in Web Dynpro
SWDP_DEMO_TUTORIALSWebdynpro Demo ApplicationDemo Web Dynpro Application concepts with Flight Booking system, Quiz System
SWDP_TESTWeb Dynpro: Tests

Many many useful Web Dynpro applications, illustrate UI elements usage and important concepts in Web Dynpro

A must look if you want to grab Web Dynpro concepts

WDR_TEST_EVENTS

SEU_TREE_CONTROLOO Framework for Tree ControlI haven't had chance to work with Tree Control object.
SOFFICEINTEGRATIONPlatform- and application-indep. Office integrationOLE. I haven't had chance to work with Office Integration.
APB_FPM_DEMOFloorplan Manager (Examples and Demo applications)Demo applications for FPM to show concepts of Guided Activity Floorplan (GAF), Object Instance Floorplan (OIF)Web Dynpro Application: FPM_DEMO_FLIGHT_OVERVIEW

 

 

So that's it. Above is my current list of useful packages. Browse through the package, find the program that illustrate the concept you want to grab. Hope it will helps you. Please comment if you know any other useful packages and I will also update this blog post when I find new useful packages. Cheers!

ABAP Objects - I Want to Believe

$
0
0

 

ABAP Objects is the Way Forward – I Want to Believe

 

New Apps 01 - Santa.png                       

When I returned from Germany to Australia in May 2012 I made a vow to myself that I would do all new programming in Object Orientated ABAP whether I liked it or not. Since then I have written a lot of blogs on the subject, for example:-

 

http://scn.sap.com/community/abap/blog/2012/10/27/crossing-the-great-divide--procedural-vs-oo-abap-programming

 

I have been reading everything on the internet about this matter, I will include a bibliography of the most helpful articles at the end of this blog, but in essence, the whole world seems to be telling be that if I write my new programs in an OO fashion, then I will get the following benefits:-

 

·         Programs are faster to write

·         Programs are easier to maintain

·         Programs are highly unlikely to break when you change them

·         Every project generates re-usable objects to make all further projects easier

 

If this is true, then to quote Ben Elton in his book “Chart Throb” I would say “I want this – I want this SO MUCH”.

 

Opportunity Knocks

 

Thus far I have been concentrating on the so called “legacy code”

 

http://scn.sap.com/community/abap/blog/2013/04/18/are-you-writing-evil-abap-code

 

i.e. the vast bulk of my companies system which is written in procedural ABAP. This year however a gigantic project has come my way, one that will need a bucket load of coding, a completely new concept, so everything has to be written from scratch. This is the acid test. Thank god my current boss lets me try out new things. Not every boss would.

 

It would be so easy to do everything just the way I have always done it, but now is the time to jump out of my comfort zone, and try and write the whole thing according to all the principles I have just learned.

 

I will take longer – of that I have no doubt – but that is because (at least for me) it takes years of playing around with OO programming before you really know what you are doing. Nonetheless, the aim of the game is can I get the other three benefits, and the more I do this the easier it will become, and then maybe I can get all four.

 

Or is the whole thing an illusion? Could it be a light? It’s just an illusion. Could it be a light? In all this confusion. There is only one way to find out.

 

He likes to keep his Fire Engine Clean – it’s a Clean Machine

 

I wrote a book review the other day on SCN

 

http://scn.sap.com/community/abap/blog/2013/06/17/are-you-writing-dirty-filthy-abap-code

 

in regard to Robert Martins’ book “The Clean Coder”. The book I actually wanted was “Clean Code” by the same author. Once I realised I had the wrong book I ordered the right one as well, and now I have got that and am reading it.

 

I had a comment that said I might not find it as useful as I might like as the vast majority of it was in Java. The funny thing is that – at least IMHO - ABAP Objects has been trying to become more and more like Java as the years have gone by – in 7.40 ABAP there is even an equivalent of the Java keyword “NEW” as far as I can see – so this is maybe more relevant to the SAP world than one might think.

 

As far as I can see thus far the bulk of the advice relates to OO programming in general, albeit always using Java as the example language. I could relate virtually all of it to ABAP Objects. There are a few guidelines presented as good programming practise, which really are designed to get around Java specific constructs.

 

For example Uncle Bob says the reason you should not have more than one or two parameters in a function is because you can’t tell which parameter the value is going to  - as far as I can see in Java you have to say DoSomething( one_value, another_value, yet_another_value) and you don’t know what the parameters are mapped to. In ABAP it is 100% the reverse, the parameter names – in OO world - are compulsory.

 

So in Java the rule makes sense, in ABAP it doesn’t.

 

So, in the book it’s easy to spot the Java specific things, but they are in the minority. Once I have finished it – and the foreword says if you finish this quickly you  haven’tgot the point – I will blog about it in great detail.

 

It’s Alive! It’s Alive! It’s Alive!

 

Naturally I can’t say what I am working on, but I can use the good old SAP practice of using SFLIGHT as an example. However that is boring, so I am going to do this as in the form of a story, and say that I am working on a project for Baron Frankenstein to create a better monster. His prior monsters did not work too well, so SAP convinced him to sign up to their rapid deployment service for cloud based, mobile, in-memory, monster making.

 

One million euros later he realised that the “out of the box” solution didn’t give him everything he wanted so he hired me to write a monster making program in SAP whereby he inputs all the attributes he wants from a monster and my program uses algorithms as complicated as the human genome project, to prepare the final data, which then gets interfaced to his monster making machine via PI during a thunderstorm.

 

Now, amazing as it might seem, some people may say that is a silly example. The funny thing is, in real life, the task ahead of me is just as complicated, if not more. I also think I am going to enjoy it – a lot – for the very reason that it is so complicated. It’s better than having to write an ALV report to dump out the contents of BSEG.

 

Memento

 

New Apps 02 - Memento.png

 

The most difficult thing for a procedural programmer like me is you have to do everything backwards – that is you START by testing, before you have written any actual code. Does that sound like madness?

 

Normally you write everything and then see if it works. Often the only way you REALLY know if it works is when it goes live in production and then you users tell you what they think.

 

The other day I got a classic email from a user, after she had tested and signed off my latest round of changes to her application, and after those changes had gone into production.

 

The email more or less said “this is now working the way we asked for it, but this is different to the way it worked before the changes”. To me, that was the definition of success, to the user it was the definition of failure. After a bit more digging around, it turned out to be the ever popular “this is just what I asked for, but not what I want” situation.

 

Out of Their Minds

 

After you have been in IT for a while, it becomes clear the only way you will ever give the users want they really want, is to magically read their desires straight out of their brains, because the actual requirements bear no relation to what you are actually going to get on any sort of specification, or even from what people will say to you they want.

 

One fine day I had to write a souped up version of F-32 which used some fancy algorithms to bring together groups of customer invoices against the payments they made. In my industry customers don’t just pay one invoice at a time, it is horribly complicated, and on top of that F-32 is a horrible transaction, the J.D.Edwards equivalent beats it into a cocked hat.

 

Anyway, none of that is really relevant; the point is I made a huge effort to make sure this (procedural) program did everything the specification asked for. I told the manager who wrote the specification I took every sentence in the specification and found a place in my program where I could cut and paste it as a comment. If I could not find such a place then that told me I may have not fulfilled the requirement. He had no idea what I was on about, but it sounded good, he said he tested it and everything was fine, into production it went.

 

The next day he came and told me that the “XYZ” rule was not being followed, and that rule was the most important rule, it was the whole reason the program was being written in the first place. A naïve programmer might have asked why, if it was so important, it was not mentioned in the specification, or even by word of mouth, but I am over such things.

 

In the famous IT article “Design By Contract” Bertrand Mayer mentions that when you hire a cook you do not actually have a clause in the contract saying “don’t burn down the kitchen” – it goes without saying. You would still feel burning down the kitchen was a breach of contract, even if it was not in the contract. In the same way, some things are so obvious to business users they literally cannot conceive you would not know it, so why bother putting it in the specification?

 

I’ll Tell You What I Want, What I Really Really Want

 

I have been in my organisation 23 years, so I know what people want. They want the same thing your users’ want, what every user wants.

 

They want the system they had before SAP. They want SPREADSHEETS. Tell me that is not true!. If it isn’t true, how come every time IT turns their back, people start doing all their tasks off system using spreadsheets? This is why in the last year I have found ABAP2XLS to be such a hit with end users.

 

So, I tracked down Victor Frankenstein’s assistant, Fritz (known as Igor), and asked him how they made monsters before the advent of SAP. It turns out they had a massive spreadsheet, and on one sheet you put in values, and a whole bunch of VLOOKUPS and the like were down on twenty other tabs full of data, and after going through assorted formulas the final result came out on the last tab.

 

Then I go to the Baron and ask him “if you could have that exact same thing in SAP, would you be happy?” and naturally the answer is “of course”. So a direct translation into ABAP would be a good starting point, and only after that could we get to the underlying problem, which is the current system (spreadsheet) doesn’t do everything he wants, which is why I was called in originally.

 

All Right Now

 

This is wonderful news in all sorts of ways, because we have a starting point. In the current system – which is a spreadsheet – if you put in a certain set of input values you get a certain set of output values. Making the – possibly dubious – assumption that the current system is correct, thenyou have a high level TEST – which is supposed to be our starting point before we right the program.

 

As an aside, in regard to the old system being presumed to be correct, experience has shown that when the new SAP system comes up with a silly answer, and it can be proved that the same answer comes from the old system with the same input, people grudgingly admit the old system was not perfect, and then the logic can be corrected.

 

The other wonderful thing about spreadsheets is that the calculations are not all done in one hit – if you have a hundred calculations and lookups, you don’t do them all in one cell, you do each calculation or lookup one at a time, in a different cell.

 

So our list of tests would look like this:-

 

·         A bunch of so called “user acceptance tests” which revolve around putting different input criteria into the “black box” of the program calculation engine and then checking the final result is correct

·         A much bigger bunch of “unit tests” which test the inputs and outputs of the much smaller blocks of code which make up the “black box” i.e. the individual calculations

 

I stress again, we haven’t written anything yet, we are going to start with the tests, hence “test driven development”.

 

New Apps 03 - Keep Calm.png

 

Figure 3 – Keep Calm

 

So, I have all my tests already because I have a whacking big spreadsheet, which just needs to be translated into ABAP as a first step.

 

I am going to start my creating the framework to run a unit test which is a “user acceptance test” i.e. I input the same things that are on the first tab in the spreadsheet and expect the same results as on the final spreadsheet tab. It will be a long time before that test passes, but we start off with an end goal and a journey of a thousand steps.

 

This is it. I am now actually going to write some ABAP. The instant problem is – will my colleagues let me, or will I be drowned in the sea of support?

 

You say Tomato, I say Tomato

 

In my recent blog

 

http://scn.sap.com/community/abap/blog/2013/06/17/are-you-writing-dirty-filthy-abap-code

 

I talked about using the “Pomadoro technique” to try and be more efficient while I write this new beast. In essence this involves setting a wind up tomato timer to 25 minutes and trying to work on something uninterrupted for that, seemingly short, time period.

 

Amazingly, you can download a 45 page book telling you how to best use your wind up tomato.

 

http://www.pomodorotechnique.com/download/pdf/ThePomodoroTechnique_v1-3.pdf

 

There is a whole web site about this, and you can even take exams and become a “master of the tomato”. This is like “The Goodies” in the UK where you became a master of hitting people over the head with a black pudding, and the better you got the bigger hat you got to wear.

 

New Apps 04 - The Goodies.png

 

Figure 4 – The Goodies

 

If that is too radical for you, a read a much simpler tip the other day for being more efficient at work – it is claimed that the average work day is a constant stream of interruptions, after each one it takes twenty minutes to really get back into what you are doing. The most common interruption is the outlook desktop alert appearing in the corner of your screen telling you a new email has just arrived.

 

I don’t know about you but I cannot stop myself from breaking off to see what it is, which is crazy, because I KNOW what it is, because the title and sender was in the little box that popped up. It is even crazier because if they are in the same building as me, regardless of whether I read the email or not, they are going to walk over to my desk ten minutes later anyway to say the exact same thing as they just wrote. It makes you wonder why they bothered writing the email.

 

Office Communicator is a million times worse, because someone can see if you are at your desk and have pressed a button on the keyboard in the last few minutes, so they know for a fact you are there, and when they send an instant message people are AMAZED if you don’t break off what you are doing and answer back straight away.

 

Here we have examples of tools which look incredibly useful at first glance, but end up paralysing the whole organisation. Really I should switch my email off for large chunks of day, but I just can’t bring myself to do that, so last Friday I took the enormous step of switching off the “desktop alert” so the little box does not keep popping up every two minutes. Next cab off the rank will be telling the office communicator (which I can’t switch off) that I cannot be disturbed because I am in a meeting, a meeting which lasts forever.

 

Simon Template

 

To start off with I am going to make all the classes local, later on we can see what might best live in a Z repository object. Again, I am sure everybody does everything differently, but I find that after about a week in the job of ABAP programming you never do anything from scratch, but have a series of skeletal templates you copy and then alter.

 

In this case I have small “type 1” executable program so I can have a selection screen (as opposed to the imaginary alternative) and inside that have some includes, a TOP in case I dare to have any global variables, and INCLUDES for the local class definitions and implementations.

 

Since unit testing is the be all and end all, the first thing to do is make sure you can test private methods. The “clean coder” book seems to imply you can’t do that at all in Java, which seems strange, and you can’t do it in ABAP either without the following workaround. The trouble with these workarounds is that SAP might take them away at a moment’s notice. In this case I really hope they do not.

 

*----------------------------------------------------------------------*
*       INTERFACE lif_unit_test
*----------------------------------------------------------------------*
* You need a blank interface defintion if you want to be able to do
* unit tests on private methods
*----------------------------------------------------------------------*
INTERFACE lif_unit_test.
ENDINTERFACE.                    "lif_unit_test

 

Next, the class that I am going to be testing needs to be FRIENDS with that interface.

 

CLASS lcl_monster_simulator DEFINITION FINAL FRIENDS lif_unit_test.

 

Lastly, the test class needs to refer to that interface also.

 

CLASS lcl_test_classDEFINITION FOR TESTING
   RISK LEVEL HARMLESS
   DURATION SHORT
   FINAL
.


 
PUBLIC SECTION.
   
INTERFACES lif_unit_test.

 
PRIVATE SECTION.
   
DATA: mo_class_under_test         TYPE REF TO lcl_monster_simulator,

 

None of the above adds any value; it is just something that has to be done to avoid an SAP limitation. Obviously you would want to test private methods; you would want to test everything, that’s the whole point of the exercise. If you don’t have an automated test, it can (and will) break when you change some seemingly unrelated part of the program.

 

Method In My Madness

 

The first method I will define in my test class will be “make monster” which is what I would describe as a “user acceptance test” i.e. it will call the main method of the class under test with the inputs and outputs of the spreadsheet as a whole.

 

METHODS: setup,
*--------------------------------------------------------------------*
* Specifications
*--------------------------------------------------------------------*
   
"IT SHOULD.....................
   
"User Acceptance Tests
    make_monster
FOR TESTING,

 

Now we come onto the subject of “domain specific languages” …

 

http://scn.sap.com/community/abap/blog/2013/01/08/domain-specific-language-in-abap

 

which is how I make the implementation of such a test method read in such a way a business expert would be able to read it.

 

METHOD make_monsterIMPLEMENTATION.

 

  Given_desired_monster_features( ).

  When_monster_is_assembled( ).

  Then_it_goes_mad_and_kills_its_creator( ).

 

ENDMETHOD.

 

As an aside, it seems that all my previous blogs are fitting together like jigsaw pieces … but hang on … did not something similar happen to Snoopy?

 

New Apps 05 - Snoopy.png

Figure 5 - Snoopy

 

Anyway, back to the GIVEN / WHEN / THEN structure which is the essence of behaviour driven development testing, in the GIVEN method you set up the input variables, in the WHEN method you call the piece of production code, and in the THEN method you verify that the results are what you expected.

 

Now to do all that we need to think about the method we are going to test in the WHEN section, and for that we actually need to define the class under test, and the method we are going to test, and it’s signature, but that’s ALL. We just need the structure; we don’t need its innards.

 

Our lovely spreadsheet tells us all this i.e. the inputs and outputs, in EXCEL cells can hold any sort of value, but to translate this into ABAP we need parameters of a certain data type. As I want to keep to that domain specific language structure I am going to fill an input structure in the GIVEN method, pass the values from that structure into the production code in the WHEN method and pass the output values into another structure, which gets evaluated in the THEN method.

 

To state the seemingly obvious, I need to define a structure with names and types. That’s so obvious and easy it goes without saying. So here I go:-

 

DATA: BEGIN OF g_typ_monster,

  Xyz123                    TYPE I,

  Meaningless_nameTYPE string,

  Wibbly                      TYPE p DECIMALS 3,

  Wobbly                     TYPE c,

  Woo                          TYPE ekpo-bstae, “same length & type, but no semantic similarity

END OF g_typ_monster.

 

You may say no-one would do something so silly, I wouldn’t have believed it until I started looking at some of my programs, and indeed some standard SAP ones.

 

When I See An Element Fly

 

It’ easy to understand that as opposed to variable names like STRING or XYZ123 if you call a variable a name that actually describes what sort of data it contains and what it is used for e.g. ERROR_MESSAGE as opposed to STRING, or HEIGHT as opposed to XYZ123, then the code becomes self-documenting to a much greater extent.

 

Moving onto the type definitions, if everything is internal then the built in SAP types are wonderful. The question is – are these values ever going to be user facing i.e. is a user going to have to enter them on a screen, maybe with an F4 help, or are they ever going to pop up on some sort of report which the user looks at, or maybe a table maintenance dialog?

 

If the answer is “yes” or even “maybe” then you know it’s likely you have to create a repository Z structure or transparent table, so it is time to think of creating custom data elements. I can hear the screaming already, what a waste of time, so much extra effort, just use standard SAP elements of the same type and length, or built in types. To make things worse, I am going to insist that whilst creating the data element you take the path less followed i.e. GOTO -> DOCUMENTATION -> CHANGE and then write what this value means in business terms.

 

A lot of developers would rather crawl over a thousand miles of broken glass than write one word of documentation in the SAP system. Many would be puzzled why I would even CARE what it means, I have the algorithm don’t I? I know it’s a value or a string, if it’s a four character string just pick EKPO-BSTAE, that’s a four character string, surely that’s good enough, and so much easier.

 

Time / Money / Learning to Fly

 

I’ll always remember that quote I read once in response to a developer posting online about testing and it went along the lines of “typical programmer … no concern about time / money”.

 

You have to take these comments as deadly serious as most management will look at the surface and if they think you are doing something the long way, then out of the door you go, regardless of whether it was the “right” thing to do.

 

This is just like training, always the first thing to be cut, and before you know it a vicious spiral occurs

·         Money is tight, so training is reduced

·         People learn from their predecessor if they are lucky / or guess

·         No-one knows what they are doing, SAP wise

·         Tasks get done slower and/or wrong

·         This has to have a negative effect on productivity, which feeds through to the bottom line

·         Money is even more tight, so training is reduced further

·         Etc. etc.

·         Then you pay a consulting company ten billion dollars to do a study to work out what went wrong

 

That is an over-simplification, but I am sure you get the idea. It is the same with programming – since 95% of programming effort is in maintenance, wouldn’t it seem a logical trade off to spend twice the effort on the first 5% if you could dramatically reduce the effort of the remaining 95%?

 

Put like that the answer is obvious, but it isn’t put like that, and to be fair to management, if all they can see is that 5%, the tip of the iceberg, then why wouldn’t they concentrate on it? All this unit testing business is so esoteric, I can’t even explain it to my ABAP colleagues, let alone the managers, not that this stops me trying with both groups. If I can’t justify that, even with arguments like “this will stop nasty surprises every time we make a change in production” then what chance do I have to justify “wasting” time by documenting things within SAP?

 

Anyway, I’m allowed to do it, so anything remotely user facing gets a data element so then they can press F1 and get a description of what the field means. There is so little of that in SAP- in standard programs let alone Z custom ones - most users would not even bother pressing F1 so they can see “XYZ field – this is the XYZ field”.

 

Welcome to the Thunder Domain

 

Z Data elements – do they need a Z domain as well? I have seen a lot of custom Z domains which are carbon copies of standard SAP ones, which seems strange. The only purpose I would see for these is to enable F4 helps, and for automatic foreign key checks, neither of which is to be sneezed at.

 

Just yesterday I created a custom domain for a Z data element, and then set the foreign key and input help in the main table which was keyed on that data element, and then all throughout the system F4 helps magically sprang up for that field, even in standard transactions like VK11 and TK11. For the past 13 YEARS people had no F4 drop down on that field and could put in any value they wanted, and I was able to fix both of these things in about five minutes in dozens of programs without touching them. That is the “open / closed” principle all over.

 

http://www.objectmentor.com/resources/articles/ocp.pdf

 

To quote from the book “Head First Design Patterns” by Eric & Elisabeth Freeman:-

Remember, code should be closed (to change) like the lotus flower in the evening, yet open (to extension) like the lotus flower in the morning.”

 

What’s this first test all about, Alfie?

 

I’ve gone a bit off topic here, as per usual, so to recap, I am writing the first unit test, because of the spreadsheet designed b the business user hunchback I know the signature (input and output parameters) of the WHEN section, so I need to write a method to fill an input structure (GIVEN), the method to call the production code (WHEN), and a method to evaluate the output structure (THEN). I can summarise this as follows:-

 

You put some data in,

You get some data out,

In, Out, In, Out, Shake it All About,

You do the Data Cokey and you turn around,

That’s what it’s all about!

 

And it goes like this…..

 

  METHOD given_desired_monster_feat."ures.

    ms_input-monster_strength  
= gc_really_strong.
    ms_input-monster_brain_type
= gc_criminal_mind.

 
ENDMETHOD."Desired Monster Features

 
METHOD when_monster_is_assembled.

    mo_class_under_test
->assemble_monster(
   
EXPORTING id_monster_strength   = ms_input-monster_strength
              id_monster_brain_type
= ms_input-monster_brain_type
   
IMPORTING ef_madness            = ms_output-is_monster_mad
              ef_creator_alive     
= ms_output-is_creator_alive ).

 
ENDMETHOD."Monster is Assembled

 
METHOD then_it_goes_mad_and_kills_it."s_creator.

    cl_abap_unit_assert
->assert_equals(act = ms_output-is_monster_mad
                                       
exp= abap_true
                                        msg
= 'Monster is still sane!’' ).

    cl_abap_unit_assert
->assert_equals(act = ms_ouput-is_creator_alive
                                       
exp= abap_false
                                        msg
= 'Creator is still alive!' ).

 
ENDMETHOD."Monster goes mad and kills it’s creator

 

You will notice I run up against the 30 character limit in ABAP for the names of things, something our Java cousins do not have to worry about... I don't suppose ABAP was ever intended to be a "literate" language given it's creation 40 years ago....

 

Global Variable Warming

 

As I have said in an earlier blog the world’s funniest statement was in one the SAP press text books and it said something like “ABAP Objects is easier to learn than procedural programming”. Not for me it isn’t!

 

I find getting your head round some of the “guidelines” makes your head spin round like an owl. For example everyone says “global variables are bad – they are the spawn of the devil”. The argument seems sound, so off I go, trying to get rid of them.

 

In the other corner you have the guideline – don’t put very many parameters in your methods, and you want to have “high cohesion” which is that the top level variables you declare in your class get used in as many methods of the class as possible.

 

I used to think that was a direct contradiction in terms, until I belatedly realised – many years on – that the private variables in the class definition are not “global” variables in the procedural sense. I thought a global variable was one that was - (a) not declared within a method and (b) not in the signature of the method - because that is the way it works in procedural programming.

 

The more you get into this, the more you realise that FORMS are not like METHODS at all, in the same way CLASSES are not like Function Modules. That takes a big mindset change, I take comfort in the fact that it took the programmers at SAP long enough to make the same jump, as evidenced by all the standard SAP function modules wrapped in static classes – what did that achieve?

 

Knuth Said

 

For test classes having the private “member” variables used by all the classes in the test methods certainly makes the code read a lot more like plain English, what is known as “literate programming”.

 

http://www.literateprogramming.com/knuthweb.pdf

 

As always, there was never any separation from a new idea from a new tool to implement this idea, but the concept was clear enough – programs should be able to be read by humans as well as the complier. This is even truer for tests, which are supposed to read like the specification.

 

Indeed, if you can take your specification and write a test that reads just like it, you win a prize, and confetti starts falling out of the sky.

 

By the way, here is a picture of Donald Knuth demonstrating his WEB tool to produce programs that humans can read:-

 

New Apps 06 - Spiderman.jpg

Figure 6 – Donald Knuth

 

Big Signature in Little China

 

So I can hide the detail of the signature of the production method I am going to test, but what should the signature of the method under test look like?

 

I could just put all the input data in a structure, and all the output data in a structure. The benefit then would be when I wanted to bring in a new piece of data I would not have to change the signature of the method, just the structure definition. I don’t know if that is a benefit though, I would still have to change the innards of the method.

 

As you will see above, I started to do just that, defining an input and output structure and then changed my mind when it came to populating the method under test.

 

I feel the need, the need for speed, and in addition the need to have the details in the actual signature of my real production method to be tested, the details of every piece of data I need and every piece of data I bring back.

 

I like to explicitly state every piece of information I need in the signature and whether it is mandatory or not. In a structure, everything is optional; you have to guess what is required.

 

The ultimate example of big structures as input parameters is the monster signatures of BAPIS, you expose an API the size of the moon to external systems and hope for the best.

 

I am back to the “design by contract” thing again, I want to make it crystal clear what the method requires and what it ensures it is going to provide.

 

Cliff-hanger Ending

 

I have now written a few lines of ABAP, the test does not even compile yet, as I have not actually created the real production method … as in this antimatter world the test code comes first…

 

So I have not even got to the tip of the iceberg…. Where do we go from here? Is it down to the lake, I fear?

 

I often get accused of writing blogs that are longer than war and peace, so I will break off here, and continue in the near future….

 

Summary

·         I want to prove that writing new programs in OO really is better than the “old” way

·         I have a real life project which allows me to do just that

·         I am going to try to document how I go on this step by step

·         The example will be silly, but based on the real project

·         I am using test driven development, so I am starting with the tests

·         To be continued…..

 

Cheersy Cheers

 

Paul

 

 

Postmortem on BD87

$
0
0

We have heard and experienced about the saying "Necessity is the mother of Invention". As far as application development is concerned, its fair and true to say that "Necessity is also the mother of reuse". Not just the need for an invention, the need to find out about things which can be reused is also driven by the requirement.

 

Ever since SAP started supporting ABAP Objects, there are several classes created and being created with the intention to be reused. But there are several solutions which are standardized and stable but it is not classified and distinguished as reusable......


 

 

One such requirement forced me to find out and reuse the SAP's way of reprocessing IDOCs i.e BD87. I had to find out what BD87 does and re-implement the same from a report. It is not possible to call it through CALL TRANSACTION since BD87 is more like a monitoring report involving an ALV tree elements which cannot be manipulated via CALL TRANSACTION or a SUBMIT program.

 

Thinking like a typical ABAP'er (I hate this noun BTW, nobody says JAVA'er or .NET'er but why title only guys who knows ABAP?), I digged into the program of BD87 and came up with another program (RBDPROCESS) which is internally submitted from the main program. This program will run when the IDOCs are processed together irrespective of the status they are in.

Digging inside the program further, the application logic is triggered by the function module IDOC_INPUT
,this FM will help to reprocess the IDOCs in 'dark' mode and if it is important to get the output ALV then RBDPROCESS will be of use.

 

What does BD87 really do ?

 

The main BD87 program does not make use of the above functionality directly. Instead, the BD87 is built around partially object oriented and partially procedural and main core of it is handled mostly by the instantiation of a two classes,BDMT_CONTROL and BD_LS_MON. The procedural part of the program calls a few methods from these classes for handling ALV tree,gathering IDOC data,displaying and reprocessing.

 

 

This was intriguing and I was interested to know whether it is possible to reuse these classes to fulfil my requirement of reprocessing IDOCs manually from a report program. And guess what, You Can !!

 

How to Reuse?

BDMT_CONTROL is a class that performs the UI part of the BD87 program and mainly for the tree structure.

 

 

 

We are not really interested in the tree but mostly on what the    button do. The class BD_LS_MON has the method PROCESS_IDOCS( )  which in turn has the check for relevant status and does the processing via above RBDPROCESS program. This is exactly what I wanted. Taking a closer look at this method, there are 3 parameters and one of them was mandatory parameter.

PROCESS_MODEOptional
IDOC_STATMandatory
IDOC_FROM_NODEOptional

 

The PROCESS_MODE has a default value 'A' which represents IDOC processing mode ( A - All, S - Selected ) and IDOC_FROM_NODE contains the list of IDOCs that need to be processed.

The mandatory parameter, IDOC_STAT should be filled with the relevant status of the IDOCs that need to be processed. The important thing to note here is, the IDOCs sent to be reprocessed should be of the same status.

 

Word of caution: But what happens when I send the status '51' and call the method process_idocs( ) ? Will it process all the IDOCs with the status '51'? Yes it will. So to stop that from happening and let only the required IDOCs to be processed, we need to set the filter for these IDOCs. We can do that by calling the method SET_FILTER( ). This method will set the selection criteria of the BD87 selection screen and only those IDOCs that fall under this selection will be taken for reprocessing.

 

But the IDOCs that come under the selection can be of one or more statuses, that can be identified with the help of the attribute IDOC_STAT. This is a table and it is filled when the method COLLECT_DATA( ) is called. With the help of all these methods, we can successfully reprocess IDOCs hassle free. No need to look for consistency checks since the necessary validations are coded inside the method process_idocs( ) will take care of it.

The result of the processing will be displayed as and ALV that displays the previous status of the IDOCs and its new status. It will be '53' if the IDOCs are processed successfully.

 

 

Getting the Results Back into the Report:

 

Now, the processing of IDOCs happen via. the program internally submitted from process_idocs( ) method and the result set will not be available in the program where process_data( ) is being called. But if you need to do further processing with the result (Like updating a Z table with the success results) then we need to get the results back.

This is where I used the trick suggested by Glen Simpson in his awesome blog Gain Programmatic Access to Data of SAPGUI ALV Reports. Using the CL_SALV_BS_RUNTIME_INFO class, the ALV data of the submitted program can be easily brought back to the report and the filter out the IDOCs with the NEW_STATUS as '53'.

 

Summing it Up:

 

Thus the four step to get things done are :

 

7-7-2013 1-00-34 PM.jpg

 

It is always fascinating and interesting to find things that makes our lives easier and it gives a sense of satisfaction if the things that we build are more structured and manageable.

Programing is always a trade off between design, efficiency and quicker development time. Efficiency and development time are measurable even by a non-programmer, but design, is always the aspect that gives sense to the code and satisfaction to the guy who maintains your code. Even-though the other two factors can get you to heights,design is one of the key differentiators between good and bad programmers.
Before beginning to develop anything, I like to think of what Alan Kay said,
Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.

 

 

P.S: Pardon me if you think that the title is a little macabre, I thought its interesting.
Disclaimer: The techniques and views represented in this blog are just my opinion and it is not related anyway to the organization that I work with. Please use it or follow it under your own discretion.

Create a dynamic role menu using Web Dynpro ABAP

$
0
0

This blog post outlines an approach that can be used to render an ordinary role menu using Web Dynpro ABAP. Whilst many customers these days are leveraging this functionality in NetWeaver Business Client, there may be a specific requirement for a role menu to be displayed in a non-SAP customer portal or even in SAP Enterprise Portal itself. One advantage of using this application is that when a role menu is extended in the back-end ABAP system by adding a SAP transaction or Web Dynpro application, the menu is automatically updated.

 

Prerequisites: I won't go into the theory and practice behind creating role menus in transaction PFCG or configuring standard tables containing URL substitution parameters. This blog post assumes that these tasks have already been carried out and that the reader is familiar with the concepts of role menu maintenance. It is also assumed that the reader is familiar with the basics of creating a Web Dynpro ABAP component.

 

Now for the rendering of the menu, I will be creating a single view with a NestedByKey table to display the hierarchy of links. Each node in the menu will use a cell editor of type LinkToURL which will display the corresponding transaction, Web Dynpro or BI application

 

Step 1: Start by creating a new Web Dynpro component and accept all the defaults. The example shown in this blog post is called ZWD_ROLE_MENU. You will end up with a single view called MAIN and a corresponding window

 

rolemenu_image1.png

 

 

Step 2: Now we'll create a context node to hold our menu structure. This node will be populated with the hierarchy and will also contain specific UI attributes used to control the display of the menu. Start by creating a node called LINKS with cardinality 0..n and with the following attributes:

 

Attribute Name
Attribute Type
TEXTSTRING
URLSTRING
IDSTRING
PARENT_IDSTRING
IS_EXPANDEDWDY_BOOLEAN
IS_LEAFWDY_BOOLEAN
CHILDREN_LOADEDWDY_BOOLEAN
DESIGNWDUI_LINK_DESIGN

 

We'll see how these attributes are bound to the UI element in later steps. For now your context should resemble the picture below:

rolemenu_image2.png

 

Step 3: Navigate back to the layout of the view and drag a new table element onto the canvas (or use the context menu if that is your preferred approach). Add this table as a child element of the main transparent container that is generated for you. Set the table properties as below:

 

PropertyValue
DesignTransparent
displayEmptyRowsUnchecked
fixedTableLayoutUnchecked
footerVisibleUnchecked
gridModeNone
rowCount-1
rowSelectableUnchecked
dataSourceBound to context node LINKS created in Step 2
selectionColumnDesignNone
selectionModeNone
visibleRowCount-1

 

Make sure you delete the default table header when creating the table element.

 

Step 4: Now we need to add the hierarchy column. This is achieved by adding a Row Arrangement column to the table and selecting the type to be "TreeByKeyTableColumn". For our purposes we will call the column COL_HIERARCHY. Be sure to remove the generated cell header afterwards. The purpose of the Row Arrangement column is to represent the hierarchy of the menu, however at this point it is useless without a cell editor to display the actual link. For this we create a cell editor in the column of type "LinkToURL" and we name it LINK_REPORT (you can name it however you like). Once we are finished, we should end up with a table that looks like below:

 

rolemenu_image3.png

 

The next task is to bind the UI elements just created to the context. Here are the bindings needed:

 

UI Element
Property
Context Attribute
COL_HIERARCHYIDLINKS->ID
COL_HIERARCHYParent IDLINKS->PARENT_ID
COL_HIERARCHYChildren LoadedLINKS->CHILDREN_LOADED
COL_HIERARCHYExpandedLINKS->EXPANDED
COL_HIERARCHYIs LeafLINKS->IS_LEAF
LINK_REPORTDesignLINKS->DESIGN
LINK_REPORTTextLINKS->TEXT
LINK_REPORTURLLINKS->URL

 

Now our layout is complete and we can move on to the populating of our menu.

 

Step 5: Populating our menu can be achieved a number of ways. One approach would be to attach a supply function to the context node and populate the list of menu items that way. In this blog post I will use an event-based approach and trigger the populating of the context node through an event raised by the window default plug. No matter what approach you use, the application needs to be told which role to display the menu for and this will be handled through a parameter in the default plug. Lets see how this is configured.

 

Firstly, open the window of the application and navigate to the default plug. Add an import parameter called 'ROLE' and set the type to be STRING so that the role name can be passed to the application as a URI parameter.

 

Once this is done, open the component controller and create an event called BUILD_ROLE with a parameter also called 'ROLE' of type STRING. This event will be triggered by the default plug of the window. Create a method in the component controller called RAISE_BUILD_EVENT which also takes a single parameter called 'ROLE' which will be used to trigger the event. Your method list in the component controller will now look like the image below:

 

blog_image.png

 

In the implementation of this method, simply call the generated method to raise the event:

 

wd_this->fire_build_role_evt( role = role ).

 

An alternative to creating this method is of course to expose the event to other controllers directly however I will leave this decision to you.

 

Finally in this step we must open the window and modify the implementation of the default plug handler. Add the following code to raise the event when the window is instantiated:

 

DATA:
lo_compctrl
TYPE REF TO IG_COMPONENTCONTROLLER .

lo_compctrl = wd_this->get_componentcontroller_ctr( ).
lo_compctrl->raise_build_event( role = role ).

 

 

Step 6: OK our final step now is to implement the event handler in the view and to write the code to populate the context. We will do this by creating the event handler method GENERATE_MENU and a separate method called GENERATE_URL which will be responsible for generating the URL for each node in the menu. This method will utilise standard PFCG function modules that read the table URL_EXITS to generate a link address based on the type of link (i.e transaction, Web Dynpro etc).

 

Open the main view and create the GENERATE_MENU method and select method type Event Handler. In the event column, use the drop-down to select the BUILD_ROLE event that we created earlier:

 

rolemenu_image7.png

 

Next, create the method GENERATE_URL with the following signature:

 

rolemenu_image5.png

Add the implementation code from the attachment titled generate_url.txt. This method is responsible for generating the URL for the given node type from the role menu. This code only supports transactions, internet URLs, Web Dynpro and BI URLs however it can easily be extended to handle other types.

 

Finally, add the implementation code from the attachment titled generate_menu.txt to the GENERATE_MENU event handler. This will read the role menu nodes from the standard AGR_* tables and call the GENERATE_URL method to generate each link.

 

Once you have saved and activated the Web Dynpro component, all that is left to do is to generate an application for it and test it! An example rendered menu is displayed below for the standard role SAP_XI_ADMINISTRATOR:

 

rolemenu_image8.png

 

I hope you find this post useful on your next project.

 


Some Tips to avoid potential/hidden bugs in programs.

$
0
0

Hello All,

 

Most of the times, bugs, small issues become very critical issues leading to big impact to the business once when a project is gone live or when some change requests are moved to production, once the user starts using the new system. Identifying these hidden bugs,potential bugs sometimes becomes very difficult since some scenarios which needs to be tested are not there in other non-production environment(cannot be replicated) due to various reasons like configurations, necessary test data not available, sometimes all possible testing done in non-production environment and working fine, but when same functionality moved to production and used by user, it results in short-dump, functionality not working as expected, etc. Hence it is very important as an ABAPer, to think on various approaches while coding or implementing the logic using appropriate ABAP statements, understanding the working of different ABAP statements and how the program flow happens or execution flow.

 

  Hence , I would like to share my knowledge on various things which we need to analyze while implementing the logic in new programs, or any changes to the existing custom and standard programs. This will avoid potential/hidden bugs found in the program at a later stage.Some of them are as follows:

 

1. Use the language key in WHERE clause in Select Query while picking data from Text tables: When picking up the data from Text tables, for example, while picking up data from database table MAKT for material description, the language key(SPRAS) should be passed in where clause.Most of the times, it is missed when this query is used in many places of a big program. Not passing the language key, results in picking up first entry from table,which is the correct material description,but not in the required language as required by the user.

 

2. Using of READ TABLE ITAB INTO ...INDEX 1 in a user exit or a generated program or custom include used in the standard program.

This is one of the big mistake done in using the READ statement. The user exit or include where you have written the READ statement with INDEX 1 might be called multiple times and ITAB will have more than one entry getting populated or values getting deleted every time the include is called.Using the INDEX 1, might result in reading the same first record of the table every time and might lead to an issue and logic being not implemented properly. Thus it is very important to analyze and understand how this table is getting populated. Instead of using INDEX 1, try to pass required key field in the READ statement,

i.e. READ TABLE ITAB INTO .. WITH KEY matnr = head-matnr.

 

3. Usage of correct BAPI in programs: The functionality of a BAPI is similar to a transaction. While using a BAPI in the program, proper analysis should be done to understand the complete functionality of it. Once when the BAPI does the functionality of what is required is achieved, we start using it, which is a big mistake. Some BAPIs will internally call different BAPIs for additional functionalities. These functionalities might be add-ons and need not be required for the user. It can be also the vice-versa, the subset of parent BAPI will alone implement our requirements. Hence, it is not needed to use the parent BAPi instead of using the subset of BAPI. So, analyze and test the functionality in standalone and understand before actually using the BAPI in your program.

 

4. Use of FMs for date calculations:  Most of the times, date calculations and conversions in programs are done using normal ABAP statements instead of using FMs which are available ready made for date calculations, date conversions, etc. with exception handling. This results in short dump or functionality not working. It might a silly mistake , but would cost a lot when such changes are moved to production. Hence FMs should be used instead of using statements like CONCATENATE etc.

 

For example, for calculating the date2 months before current date, direct subtraction was done using normal ABAP statement:

 

            Say the current date is 04/02/2013 (sy-datum - 20130204)


          month = sy-datum+4(2) - 0002.                                           " result ----month = 0                                                

          CONCATENATE sy-datum+6(2) '/' month '/'sy-datum+0(4) INTO pdate. 

 

          Result:  pdate = 04/00/2013 - which is an invalid date.

 

- will result in date becoming 04/00/2013 - which is invalid date, which when used in next step or later might result in functionality not working, or even run-time error will occur if the date is used in the where clause of Select query.

 

Instead use FM BKK_ADD_MONTH_TO_DATE for the same, which will give proper result.

 

CALLFUNCTION'BKK_ADD_MONTH_TO_DATE'

     EXPORTING

       months  = c_2      "-2

       olddate = sy-datum

     IMPORTING

                               newdate = p_date.          --------------result ---- pdate = 04/12/2012 - which is Valid date.


This is a very simple example, but there might be very complex calculations required for date, day,month,year calculations in some cases,hence it is best to use Function Modules.

 

5. Use of FMs Conversion alpha exits/ conversions of key fields like material number,sales order number before using in select queries:

 

Sometimes in module pool programs, when input is provided without preceding zeros, when conversion to internal format is not done before querying to the table, it might result in record not found for fields like material number or sales order number or maybe any field. Hence using the FM Conversion Alpha exit input, the input needs to be converted to internal format, i.e. populate preceding zeros in them and then pass it to select query.

 

Note : This blog is only for beginners. Most of the sometimes, the beginners forget or don't bother to go through the code inspector or the consistency checks,once the development or code changes are done. Hence  thought of sharing the same.

 

Thanks!

Viewing all 948 articles
Browse latest View live


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