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

[CAP] min and max functions

Since there is nothing in the official CAP documents about min and max functions, I figured out the following syntax:

    const result1 = await cds.run(`SELECT *, MAX(counter) FROM ${myTable} LIMIT 1`) //returns array

    const result2 = await SELECT.one.from(myTable, [`MAX(counter)`]).columns('*') //returns object 

    const result3 = await SELECT.one.from(myTable).columns('MAX(counter)') //returns object containing only the max counter value

[CAP] Posting form data to a destination using executeHttpRequest

        const { executeHttpRequest } = require('@sap-cloud-sdk/http-client')
        const FormData = require('form-data')

        try {
            //Create payload
            const form = new FormData()
            form.append('file', fileContent, {
                contentType: 'application/pdf'
                filename: 'test.pdf'

            //Create headers
            const headers = {
                'Content-Length': form.getLengthSync(),

            //Send to Destination
            const response = await executeHttpRequest(
                { destinationName: 'TESTINATION' },
                    method: 'POST',
                    url: 'myApiPath',
                    headers: headers,
                    data: form,
                    responseType: 'arraybuffer' // if you need the response data as buffer to prevent UTF-8 encoding
        } catch (error) {

[CAP] Fiori Elements – Add section with PDFViewer

I have a CAP Service that provides a PDF file that I needed to display in a Fiori Elements frontend using the sap.m.PDFViewer. The viewer should be placed in a section on the object page after navigating from the ListReport main page.

My CAP Service has the following annotations to provide the PDF.

  entity pdfFiles : cuid, managed {
    content            : LargeBinary @stream @Core.MediaType: mediaType @Core.ContentDisposition.Filename: fileName @Core.ContentDisposition.Type: 'inline';
    mediaType          : String      @Core.IsMediaType: true;
    fileName           : String      @mandatory;

Add a custom section to your view following this example: https://sapui5.hana.ondemand.com/test-resources/sap/fe/core/fpmExplorer/index.html#/customElements/customSectionContent
Two steps are necessary.

1. Add a new section via the manifest. The template path should match your app namespace.

        "ObjectPage": {
          "type": "Component",
          "id": "ObjectPage",
          "name": "sap.fe.templates.ObjectPage",
          "viewLevel": 1,
          "options": {
            "settings": {
              "editableHeaderContent": false,
              "entitySet": "pdfFiles",
             "content": {
                "body": {
                  "sections" : {
                    "myCustomSection": {
                      "template": "sap.fe.core.fpmExplorer.customSectionContent.CustomSection",
                      "title": "{i18n>pdfSection}",
                      "position": {
                        "placement": "After",
                        "anchor": "StandardSection"

2. Add the section content by defining a new fragment in the file CustomSection.fragment.xml

<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:l="sap.ui.layout" xmlns:macro="sap.fe.macros">
		<FlexBox direction="Column" renderType="Div" class="sapUiSmallMargin">
			<PDFViewer source="{content}" title="{fileName}" height="1200px">
					<FlexItemData growFactor="1" />

On the ObjectPage you will now have a new section containing the PDFViewer.

[CAP] Fiori Elements – Display managed fields as value help


using {
} from '@sap/cds/common';

entity managedEntity: managed {
    key ID    : UUID;
        field : String;


using myService as service from '../../srv/myService';

annotate service.managedEntity with @(
    Capabilities.SearchRestrictions: {Searchable: false},
    UI.PresentationVariant         : {
        SortOrder     : [{
            Property  : createdAt,
            Descending: true
        Visualizations: ['@UI.LineItem']
    UI.HeaderInfo                  : {
        TypeName      : '{i18n>myEntity}',
        TypeNamePlural: '{i18n>myEntities}',
    UI.SelectionFields             : [
    UI.LineItem                    : [
) {
    createdAt @UI.HiddenFilter : false;
    createdBy @UI.HiddenFilter : false;

[CAP] CQL Expand Composition / Deep read

In the documentation they always use a star in string literals like this o => o.`*` to select all fields, but when running this it always failed. However, after some tests I found that this format works with brackets o => o.('*')


entity myEntity: cuid, managed {
    field1          : String;
    comp            : Composition of one myComposition;
aspect myComposition: cuid, managed {
    myCompField: String;
        const result = await SELECT.from(myEntity)
            .columns(e => {
                e.comp(c => c.myCompField) //expand composition, but only select 'myCompField'

[CAP] CQL Deep Update

entity myEntity: cuid, managed {
    field1          : String;
    comp            : Composition of one myComposition;

aspect myComposition: cuid, managed {
    myCompField: String;
            const { myEntity } = cds.entities

            await UPDATE(myEntity)
                    ID: '0732eae8-8858-4917-8865-e4fa2c40xxxx'
                    comp : [{ myCompField: 'my string data' }]

[CAP] UploadSet http test file

How to create an uploadSet in combination with a CAP backend: https://blogs.sap.com/2021/08/18/my-journey-towards-using-ui5-uploadset-with-cap-backend/

You can test the uploadSet CAP backend part using these http calls:

### Create file
# @name file
POST http://localhost:4004/v2/admin/Files
Authorization: Basic admin:
Content-Type: application/json

    "mediaType": "image/png",
    "fileName": "picture.png",
    "size": 1000

### Fill Variable from Response
@ID = {{file.response.body.$.d.ID}}

### Upload Binary PNG content
PUT http://localhost:4004/v2/admin/Files({{ID}})/content
Authorization: Basic admin:
Content-Type: image/png

< ./picture.png

### Get uploaded png
GET http://localhost:4004/v2/admin/Files({{ID}})/content
Authorization: Basic admin:

The picture.png file must be in the same folder as the http test file.