nocin.eu

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

[ABAP] E-Mail-Templates in S/4HANA

Recently I had to create a mail process where I used the first time the “new” E-Mail-Templates. The following Blogs helped me do this:

https://weberpatrick.de/e-mail-templates/
https://weberpatrick.de/e-mail-templates-einfaches-beispiel/
https://weberpatrick.de/e-mail-template-daten-per-code-statt-cds/

https://community.sap.com/t5/enterprise-resource-planning-blogs-by-members/e-mail-templates-in-s-4-hana/ba-p/13397719
https://community.sap.com/t5/enterprise-resource-planning-blogs-by-members/e-mail-templates-in-s-4-hana-translations/ba-p/13440792
https://community.sap.com/t5/enterprise-resource-planning-blogs-by-members/e-mail-templates-in-s-4-hana-display-table-in-email-template/ba-p/13546304

In my case it was not possible to fetch the data via CDS View, I therefore had to manually fill the variables. Following a simplified version of my code.

You must create a CDS View, as this is the structure in which the variables defined in the mail text are mapped to, even if you do this manually.

define view entity ZMAIL_MY_TEMPLATE as select from pa0001 {
    key pa0001.pernr,
    pa0001.ename,
    cast ( '' as abap.char( 20 ) ) as custom_field // this way you can add a field, that does not exist in the selected table
}

This is just one way, how you can manually fill the variables. Other ways are possible using the class cl_smtg_email_api. I choose the method render_w_data because it returned the mail text, and you manually can do additional changes to the mail text, like adding HTML-Table content, which otherwise gets “escaped” when filled via a replacement variable.

    " dynamicaly build table for mail variables
    DATA(lt_comp) = VALUE abap_component_tab( ( name = 'ename' type = CAST #( cl_abap_typedescr=>describe_by_name( 'EMNAM'   ) ) )
                                              ( name = 'pernr' type = CAST #( cl_abap_typedescr=>describe_by_name( 'PERNR_D' ) ) ) ) .

    " fill table with concrete data
    DATA(lo_struct) = cl_abap_structdescr=>get( lt_comp ).
    CREATE DATA mr_data TYPE HANDLE lo_struct.
    ASSIGN mr_data->* TO FIELD-SYMBOL(<ls_data>).
    <ls_data>-(1) = ename.
    <ls_data>-(2) = pernr.

    " create instance of eMail API, provide name of Mail template
    DATA(lo_email_api) = cl_smtg_email_api=>get_instance( iv_template_id = 'ZMAIL_MY_TEMPLATE' ).

    " render E-Mail for CL_BCS class. This replaces all placeholders with real data
    lo_email_api->render_w_data( EXPORTING iv_language  = sy-langu
                                           ir_data      = mr_data
                                 IMPORTING ev_subject   = DATA(subject)
                                           ev_body_html = DATA(body_html) ).

    TRY.
        " create Sender & Receiver
        DATA(lo_sender)    = cl_cam_address_bcs=>create_internet_address( i_address_string = 'noreply@test.de'
                                                                          i_address_name   = 'Test' ).
        DATA(lo_recipient) = cl_cam_address_bcs=>create_internet_address( i_address_string = 'receiver@test.de').

        " create mail document
        DATA(lo_mail_document) = cl_document_bcs=>create_document( i_type    = 'HTM'
                                                                   i_subject = CONV #( subject )
                                                                   i_text    = cl_bcs_convert=>string_to_soli( body_html ) ).

        " create Business Communication Service
        DATA(lo_bcs) = cl_bcs=>create_persistent( ).
        lo_bcs->set_document( lo_mail_document ).
        lo_bcs->set_sender( lo_sender ).
        lo_bcs->add_recipient( lo_recipient ).
        lo_bcs->send( ).
        COMMIT WORK.                                       
      CATCH cx_smtg_email_common INTO DATA(ls_cx).
        DATA(lv_message) = ls_cx->get_text( ).
        MESSAGE s899(id) WITH 'Unable to send message:'(004) lv_message.
    ENDTRY.

[VSC] Get X-CSRF-Token via REST Client

### Get CSRF-Token
# @name tokenResponse
HEAD https://url.com/api/endpoint HTTP/1.1
Authorization: Basic {{$dotenv auth_base64}}
x-csrf-token: Fetch

@x-csrf-token = {{ tokenResponse.response.headers.x-csrf-token }}   


### Use Token
POST https://url.com/api/endpoint HTTP/1.1
Authorization: Basic {{$dotenv auth_base64}}
Content-Type: application/json
x-csrf-token: {{x-csrf-token}}

{
      "data" : 1
}

[Git] Bundle/export a git repository as a single file

# run command inside the root directory of the project to bundle including all branches
git bundle create reponame.bundle --all

#  to bundle only the main branch
git bundle create reponame.bundle main

# to unbundle, use the following command
git clone reponame.bundle

# after cloning, you will see the bundle is set as default remote repository origin
git remote -v
> origin  /home/user/projects/reponame.bundle (fetch)
> origin  /home/user/projects/reponame.bundle (push)

# if you want to add a new remote repo as origin, you first have to remove the current origin repository, but this means loosing access to your branches etc.
git remote rm origin

# alternatively, you can provide a new name while cloning
git clone --origin <new_name> reponame.bundle

[Windows] Snipping Tool – Shortcuts

Win + Shift + S to take a screenshot of a specific area

Win + Shift + R to create a short video

Bonus: Holding Alt while pressing Print will only take a screenshot of the current active window.
And you can also use Win + V to set up clipboard history so you can take 3 screenshots at once then post them all at the same time.

[Hardware] ASUS TUF GAMING B550M-PLUS (WIFI) – Bluetooth broken

Somehow the onboard Bluetooth of my Motherboard stopped working, but the Wi-Fi was still working fine. This confused me because both are provided by the Intel Wi-Fi 6 AX200 card. The blueman-manager simply could not find the Bluetooth device anymore. Also, when running the command rfkill, it was just listing the Wi-Fi device. The second entry was missing (I took the screenshot, after Bluetooth was working again).

Since I had recently upgraded to a new kernel, I assumed this must be the problem. After testing many different kernels, it still didn’t work. Even on a kernel where it definitely worked before.

Then I stumbled across this thread Intel Wi-Fi 6 AX200 Bluetooth Stopped Working Yet Wifi is still fine. The last commenter solved his issue by unplugging the Intel Wi-Fi Card from his Motherboard and plugging it back in. To be honest, I’m not even sure if this is possible on my motherboard, as it is some onboard thing directly on the board. But this post leads me to reconnect the external antenna, which is connected with two cables on the back of the PC. Since Wi-Fi was still working all along, I did not expect anything from it, but after turning the PC back on, suddenly Bluetooth was working again. WTF! No idea how this is possible, as I have used Bluetooth and WI-FI for many months without the external antenna. Fortunately, however, it works again.

[HR] Abwesenheiten (IT2001) – Anzeige Kontingentabtragungen

Bei einer Abwesenheit wie z.B. Urlaub, die über eine Monatsgrenze oder über einige Feiertage hinweg geht, kann es hilfreich sein, die konkreten Abtragungen einzusehen, um zu verstehen, welche Tage in dem Zeitraum denn wirklich Urlaub waren.

Dazu einfach die Abwesenheit öffnen in der PA20 und auf Springen → Abtragungen (Shift+F8) gehen.

Man kann die Kontingentabtragung auch für das komplette Kontingent eines Jahres einsehen via IT2006.

Die zugehörige Datenbanktabelle ist PTQUODED. Um die Abträge für eine bestimmte Abwesenheitsart zu selektieren, muss noch ein JOIN auf die PA2001 über die DOCNR gemacht werden. Zumindest ist das der einzige Weg, den ich herausfinden konnte. 🙂

SELECT SUM( a~quode )
    FROM ptquoded AS a
    JOIN pa2001   AS b
      ON a~pernr = b~pernr
     AND a~docnr = b~docnr
    INTO DATA(urlaubsabtrag)
    WHERE a~pernr = pernr-pernr
     AND a~datum BETWEEN pn-begda AND pn-endda
     AND b~subty = 0100. " Abwesenheitsart, welche Selektiert werden soll

[DerpFest] Xiaomi Pad 5 (nabu)

I recently bought a used Xiaomi Pad 5 for 139.99€ from homezesting.com. It arrived in perfect condition.
The latest official Android version by Xiaomi is Android 13 with MIUI 14.0.5. This is kinda old, and I directly ran into an issue due to the old webview version in combination with the Home Assistant app (see here).

I therefore looked for a custom ROM and the first ROM I found for this device was DerpFest. I’ve never used it before, but flashing it shouldn’t be too different from other ROMs.
There are not much information on their website, but I found everything needed to know in their related telegram group: https://t.me/c/2284318430/8189

Unlocking the bootloader for Xiaomi devices can be annoying, but turned out, the bootloader of my purchased Pad 5 was already unlocked. Great!
(Update 10.02.2025: I asked the customer support and apparently they already sell all devices unlocked. Good to know!)

To make my life even simpler, I used the Auto-Installer shell script to install DerpFest 15. Unfortunately, it was running into an error, but it was easy to fix. (Seems like there is already a fixed version when downloading from GitHub here).

# make it executable
sudo chmod +x install_derpfest_linux.sh         

# start script
./install_derpfest_linux.sh  
# resulted in the error: /bin/bash^M: bad interpreter

# fix
sudo apt-get install dos2unix
dos2unix install_derpfest_linux.sh   
./install_derpfest_linux.sh                                                                                

Then the script ran without any issues.

When starting the device the first time, I skipped the Google Login step, so I wasn’t able to use the Play Store. But since not even a web browser is installed by default (which I think is really great to not be bloated from the beginning :-), I had to enable USB-Debugging mode and sideload F-Droid to install basic apps like a file explorer and browser.

adb install F-Droid.apk 

The Tablet is running super smooth and so far I could not find any issues! 🙂