cancel
Showing results for 
Search instead for 
Did you mean: 

@sap/cds-odata-v2-adapter-proxy doesn't return aggregated measure as integer

gregorw
Active Contributor

Hello CAP(M) Experts,

with the commit 21ad5225404a03020a5ba248b28a65bb2e1c4a75 I've added annotations for Analytics. Unfortunately the service returns the aggregated measure as a String when requested via the @sap/cds-odata-v2-adapter-proxy. For that I'm using the URL:

http://localhost:4004/v2/catalog/Books?$select=author_ID,stock&$orderby=stock&$inlinecount=allpages

I get back:

{
  "d": {
    "results": [
      {
        "author_ID": 107,
        "__metadata": {
          "uri": "http://localhost:4004/v2/catalog/Books(aggregation'{\"key\":{\"author_ID\":107},\"value\":[\"stock\"]}')",
          "type": "CatalogService.Books"
        },
        "stock": "11"
      },
      {
        "author_ID": 101,
        "__metadata": {
          "uri": "http://localhost:4004/v2/catalog/Books(aggregation'{\"key\":{\"author_ID\":101},\"value\":[\"stock\"]}')",
          "type": "CatalogService.Books"
        },
        "stock": "12"
      },
      {
        "author_ID": 170,
        "__metadata": {
          "uri": "http://localhost:4004/v2/catalog/Books(aggregation'{\"key\":{\"author_ID\":170},\"value\":[\"stock\"]}')",
          "type": "CatalogService.Books"
        },
        "stock": "22"
      },
      {
        "author_ID": 150,
        "__metadata": {
          "uri": "http://localhost:4004/v2/catalog/Books(aggregation'{\"key\":{\"author_ID\":150},\"value\":[\"stock\"]}')",
          "type": "CatalogService.Books"
        },
        "stock": "888"
      }
    ],
    "__count": 4
  }
}

As you can see the stock is returned as a string. In contrast to that when the aggregation is done with OData V4:

http://localhost:4004/catalog/Books?$apply=groupby((author_ID),aggregate(stock%20with%20sum%20as%20S...

I get:

{
  "@odata.context": "$metadata#Books(author_ID,StockTotal)",
  "@odata.metadataEtag": "W/\"q/OUzjzknmb3bMu6Fb8dAUuX53w4FSBIFhXoCuLQjeI=\"",
  "value": [
    {
      "@odata.id": null,
      "author_ID": 101,
      "StockTotal@odata.type": "#Decimal",
      "StockTotal": 12
    },
    {
      "@odata.id": null,
      "author_ID": 107,
      "StockTotal@odata.type": "#Decimal",
      "StockTotal": 11
    },
    {
      "@odata.id": null,
      "author_ID": 150,
      "StockTotal@odata.type": "#Decimal",
      "StockTotal": 888
    },
    {
      "@odata.id": null,
      "author_ID": 170,
      "StockTotal@odata.type": "#Decimal",
      "StockTotal": 22
    }
  ]
}

And the StockTotal is an Integer.

Looking forward for your help.

Best regards
Gregor

Accepted Solutions (0)

Answers (2)

Answers (2)

OliverKlemenz
Advisor
Advisor
0 Kudos

Hello Gregor,

thanks for your question:

According to JSON Format (OData Version 2.0)

https://www.odata.org/documentation/odata-version-2-0/json-format/

"Decimal" is encoded as JSON string.

Edm.DecimalLiteral form of Edm.Decimal as used in URIs formatted as a JSON string

I also double-checked this with the ABAP Analytical Engine, and there the values are also returned as strings.


Where does this make problems? In UI?

Or is it just as it is different to OData V4?

Thanks and Best regards,

Oliver

gregorw
Active Contributor
0 Kudos

Hi Oliver,

thank you for picking up this topic. I understand that my fix is not perfect. But as the field for that I do the aggregation is an Integer as you can see in:

https://github.com/gregorwolf/bookshop-demo/blob/master/db/schema.cds#L28

it seems that the Fiori Elements apps still expects to get it as an a JSON number. Maybe the issue isn't in the proxy but in the Fiori Elements layer.

Best regards
Gregor

OliverKlemenz
Advisor
Advisor
0 Kudos

Hi Gregor,


thanks for your comment. I think you're right, and it's not an issue in Fiori Elements layer.

It looks like an issue in combination of CDS and the CDS OData v2 Adapter Proxy.

CDS Service Runtime, need to fill the "@odata.type" correctly, currently it's always "#Decimal".

The CDS OData v2 Adapter Proxy needs to stringify only based on the "@odata.type" information.

We further investigate into this, and we will provide fixes.

Thanks for reporting this issue.

Best regards,

Oliver

pierre_dominique2
Contributor
0 Kudos

Hi Gregor,

This is probably just a bug but maybe oliver.klemenz can confirm?

Cheers,

Pierre

gregorw
Active Contributor
0 Kudos

Seems to be clearly a bug. I've created an implementation in ABAP CDS and there I get by requesting

https://vhcalnplci.dummy.nodomain:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD?$select=data...

this result:

{
 "d": {
 "__count": "3",
 "results": [
 {
 "__metadata": {
 "id": "https://VHCALNPLCI.DUMMY.NODOMAIN:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD('.84~Any%20DB')",
 "uri": "https://VHCALNPLCI.DUMMY.NODOMAIN:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD('.84~Any%20DB')",
 "type": "ZFAS_APPS_DD_CDS.ZFAS_APPS_DDType"
 },
 "databasename": "Any DB",
 "counter": 139
 },
 {
 "__metadata": {
 "id": "https://VHCALNPLCI.DUMMY.NODOMAIN:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD('.84~HANA%20DB%20exclusive')",
 "uri": "https://VHCALNPLCI.DUMMY.NODOMAIN:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD('.84~HANA%20DB%20exclusive')",
 "type": "ZFAS_APPS_DD_CDS.ZFAS_APPS_DDType"
 },
 "databasename": "HANA DB exclusive",
 "counter": 2000
 },
 {
 "__metadata": {
 "id": "https://VHCALNPLCI.DUMMY.NODOMAIN:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD('.84~HANA%20DB%20or%20HANA%20side-by-side')",
 "uri": "https://VHCALNPLCI.DUMMY.NODOMAIN:50001/sap/opu/odata/sap/ZFAS_APPS_DD_CDS/ZFAS_APPS_DD('.84~HANA%20DB%20or%20HANA%20side-by-side')",
 "type": "ZFAS_APPS_DD_CDS.ZFAS_APPS_DDType"
 },
 "databasename": "HANA DB or HANA side-by-side",
 "counter": 409
 }
 ]
 }
}
gregorw
Active Contributor
0 Kudos

Fixed it for the moment with this patch in the convertAggregation method in the file node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js. Simply replace:

           data[key.substr(AggregationPrefix.length)] = String(data[key]);

with:

          if(typeof data[key] === 'number') {
            data[key.substr(AggregationPrefix.length)] = data[key]
          } else {
            data[key.substr(AggregationPrefix.length)] = String(data[key]);
          }
OliverKlemenz
Advisor
Advisor
0 Kudos

I just saw, that you also tried to re-check it with ABAP CDS.

I also did this, and in my case, the decimals are returned as strings...

As OData V4 always returns @odata.type": "#Decimal" I also converted always to string, as decimal is represented as string in OData v2.

Maybe OData V4 needs to return different type in case of sum of integers (which stays in type integers)

Then I could react to it, and stringify depending on the @odata.type...

But the code replacement you did in the proxy is not correct for decimals, as those are represented by JSON numbers in v4 and as JSON string in v2...