Thursday, February 23, 2012

Buffer problems with HR_READ_INFOTYPE HR_INFOTYPE_OPERATION and the TBUFF


Hi Folks,
i had an enquiry today. the problem is a report that makes some 20000 HR_INFOTYPE_OPERATION function calls on different pernr/persons.
The run time grows exponentially  with the number of pernr processed.

The reason for this is the buffering scheme in the HR_INFOTYPE_OPERATION FUNCTION
Calling the HR_PSBUFFER_INITIALIZE before processing each person leads to a linear run time.
The reason is that with each person processed the PS buffer table grows by several lines.

In SAP HR there are several buffers with this tricky behaviour:
  1. TBUFF: the buffer of the PCLx (PCL1,PCL2...PCL4) tables. The import export macros use a form that buffers the data when reading and writing. It can be cleared with the RP-INIT-BUFFER macro (Table TRMAC)
  2. PS Buffer: already mentioned above int the HR_IT_OPERATION VERSION
  3. PS Buffer HR_READ_INFOTYPE the same buffer as above, (ususally the tables are common parts) can be cleared with HR_INITIALIZE_BUFFER
  4. PNP Buffer the so called PRELP Buffer. This one you cannot clear, and usually it does not create problems, because it is designed to work with huge amounts of data.
One important and interesting thing is that you must know what buffer you  are using (even if indirectly with standard function calls).
So in a PNP program you should not call functions that read the infotypes with the PS buffer or with another buffer. Because you would break the buffer, causing time wasting reads in the best case, and in the worst case reading fake information from the database leading to data corruption.

So in a PNP program you should always call the "read-infotype form in program SAPDBPNP" Possibly with the TRMAC Macro RP-READ-INFOTYPE
While in  masterdata (pa30 and the like) you should use the PS buffer functions and forms. just like     PERFORM READ_INFOTYPE(SAPFP50P) USING...

So watch your buffers, and ...have a happy run time!
Happy hacking!


-- The TRMAC RP-READ-INFOTYPE macro

RP-READ-INFOTYPE    001    ****************************************
RP-READ-INFOTYPE    002    * RP-READ-INFOTYPE                     *
RP-READ-INFOTYPE    003    ****************************************
RP-READ-INFOTYPE    004    * PARAMETERS:                          *
RP-READ-INFOTYPE    005    *   PERNR      REQUESTED PERSONALNUMBER*
RP-READ-INFOTYPE    006    *   INFTY      REQUESTED INFOTYPNUMBER *
RP-READ-INFOTYPE    007    *   INFTY-TABLE OUTPUT-TABLE LIKE PNNNN*
RP-READ-INFOTYPE    008    *   BEGDA      REQUESTED INTERVAL-BEGIN*
RP-READ-INFOTYPE    009    *   ENDDA      REQUESTED INTERVAL-END  *
RP-READ-INFOTYPE    010    ****************************************
RP-READ-INFOTYPE    011    *SET DEBUGGING INTERRUPT ON            *
RP-READ-INFOTYPE    012    PERFORM READ-INFOTYPE(SAPDBPNP)        *
RP-READ-INFOTYPE    013    TABLES &3                      *
RP-READ-INFOTYPE    014    USING  &1 '&2' &4 &5
RP-READ-INFOTYPE    015    *SET DEBUGGING INTERRUPT OFF           *


--- The RP-INIT-BUFFER macro coding from table TRMAC

RP-INIT-BUFFER    001    ****************************************
RP-INIT-BUFFER    002    * RP: initialisierung puffer-tabellen  *
RP-INIT-BUFFER    003    ****************************************
RP-INIT-BUFFER    004    CLEAR:   BUFFER_DIR
RP-INIT-BUFFER    005    REFRESH: BUFFER_DIR
RP-INIT-BUFFER    006    CLEAR:   TBUFF
RP-INIT-BUFFER    007    REFRESH: TBUFF
RP-INIT-BUFFER    008    CLEAR:   BEFORE_IMAGE_PCLX
RP-INIT-BUFFER    009    REFRESH: BEFORE_IMAGE_PCLX
RP-INIT-BUFFER    010    CLEAR:   DEL_PCLX_TAB
RP-INIT-BUFFER    011    REFRESH: DEL_PCLX_TAB
RP-INIT-BUFFER    012    CLEAR: PAYR_BUFFER
RP-INIT-BUFFER    013    REFRESH: PAYR_BUFFER

Wednesday, February 15, 2012

Off topic: how time evaluation (SAP RPTIME00) sets the retrocalculation date for payroll

One insteresting question today: 
How does the TM RPTIME00 time evaluation engine sets the retrocalculation date RRDAT on the IT0003 to trigger a payroll recalculation?

the answer is simple, but as always the thingy is tricky
In form SET_PAYROLL_RECALCULATION. if the retro switch for TM is set the the evaluation period of TM is checked, and a routine checks whether for each recalculated day a change has occurred in the ZL table compared to the existing ZL of the previous calculation.
the oldes change date in ZL i writte to RRDAT of IT0003

the enabling of the retro switch "SW_FUNC-RLG" happens through the statement
CHECK      RPR 
in the Time evaluation schema


Here the routine.
*---------------------------------------------------------------------*
*       FORM SET_PAYROLL_RECALCULATION                              *
*---------------------------------------------------------------------*
*$*$ Bestimmt RR-Datum für L&G von Sicht des RPTIME00
*$*$ Lücke: Falls RR-Datum von L&G schon für die Vorperiode sitzt wird
*$*$     nicht die RPTIME-spezfische Rückrechnungserkennung durchlaufen.
*       Vorgehen:
*       1. Ist die aktuelle Periode von L&G schon abgerechnet?
*          Wenn nein: stop.
*       2. Liegt das RR-Datum-LG vor Beginn der aktuellen Periode?
*          Wenn ja: stop.
*       3. Bestimme den Tag, an dem sich Daten fuer L&G geaendert
*          haben. (FORM CHECK_RECALCULATION)
*$*$ Punkt 5 wird nun in EXPORT_PERSON überprüft, da die RR-Relevanz für
*$*$ L&G auch dann für das Setzen des Matchcode W gebraucht wird, wenn
*$*$ schon ein RR-Datum für L&G gesetzt ist.
**      5. Ist das RR-Datum-LG kleinergleich dem RR-Datum-ZE?
**         Wenn ja: stop.
*       6. Es muss eine RR fuer L&G gesetzt werden.
*---------------------------------------------------------------------*
FORM SET_PAYROLL_RECALCULATION.
  DATA: SET_RECALC_DATE TYPE D.

  CHECK SW_FUNC-RLG EQ '1'.

* Check ob L&G den Monat schon abgerechnet hat:
  CHECK P0003-ABRDT GE ACT_PERIOD-BEGDA.

* Check ob L&G schon eine RR sitzen hat, die vor Beginn der Per. ist:
  CHECK P0003-RRDAT IS INITIAL OR P0003-RRDAT GE PER-BEGDA.

* Ueberpruefen, ob RR zu setzen ist: This one compars the ZL with the original ZL
  PERFORM CHECK_RECALCULATION USING SET_RECALC_DATE.
* nur wenn Datum kleiner als P0003-rrdat
  CHECK SET_RECALC_DATE NE HIGH-DATE.

* This check is now done in EXPORT_PERSON
* check p0003-rrdat gt set_recalc_date or p0003-rrdat is initial.
                                       "XAYP30K136788

* -- RR ist von Sicht des RPTIME00 zu setzen:
* P0003-RRDAT = SET_RECALC_DATE.                             "YLLK63068
* MODIFY P0003 INDEX 1.                                      "YLLK63068
  IF SET_P0003-RRDAT IS INITIAL                             "YLLK63068
      OR SET_RECALC_DATE LT SET_P0003-RRDAT.                "YLLK63068
    SET_P0003-RRDAT = SET_RECALC_DATE.                      "YLLK63068
  ENDIF.                                                    "YLLK63068
ENDFORM.                               "OF SET_RECALCULATION.

Interestingly enough function check RLG has no coding but is handled in a very special way that puzzles me every time i have to look it up. So this time i write it down, so hopefully it will be the last time i have to look it up.

form RPTASI00_FILL_VARIABLES_FROM_F filles the "SW_FUNC" fields dynamically (with assigns)
the table FIELDS that containes information on what field to set is saved on the cluster with the generated TM schema:

  perform clear_variables_from_fields.                     "note757356
  perform get_schema(rpuscgt0)
                    using vschema '1'
                          print sw-schema_update
                          space space
                          returncode.
  read table as-source with key schem = vschema.            "PH4K008260
  if returncode = 0.                                        "NOTE202647
    perform fill_variables_from_fields.                     "PH4K008260
  endif.     

And guess what: the fields table is filled in the generation of the TM schema and written with the generated schema directly to cluster PS.
Here a screen shot.




HTH
happy hacking
cheers

Thursday, February 2, 2012

Mastering the SAP PAL (HR_PAL_): Icons in the PAL application Log

If you want an icon to show up in a PAL log it is sufficient to create a text column (for example in your DDIC structure or in your field catalog). I used a TEXT30 data element.
Then you write one of the codes you find below  (the ones with @xx@ to the text field.
The result is in the picture below




This is really trivial, but useful to know!
Have fun

----- From the type pool "icon"
 
 
ICON_2 ICON_DUMMY                     '@00@'."  PlaceholderIcon
ICON_2 ICON_CHECKED                   '@01@'."  Checked; OK
ICON_2 ICON_INCOMPLETE                '@02@'."  Incomplete
ICON_2 ICON_FAILURE                   '@03@'."  Failed
ICON_2 ICON_POSITIVE                  '@04@'."  Positive
ICON_2 ICON_NEGATIVE                  '@05@'."  Negative
ICON_2 ICON_LOCKED                    '@06@'."  Locked
ICON_2 ICON_UNLOCKED                  '@07@'."  Free; unlock
ICON_4 ICON_GREEN_LIGHT               '@08@'."  Green light; positive
ICON_4 ICON_YELLOW_LIGHT              '@09@'."  Yellow light; neutral
ICON_4 ICON_RED_LIGHT                 '@0A@'."  Red light; negative
ICON_2 ICON_TOTAL_LEFT                '@0B@'."  Extreme left; first ...
ICON_2 ICON_TOTAL_RIGHT               '@0C@'."  Extreme right; last ...
ICON_2 ICON_COLUMN_LEFT               '@0D@'."  Column left; previous ..
ICON_2 ICON_COLUMN_RIGHT              '@0E@'."  Column right; next ...
ICON_2 ICON_PAGE_RIGHT                '@0F@'."  Page right
ICON_2 ICON_PAGE_LEFT                 '@0G@'."  Page left
ICON_2 ICON_PREVIOUS_VALUE            '@0H@'."  Previous value; next ent
ICON_2 ICON_NEXT_VALUE                '@0I@'."  Next value; previous ent
ICON_2 ICON_ANNOTATION                '@0J@'."  Note; remark
ICON_2 ICON_CREATE_NOTE               '@0K@'."  Create note
ICON_2 ICON_DISPLAY_NOTE              '@0L@'."  Display note
ICON_2 ICON_CALCULATION               '@0M@'."  Costing
ICON_2 ICON_GRAPHICS                  '@0N@'."  Graphics
ICON_2 ICON_CREATE_TEXT               '@0O@'."  Create text
ICON_2 ICON_DISPLAY_TEXT              '@0P@'."  Display text
ICON_2 ICON_CHANGE_TEXT               '@0Q@'."  Text
ICON_2 ICON_VARIANTS                  '@0R@'."  Variants
ICON_2 ICON_INFORMATION               '@0S@'."  Information
ICON_2 ICON_ADDRESS                   '@0T@'."  Address
ICON_2 ICON_VIEWER_OPTICAL_ARCHIVE    '@0U@'."  Optical archive viewer
ICON_2 ICON_OKAY                      '@0V@'."  OK; Continue; Choose
ICON_2 ICON_CANCEL                    '@0W@'."  Cancel
ICON_2 ICON_PRINT                     '@0X@'."  Print
ICON_2 ICON_CREATE                    '@0Y@'."  Create
ICON_2 ICON_CHANGE                    '@0Z@'."  Change
ICON_2 ICON_DISPLAY                   '@10@'."  Display
ICON_2 ICON_DELETE                    '@11@'."  Delete
ICON_2 ICON_TEST                      '@12@'."  Test
ICON_2 ICON_SEARCH                    '@13@'."  Find
ICON_2 ICON_COPY_OBJECT               '@14@'."  Copy 

Wednesday, January 11, 2012

Mastering the SAP PAL (HR_PAL_) Application log: adding the log to a payroll simulation and wage type extraction program

Hi Folks!
In this post i would like to explore the "new" PAL application log.
In the past i have been using the old "E3L" P99S application log that was really ugly.
I have seen that this new application log (PAL) is really flexible and covers most reporting needs, so i would like to add it to my tool box, and at the same time share it with you all.

At the end of this post you find some working coding, where the log has been put in a payroll simulation program.

I will not cover all possibilities, but provide the insight needed for most cases. 


Tha PAL is based on the Basis "BAL" log. the BAL Log is quite powerful and you can find several documents on the web, but also the example programs "SBAL_DEMO*" in se38 are quite enough. See also transactions SLG0 SLG1 SLG2

The PAL is a kind of wrapper around the BAL. You intialize it, write data to it, and then show it.

To initialize the log you need to tell it the structure of the nodes you want to show up the the log tree (the "node categories)
For the structure you can either use a DDIC structure, or compile manually a field catalogue ( SLIS )  and pass it to the function HR_PAL_CREATE_NODE_CATEG

For each category you have to create the node with function 'HR_PAL_NODE_ADD'


For example our log will look like this:


In the tree box the first two rows (the ones with a table icon) are created with the following calls

   CALL FUNCTION 'HR_PAL_CREATE_NODE_CATEG'
    EXPORTING
      i_categ_id       = 'MYLOG'
      is_pushbuttons   = l_pushbuttons
      i_structure_name = 'P15_IMPIEGATI'.
  CALL FUNCTION 'HR_PAL_NODE_ADD'
    EXPORTING
      i_relatkey = 'ROOT'
      i_categ_id = 'MYLOG'
      i_node_txt = 'CID elaborati'
    IMPORTING
      e_node_key = gv_risul_node.

Once the node is added using the "gv_risul_node" you can add lines to the table with the call

      DATA ls_str TYPE    p15_impiegati.
        ls_str-pernr = pernr_selection-pernr.
        ls_str-name  = 'TOOLAZYTOREADIT0001'.

        CALL FUNCTION 'HR_PAL_NODE_ADD_ROW'
          EXPORTING
            i_node_key = gv_risul_node
            i_row_data = ls_str.

Each call will create a line in the table.

The to nice push buttons (gift and log in the figure above) are created really simply:
fill the pushbuttons structure and pass it to the node category that will show the buttons (in our case the first one)
  DATA l_pushbuttons TYPE hrpad_pal_s_pushbuttons.

  l_pushbuttons-cat_push1-active = 'X'.
  l_pushbuttons-cat_push1-position = 1.
  l_pushbuttons-cat_push1-def-text = 'GIFT'.
  l_pushbuttons-cat_push1-def-icon_text = 'GIFT'.
  l_pushbuttons-cat_push1-def-quickinfo = 'GIFT'.
  l_pushbuttons-cat_push1-clbk-userexitp = sy-repid.
  l_pushbuttons-cat_push1-clbk-userexitf = 'CALLBACK_FORM'.
  l_pushbuttons-cat_push1-def-icon_id = icon_extra .




The callback form looks like this


*&---------------------------------------------------------------------*
*&      Form  callback_form
*&---------------------------------------------------------------------*
FORM callback_form  USING p_var_tab TYPE table
                CHANGING c_s_state TYPE bal_s_cbuc.       
  CASE c_s_state-ucomm.

    WHEN '%CAT_PUSH2'. "Log

      ENDIF.

    WHEN '%CAT_PUSH1'. "Gift
      BREAK-POINT.


  ENDCASE.

ENDFORM.                    "callback_form
 So at the end we have only global and Person related messages left
The two lines in our figure "generic messages" and " person related messages " (the ones with the green and red traffic light) are really simple. You just need to call a function to write a message to that area:
 'HR_PAL_GENRL_MSG_ADD'

 'HR_PAL_PERNR_MSG_ADD'
and you can pass it typical T100 messages (so you can maintain them from SE91).

Finally you can show the log with the function 'HR_PAL_LOG_DISPLAY'
Its parameters allow you to set some data like the header text of the different log areas, and to decide whether the trre is on top or on the side. 
I would suggest looking into the structures 
 hrpad_pal_disp_prof
  hrpad_pal_flat_prof
And trying out the different possible values 

Conclusion: with a few lines of coding you have a nice flexible and professional looking application log that you can add to most applications.

Here is the example coding
REPORT zestr_payroll_sim.

TYPE-POOLS: slis.
INCLUDE .

DATA: pernr_selection LIKE pay_sim_pernr OCCURS 0 WITH HEADER LINE.

DATA: BEGIN OF mem_key,
      uname LIKE sy-uname,
      datum LIKE sy-datum,
    END OF mem_key.

DATA: BEGIN OF gt_out OCCURS 0,
    pernr TYPE p_pernr,
    paper TYPE paper,
    lgart TYPE pc207-lgart,
    betrg TYPE pc207-betrg,
    anzhl TYPE pc207-anzhl,
    betpe TYPE pc207-betpe,
END OF gt_out.

DATA gv_risul_node          TYPE tv_nodekey.
DATA gv_errlg_node          TYPE tv_nodekey.
DATA gv_var_node            TYPE tv_nodekey.

TABLES: pcl1, pcl2, pa0001, t549q, pc207.

INCLUDE rpppxd00.            "buffer handling
INCLUDE rpppxd10.
INCLUDE rpppxm00.

DATA paper TYPE paper.

SELECT-OPTIONS spernr FOR pa0001-pernr.
PARAMETERS: pabrp TYPE t549q-pabrp.
PARAMETERS: pabrj TYPE t549q-pabrj.
PARAMETERS: pabkrs TYPE pa0001-abkrs.
SELECT-OPTIONS: spaper FOR paper.
SELECT-OPTIONS: plgart FOR pc207-lgart.
PARAMETERS: variant LIKE vari-variant DEFAULT 'XXX'.
PARAMETERS: program LIKE sy-cprog DEFAULT 'RPCALCX0'.

PARAMETERS: showlog AS CHECKBOX DEFAULT 'X'.
PARAMETERS: logcalc AS CHECKBOX DEFAULT 'X'.


START-OF-SELECTION.

  PERFORM initialize_log.


  SELECT pernr FROM pa0001
      INTO CORRESPONDING FIELDS OF TABLE pernr_selection
                                      WHERE pernr IN spernr AND
                                            endda = '99991231'.

  PERFORM add_message
              USING '' 'I' 'N pernr selected: '
                        sy-dbcnt '' ''.

  mem_key-uname = sy-uname.
  mem_key-datum = sy-datum.

  CALL FUNCTION 'HR_PAYROLL'
    EXPORTING
      payroll_area              = pabkrs
      payroll_period            = pabrp
      payroll_year              = pabrj
*   PAYROLL_TYPE              =
*   PAYROLL_ID                =
*   PAYROLL_DATE              =
*   PAYROLL_OCRSN             =
      selection_variant         = variant
      program_name              = program
*   OFF_CYCLE                 = ' '
      log_mem_key               = mem_key
*   COUNTRY_GRP               =
      tst_on                    = 'X'
*   IMP_BUFF                  = ' '
*   OBJ_IPREL                 =
*   COSTPLANNING              = ' '
    prt_prot                  = logcalc
*   SEL_ALL_AREAS             = ' '
    TABLES
      employee_numbers          = pernr_selection
*   ADVANCE_PERIODS           =
      buffer                    =  tbuff
      buffer_directory          =  buffer_dir
*   DELETE_PCLX               =
*   PS_OPER                   =
   EXCEPTIONS
     program_not_exist         = 1
     variant_not_exist         = 2
     missing_parameter         = 3
     wrong_parameter           = 4
     wrong_country_group       = 5
     OTHERS                    = 6
            .
  IF sy-subrc <> 0.
    PERFORM add_message
                USING '' 'E' 'ERROR from HR_PAYROLL:'
                          sy-subrc '' ''.
  ENDIF.

  LOOP AT pernr_selection WHERE retcd NE 0.

    PERFORM add_message USING pernr_selection-pernr 'E' 'ERROR payroll per CID'
                        pernr_selection-pernr pernr_selection-retcd ''.


    DELETE pernr_selection.

  ENDLOOP.

*  IF sy-subrc EQ 0 OR NOT showlog = ' '.
*    IF showlog NE space.
*      CALL FUNCTION 'HR_PL_IMPORT_LOG_FROM_MEMORY'
*        EXPORTING
*          mem_key = mem_key.
*
*      CALL FUNCTION 'HR_PL_DISPLAY_LOG'
*        EXPORTING
*          procl  = 'C'
*        EXCEPTIONS
*          OTHERS = 0.
*    ENDIF.
*  ENDIF.

  LOOP AT buffer_dir.
    buffer_dir-relid+0(1) = '$'.
    MODIFY buffer_dir.
  ENDLOOP.
  SORT buffer_dir BY sgart client relid srtfd.

  LOOP AT tbuff.
    tbuff-relid+0(1) = '$'.
    MODIFY tbuff.
  ENDLOOP.

  DATA: l_molga TYPE molga,
        BEGIN OF ocd-version.
          INCLUDE STRUCTURE pc2_cd.
  DATA: END OF ocd-version.
  DATA: rgdir LIKE pc261 OCCURS 0 WITH HEADER LINE.
  DATA: lt_rt LIKE pc207 OCCURS 0 WITH HEADER LINE.

  LOOP AT pernr_selection WHERE retcd EQ 0.
    no_authority_check_cluster = 'X'.
*    pcl2-client = sy-mandt.
*    pcl2-relid = '$U'.
*    pcl2-srtfd = pernr_selection-pernr.
*    PERFORM pcl2_exp_imp USING 'READ'.
    IMPORT cd-version TO ocd-version rgdir
       FROM DATABASE pcl2($u) ID pernr_selection-pernr
                              USING pcl2_exp_imp.

    IF sy-subrc <> 0.     "no payroll results
      PERFORM add_message
             USING pernr_selection-pernr 'E' 'CID Simulato non ha payres'
                       pernr_selection-pernr '' ''.
    ELSE.
      l_molga = ocd-version-molga.
    ENDIF.
    IF l_molga EQ 15.
*      DATA l_paper TYPE paper.
*      l_paper+0(4) = pabrj.
*      l_paper+4(2) = pabrp.

*      READ TABLE rgdir WITH KEY fpper = l_paper
*                                srtza = 'A'.
*      IF sy-subrc EQ 0.
      LOOP AT rgdir WHERE fpper IN spaper AND
                          srtza = 'A'.
        DATA rx_key LIKE pc200.

        REFRESH: lt_rt. CLEAR: lt_rt.
        rx_key-pernr = pernr_selection-pernr.
        rx_key-seqno = rgdir-seqnr.

        IMPORT rt TO lt_rt
           FROM DATABASE pcl2($i) ID rx_key
                                  USING pcl2_exp_imp.
        IF NOT sy-subrc IS INITIAL.
          PERFORM add_message
                 USING rx_key-pernr 'E' 'Pernr error in $I import (RI):'
                           pernr_selection-pernr rx_key ''.
        ELSE.
          PERFORM add_message
                USING rx_key-pernr 'E' 'Pernr error in $I import (RI):'
                          pernr_selection-pernr rx_key ''.

        ENDIF.
        no_authority_check_cluster = space.

        DATA ls_str TYPE    p15_impiegati.
        ls_str-pernr = pernr_selection-pernr.
        ls_str-name  = 'TOOLAZYTOREADIT0001'.

        CALL FUNCTION 'HR_PAL_NODE_ADD_ROW'
          EXPORTING
            i_node_key = gv_risul_node
            i_row_data = ls_str.



        DATA l_tabix TYPE sy-tabix.
        CLEAR l_tabix.

        LOOP AT lt_rt WHERE lgart IN plgart.

          CLEAR gt_out.

          gt_out-paper = rgdir-fpper.
          gt_out-pernr = pernr_selection-pernr.
          gt_out-anzhl = lt_rt-anzhl.
          gt_out-betrg = lt_rt-betrg.
          gt_out-lgart = lt_rt-lgart.

          COLLECT gt_out.

          l_tabix = sy-tabix.

          READ TABLE gt_out INDEX l_tabix.

          gt_out-betpe = lt_rt-betpe.

          MODIFY gt_out INDEX l_tabix.

        ENDLOOP.

      ENDLOOP. "Rgdir in spaper
*      ENDIF.
    ENDIF.
  ENDLOOP.

  PERFORM add_message
              USING '' 'I' 'Done!' '' '' ''.

END-OF-SELECTION.

*  PERFORM show_error_list.



  LOOP AT gt_out.
    CALL FUNCTION 'HR_PAL_NODE_ADD_ROW'
      EXPORTING
        i_node_key = gv_var_node
        i_row_data = gt_out.
  ENDLOOP.

  PERFORM  display_log.

*---------------------------------------------------------------------*
*       FORM add_message                                              *
*---------------------------------------------------------------------*
FORM add_message USING ppernr msgty text par1 par2 par3.

  DATA lv_msgv1 TYPE sy-msgv1.
  DATA lv_msgv2 TYPE sy-msgv2.
  DATA lv_msgv3 TYPE sy-msgv3.
  DATA lv_msgv4 TYPE sy-msgv4.

  lv_msgv1 = text.
  lv_msgv2 = par1.
  lv_msgv3 = par2.
  lv_msgv4 = par3.


  IF ppernr IS INITIAL.

    CALL FUNCTION 'HR_PAL_GENRL_MSG_ADD'
      EXPORTING
*      I_NODE_KEY          =
        i_msgid             = 'RP'
       i_msgty             = msgty
        i_msgno             = 16
        i_msgv1                = lv_msgv1
        i_msgv2                = lv_msgv2
        i_msgv3                = lv_msgv3
        i_msgv4                = lv_msgv4
*    IMPORTING
*      E_NODE_KEY          =
     EXCEPTIONS
       program_error       = 1
       OTHERS              = 2.

  ELSE.

    CALL FUNCTION 'HR_PAL_PERNR_MSG_ADD'
      EXPORTING
*       I_NODE_KEY             =
        i_pernr                = ppernr
        i_msgid                = 'RP'
       i_msgty                = msgty
        i_msgno                = 16
        i_msgv1                = lv_msgv1
        i_msgv2                = lv_msgv2
        i_msgv3                = lv_msgv3
        i_msgv4                = lv_msgv4
*     IMPORTING
*       E_PERNR_NODE_KEY       =
     EXCEPTIONS
       program_error          = 1
       OTHERS                 = 2.

  ENDIF.

ENDFORM.                    "add_message

*---------------------------------------------------------------------*
*       FORM show_error_list                                          *
*---------------------------------------------------------------------*
*FORM show_error_list.
*
*  DATA lt_error TYPE TABLE OF hrerror.
*
*  CALL FUNCTION 'HR_GET_ERROR_LIST'
** EXPORTING
**   USE_ABAP_MEMORY       = ' '
*   TABLES
*     error                 = lt_error
**   ERRORTEXTS            =
*   EXCEPTIONS
*     no_errors             = 1
*     OTHERS                = 2
*            .
*  IF sy-subrc <> 0.
*  ENDIF.
*
*  CALL FUNCTION 'HR_IT_SHOW_ANY_TABLE_ON_ALV'
*    TABLES
*      table    = lt_error
*    EXCEPTIONS
*      fb_error = 1
*      OTHERS   = 2.
*  IF sy-subrc <> 0.
*  ENDIF.
*
*  CALL FUNCTION 'HR_IT_SHOW_ANY_TABLE_ON_ALV'
*    TABLES
*      table    = gt_out
*    EXCEPTIONS
*      fb_error = 1
*      OTHERS   = 2.
*  IF sy-subrc <> 0.
*  ENDIF.
*
*
*ENDFORM.                    "show_error_list


*&---------------------------------------------------------------------*
*&      Form  initialize_log
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM initialize_log.

  DATA lt_fieldcatalog_pernr   TYPE slis_t_fieldcat_alv.
  DATA lt_fieldcatalog_vart    TYPE slis_t_fieldcat_alv.
  DATA l_pushbuttons TYPE hrpad_pal_s_pushbuttons.

  PERFORM create_var_catalog CHANGING lt_fieldcatalog_vart.

  l_pushbuttons-cat_push1-active = 'X'.
  l_pushbuttons-cat_push1-position = 1.
  l_pushbuttons-cat_push1-def-text = 'GIFT'.
  l_pushbuttons-cat_push1-def-icon_text = 'GIFT'.
  l_pushbuttons-cat_push1-def-quickinfo = 'GIFT'.
  l_pushbuttons-cat_push1-clbk-userexitp = sy-repid.
  l_pushbuttons-cat_push1-clbk-userexitf = 'CALLBACK_FORM'.
  l_pushbuttons-cat_push1-def-icon_id = icon_extra .

  l_pushbuttons-cat_push2-active = 'X'.
  l_pushbuttons-cat_push2-position = 1.
  l_pushbuttons-cat_push2-def-text = 'LOG'.
  l_pushbuttons-cat_push2-def-icon_text = 'LOG'.
  l_pushbuttons-cat_push2-def-quickinfo = 'LOG'.
  l_pushbuttons-cat_push2-clbk-userexitp = sy-repid.
  l_pushbuttons-cat_push2-clbk-userexitf = 'CALLBACK_FORM'.
  l_pushbuttons-cat_push2-def-icon_id = icon_protocol .


  CALL FUNCTION 'HR_PAL_CREATE_NODE_CATEG'
    EXPORTING
      i_categ_id       = 'MYLOG'
      is_pushbuttons   = l_pushbuttons
      i_structure_name = 'P15_IMPIEGATI'.
*TODO
  CALL FUNCTION 'HR_PAL_CREATE_NODE_CATEG'
    EXPORTING
      i_categ_id  = 'VART'
      it_fieldcat = lt_fieldcatalog_vart.


  CALL FUNCTION 'HR_PAL_NODE_ADD'
    EXPORTING
      i_relatkey = 'ROOT'
      i_categ_id = 'MYLOG'
      i_node_txt = 'CID elaborati'
    IMPORTING
      e_node_key = gv_risul_node.

  CALL FUNCTION 'HR_PAL_NODE_ADD'
    EXPORTING
      i_relatkey = 'ROOT'
      i_categ_id = 'VART'
      i_node_txt = 'Risultati'
    IMPORTING
      e_node_key = gv_var_node.




ENDFORM.                    "initialize_log


*&---------------------------------------------------------------------*
*&      Form  create_var_catalog
*&---------------------------------------------------------------------*
FORM create_var_catalog
                  CHANGING ct_fieldcatalog TYPE slis_t_fieldcat_alv.

* Data declarations
  DATA ls_fieldcatalog              TYPE slis_fieldcat_alv.
  DATA lv_position                  TYPE i.

  DEFINE af.

    add 1 to lv_position.
    ls_fieldcatalog-fieldname = &1.
    ls_fieldcatalog-rollname  = &2.
    ls_fieldcatalog-col_pos   = lv_position.
    append ls_fieldcatalog to ct_fieldcatalog.
    clear ls_fieldcatalog.

  END-OF-DEFINITION.

  af:
  'PERNR' 'P_PERNR',
  'PAPER' 'PAPER',
  'LGART' 'LGART',
  'BETRG' 'MAXBT',
  'ANZHL' 'PRANZ',
  'BETPE' 'BETPE'.


ENDFORM.                    "create_var_catalog




*&---------------------------------------------------------------------*
*&      Form  callback_form
*&---------------------------------------------------------------------*
FORM callback_form  USING p_var_tab TYPE table
                CHANGING c_s_state TYPE bal_s_cbuc.         "#EC NEEDED

  BREAK-POINT.
  CASE c_s_state-ucomm.

    WHEN '%CAT_PUSH2'. "Log

      IF showlog NE space.
        CALL FUNCTION 'HR_PL_IMPORT_LOG_FROM_MEMORY'
          EXPORTING
            mem_key = mem_key.

        CALL FUNCTION 'HR_PL_DISPLAY_LOG'
          EXPORTING
            procl  = 'C'
          EXCEPTIONS
            OTHERS = 0.
      ENDIF.



    WHEN '%CAT_PUSH1'. "Gift
      BREAK-POINT.


  ENDCASE.

ENDFORM.                    "callback_form


*&---------------------------------------------------------------------*
*&      Form  display_log
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM display_log.
* Just show what was drawn
  DATA: l_display_profile TYPE hrpad_pal_disp_prof.
  DATA: l_flat_profile    TYPE hrpad_pal_flat_prof.
  DATA  ls_expand         TYPE hrpad_pal_s_header_node.

  ls_expand = gv_risul_node.
  APPEND ls_expand TO l_display_profile-expanded_nodes.

  l_display_profile-tree_ontop     = 'Y'.
  "l_display_profile-flat           = 'Y'.
  CALL FUNCTION 'HR_PAL_LOG_DISPLAY'
    EXPORTING
      i_s_display_profile = l_display_profile
      i_s_flat_profile    = l_flat_profile.

ENDFORM.                    " DISPLAY_LOG