Homelab, Linux, JS & ABAP (~˘▾˘)~
 

[HR] A1-Meldeverfahren

Übersicht

Gute Zusammenfassung: https://www.iprocon.de/abbildung-des-a1-meldeverfahrens-in-sap-hcm/

2682093 – Informationen zur Umsetzung des A1-Meldeverfahrens im SAP-System (siehe auch das PDF im Hinweis)

2730927 – A1-Verfahren: Hilfestellung zum Customizing

2833850 – A1-Verfahren: Archivierung der A1-Bescheinigung und Erweiterung für das BAdI HRPAYDE_A1_EMAIL

2841779 – A1-Verfahren: ESS-Szenario (Web-Dynpro ABAP) (Paket PAOC_ESS_A1_DE)

Die Datenerfassung der Antragsdaten erfolgt im Infotyp: 0700 (Elektronischer Datenaustausch)
Subtypen:

  • DXA1 (A1: Antrag Entsendebescheinigung)
  • DXAV (A1: Antrag Ausnahmevereinbarung)

Reports zur Erstellung der Meldungen und der Meldedateien:

  • Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Abrechnungszusatz → A1-Meldeverfahren → Ausgangsmeldungen

Reports zur Verarbeitung der Eingangsmeldungen:

  • Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Abrechnungszusatz → A1-Meldeverfahren → Eingangsmeldungen

Behördenkommunikation (B2A): Transaktion PB2A

  • Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Behördenkommunikation (B2A) → B2A-Manager

Hilfreiche Entwicklungsobjekte

Paket: P01S

Reports:

Klassen:

Für mich hilfreich waren folgenden Klassen:

  • CL_HRPAYDE_A1_NOTIF (Klasse für A1-Meldungen)
  • CL_HRPAYDE_A1_NOTIF_DISPLAYER (ALV-Ausgabe für A1-Meldungen)
  • CL_HRPAYDE_A1_ALV_EVNT_HANDLER (Ereignisbehandler für A1-spezifische Ereignisse)

PDFs der A1-Meldungen von Datenbank lesen

*&---------------------------------------------------------------------*
*& Tabellen A1-Meldeverfahren:
*& P01A1_STAT    - A1-Verfahren: Verwaltungstabelle
*& P01A1_RAWDATA - A1-Verfahren: Rohdaten einer Meldung
*&---------------------------------------------------------------------*

GET peras.

  SELECT * INTO TABLE @DATA(lt_p01a1_stat) FROM p01a1_stat
    WHERE pernr  = @pernr-pernr
      AND mdtyp  = '2'
      AND status = '23'
      AND mzbeg <= @pn-endda
      AND mzbeg >= @pn-begda.

  LOOP AT lt_p01a1_stat INTO DATA(ls_p01a1_stat).

    SELECT SINGLE * INTO @DATA(ls_p01a1_rawdata) FROM p01a1_rawdata
      WHERE guid = @ls_p01a1_stat-guid
        AND lfdnr = ( SELECT MAX( lfdnr ) FROM p01a1_rawdata WHERE guid = @ls_p01a1_stat-guid ). "höchste lfdnr nehmen

    DATA(pdf_xstring) = ls_p01a1_rawdata-rawdata.

  ENDLOOP.

[Home Assistant] Combine Adaptive Lightning, motion activated light and lights turned on by sunset

In my home, I have some motion activated lights, for example in the kitchen. During daytime, the kitchen light should simply be turned on and off by the motion sensor. But when the sun sets, I like to turn on most of the lights in the house to 1% brightness, so that you never walk into a completely dark room. In this case, the motion sensor should not turn the kitchen light on and off, but instead should increase the brightness and afterward go back to the previous state of 1% brightness. And with “increase the brightness”, I don’t mean a fix value, but instead it should set the right brightness provided by the Adaptive Lightning integration. When it’s late, and the sleep mode is tuned on for the house, the kitchen light of course should be turned off, and when it is turned on, it should respect the configured sleep values from Adaptive Lightning settings.

Most things turned out to be quite easy by using Scenes to store the current light state and of course by using the great Adaptive Lightning features. But my automation had one important gap. When someone was is the kitchen, means kitchen light was turned on by the motion sensor, and we had sunset in this exact moment, it would always turn down the brightness to 1%, because the automation which turns on all lights to 1% brightness when the sun sets got triggered. Also, when the person left the kitchen, the previous stored scene was loaded, which was created before sunset, means it turned off the kitchen light, instead of the now required 1% brightness. This was of course really confusing for people in the kitchen…

I needed a way, to only activate the 1% sunset brightness, when no one is currently in the kitchen. The solution was a wait_template which checks if currently a motion automation is running in the kitchen. I could have also used the wait check on motion sensor directly, but I wanted to be able to use timeouts in my automation, which can be longer than the actual motion detection.

The important snippet is this one, which checks if no automation is currently running:

{{ is_state_attr('automation.bewegungsmelder_kuche', 'current', 0) }}

And this is the whole part I have added to my sunset automation (and also for the sleep automation similarly) for every room, which has a motion activated light:

sequence:
  - wait_template: "{{ is_state_attr('automation.bewegungsmelder_kuche', 'current', 0) }}"
    continue_on_timeout: true
  - action: adaptive_lighting.set_manual_control
    metadata: {}
    data:
      manual_control: true
      lights:
        - light.kueche
  - action: light.turn_on
    metadata: {}
    data:
      brightness_pct: 1
      kelvin: 2000
    target:
      entity_id: light.kueche
enabled: true

It simply waits until the motion sensor automation is done, then turns on the manual_control flag in Adaptive Lightning, so it does not adjust the light automatically, as it should stay at 1%, and finally turns on the light with 1% brightness. The only drawback is, that there is a millisecond where the light is turned off by the motion automation and until this wait_template fires and turns the light back on to 1% brightness. But as in this case no one should be in the room anymore, I can live with that.

And this is my motion sensor automation for the kitchen:

alias: Bewegungsmelder Küche
description: ""
mode: single
triggers:
  - entity_id:
      - binary_sensor.0xb4e3f9fffeb689d4_occupancy
    to: "on"
    trigger: state
conditions: []
actions:
  - data:
      scene_id: zustand_kueche_alt
      snapshot_entities:
        - light.kueche
    action: scene.create
  - action: adaptive_lighting.set_manual_control
    metadata: {}
    data:
      manual_control: false
      lights:
        - light.kueche
  - target:
      entity_id:
        - light.kueche
    data:
      transition: 5
    action: light.turn_on
    enabled: true
  - wait_for_trigger:
      - entity_id:
          - binary_sensor.0xb4e3f9fffeb689d4_occupancy
        to: "off"
        for:
          hours: 0
          minutes: 0
          seconds: 10
        trigger: state
  - target:
      entity_id: scene.zustand_kueche_alt
    data:
      transition: 5
    action: scene.turn_on

Before turning on the kitchen light, it stores the current state in a scene, then always disables the manual_control flag (in case the sunset automation turned it on), so that when in the next step the light is turned on, it automatically adjusts the brightness to the right value. When no motion is detected for 10 seconds, it restores the previous scene.

[ABAP] Read attendance/absence quotas

DATA pernr TYPE pernr_d VALUE 1.

DATA(time_accounts) = cl_hcmfab_att_abs_bl_apis=>get_instance( )->read_time_accounts( iv_pernr = pernr
                                                                                      iv_begda = sy-datum
                                                                                      iv_endda = sy-datum ). "iv_endda is never used!

cl_demo_output=>display( time_accounts ).

Although there is an obligatory iv_endda parameter, it is never used inside of method read_time_accounts. Instead, there is some logic which checks for a T77S0 Parameter, and it will use either highdate or begda as endda value.

IMO, it would have made sense to mark iv_endda as optional, so it would be downward compatible and the parameter could be omitted on newer releases. Now it is a bit misleading.

[ABAP] REDUCE as an alternative to line_exists for the use of other comparison operators such as >, <, >=, <=, CS, CN

By using line_exists you can check if a line exists or not exists, but it is not possible to use other comparison operators. A workaround can be REDUCE in that case.

In the following snippet, we want to check if there is a flight that costs more than $1000,

SELECT * FROM sflight INTO TABLE @DATA(flights).

* Check if flight with price > 1000 exist
IF REDUCE abap_bool( INIT price_gt_1000 = abap_false
                     FOR  line IN flights WHERE ( price > 1000 )
                     NEXT price_gt_1000 = abap_true ) EQ abap_true.
  " flight with price > 1000 exists
ENDIF.

[Blog] Umzug von Strato zu Netcup

Mein letzter Blog-Umzug war im Juli 2020 von DigitalOcean zu Strato (siehe hier). Nun war es mal wieder Zeit.

Der Blog und alle meine weiteren Docker Container sind nun endlich nach über 4 Jahren von einem Strato VPS zu einem Netcup VPS auf ARM Basis umgezogen. Obwohl ich schon viele schlechte Erfahrungen mit Strato gemacht hatte, habe ich trotzdem damals den VPS bei Strato abgeschlossen, da dieser mit 1TB SSD Speichern zu der Zeit konkurrenzlos viel Speicher für 15 € im Monat bot. Das war für den Betrieb einer Nextcloud für mich entscheidend. Aber meine schlechten Erfahrungen setzten sich fort. Ich kann gar nicht aufzählen, wie viele Performanceprobleme und Ausfälle es gab. Manchmal nur ein paar Minuten oder Stunden. Manchmal auch einfach mehrere Tage. Anfangs habe ich noch Tickets aufgemacht, aber irgendwann hatte ich darauf auch keine Lust mehr. Warum ich trotzdem so lange bei Strato war? Wohl einfach aus faulheit… Aber als Strato diesem Sommer auch noch den Preis für den V40-16 von 15€ auf 17,70€ angehoben hat, vermutlich primär um die Altkunden loszuwerden bzw. diese zu drängen von der Virtuozzo auf die neue KVM Virtualisierungsplattform zu wechseln, war es endgültig genug. Hab mich einige Wochen nach VPS Anbietern umgeschaut, die einen VPS mit viel Speicher anbieten und wurde Ende Oktober bei Netcup fündig, als es eine Angebotsaktion gab, bei der für bestimmte VPS der Speicher verdoppelt wurde. Die Aktionsproduktseite gibt es nicht mehr, aber es handelt sich quasi um dieses Produkt mit doppeltem Speicher:
https://www.netcup.com/de/server/arm-server/vps-3000-arm-g11-mnz#vps-3000-arm-g11-vie
In meinem Fall also: VPS 3000 ARM G11 SE VIE SPS24 mit 1536 GB NVMe Speicher für 16,95 €

Das ganze auch noch monatlich kündbar und nicht mehr wie bei Strato jährlich. Für quasi das gleiche Geld gab es hier also erheblich mehr Leistung. Einziger “Knackpunkt”, der neue Server bedeutete auch ein Wechsel der CPU Architektur von x86 auf ARM. Ich habe daher sicherheitshalber erstmal für meine aktuell genutzten Anwendungen

  • WordPress
  • Nginx Proxy Manager
  • Nextcloud
  • OnlyOffice
  • Collabora
  • Vaultwarden
  • SMTP
  • Portainer
  • TeamSpeak3

geprüft, ob auch Docker Images für ARM bereitgestellt werden. Lediglich bei zwei Anwendungen war das nicht der Fall. Der Teamspeak3 Server, sowie der SMTP Container. Nach kurze Recherche habe ich aber direkt Ersatz gefunden (TS3 & SMTP). Wirklich neu aufsetzen musste ich daher lediglich den TeamSpeak3 Server, aber der Aufwand hielt sich in Grenzen.

Die ganze Migration verlief erheblich einfacher als erwartet. Mit dem folgenden Befehl habe ich jeden Ordner meiner Docker Anwendungen (praktischerweise hab ich damals alles ohne Docker Volumes aufgesetzt, alle Daten liegen also direkt in dem gleichen Ordner wie die docker-compose.yml) nacheinander auf den neuen Server übertragen. Bis auf die Nextcloud, eine Sache von wenigen Minuten.

sudo rsync -azP /opt/containers/nextcloud/ root@ip-address:/opt/containers/nextcloud

Danach noch die DNS Einträge angepasst und gewartet, bis diese sich aktualisieren. Bei der Nextcloud und Vaultwarden gingen komischerweise die User:Group Zuordnungen zum Teil nicht sauber rüber. Da musste ich daher noch kurz etwas nacharbeiten. Im Nginx Proxy Manager habe ich noch alle Zertifikate einmal aktualisiert und nach wenigen Stunden waren dann alle Container wieder über alte URL erreichbar.

Hätte ich geahnt, dass der Serverumzug so reibungslos verläuft, hätte ich das auf jeden Fall schon vor Jahren gemacht. Mit Netcup bin ich vollkommen zufrieden und mein Uptime Kuma konnte bisher kein einziges Erreichbarkeitsproblem des VPS feststellen, im Gegensatz zum Strato VPS, der immer mal wieder für einige Minuten nicht auf den Ping Test reagiert. Ich kann daher nur nochmals von den Strato VPS Produkten abraten.

[Workflow] How do delete a Workflow in status COMPLETED

While searching for a way to delete a workflow, I came across this blog post: https://community.sap.com/t5/technology-blogs-by-members/how-to-logically-delete-workflows/ba-p/12991725
Unfortunately, logically deleting workflows is only possible when the workflow is not in the status COMPLETED.

Since my workflow was already in this state, I had to find another way, and found it with transaction code SWWL. Simply find the unique Identification of the top level workitem via t-code SWIA and then use it in SWWL. When running the report, you will first get a list, then simply select the result items you want to delete and hit the trash icon, or restart the selection and check the flag for Delete immediately.