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

[ABAP] ALV traffic lights

TYPES: BEGIN OF ty_log,
         status TYPE icon-id,
       END OF ty_log.

DATA gt_log TYPE TABLE OF ty_log.

gt_log = VALUE #( ( status = icon_red_light    )
                  ( status = icon_yellow_light )
                  ( status = icon_green_light  ) ).

TRY.
    cl_salv_table=>factory( IMPORTING r_salv_table = DATA(alv_table)
                            CHANGING  t_table      = gt_log ).

    alv_table->display( ).

  CATCH cx_salv_msg.
ENDTRY.

icon_red, icon_yellow etc. will be automatically loaded from the TYPE-POOL: icon during runtime.

You can check all available icons via the table icon.

SELECT SINGLE id INTO @DATA(icon_red) FROM icon WHERE name = 'ICON_RED_LIGHT'.

[ABAP] Download Transport as ZIP

*&---------------------------------------------------------------------*
*& Report ZIP_TRANSPORT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zip_transport.

SELECTION-SCREEN BEGIN OF BLOCK bl01 WITH FRAME TITLE TEXT-t01.
PARAMETERS p_trkorr LIKE e070-trkorr OBLIGATORY.
PARAMETERS p_ttext  TYPE as4text.
SELECTION-SCREEN END OF BLOCK bl01.

SELECTION-SCREEN BEGIN OF BLOCK bl02 WITH FRAME TITLE TEXT-t02.
PARAMETERS p_sapdir TYPE string LOWER CASE OBLIGATORY DEFAULT '/usr/sap/trans/'.
PARAMETERS p_lcldir TYPE string LOWER CASE OBLIGATORY DEFAULT 'C:\temp\'.
SELECTION-SCREEN END OF BLOCK bl02.


START-OF-SELECTION.

  " Check if Transport is released
  DATA ls_request TYPE trwbo_request.
  CALL FUNCTION 'TR_READ_REQUEST'
    EXPORTING
      iv_read_e070     = abap_true
      iv_read_e07t     = abap_true
      iv_trkorr        = p_trkorr
    CHANGING
      cs_request       = ls_request
    EXCEPTIONS
      error_occured    = 1
      no_authorization = 2
      OTHERS           = 3.
  IF ls_request-h-trstatus <> 'R'.
    MESSAGE 'Transport not yet released' TYPE 'E'.
  ENDIF.


  " Read released Transport
  DATA lv_xcontent_k TYPE xstring.
  DATA lv_xcontent_r TYPE xstring.

  DATA(lv_transdir_k) = |{ p_sapdir }cofiles/K{ p_trkorr+4 }.{ p_trkorr(3) }|.
  DATA(lv_transdir_r) = |{ p_sapdir }data/R{    p_trkorr+4 }.{ p_trkorr(3) }|.


  TRY.

      " K
      OPEN  DATASET lv_transdir_k FOR INPUT IN BINARY MODE.
      READ  DATASET lv_transdir_k INTO lv_xcontent_k.
      CLOSE DATASET lv_transdir_k.

      " R
      OPEN  DATASET lv_transdir_r FOR INPUT IN BINARY MODE.
      READ  DATASET lv_transdir_r INTO lv_xcontent_r.
      CLOSE DATASET lv_transdir_r.

      " Add to ZIP
      DATA(lo_zipper) = NEW cl_abap_zip( ).

      lo_zipper->add( name    = |K{ p_trkorr+4 }.{ p_trkorr(3) }|
                      content = lv_xcontent_k ).

      lo_zipper->add( name    = |R{ p_trkorr+4 }.{ p_trkorr(3) }|
                      content = lv_xcontent_r ).


      " Download ZIP
      DATA(lv_xzip) = lo_zipper->save( ).

      " Convert to raw data
      DATA(lt_data) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_xzip ).

      " Set zip filename
      DATA(lv_zip_name) = COND #( WHEN p_ttext IS INITIAL THEN |{ ls_request-h-as4text }_{ p_trkorr }|
                                                          ELSE |{ p_ttext              }_{ p_trkorr }| ).

      " Replace every character that is not [a-zA-Z0-9_] with '_'.
      REPLACE ALL OCCURRENCES OF REGEX '[^\w]+' IN lv_zip_name WITH '_'.

      cl_gui_frontend_services=>gui_download( EXPORTING filename = p_lcldir && lv_zip_name && '.zip'
                                                        filetype = 'BIN'
                                              CHANGING  data_tab = lt_data ).

    CATCH cx_root INTO DATA(e_text).
      MESSAGE e_text->get_text( ) TYPE 'E'.
  ENDTRY.

  MESSAGE |{ lv_zip_name }.zip created and downloaded to { p_lcldir }| TYPE 'S'.

[CAP] Download MTA deployment logs after deployment

With this simple command, you can download the MTA deployment logs of your recent deployment. Instead of manually having to use cf dmol -i <operation id>, just save the command (replace appId with your Id) as a shell script, make it executable (chmod +x) and run the script after your deployment. It stores the recent logs into the folder logs.

dmol is short for download-mta-op-logs

cf download-mta-op-logs --mta <appId> --last 1 -d logs  

To just have a quick look at the recent logs, use

cf logs <appId>-srv --recent

[CAP] Check if User exists in SuccessFactors

To check if a record exists, you can simply use the HEAD query.

“HEAD is almost identical to GET, but without the response body.” (https://www.w3schools.com/tags/ref_httpmethods.asp)

Unfortunately, there is no shortcut in CAP for a HEAD query, so simply use send with method HEAD.

    sfsfSrv = await cds.connect.to('sfsf')

    try {
        await sfsfSrv.send('HEAD', `/User('${userId}')`)
        return true  // status 200
    } catch (err) {
        return false // status 404
    }

[ABAP] OData – GET_STREAM implementation to return a PDF

  METHOD /iwbep/if_mgw_appl_srv_runtime~get_stream.

* This method get's called when a media file is queried with $value. A binary stream will be returned.

    TRY.
        DATA(file_id) = VALUE zfile_id( it_key_tab[ name = 'file_id' ]-value ).
      CATCH cx_sy_itab_line_not_found.
        RETURN. " leave here when no file_id provided
    ENDTRY.
  
    DATA(ls_file) = get_file( file_id ) " read your file you want to return (if it's not yet a binary stream, convert it)

    DATA(ls_stream) = VALUE ty_s_media_resource( value     = ls_file-value
                                                 mime_type = ls_file-mimetype ). " in my case it's 'application/pdf'

    " necessary to display the filename instead of $value in the viewer title
    TRY.
        " create pdf object
        DATA(lo_fp)     = cl_fp=>get_reference( ).
        DATA(lo_pdfobj) = lo_fp->create_pdf_object( connection = 'ADC' ).
        lo_pdfobj->set_document( pdfdata = ls_stream-value ).
        " set title
        lo_pdfobj->set_metadata( VALUE #( title = ls_file-filename ) ).
        lo_pdfobj->execute( ).
        " get pdf with title
        lo_pdfobj->get_document( IMPORTING pdfdata = ls_stream-value ).

      CATCH cx_fp_runtime_internal
            cx_fp_runtime_system
            cx_fp_runtime_usage INTO DATA(lo_fpex).
    ENDTRY.

    copy_data_to_ref( EXPORTING is_data = ls_stream
                      CHANGING  cr_data = er_stream ).

    " necessary for the pdf to be opened inline instead of a download (also sets the filename when downloaded)
    /iwbep/if_mgw_conv_srv_runtime~set_header( VALUE #( name  = 'content-disposition'
                                                        value = |inline; filename={ ls_file-filename }| ) ).

  ENDMETHOD

Quick way to open a PDFViewer in your UI5 App:

			const pdfViewer = new PDFViewer()
			pdfViewer.setSource("/sap/opu/odata/ZMY_SEVICE" + my_path + "/$value")  // my_path could be something like this "/PdfSet('file_id')"
			pdfViewer.setTitle("My PDFViewer Title") // title of the popup, not the viewer
			pdfViewer.open()