ZHR_AUSW02 – Auswertung der Urlaubskontingente

Dieses Programm aus eigener Feder wertet die Urlaubskontingente aus.

Abhängig vom Vorjahresurlaubskontingent oder vom Anspruch der Urlaubstage aus den Arbeitszeitmodell wird das neue Urlaubskontingent berechnet und vielfach auf Plausibilität überprüft.

Damit ist es möglich, die Urlaubskontingente für eine ganze Firma für ein ganzes Jahr in kürzester Zeit zu erzeugen.

Ein Ampelsystem zeigt an, bei welchen Personalnummern schon Kontingente vorhanden sind (Grün), welche ausgeschieden sind (Gelb) und bei welchen ein Kontingent erzeugt werden könnte (Rot). Inkl. Testlauf.

REPORT zhr_ausw02.

* Auswertung des Urlaubskontingents
* Offene Probleme
*   Endedatum Kontingent in Zukunft 2099 etc.
*   Zwei Kontingente, die im selben Jahr enden oder beginnen.
*   Zwei Kontingente, wo dasselbe Anfangsdatum ist, wird fehlerhaft upgedatet.
*     Kontrolle, dass kein Kontingent existiert, dass sich überschneidet, vermutlich zuviele Fehler.
*   Eintrag in IT0041

* Update des Urlaubskontingents
* 20191105 HST Version 6
*  AZP ergänzt
*  Kein Update, wenn AZP 0 Tage anzeigt (Altersteilzeit AZP FREI)
* 20191105 HST Version 5
*  Korrektur Fehler Abtragung beim Update / Insert wurde mitübernommen (Temp Speicher)
* 20190818 HST Version 4
*  Update Selektion von Einzelsätzen möglich
*  Korrektur bei überschneidenen Kontingenten
*  Kontrolle ob neues Kontingent Überschneidungen hat.
* 20190813 HST Version 3
*  Aktivdatum
*  Endedatum im Zeitraum und nicht von bis im Selektionszeitraum
*  Ganzes Jahr Kontingent überprüfen, sonst kein Update
*  Selektionszeitraum auf ein Jahr einschränken
*  Kontingent oder Sollarbeitszeitinfo für Urlaub
*  Korrektur Fehler Update wenn mehr als 1 Satz Urlaub im nächsten Jahr (genau 1 Satz war abgefangen)
*  Korrektur Fehler Update wenn Kontingent neues Beginndatum im Selektionszeitraum hatte
*   (nur Beginndatum im Zeitraum nach Selektionszeitraum war abgefangen)
* 20190213 HST Version 2
*  Einbau der Anzeige von ausgeschiedenen Mitarbeitern, für die aber auch kein Update erfolgt



TABLES: pa0001, pa0007, pa2001, pa2002.
TYPE-POOLS: icon.
TYPES: BEGIN OF ty_alv,
         ampel(4)  TYPE c,
         update    TYPE c,
         pernr     TYPE persno,
         nachn     TYPE pad_nachn,
         vorna     TYPE pad_vorna,
         begdaa    TYPE begda, "Aktivdatum
         enddaa    TYPE endda, "Aktivdatum
         begda     TYPE begda,
         endda     TYPE endda,
         anzhl     TYPE ptm_quonum,
         anzhls    TYPE ptm_quonum,
         desta     TYPE ptm_dedstart,
         deend     TYPE ptm_dedend,
         persk     TYPE persk,
         schkz     TYPE schkn, "Arbeitszeitplanregel "20191105HST
         begdan    TYPE begda, "Neues Kontingent
         enddan    TYPE endda, "Neues Kontingent
         anzhln    TYPE ptm_quonum, "Neues Kontingent
*         ausw(6)   TYPE c,
*         "datvo type
*         kunnr     TYPE bsad-kunnr,
*         name1     TYPE kna1-name1,
*         belnr     TYPE bsad-belnr,
*         gjahr     TYPE bsad-gjahr,
*         shkzg     TYPE bsad-shkzg,
*         dmbtr     TYPE bsad-dmbtr,
*         sknto     TYPE bsad-sknto,
*         blart     TYPE bsad-blart,
*         budat     TYPE bsad-budat,
*         bldat     TYPE bsad-bldat,
*         "faedt     TYPE bsad-faedt,
*         augdt     TYPE bsad-augdt,
*         zfbdt     TYPE bsad-zfbdt,
*         zbd1t     TYPE bsad-zbd1t,
*         zbd2t     TYPE bsad-zbd2t,
*         zbd1p     TYPE bsad-zbd1p,
*         zbd2p     TYPE bsad-zbd2p,
*         faed1     TYPE bsad-zfbdt, "FälligSkonto
*         faed2     TYPE bsad-zfbdt, "FälligNetto
*         meng1     TYPE bsad-zbd1t,
*         meng2     TYPE bsad-zbd1t,
*         bewer     TYPE mseg-menge, "Bewertung
         bemer(50) TYPE c,
       END OF ty_alv.
DATA: gt_alv_pers TYPE STANDARD TABLE OF ty_alv,
      gt_alv      TYPE STANDARD TABLE OF ty_alv,
      gs_alv      TYPE ty_alv.
DATA: gref_salv TYPE REF TO cl_salv_table.


SELECTION-SCREEN BEGIN OF BLOCK all WITH FRAME.
SELECTION-SCREEN BEGIN OF BLOCK per WITH FRAME TITLE text-001.
SELECT-OPTIONS: so_pernr FOR pa0001-pernr MATCHCODE OBJECT prem DEFAULT '1080'.
SELECT-OPTIONS: so_persk FOR pa0001-persk."Mitarbeiterkreis AE Arbeiter AH Angestellte
SELECT-OPTIONS: so_persg FOR pa0001-persg."Mitarbeitergruppe Aktiv etc.
SELECT-OPTIONS: so_abkrs FOR pa0001-abkrs."Abrechnungskreis A1, A2
SELECT-OPTIONS: so_zterf FOR pa0007-zterf NO-DISPLAY."Zeiterfasssungskennzeichen 1 aktiv
PARAMETERS:
  p_zterf TYPE xfeld AS CHECKBOX DEFAULT ''.
SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF LINE.
"Werden weiter unten ausgeblendet
PARAMETERS :
  p_arb  RADIOBUTTON GROUP g1,
  p_ang  RADIOBUTTON GROUP g1,
  p_alle RADIOBUTTON GROUP g1 DEFAULT 'X'.
SELECTION-SCREEN END OF LINE.
"parameters: p_orgeh type orgeh.
SELECTION-SCREEN END OF BLOCK per.
SELECTION-SCREEN BEGIN OF BLOCK dat WITH FRAME TITLE text-002.
SELECT-OPTIONS: so_datum FOR sy-datum OBLIGATORY NO-EXTENSION.
"Ohne Verwendung ????
PARAMETERS: p_factid TYPE wfcid DEFAULT 'AT' NO-DISPLAY.
PARAMETERS: p_werks TYPE pa0001-werks DEFAULT '1000' NO-DISPLAY.
SELECTION-SCREEN END OF BLOCK dat.

SELECTION-SCREEN BEGIN OF BLOCK opt WITH FRAME TITLE text-003.
PARAMETERS:
  p_urlaub TYPE xfeld AS CHECKBOX DEFAULT abap_true,  "Urlaubskontingent
  p_ohne   TYPE xfeld AS CHECKBOX DEFAULT abap_false, "Ohne neues Urlaubskontingent
  p_aktiv  TYPE xfeld AS CHECKBOX DEFAULT abap_false. "Nur aktive MA
SELECTION-SCREEN END OF BLOCK opt.

SELECTION-SCREEN BEGIN OF BLOCK sort WITH FRAME TITLE text-004.
PARAMETERS:
  p_sort0 RADIOBUTTON GROUP g2 DEFAULT 'X',           "Nachname sortiert
  p_sort1 RADIOBUTTON GROUP g2.                       "Personalnummer sortiert
SELECTION-SCREEN END OF BLOCK sort.

SELECTION-SCREEN BEGIN OF BLOCK updt WITH FRAME TITLE text-006.
PARAMETERS:
  p_test TYPE xfeld AS CHECKBOX DEFAULT 'X'.
PARAMETERS:
  p_vorj RADIOBUTTON GROUP g4 ,                       "Vorjahreswert Kontingent
  p_soll RADIOBUTTON GROUP g4 DEFAULT 'X'.            "Aus Solldaten
SELECTION-SCREEN END OF BLOCK updt.

SELECTION-SCREEN BEGIN OF BLOCK outp WITH FRAME TITLE text-005.
PARAMETERS: p_visibl TYPE xfeld AS CHECKBOX DEFAULT ''.
PARAMETERS:
  p_out0 RADIOBUTTON GROUP g3 , "DEFAULT 'X',         "Dialog Output
  p_out1 RADIOBUTTON GROUP g3 DEFAULT 'X'.            "ALV Output
SELECTION-SCREEN END OF BLOCK outp.


SELECTION-SCREEN END OF BLOCK all.

DATA lt_pa0007 TYPE TABLE OF pa0007."AZP Aktiv
DATA lt_pa0000 TYPE TABLE OF pa0000."Maßnahmen (Aktiv)
DATA lt_pa0002 TYPE TABLE OF pa0002."Namen- und Adressdaten
DATA lt_pa0001 TYPE TABLE OF pa0001."Orgzugehörigkeit
DATA lt_pa2001 TYPE TABLE OF pa2001."Abwesenheiten
DATA lt_pa2002 TYPE TABLE OF pa2002."Anwesenheiten

DATA lt_pa2006 TYPE TABLE OF pa2006."Urlaubskontingente
DATA ls_pa2006 TYPE pa2006."Urlaubskontingente


TYPES: BEGIN OF ty_pers,
         pernr TYPE persno,
         begda TYPE begda,
         endda TYPE endda,
       END OF ty_pers.

DATA ls_pa TYPE ty_pers.
DATA lt_pa TYPE TABLE OF ty_pers.


*----------------------------------------------------------------------*
*       CLASS cl_event_handler DEFINITION
*----------------------------------------------------------------------*
CLASS cl_event_handler DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS on_before_salv_function         " BEFORE_SALV_FUNCTION
      FOR EVENT if_salv_events_functions~before_salv_function
                  OF cl_salv_events_table
      IMPORTING e_salv_function.

    CLASS-METHODS on_after_salv_function          " AFTER_SALV_FUNCTION
      FOR EVENT if_salv_events_functions~before_salv_function
                  OF cl_salv_events_table
      IMPORTING e_salv_function.

    CLASS-METHODS on_added_function               " ADDED_FUNCTION
      FOR EVENT if_salv_events_functions~added_function
                  OF cl_salv_events_table
      IMPORTING e_salv_function.

    CLASS-METHODS on_top_of_page                  " TOP_OF_PAGE
      FOR EVENT if_salv_events_list~top_of_page
                  OF cl_salv_events_table
      IMPORTING r_top_of_page
                  page
                  table_index.

    CLASS-METHODS on_end_of_page                  " END_OF_PAGE
      FOR EVENT if_salv_events_list~end_of_page
                  OF cl_salv_events_table
      IMPORTING r_end_of_page
                  page.

    CLASS-METHODS on_double_click                 " DOUBLE_CLICK
      FOR EVENT if_salv_events_actions_table~double_click
                  OF cl_salv_events_table
      IMPORTING row
                  column.

    CLASS-METHODS on_link_click                   " LINK_CLICK
      FOR EVENT if_salv_events_actions_table~link_click
                  OF cl_salv_events_table
      IMPORTING row
                  column.
ENDCLASS.                    "cl_event_handler DEFINITION

*----------------------------------------------------------------------*
*       CLASS cl_event_handler IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS cl_event_handler IMPLEMENTATION.

  METHOD on_before_salv_function.
    "BREAK-POINT.
  ENDMETHOD.                    "on_before_salv_function

  METHOD on_after_salv_function.
    "BREAK-POINT.
  ENDMETHOD.                    "on_after_salv_function

  METHOD on_added_function.
    PERFORM user_command USING e_salv_function.
  ENDMETHOD.                    "on_added_function

  METHOD on_top_of_page.
    "BREAK-POINT.
  ENDMETHOD.                    "on_top_of_page

  METHOD on_end_of_page.
    "BREAK-POINT.
  ENDMETHOD.                    "on_end_of_page

  METHOD on_double_click.
    PERFORM action TABLES gt_alv USING row column.
  ENDMETHOD.                    "on_double_click

  METHOD on_link_click.
    PERFORM action TABLES gt_alv USING row column.
  ENDMETHOD.                    "on_link_click
ENDCLASS.                    "cl_event_handler IMPLEMENTATION


*&---------------------------------------------------------------------*
*&      INITIALIZATION
*&---------------------------------------------------------------------*
*  Grundlegende Eingabevoreinstellungen, wird nur einmalig durchlaufen
*----------------------------------------------------------------------*
INITIALIZATION.
*
*  CLEAR so_matnr.
*  so_matnr-sign = 'I'.
*  so_matnr-option = 'CP'.
*  so_matnr-low = '800000004*'.
*  APPEND so_matnr.
*
  so_datum-sign = 'I'.
  so_datum-option = 'BT'.
  "so_datum-low = sy-datum.
  CONCATENATE sy-datum(6) '16' INTO so_datum-low.
  DATA: lv_date TYPE endda.
  lv_date = so_datum-low + 20.

  CONCATENATE lv_date(6)  '15' INTO so_datum-high.

  MOVE '20181201' TO so_datum-low.
  lv_date = so_datum-low + 31.
  CONCATENATE lv_date(6) '01' INTO so_datum-high.
  so_datum-high = so_datum-high - 1.

  MOVE '20180101' TO so_datum-low.
  MOVE '20181231' TO so_datum-high.

  APPEND so_datum.



*&---------------------------------------------------------------------*
*&      AT SELECTION-SCREEN OUTPUT
*&---------------------------------------------------------------------*
*  Wird mehrfach abgefeuert
*----------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.

  "Parameter ausblenden
  LOOP AT SCREEN.
    IF screen-name = 'P_ALLE' OR screen-name = 'P_ARB' OR screen-name = 'P_ANG'.
      screen-input = 0.
      screen-invisible = abap_true.
      screen-active = 0.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.


*&---------------------------------------------------------------------*
*&      START-OF-SELECTION
*&---------------------------------------------------------------------*
*  Hauptprogramm
*----------------------------------------------------------------------*
START-OF-SELECTION.

  "Plausibitität ob mehr als 1 Jahr oder 365 Tage bzw. 366 Tage bei Schaltjahr
  DATA(lv_diff) = so_datum-high - so_datum-low.
  DATA lv_schalt TYPE p DECIMALS 2.
  DATA lv_schalt2 TYPE p DECIMALS 0.
  lv_schalt = so_datum-low(4) / 4.
  lv_schalt2 = so_datum-low(4) / 4.
  IF ( lv_schalt EQ lv_schalt2 AND lv_diff GE 366 ) OR
    ( lv_schalt NE lv_schalt2 AND lv_diff GE 365 ).
    MESSAGE e534(0u) WITH 'Mehr ' 'als ' '1 Jahr ' 'nicht erlaubt'.
    EXIT.
  ENDIF.

  IF p_urlaub = 'X'.
    PERFORM initial.
    PERFORM collect_pers.
    PERFORM collect_data.
    PERFORM sort_data.
    PERFORM show_data.


    IF p_test IS INITIAL
      AND sy-ucomm = 'UPDATE'. "Hier kommt er nie zurück mit UPDATE
      "Toter Code
      "AND sy-ucomm = '&F03'. "Schreiben der Daten und nochmalige Auswertung und Anzeige
      PERFORM update_data_alle.
      "PERFORM collect_data.
      "PERFORM sort_data.
      PERFORM show_data.
    ENDIF.

  ENDIF.

  EXIT.


*&---------------------------------------------------------------------*
*&      FORM INITIAL
*&---------------------------------------------------------------------*
*  Grundlegende Parameterverarbeitung
*----------------------------------------------------------------------*
FORM initial.

  CLEAR gt_alv_pers.

  "Zeiterfassungscheckbox in Select Option umsetzen
  IF p_zterf EQ 'X'.
    so_zterf-sign = 'I'.
    so_zterf-option = 'EQ'.
    so_zterf-low = '1'.
    APPEND so_zterf.
  ELSE.
    CLEAR so_zterf.
  ENDIF.

  "Parameter Arbeiter oder Angestellte umsetzen
  "Derzeit nicht in Verwendung
  IF p_arb EQ abap_true.
    so_persk-sign = 'I'.
    so_persk-option = 'EQ'.
    so_persk-low = 'AE'.
    APPEND so_persk.
  ENDIF.
  IF p_ang EQ abap_true.
    so_persk-sign = 'I'.
    so_persk-option = 'EQ'.
    so_persk-low = 'AH'.
    APPEND so_persk.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM collect_pers
*&---------------------------------------------------------------------*
*  Sammeln der Mitarbeiterdaten
*----------------------------------------------------------------------*
FORM collect_pers.
  "Selektion der MA über PA0007
  "Begin muss im Selektionszeitraum liegen
  "oder
  "Ende muss im Selektionszeitraum liegen
  "oder
  "Selektionszeitraum muss nach Begin und vor Endedatum liegen.
  SELECT pernr FROM pa0007 AS a "Sollarbeitszeit
  INTO CORRESPONDING FIELDS OF TABLE lt_pa "0007
  WHERE a~pernr IN so_pernr
  "AND a~begda LT sy-datum
  "AND a~endda GT sy-datum
  AND a~zterf IN so_zterf "Zeiterfassung aktiv, wenn ausgewählt
  AND
  (
  a~begda IN so_datum
  OR
  a~endda IN so_datum
  OR
  (
  a~begda LT so_datum-low
  AND
  a~endda GT so_datum-high
  )
  )
  GROUP BY pernr
  .


  IF sy-subrc IS INITIAL.
    "if lt_pa0007[] is not initial.  ist besser.
    "lt_pa0007 darf nicht leer sein, sonst werden alle Sätze genommen.
    "Auswahl der Maßnahmen 3 Beschäftigt im besagtem Zeitraum
    SELECT * FROM pa0000 AS a INTO TABLE lt_pa0000
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND stat2 = '3' "Beschäftigung ist aktiv
    AND
    (
    a~begda IN so_datum
    OR
    a~endda IN so_datum
    OR
    (
    a~begda LT so_datum-low
    AND
    a~endda GT so_datum-high
    )
    ).
    "Selektion für alle MA
    "Selektion für noch aktive MA
    "AND begda LT so_datum-high"LE so_datum-low
    "AND endda GE so_datum-high.

    "Auswahl der Org. Zugehörigkeit im besagtem Zeitraum
    SELECT * FROM pa0001 AS b INTO TABLE lt_pa0001
    FOR ALL ENTRIES IN lt_pa "Darf ja nicht leer sein.
    WHERE pernr = lt_pa-pernr
    AND b~werks EQ p_werks
    AND b~persk IN so_persk "Personenkreis Angestelle und Arbeiter
    AND b~persg IN so_persg
    AND b~abkrs IN so_abkrs
    AND b~begda LT so_datum-high"LE so_datum-low
    AND b~endda GE so_datum-high.
    "Auswahl der Namens- und Adressdaten im besagtem Zeitraum
    SELECT * FROM pa0002 INTO TABLE lt_pa0002
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND begda LT so_datum-high"LE so_datum-low
    AND endda GE so_datum-high.
    "Auswahl der Sollarbeitszeit
    SELECT * FROM pa0007 INTO TABLE lt_pa0007
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND zterf IN so_zterf
    AND begda LT so_datum-high"LE so_datum-low
    AND endda GE so_datum-high.
  ELSE.
    EXIT.
  ENDIF.

  "Durchgehen aller MA
  "Ergänzung um Maßnahme
  "Ergänzung um Adresse
  "Ergänzung um Personalkreis
  "Ergänzung um Sollarbeitszeit
  "Tabelle gt_alv_pers wird mit einem Satz pro MA gefüllt

  DATA: lv_ok0, lv_ok1, lv_ok2, lv_ok7 TYPE c.


  LOOP AT lt_pa
  ASSIGNING FIELD-SYMBOL(<pa>).
    CLEAR gs_alv.
    CLEAR lv_ok0.
    CLEAR lv_ok1.
    CLEAR lv_ok2.
    CLEAR lv_ok7.
    gs_alv-pernr = <pa>-pernr.
    LOOP AT lt_pa0000 ASSIGNING FIELD-SYMBOL(<pa0000>) WHERE pernr = <pa>-pernr.
      gs_alv-begda = <pa0000>-begda. "Maßnahme Beginn Datum
      gs_alv-endda = <pa0000>-endda. "
      <pa>-begda = <pa>-begda.
      <pa>-endda = <pa>-endda.
      lv_ok0 = 'X'.
    ENDLOOP.
    "Ergänzen der Adress- und Namensinformation
    LOOP AT lt_pa0002 ASSIGNING FIELD-SYMBOL(<pa0002>) WHERE pernr = <pa>-pernr.
      gs_alv-nachn = <pa0002>-nachn.
      gs_alv-vorna = <pa0002>-vorna.
      lv_ok2 = 'X'.
    ENDLOOP.
    "Ergänzen der Daten um Personalkreiszugehörigkeit Angestellte und Arbeiter.
    LOOP AT lt_pa0001 ASSIGNING FIELD-SYMBOL(<pa0001>) WHERE pernr = <pa>-pernr.
      gs_alv-persk = <pa0001>-persk.
      lv_ok1 = 'X'.
    ENDLOOP.
    "Sollarbeitszeit
    LOOP AT lt_pa0007 ASSIGNING FIELD-SYMBOL(<pa0007>) WHERE pernr = <pa>-pernr.
      gs_alv-pernr = <pa>-pernr."Satz ist immer vorhanden
      gs_alv-anzhls = <pa0007>-wkwdy * 5. "5 Wochen
      gs_alv-schkz = <pa0007>-schkz. "20191105HST
      lv_ok7 = 'X'.
    ENDLOOP.
    IF lv_ok0 = 'X' AND lv_ok1 = 'X' AND lv_ok2 = 'X' AND lv_ok7 = 'X'.
      APPEND gs_alv TO gt_alv_pers.
    ENDIF.

    "cl_demo_output=>display( <ls_alv>-pernr ).
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM collect_data
*&---------------------------------------------------------------------*
*  Sammeln der Miterarbeiter Bewegungsdaten
*----------------------------------------------------------------------*
FORM collect_data.

  FIELD-SYMBOLS: <ls_alv> TYPE ty_alv.

  DATA lv_begda TYPE d.
  DATA lv_endda TYPE d.
  "DATA lv_year TYPE n.
  DATA lv_int TYPE integer.

  CLEAR gt_alv.
  "ASSIGN gs_alv TO <ls_alv>.
  LOOP AT gt_alv_pers INTO DATA(wa).
    "Nur aktive MA
    IF p_aktiv EQ 'X'. "Nur Aktive MA ausgeben
      IF wa-endda LE so_datum-high OR wa-endda LE '20991231'.
        CONTINUE.
      ENDIF.
    ENDIF.


    "Abwesenheiten
    SELECT * FROM pa2006 INTO TABLE lt_pa2006 WHERE pernr = wa-pernr AND
      "( begda IN so_datum OR endda IN so_datum ).
      ( endda IN so_datum ).
    IF sy-subrc = 0.
      "Dürfte eigentlich nur 1 Satz sein, aber...
      LOOP AT lt_pa2006 ASSIGNING FIELD-SYMBOL(<pa2006>).


        "Kontrolle, ob noch kein neuerer Satz angelegt wurde.
        "Korrektur wenn Kontingente überschneidend 1 Tag angelegt wurden.
        CLEAR lv_int.
        SELECT DISTINCT 1 FROM pa2006 INTO @lv_int
          "WHERE pernr = @<pa2006>-pernr AND begda GT @so_datum-high.
          "WHERE pernr = @<pa2006>-pernr AND begda GE @<pa2006>-endda.
          WHERE pernr = @<pa2006>-pernr AND begda GT @<pa2006>-begda.
        ENDSELECT.

        IF sy-subrc = 4 OR p_ohne IS INITIAL. "Auch Personen mit bereits vorhandenen Kontingent
          APPEND INITIAL LINE TO gt_alv ASSIGNING <ls_alv>.
          MOVE-CORRESPONDING wa TO <ls_alv>.
          MOVE wa-begda TO <ls_alv>-begdaa.
          MOVE wa-endda TO <ls_alv>-enddaa.
          MOVE-CORRESPONDING <pa2006> TO <ls_alv>.
          <ls_alv>-update = 'X'.
          IF p_out0 = 'X'.
            <ls_alv>-ampel = 'ROT'.
          ELSE.
            <ls_alv>-ampel = '@0A@'. "Rot noch anzulegen.
          ENDIF.
          IF lv_int GE 1. "Korrektor: Vorher Genau ein Satz, jetzt, wenn mehr als 1 Satz.
            CLEAR <ls_alv>-update.
            <ls_alv>-bemer = 'Kontingent bereits vorhanden.'.
            IF p_out0 = 'X'.
              <ls_alv>-ampel = 'GRÜN'. "Grün bereits angelegt.
            ELSE.
              <ls_alv>-ampel = '@08@'. "Grün bereits angelegt.
            ENDIF.
          ENDIF.
          "MOVE <pa2006>-begda TO <ls_alv>-begda.
          "MOVE <pa2006>-endda TO <ls_alv>-endda.
          "MOVE <pa2006>-anzhl TO <ls_alv>-anzhl.
          "MOVE <pa2006>-desta TO <ls_alv>-desta.
          "MOVE <pa2006>-deend TO <ls_alv>-deend.
        ENDIF.
        "Check Kontingent über ein Jahr oder kürzer, wenn Kontingent als Grundlage verwendet wird.
        IF <ls_alv>-update = 'X' AND p_vorj EQ 'X'.

          lv_begda = <ls_alv>-begda - 1 .
          CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
            EXPORTING
              date      = <ls_alv>-endda
              days      = 0
              months    = 0
              signum    = '-'
              years     = 1
            IMPORTING
              calc_date = lv_endda.
          IF lv_begda NE lv_endda. "Kein volles Jahr
            <ls_alv>-bemer = 'Kein volles Jahr.'.
            IF p_out0 = 'X'.
              <ls_alv>-ampel = 'BLAU'.
            ELSE.
              <ls_alv>-ampel = icon_negative. "Kein volles Jahr
            ENDIF.
            CLEAR <ls_alv>-update.
          ENDIF.
        ENDIF.
        IF <ls_alv>-anzhls EQ 0. "20191105HST Anfang
          <ls_alv>-bemer = 'AZP 0 Tage'. "AZP FREI
          IF p_out0 = 'X'.
            <ls_alv>-ampel = 'BLAU'.
          ELSE.
            <ls_alv>-ampel = icon_negative. "Kein volles Jahr
          ENDIF.
          CLEAR <ls_alv>-update.
        ENDIF. "20191105HST Ende


        "MA Kein Update, wenn nicht mehr aktiv, sprich Endedatum.
        "Korrektur Fehler bei ausgeschiedenen
        IF wa-endda LE so_datum-high OR wa-endda LE '20991231'.
          CLEAR <ls_alv>-update.
          <ls_alv>-bemer = 'Ausgeschieden.'.
          IF p_out0 = 'X'.
            <ls_alv>-ampel = 'GELB'. "Gelb Mitarbeiter läuft aus.
          ELSE.
            <ls_alv>-ampel = '@09@'. "Gelb Mitarbeiter läuft aus.
          ENDIF.
        ENDIF.

        "Bearbeitung der wirklich für Update geeigneten Sätze
        "Neues Kontingent errechnen, begin ende anzahl
        "Bemerkung
        "Korrektur Fehler bei keinen vollen Jahren
        "Neues Beginndatum 1 Tag nach Ende
        "Neues Endedatum 1 Jahr minus 1 nach Beginn


        "Kontrolle, ob kein überschneidender Satz im Zeitraum
        IF <ls_alv>-update = 'X'.
          SELECT COUNT( * ) FROM pa2006 INTO @lv_int
            WHERE pernr = @<ls_alv>-pernr
            AND ( ( begda GE @<ls_alv>-begda AND begda LE @<ls_alv>-endda )
            or ( endda GE @<ls_alv>-begda AND endda LE @<ls_alv>-endda ) ) .
          IF lv_int ne 1.
            <ls_alv>-bemer = 'Zwei überschn. Kont. in der Ausw.'.
            CLEAR <ls_alv>-update.
            IF p_out0 = 'X'.
              <ls_alv>-ampel = 'BLAU'.
            ELSE.
              <ls_alv>-ampel = icon_negative. "Kein volles Jahr
            ENDIF.
          ENDIF.
        ENDIF.



        IF <ls_alv>-update = 'X'.

          lv_endda = <ls_alv>-endda.
          CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
            EXPORTING
              "date      = <ls_alv>-begda
              date      = lv_endda
              days      = 1
              months    = 0
              signum    = '+'
              years     = 0
            IMPORTING
              calc_date = <ls_alv>-begdan.
          CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
            EXPORTING
              "date      = <ls_alv>-endda
              date      = lv_endda
              days      = 0
              months    = 0
              signum    = '+'
              years     = 1
            IMPORTING
              calc_date = <ls_alv>-enddan.

          IF p_vorj = 'X'.
            <ls_alv>-anzhln = <ls_alv>-anzhl.
          ELSE.
            <ls_alv>-anzhln = <ls_alv>-anzhls.
          ENDIF.

          "Double Check, dass kein anderer Satz im neuen Zeitfenster ist.
          "          SELECT DISTINCT 1 FROM pa2006 INTO @lv_int
          "            WHERE pernr = @<ls_alv>-pernr AND begda GE @<ls_alv>-begda AND endda LT @<ls_alv>-endda.
          "          ENDSELECT.
          SELECT COUNT( * ) FROM pa2006 INTO @lv_int
            WHERE pernr = @<ls_alv>-pernr AND begda GE @<ls_alv>-begda AND endda LT @<ls_alv>-endda.
          "ENDSELECT.
          IF sy-subrc NE 4.
            <ls_alv>-bemer = 'Fehler!!!!'.
            CLEAR <ls_alv>-update.
            IF p_out0 = 'X'.
              <ls_alv>-ampel = 'BLAU'.
            ELSE.
              <ls_alv>-ampel = icon_negative. "Kein volles Jahr
            ENDIF.
          ENDIF.
          IF <ls_alv>-update EQ 'X'. "20191105HST Korrektur Bemer nur wenn update, sonst Fehlermeldung lassen
            IF p_test IS INITIAL.
              <ls_alv>-bemer = 'Echtlauf: Wird ein Update erhalten.'.
            ELSE.
              <ls_alv>-bemer = 'Testlauf: Würde ein Update erhalten.'.
            ENDIF.
          ENDIF.
        ENDIF.

      ENDLOOP.
    ENDIF.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM sort_data
*&---------------------------------------------------------------------*
*  Sortieren der Ausgabedaten
*----------------------------------------------------------------------*
FORM sort_data.
  IF p_sort0 = 'X'.
    SORT gt_alv BY nachn begda.
  ELSE.
    SORT gt_alv BY pernr begda.
  ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*&      FORM show_dialog
*&---------------------------------------------------------------------*
*  Anzeigeprogramm für Dialoganzeige
*----------------------------------------------------------------------*
FORM show_dialog.

  cl_demo_output=>display( data = gt_alv name = 'Urlaubskontingente' ).


  IF 1 = 1. "Testmodus
    DATA name TYPE string.
    DATA lv_anz TYPE integer.
    "data value type data.

    cl_demo_output=>display( gt_alv_pers ).
    lv_anz = lines( gt_alv_pers ).
    cl_demo_output=>write_data( value = lv_anz name = 'Anzahl der Sätze' ).
    cl_demo_output=>display( ).
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM show_alv
*&---------------------------------------------------------------------*
*  Anzeigeprogramm für ALV Anzeige
*----------------------------------------------------------------------*
FORM show_alv.

  "Initialisierung
  DATA: lr_layout TYPE REF TO cl_salv_layout,
        ls_key    TYPE salv_s_layout_key.
  DATA: lr_functions TYPE REF TO cl_salv_functions_list.

  DATA: lo_events    TYPE REF TO cl_salv_events_table. "HST 20190712


* ALV aufbauen,
* gref_salv zeigt danach auf das Objekt,
* gt_alv_pers ist die Tabelle, die als Info mitgegeben wird, wo die Daten zukünftig gespeichert werden.
  TRY.
      CALL METHOD cl_salv_table=>factory
        IMPORTING
          r_salv_table = gref_salv
        CHANGING
          t_table      = gt_alv.

      lo_events = gref_salv->get_event( ).

      SET HANDLER cl_event_handler=>on_before_salv_function FOR lo_events.
      SET HANDLER cl_event_handler=>on_after_salv_function FOR lo_events.
      SET HANDLER cl_event_handler=>on_added_function FOR lo_events.
      SET HANDLER cl_event_handler=>on_top_of_page FOR lo_events.
      SET HANDLER cl_event_handler=>on_end_of_page FOR lo_events.
      SET HANDLER cl_event_handler=>on_double_click FOR lo_events.
      SET HANDLER cl_event_handler=>on_link_click FOR lo_events.


    CATCH cx_salv_msg .
  ENDTRY.

  "Die Keydaten werden gefüllt
  ls_key-report = sy-repid.
  "gr_layout zeigt auf das Layout des ALV
  lr_layout  = gref_salv->get_layout( ).
  "Layout erhält Keydaten: Program Name
  lr_layout->set_key( ls_key ).
  "Layout Speichern erlaubt (3 Werte möglich) User can save
  lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).
* Layout auf Kundenspezifisches Layout einstellen
*  IF sy-slset = 'CUS&Z_PPMDT_01'.
*    gr_layout->set_initial_layout( value = '/Z_PPMDT_TEL' ).
*  ENDIF.
  "lr_functions zeigt auf die Funktionen des ALV
  lr_functions = gref_salv->get_functions( ).
  "lr_functions einschalten
  "  lr_functions->set_default( ).      "minimal
  lr_functions->set_all( abap_true ). "Standard

* Feldkatalog ändern
  DATA: lr_columns TYPE REF TO cl_salv_columns_table,
        lr_column  TYPE REF TO cl_salv_column_table.

  lr_columns = gref_salv->get_columns( ).
* lr_columns->set_optimize( abap_true ).

  TRY.

      lr_column ?= lr_columns->get_column( 'PERNR' ).
      lr_column->set_output_length( '5' ).
      lr_column->set_cell_type( if_salv_c_cell_type=>hotspot ).


      lr_column ?= lr_columns->get_column( 'NACHN' ).
      lr_column->set_output_length( '20' ).

      lr_column ?= lr_columns->get_column( 'VORNA' ).
      lr_column->set_output_length( '20' ).

      lr_column ?= lr_columns->get_column( 'BEGDA' ).
      lr_column->set_short_text( 'Beginn').
      lr_column->set_medium_text( 'Beginn Datum').
      lr_column->set_long_text( 'Beginn Datum').

      lr_column ?= lr_columns->get_column( 'ENDDA' ).
      lr_column->set_short_text( 'Ende').
      lr_column->set_medium_text( 'Ende Datum').
      lr_column->set_long_text( 'Ende Datum').

      lr_column ?= lr_columns->get_column( 'BEGDAN' ).
      lr_column->set_short_text( 'Beginn NK.').
      lr_column->set_medium_text( 'Beginn Datum N.K.').
      lr_column->set_long_text( 'Beginn Datum Neues Kontingent').

      lr_column ?= lr_columns->get_column( 'ENDDAN' ).
      lr_column->set_short_text( 'Ende NK.').
      lr_column->set_medium_text( 'Ende Datum N.K.').
      lr_column->set_long_text( 'Ende Datum Neues Kontingent').

      lr_column ?= lr_columns->get_column( 'ANZHL' ).
      lr_column->set_short_text( 'Anzahlk.').
      lr_column->set_medium_text( 'Anzahl Tage K.').
      lr_column->set_long_text( 'Anzahl Tage K.').
      lr_column->set_cell_type( if_salv_c_cell_type=>hotspot ).

      lr_column ?= lr_columns->get_column( 'ANZHLS' ).
      lr_column->set_short_text( 'Anzahl S.').
      lr_column->set_medium_text( 'Anzahl Tage S.').
      lr_column->set_long_text( 'Anzahl Tage S.').
      lr_column->set_cell_type( if_salv_c_cell_type=>hotspot ).

      lr_column ?= lr_columns->get_column( 'ANZHLN' ).
      lr_column->set_short_text( 'Anzahl NK.').
      lr_column->set_medium_text( 'Anzahl Tage N.K.').
      lr_column->set_long_text( 'Anzahl Tage Neues Kontingent').
      lr_column->set_cell_type( if_salv_c_cell_type=>hotspot ).

      lr_column ?= lr_columns->get_column( 'DESTA' ).
      lr_column->set_short_text( 'Abtr.Beg.').
      lr_column->set_medium_text( 'Abtr. Beginn Datum').
      lr_column->set_long_text( 'Abtragung Beginn Datum').

      lr_column ?= lr_columns->get_column( 'DEEND' ).
      lr_column->set_short_text( 'Abtr.Ende').
      lr_column->set_medium_text( 'Abtr. Ende Datum').
      lr_column->set_long_text( 'Abtraung Ende Datum').

*    lr_column ?= lr_columns->get_column( 'MENG1' ).
*    lr_column->set_short_text( 'Abw.Tg.S.').
*    lr_column->set_medium_text( 'Abw.Tg.Skonto').
*    lr_column->set_output_length( '10' ).
*    lr_column->set_sign( abap_true ).

      lr_column ?= lr_columns->get_column( 'PERSK' ).
      lr_column->set_output_length( '10' ).
      lr_column->set_short_text( 'Pers.Kreis').
      lr_column->set_medium_text( 'Personenkreis').
      lr_column->set_long_text( 'Personenkreis').

      lr_column ?= lr_columns->get_column( 'AMPEL' ).
      lr_column->set_short_text( 'Status').
      lr_column->set_medium_text( 'Status').
      lr_column->set_long_text( 'Aktueller Status').
      lr_column->set_icon( abap_true ).

      lr_column ?= lr_columns->get_column( 'UPDATE' ).
      lr_column->set_short_text( 'Update').
      lr_column->set_medium_text('Update').
      lr_column->set_long_text('Update').

      lr_column ?= lr_columns->get_column( 'BEMER' ).
      lr_column->set_short_text( 'Bem.').
      lr_column->set_medium_text('Bemerkung').
      lr_column->set_long_text('Bemerkung').


** Zusatzinfo ausblenden
*    IF p_zusatz IS INITIAL.
*      lr_column ?= lr_columns->get_column( 'ZFBDT' ).
*      lr_column->set_visible( '' ).
*      lr_column ?= lr_columns->get_column( 'ZBD1T' ).
*      lr_column->set_visible( '' ).
*      lr_column ?= lr_columns->get_column( 'ZBD2T' ).
*      lr_column->set_visible( '' ).
*      lr_column ?= lr_columns->get_column( 'ZBD1P' ).
*      lr_column->set_visible( '' ).
*      lr_column ?= lr_columns->get_column( 'ZBD2P' ).
*      lr_column->set_visible( '' ).
*    ENDIF.

      IF p_visibl EQ 'X'.
        PERFORM visible USING lr_columns 'SCHKZ' abap_true.  "Arbeitszeitplan
      ELSE.
        PERFORM visible USING lr_columns 'SCHKZ' abap_false.  "Arbeitszeitplan
      ENDIF.

      lr_columns->set_column_position( columnname = 'UPDATE' position = 1 ).
      lr_columns->set_column_position( columnname = 'PERSK'  position = 1 ).
      lr_columns->set_column_position( columnname = 'DEEND'  position = 1 ).
      lr_columns->set_column_position( columnname = 'DESTA'  position = 1 ).
      lr_columns->set_column_position( columnname = 'ANZHLS' position = 1 ).
      lr_columns->set_column_position( columnname = 'ANZHL'  position = 1 ).
      lr_columns->set_column_position( columnname = 'ENDDA'  position = 1 ).
      lr_columns->set_column_position( columnname = 'BEGDA'  position = 1 ).
      lr_columns->set_column_position( columnname = 'ENDDAA' position = 1 ).
      lr_columns->set_column_position( columnname = 'BEGDAA' position = 1 ).
      lr_columns->set_column_position( columnname = 'VORNA'  position = 1 ).
      lr_columns->set_column_position( columnname = 'NACHN'  position = 1 ).
      lr_columns->set_column_position( columnname = 'PERNR'  position = 1 ).
      lr_columns->set_column_position( columnname = 'AMPEL'  position = 1 ).

      "lr_columns->get_count_column

    CATCH cx_salv_not_found.
      cl_demo_output=>display('Error' ).
  ENDTRY.

* Ausgabe
  "  set pf-status 'SAVE' .


  "copy SE41 SAPLSALV Status Standard to own programm status SAVENEW

  IF p_test IS INITIAL.
    CALL METHOD gref_salv->set_screen_status(
      EXPORTING
        report        = sy-repid
        pfstatus      = 'SAVE'
        set_functions = gref_salv->c_functions_all ).
  ENDIF.
  gref_salv->display( ).
ENDFORM.
"Unterprogramm von show_alv
FORM visible
   USING
         lr_columns TYPE REF TO cl_salv_columns_table
         lv_column
         lv_visibl .
  DATA lr_column  TYPE REF TO cl_salv_column_table.

  TRY.
      lr_column ?= lr_columns->get_column( lv_column ).
      IF lv_visibl IS INITIAL.
        lr_column->set_visible( '' ).
      ELSE.
        lr_column->set_visible( abap_true ).
      ENDIF.
    CATCH cx_salv_not_found.
      cl_demo_output=>display('Error' ).
  ENDTRY.
ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM update_data_alle
*&---------------------------------------------------------------------*
*  Update von allen Zeilen
*----------------------------------------------------------------------*
FORM update_data_alle.

  DATA: lv_anz TYPE integer.
  "DATA: ls_alv TYPE ty_alv.
  FIELD-SYMBOLS <ls_alv> TYPE ty_alv.


  LOOP AT gt_alv ASSIGNING <ls_alv> WHERE update = 'X'.
    PERFORM update_data_pernr USING 'ANZHLN' CHANGING <ls_alv>.
    ADD 1 TO lv_anz.
  ENDLOOP.

  "DATA : lv_anz_pers TYPE integer. "Stimmt wegen update nicht
  "cl_demo_output=>display( gt_alv ).
  "lv_anz_pers = lines( gt_alv ).
  "cl_demo_output=>write_data( value = lv_anz_pers name = 'Anzahl der Personen' ).
  "cl_demo_output=>write_data( value = lv_anz name = 'Anzahl der Sätze' ).
  "cl_demo_output=>display( ).

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM update_data_pernr
*&---------------------------------------------------------------------*
*  Unterprogramm von update_data_alle und update_data_einzeln
*----------------------------------------------------------------------*
FORM update_data_pernr USING column TYPE salv_de_column CHANGING ls_alv TYPE ty_alv .

  DATA : return LIKE bapireturn1.
  DATA : key LIKE bapipakey.
  DATA: ls_p2006 TYPE p2006.

  SELECT * FROM pa2006 INTO TABLE lt_pa2006 WHERE pernr = ls_alv-pernr AND
 ( " begda IN so_datum or
    endda IN so_datum ).

  "HST20190814 Nur ein Satz mit Kontingent Ende im Zeitraum, sonst zu ungenau
  IF lines( lt_pa2006 ) NE 1.
    DATA lv_message(50) TYPE c.
    CONCATENATE `Nicht genau ein Satz - Pers.Nr.: ` ls_alv-pernr INTO lv_message.
    MESSAGE lv_message TYPE 'E'.
  ENDIF.

  "Sollte nur ein Satz sein
  READ TABLE lt_pa2006 INTO ls_pa2006 INDEX 1.

  LOOP AT lt_pa2006 INTO ls_pa2006.
    "Default Felder füllen
    MOVE-CORRESPONDING ls_pa2006 TO ls_p2006.


    CLEAR return.

    "PERNR entsperren
    CALL FUNCTION 'BAPI_EMPLOYEE_ENQUEUE'
      EXPORTING
        number = ls_p2006-pernr
      IMPORTING
        return = return.

    IF return IS NOT INITIAL.

      WRITE: / 'Echtlauf: gesperrte Personalnummer: ' ,ls_p2006-pernr.
      ls_alv-bemer = 'Echtlauf: Gesperrte Personalnummer'.
      CONTINUE.
    ENDIF.

    IF p_test IS INITIAL. "Schreibblock


      IF 1 = 1.
        ls_p2006-begda = ls_alv-begdan.
        ls_p2006-endda = ls_alv-enddan.

        "Update erfolgt
        ls_alv-update = 'S'.
        IF p_out0 = 'X'.
          ls_alv-ampel = 'GRÜN'. "Grün bereits angelegt.
        ELSE.
          ls_alv-ampel = '@08@'. "Grün bereits angelegt.
        ENDIF.

        IF column EQ 'ANZHL'.
          ls_p2006-anzhl = ls_alv-anzhl.
          ls_alv-anzhln = ls_alv-anzhl.
        ELSEIF column EQ 'ANZHLS'.
          ls_p2006-anzhl = ls_alv-anzhls.
          ls_alv-anzhln = ls_alv-anzhls.
        ELSEIF column EQ 'ANZHLN'.
          ls_p2006-anzhl = ls_alv-anzhln.
          ls_alv-anzhln = ls_alv-anzhln.
        ENDIF.

        ls_p2006-desta = ls_alv-begdan.
        CLEAR ls_p2006-quonr. "Kontingentnummer gleich null setzen, damit es eine neue Nummer erhält
        CLEAR ls_p2006-kverb. "Abtragung gleich null setzen
        "ls_p2006-deend = <ls_alv>-."Bleibt gleich

        CALL FUNCTION 'HR_INFOTYPE_OPERATION'
          EXPORTING
            infty         = '2006'
            number        = ls_p2006-pernr
            subtype       = ls_p2006-subty
            objectid      = ls_p2006-objps
            lockindicator = ls_p2006-sprps
            validityend   = ls_p2006-endda
            validitybegin = ls_p2006-begda
            recordnumber  = ls_p2006-seqnr
            record        = ls_p2006
            operation     = 'INS'
            tclas         = 'A'
            dialog_mode   = '0'
          IMPORTING
            return        = return
            key           = key.

        IF return IS NOT INITIAL.
          WRITE: / 'Fehler bei Personalnummer: ' ,ls_p2006-pernr.
          ls_alv-bemer = 'Echtlauf: Fehler beim Update aufgetreten.'.
          CONTINUE.
        ELSE.
          ls_alv-bemer = 'Echtlauf: Hat ein Update erhalten.'.
        ENDIF.
      ENDIF.

    ENDIF. "Schreibblock Ende
    CALL FUNCTION 'BAPI_EMPLOYEE_DEQUEUE'
      EXPORTING
        number = ls_p2006-pernr.



    "WRITE: <ls_alv>-pernr, lines( lt_pa2006 ).
    "NEW-LINE.
  ENDLOOP.

  "DATA : lv_anz_pers TYPE integer. "Stimmt wegen update nicht
  "cl_demo_output=>display( gt_alv ).
  "lv_anz_pers = lines( gt_alv ).
  "cl_demo_output=>write_data( value = lv_anz_pers name = 'Anzahl der Personen' ).
  "cl_demo_output=>write_data( value = lv_anz name = 'Anzahl der Sätze' ).
  "  cl_demo_output=>display( ).

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM update_data_einzeln
*&---------------------------------------------------------------------*
*  Update von einzelnen Zeilen
*----------------------------------------------------------------------*
FORM update_data_einzeln  TABLES gt_alv USING row TYPE salv_de_row column TYPE salv_de_column.

  FIELD-SYMBOLS: <ls_alv> TYPE ty_alv.

  ASSIGN  gt_alv[ row ] TO <ls_alv>.

  IF <ls_alv>-update = 'X'.
    PERFORM update_data_pernr USING column CHANGING <ls_alv> .
  ENDIF.
  gref_salv->refresh( ).

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM show_data
*&---------------------------------------------------------------------*
*  Verzweigung in die 2 Anzeige Varianten
*----------------------------------------------------------------------*
FORM show_data.
  IF p_out0 = 'X'. "Dialog Output
    PERFORM show_dialog.
  ELSE. "ALV Output
    PERFORM show_alv.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM call_transaction
*&---------------------------------------------------------------------*
*  Call standard transactions with authority check and progress indicator
*----------------------------------------------------------------------*
"HST 20190712
FORM call_transaction USING trx TYPE tcode.
  DATA: lv_message TYPE string.
  CONCATENATE 'Opening transaction' trx '...' INTO lv_message SEPARATED BY space. "#EC NOTEXT
  CALL FUNCTION 'AUTHORITY_CHECK_TCODE'
    EXPORTING
      tcode  = trx
    EXCEPTIONS
      ok     = 0
      not_ok = 1
      OTHERS = 2.
  IF sy-subrc NE 0.
    MESSAGE e172(00) WITH trx.
  ELSE.
    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        text = lv_message.
    CALL TRANSACTION trx AND SKIP FIRST SCREEN.
  ENDIF.
ENDFORM.  "call transaction

*&---------------------------------------------------------------------*
*&      FORM display_pa30
*&---------------------------------------------------------------------*
*  Anzeige des Personalstammes
*----------------------------------------------------------------------*
FORM display_pa30 TABLES gt_alv USING row TYPE salv_de_row column TYPE salv_de_column.


  TRY.
      gs_alv  = gt_alv[ row ].

      SET PARAMETER ID: 'PER' FIELD gs_alv-pernr.

      PERFORM call_transaction USING 'PA30'.
      "BREAK-POINT.
    CATCH cx_sy_itab_line_not_found.

      cl_demo_output=>display('Einzelzeile auswählen' ).
      "cl_abap_browser=>show_html( html = VALUE #( ( 'Einzelzeile MATNR auswählen' ) ) ).
  ENDTRY.
ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM action
*&---------------------------------------------------------------------*
*  Aufruf bei Event Hotlink oder Doubleklick
*----------------------------------------------------------------------*
FORM action TABLES gt_alv USING row TYPE salv_de_row column TYPE salv_de_column.


  IF column EQ 'PERNR'.
    PERFORM display_pa30 TABLES gt_alv USING row column.
  ELSEIF column EQ 'ANZHL'.
    PERFORM update_data_einzeln TABLES gt_alv USING row column.
  ELSEIF column EQ 'ANZHLS'.
    PERFORM update_data_einzeln TABLES gt_alv USING row column.
  ELSEIF column EQ 'ANZHLN'.
    PERFORM update_data_einzeln TABLES gt_alv USING row column.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*&      FORM user_command
*&---------------------------------------------------------------------*
* Aufruf bei Event add_function (user_command)
*----------------------------------------------------------------------*
FORM user_command USING e_salv_function TYPE salv_de_function.
*---for creating pf status go to se41 and give the program name SAPLSALV and pf-status as STANDARD and choose copy pf-status to this program .
*Error rendering macro 'code': Invalid value specified for parameter 'lang'
  CASE e_salv_function.

    WHEN 'UPDATE'.

      MESSAGE : 'Update wird nun erfolgen' TYPE 'I'.
      IF p_test IS INITIAL
        AND ( sy-ucomm = 'UPDATE' OR sy-ucomm = 'UPDATE2' ).
        "AND sy-ucomm = '&F03'. "Schreiben der Daten und nochmalige Auswertung und Anzeige
        PERFORM update_data_alle.
        gref_salv->refresh( ).
        "PERFORM collect_data.
        "PERFORM sort_data.
        "PERFORM show_data.
      ENDIF.
  ENDCASE.

ENDFORM.