Skip to Content
Author's profile photo David Halitsky

SOA is an S(tate)O(f)M(ind) 1st … a bag of tricks 2nd …

In these three recent blogs:


[Without bread-crumbs, Hansel and Gretel meet the WWW (Wicked Witch of Web-Services) | Without bread-crumbs, Hansel and Gretel meet the WWW (Wicked Witch of Web-Services)]
[CodExpertise vs BPXpertise: which is the tail and which is the dog? | CodExpertise vs BPXpertise: which is the tail and which is the dog?]
[Into the Valley of Depth  Rode the Implicit Enhancers | Into the Valley of Depth  Rode the Implicit Enhancers]


I’ve tried to keep a promise to Mark Finnern – namely, to show that SOA is really an SOM (StateOfMind) that one can cultivate, even if one does not have access to particular tools for implementing SOA (e.g. PI7.1, WDA, etc.)


Here is another example from real-life to make the same point.


The client wants a download to BW/BPC of the on-line report you get from MD4C when you choose a project on the project tab. 


But here’s the kicker – the client wants the correct WBS element associated with each line of the MD4C project report download 


Well – in some cases this is easy – for some MD4C elements, you can get a pspel from PLAF which you can take into PRPS and get a WBS.


But for other cases, not so easy.


So what to do?


Well, you poke around for a few days and all of a sudden you realize that what you really want to do is to solve this problem using two itabs that standard SAP code already generates:  the ioel itab underlyng the MD4C report (actually generated by the program PP_ORDER_PROGRESS) with certain elements of the g_tree_tab itab underlying the CN41N report on a project (actually generated by program RPSINFO.


Why? Because the g_tree_tab itab generated by RPSINFO actually contains enough information to tie elements of this itab to elements of the ioel itab.  And, by using a little bit of hashing and reverse-order table reads, you can get the associations you need without ever leaving memory to do a single select against PLAF, PRPS, PRHI, etc.


But how do you get the g_tree_itab from CN41N/RPSINFO into the same address space as the ioel itab from MD4C/PP_ORDER_PROGRESS (so you can bounce from one to the other to your heart’s content …)


Well, what you do is get into an SOA SOM.


First, you do an implicit enhancement to the EXPORT_TABLES_TO_MEMORY form of RPSINFO so that if a certain SET/GET memory parameter is set to certain value, you leave the program after exporting excerpts of the itabs in this form to memory.  (Note: you don’t export the actual SAP itabs because you don’t need everything that’s in them; also, you really only need g_tree_itab but you take excerpts of all of them because they might come in handy later on.)


Second, you do an implicit enhancement to the function module  MD_PROJECT_REPORT that’s called by MD4C/PP_ORDER_PROGRESS, so that the ioel table is exported to memory as soon as it’s built.  Furthermore, to make sure that this function module has all the parameters it wants, you don’t call it directly – you perform START_SELECTION NEW in PP_ORDER_PROGRESS.


Finally, you write a piece of code that: 1) calls RPSINFO and then imports the ioel table that you’ve exported in your enhancement; 2) performs START_SELECTION_NEW in PP_ORDER_PROGRESS and then imports the excerpt of g_tree_itab (and the other itabs) that you’ve expored in your enhancement to MD_PROJECT_REPORT.


And now, you can bounce from your ioel itab excerpt into your gt_tree_itab excerpt to your heart’s content, finding the right WBS element in the latter for each element of the former.  (To make this efficient, it’s worthwhile hashing your excerpt of gt_tree_itab so that you can immediately find out where you need to be in the standard excerpt of gt_tree_itab, so that you can simply read upwards to find the lowest available WBS element.)


But look at what you’ve done here: you’ve done SOA without ever using PI 7.1 or WDA.  Because what SOA is really about in the SAP environment is figuring out how to deconstruct and reconstruct SAP code so that you can take only what you need from it, and never have to write a line of custom code that you really don’t need to write.


To show that the above is not “blue sky”, all the relevant code (except the hashing and bouncing) appears below.  (The other reason I’m exhibiting this code is to show that a class-based persistence approach would be a lot better than using FG’s and secondary exports to session memory …)


Here’s the main function that lets you bring your ioel and g_tree_tab excerpts together in the same address space:




<br />“Local Interface:<br />”  IMPORTING

<br />DATA:<br />  lv_zbpcmd4c              TYPE xfeld,<br />  lv_selscr                TYPE sy-dynnr,<br />  lv_pspid                 TYPE ps_pspid,<br />  lv_posid                 TYPE ps_posid,<br />  lv_pshir                 TYPE pshir,<br />  lv_plnum                 TYPE plnum,<br />  lv_aufnr                 TYPE aufnr,<br />  lv_netw                  TYPE nw_aufnr,<br />  gt_vbap                  LIKE TABLE OF vbap WITH HEADER LINE,<br />  l_werks                  TYPE werks_d.</p><p>DATA:  BEGIN OF gt_matnr OCCURS 0,<br />         matnr LIKE afpod-matnr,<br />       END OF gt_matnr.</p><p>  SET PARAMETER ID ‘PFL’    FIELD ‘000000000001’.<br />  SET PARAMETER ID ‘PROFID’ FIELD ‘000000000001’.<br />  SET PARAMETER ID ‘ZBPCMD4C’ FIELD ‘X’.</p><p>  SUBMIT RPSINFO<br />    USING SELECTION-SCREEN 1000<br />    WITH                   cn_projn = project<br />    AND                    RETURN.</p><p>  lv_selscr = ‘0020’.<br />  lv_pspid  = project.<br />  PERFORM start_selection_new IN PROGRAM PP_ORDER_PROGRESS<br />    USING<br />      lv_selscr<br />      gt_vbap[]<br />      gt_matnr[]<br />      l_werks<br />      lv_pspid<br />      lv_posid<br />      lv_pshir<br />      lv_plnum<br />      lv_aufnr<br />      lv_netw.</p><p>  IMPORT gt_ioel   FROM MEMORY ID ‘ZBPCMD4C_IOEL’.<br />  IMPORT gt_act    FROM MEMORY ID ‘ZBPCMD4C_ACT’.<br />  IMPORT gt_affh   FROM MEMORY ID ‘ZBPCMD4C_AFFH’.<br />  IMPORT gt_afru   FROM MEMORY ID ‘ZBPCMD4C_AFRU’.<br />  IMPORT gt_kbed   FROM MEMORY ID ‘ZBPCMD4C_KBED’.<br />  IMPORT gt_netwrk FROM MEMORY ID ‘ZBPCMD4C_NETWRK’.<br />  IMPORT gt_plaf   FROM MEMORY ID ‘ZBPCMD4C_PLAF’.<br />  IMPORT gt_proj   FROM MEMORY ID ‘ZBPCMD4C_PROJ’.<br />  IMPORT gt_prps   FROM MEMORY ID ‘ZBPCMD4C_PRPS’.<br />  IMPORT gt_resb   FROM MEMORY ID ‘ZBPCMD4C_RESB’.<br />  IMPORT gt_tree   FROM MEMORY ID ‘ZBPCMD4C_TREE’.</p><p>ENDFUNCTION.</p><p> </p><p>Here’s the enhancement to RPSINFO:</p><p> </p><p>FORM export_tables_to_memory .<br />”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””$”$SE:(1) Form EXPORT_TABLES_TO_MEMORY, Start                                                                                A<br />$$-Start: (1)—-

$$<br />ENHANCEMENT 1  ZMME_INTERCEPT_RSPINFO.    “active version<br />

</p><p><br />DATA:<br />  lv_zbpcmd4c             TYPE xfeld.</p><p>  GET PARAMETER ID ‘ZBPCMD4C’ FIELD lv_zbpcmd4c.</p><p>  IF lv_zbpcmd4c = ‘X’.<br />    PERFORM create_rspinfo_itab_xcrpts.<br />    LEAVE PROGRAM.<br />  ENDIF.</p><p>ENDENHANCEMENT.<br />$*$-End:   (1)

$$<br />  EXPORT :<br />      g_tree_tab<br />      g_imtp<br />      g_proj<br />      g_prps<br />      g_vbak<br />      g_vbap<br />      g_plaf<br />      g_afab<br />      g_kbed<br />      g_resb<br />      g_afru<br />      g_mlst<br />      g_pstx<br />      g_drad<br />      g_affh<br />      g_act<br />      g_netwrk<br />      g_vsindex<br />      g_out_s000<br />      textsymbols TO MEMORY ID ‘CNIS_SHARED_TABS’.</p><p>ENDFORM.                    ” tablesto_memory</p><p>”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””$”$SE:</p><p> </p><p>Here’s the second enhancement to RPSINFO to take excerpts of the SAP itabs:</p><p> </p><p>ENHANCEMENT 1  ZMME_INTERCEPT_RSPINFO_FORM.    “active version<br />FORM create_rspinfo_itab_xcrpts.</p><p>FIELD-SYMBOLS:<br />  <fs_oact>                TYPE cnpsj_act_type,<br />  <fs_oaffh>               TYPE cnpsj_affh_type,<br />  <fs_oafru>               TYPE cnpsj_afru_type,<br />  <fs_okbed>               TYPE cnpsj_kbed_type,<br />  <fs_onetwrk>             TYPE cnpsj_net_type,<br />  <fs_oplaf>               TYPE cnpsj_plaf_type,<br />  <fs_oproj>               TYPE cnpsj_proj_type,<br />  <fs_oprps>               TYPE cnpsj_prps_type,<br />  <fs_oresb>               TYPE cnpsj_resb_type,<br />  <fs_otree>               TYPE cnpsj_struc,</p><p>  <fs_act>                TYPE ZMDS_RPS_ACT_XCRPT,<br />  <fs_affh>               TYPE ZMDS_RPS_AFFH_XCRPT,<br />  <fs_afru>               TYPE ZMDS_RPS_AFRU_XCRPT,<br />  <fs_kbed>               TYPE ZMDS_RPS_KBED_XCRPT,<br />  <fs_netwrk>             TYPE ZMDS_RPS_NETWRK_XCRPT,<br />  <fs_plaf>               TYPE ZMDS_RPS_PLAF_XCRPT,<br />  <fs_proj>               TYPE ZMDS_RPS_PROJ_XCRPT,<br />  <fs_prps>               TYPE ZMDS_RPS_PRPS_XCRPT,<br />  <fs_resb>               TYPE ZMDS_RPS_RESB_XCRPT,<br />  <fs_tree>               TYPE ZMDS_RPS_TREE_XCRPT.</p><p>DATA:<br />  lt_act                  TYPE STANDARD TABLE OF ZMDS_RPS_ACT_XCRPT,<br />  lt_affh                 TYPE STANDARD TABLE OF ZMDS_RPS_AFFH_XCRPT,<br />  lt_afru                 TYPE STANDARD TABLE OF ZMDS_RPS_AFRU_XCRPT,<br />  lt_kbed                 TYPE STANDARD TABLE OF ZMDS_RPS_KBED_XCRPT,<br />  lt_netwrk               TYPE STANDARD TABLE OF ZMDS_RPS_NETWRK_XCRPT,<br />  lt_plaf                 TYPE STANDARD TABLE OF ZMDS_RPS_PLAF_XCRPT,<br />  lt_proj                 TYPE STANDARD TABLE OF ZMDS_RPS_PROJ_XCRPT,<br />  lt_prps                 TYPE STANDARD TABLE OF ZMDS_RPS_PRPS_XCRPT,<br />  lt_resb                 TYPE STANDARD TABLE OF ZMDS_RPS_RESB_XCRPT,<br />  lt_tree                 TYPE STANDARD TABLE OF ZMDS_RPS_TREE_XCRPT,</p><p>  ls_return               TYPE bapiret2.</p><p>  LOOP AT g_act ASSIGNING <fs_oact>.<br />    APPEND INITIAL LINE TO lt_act ASSIGNING <fs_act>.<br />    MOVE-CORRESPONDING <fs_oact> TO <fs_act>.<br />  ENDLOOP.<br />  CLEAR g_act.</p><p>  LOOP AT g_affh ASSIGNING <fs_oaffh>.<br />    APPEND INITIAL LINE TO lt_affh ASSIGNING <fs_affh>.<br />    MOVE-CORRESPONDING <fs_oaffh> TO <fs_affh>.<br />  ENDLOOP.<br />  CLEAR g_affh.</p><p>  LOOP AT g_afru ASSIGNING <fs_oafru>.<br />    APPEND INITIAL LINE TO lt_afru ASSIGNING <fs_afru>.<br />    MOVE-CORRESPONDING <fs_oafru> TO <fs_afru>.<br />  ENDLOOP.<br />  CLEAR g_afru.</p><p>  LOOP AT g_kbed ASSIGNING <fs_okbed>.<br />    APPEND INITIAL LINE TO lt_kbed ASSIGNING <fs_kbed>.<br />    MOVE-CORRESPONDING <fs_okbed> TO <fs_kbed>.<br />  ENDLOOP.<br />  CLEAR g_kbed.</p><p>  LOOP AT g_netwrk ASSIGNING <fs_onetwrk>.<br />    APPEND INITIAL LINE TO lt_netwrk ASSIGNING <fs_netwrk>.<br />    MOVE-CORRESPONDING <fs_onetwrk> TO <fs_netwrk>.<br />  ENDLOOP.<br />  CLEAR g_netwrk.</p><p>  LOOP AT g_plaf ASSIGNING <fs_oplaf>.<br />    APPEND INITIAL LINE TO lt_plaf ASSIGNING <fs_plaf>.<br />    MOVE-CORRESPONDING <fs_oplaf> TO <fs_plaf>.<br />  ENDLOOP.<br />  CLEAR g_plaf.</p><p>  LOOP AT g_proj ASSIGNING <fs_oproj>.<br />    APPEND INITIAL LINE TO lt_proj ASSIGNING <fs_proj>.<br />    MOVE-CORRESPONDING <fs_oproj> TO <fs_proj>.<br />  ENDLOOP.<br />  CLEAR g_proj.</p><p>  LOOP AT g_prps ASSIGNING <fs_oprps>.<br />    APPEND INITIAL LINE TO lt_prps ASSIGNING <fs_prps>.<br />    MOVE-CORRESPONDING <fs_oprps> TO <fs_prps>.<br />  ENDLOOP.<br />  CLEAR g_prps.</p><p>  LOOP AT g_resb ASSIGNING <fs_oresb>.<br />    APPEND INITIAL LINE TO lt_resb ASSIGNING <fs_resb>.<br />    MOVE-CORRESPONDING <fs_oresb> TO <fs_resb>.<br />  ENDLOOP.<br />  CLEAR g_resb.</p><p>  LOOP AT g_tree_tab ASSIGNING <fs_otree>.<br />    APPEND INITIAL LINE TO lt_tree ASSIGNING <fs_tree>.<br />    MOVE-CORRESPONDING <fs_otree> TO <fs_tree>.<br />  ENDLOOP.<br />  CLEAR g_tree_tab.</p><p>CALL FUNCTION ‘ZMD_GLBLZ_RSP_ITABS'<br />  EXPORTING<br />    ACT           = lt_act<br />    AFFH          = lt_affh<br />    AFRU          = lt_afru<br />    KBED          = lt_kbed<br />    NETWRK        = lt_netwrk<br />    PLAF          = lt_plaf<br />    PROJ          = lt_proj<br />    PRPS          = lt_prps<br />    RESB          = lt_resb<br />    TREE          = lt_tree<br />  IMPORTING<br />    return        = ls_return.</p><p>ENDFORM.</p><p>ENDENHANCEMENT.</p><p> </p><p>Here’s the function that sends your RPSINFO excerpts to memory </p><p>FUNCTION ZMD_GLBLZ_RSP_ITABS.<br />*”


<br />  gt_act[]    = act[].<br />  gt_affh[]   = affh[].<br />  gt_afru[]   = afru[].<br />  gt_kbed[]   = kbed[].<br />  gt_netwrk[] = netwrk[].<br />  gt_plaf[]   = plaf[].<br />  gt_proj[]   = proj[].<br />  gt_prps[]   = prps[].<br />  gt_resb[]   = resb[].<br />  gt_tree[]   = tree[].</p><p>  EXPORT gt_act    TO MEMORY ID ‘ZBPCMD4C_ACT’.<br />  EXPORT gt_affh   TO MEMORY ID ‘ZBPCMD4C_AFFH’.<br />  EXPORT gt_afru   TO MEMORY ID ‘ZBPCMD4C_AFRU’.<br />  EXPORT gt_kbed   TO MEMORY ID ‘ZBPCMD4C_KBED’.<br />  EXPORT gt_netwrk TO MEMORY ID ‘ZBPCMD4C_NETWRK’.<br />  EXPORT gt_plaf   TO MEMORY ID ‘ZBPCMD4C_PLAF’.<br />  EXPORT gt_proj   TO MEMORY ID ‘ZBPCMD4C_PROJ’.<br />  EXPORT gt_prps   TO MEMORY ID ‘ZBPCMD4C_PRPS’.<br />  EXPORT gt_resb   TO MEMORY ID ‘ZBPCMD4C_RESB’.<br />  EXPORT gt_tree   TO MEMORY ID ‘ZBPCMD4C_TREE’.</p><p>ENDFUNCTION.</p><p> </p><p>Here’s the enhancement to MD_PROJECT_REPORT (called by PP_ORDER_PROGRESS)</p><p> </p><p>ENHANCEMENT 1  ZMDE_INTERCEPT_PP_ORDER_PRGRS2.    “active version</p><p>FIELD-SYMBOLS:<br />  <fs_oioelx>             TYPE ioel,<br />  <fs_ioel>               TYPE ioel.</p><p>DATA:<br />  lv_zbpcmd4c             TYPE xfeld,<br />  lt_ioel                 TYPE MD_IOELX,<br />  ls_return               TYPE bapiret2.</p><p>  GET PARAMETER ID ‘ZBPCMD4C’ FIELD lv_zbpcmd4c.<br />  IF lv_zbpcmd4c <> ‘X’.<br />    RETURN.<br />  ENDIF.</p><p>  LOOP AT ioelx ASSIGNING <fs_oioelx>.<br />    APPEND INITIAL LINE to lt_ioel ASSIGNING <fs_ioel>.<br />    MOVE-CORRESPONDING <fs_oioelx> TO <fs_ioel>.<br />  ENDLOOP.</p><p>  CALL FUNCTION ‘ZMD_GLBLZ_PP_ORD_PRGRS_IOEL'<br />    EXPORTING<br />      IOEL          = lt_ioel<br />    IMPORTING<br />      RETURN        = ls_return.</p><p>ENDENHANCEMENT.<br />$$-End:   (1)

$$<br />ENDFUNCTION.</p><p> </p><p>Here’s the auxilary function that exports your ioel excerpt to memory:</p><p> </p><p>FUNCTION ZMD_GLBLZ_PP_ORD_PRGRS_IOEL.<br />*”

<br />“Local Interface:<br />”  IMPORTING<br />”     VALUE(IOEL) TYPE  MD_IOELX<br />”  EXPORTING<br />”     REFERENCE(RETURN) TYPE  BAPIRET2<br />*”—

  gt_ioel[] = ioel[].








Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo David Halitsky
      David Halitsky
      Since MD4C is actually MD04 when run from the "Project" tab, you can't completely duplicate the MD04 stock requirements list data unless you also run some function(s) to get the mdps table that SAP MRP gives you - the one with the "aussl" error codes ... but there are a million ways to do this, so it's not a big deal.  The basic data is still in the gt_tree_itab from RPSINFO and the ioel table from PP_ORDER_PROGRESS.  In fact, the objektid's in the g_tree_itab table are going to give you the delnr's that you have to look for in the mdps table from your MRP function(s)-of-choice ...