SAP Knowledge Base Article - Public

3744148 - API_MANAGE_WORKFORCE_TIMESHEET: Supported Capabilities

Symptom

When using the API_MANAGE_WORKFORCE_TIMESHEET OData V2 API, the following scenarios are observed where the API fails silently:

  • Scenario 1: $orderby is silently ignored. Requests containing $orderby on TimeSheetEntryCollection return results without ordering, with no error returned to the caller.
  • Scenario 2: The $filter operators gt (greater than) and lt (less than) on TimeSheetDate are either ignored or return incorrect results. Only EQ, GE, LE, and BT produce correct behaviour.
  • Scenario 3: $inlinecount=allpages is silently ignored. The __count property is absent from the response body even when explicitly requested.
  • Scenario 4: A POST request submitted without the TimeSheetOperation field returns HTTP 201 with no error message, but no timesheet entry is created or modified (silent failure).

Environment

SAP S/4HANA Cloud Public Edition.

Reproducing the Issue

Scenario 1 – $orderby silently ignored

  • Send a GET request to TimeSheetEntryCollection with an $orderby clause, for example:

GET /sap/opu/odata/sap/API_MANAGE_WORKFORCE_TIMESHEET/TimeSheetEntryCollection?$filter=PersonWorkAgreementExternalID eq 'EXT001' and CompanyCode eq '1000'&$orderby=TimeSheetDate desc

  • The response returns results in an unspecified order. No error or warning is returned to indicate that $orderby was not applied.

Scenario 2 – $filter operators gt and lt defective

  • Send a GET request using gt or lt on TimeSheetDate, for example:

GET /sap/opu/odata/sap/API_MANAGE_WORKFORCE_TIMESHEET/TimeSheetEntryCollection?$filter=TimeSheetDate gt datetime'2024-01-31T00:00:00'

  • The response either returns all records (filter ignored) or returns an incorrect result set that does not match the expected boundary condition.
  • The same request using ge instead of gt returns correct results.

Scenario 3 – $inlinecount=allpages ignored, no __count in response

  • Send a GET request with $inlinecount=allpages, for example:

GET /sap/opu/odata/sap/API_MANAGE_WORKFORCE_TIMESHEET/TimeSheetEntryCollection?$filter=PersonWorkAgreementExternalID eq 'EXT001' and CompanyCode eq '1000'&$inlinecount=allpages

  • The response body does not contain the __count property. The total record count is not returned inline, regardless of the number of entries matching the filter.

Scenario 4 – POST without TimeSheetOperation returns HTTP 201, no entry created

  • Send a POST request to TimeSheetEntryCollection with a valid payload but without the TimeSheetOperation field (or with TimeSheetOperation set to an empty string):

POST /sap/opu/odata/sap/API_MANAGE_WORKFORCE_TIMESHEET/TimeSheetEntryCollection

  • The API returns HTTP 201 Created with no error message.
  • No timesheet entry is created, updated, or deleted in the system. The TimeSheetRecord in the response is empty or zero.
  • The caller receives no indication that the operation was not performed.

Cause

Scenario 1 – $orderby

$orderby is not implemented in the TimeSheetEntryCollection GET handler. The underlying data retrieval (function module HCM_CATS_MANAGE_GET_TIMEENTRY) does not expose a sort parameter, and the OData layer does not apply post-retrieval sorting. The SEGW / IWBEP framework accepts the $orderby clause in the URL without validation and silently discards it.

Scenario 2 – gt and lt operators

The $filter parsing in the GET entity set handler maps TimeSheetDate filter values to the iv_startdate and iv_enddate parameters of HCM_CATS_MANAGE_GET_TIMEENTRY. Only the EQ and BT conditions are explicitly handled in the filter loop; the gt and lt operators are not mapped to an equivalent exclusive boundary. When gt or lt is encountered, the filter condition is either discarded or treated equivalently to ge / le, producing incorrect boundary behaviour.

Scenario 3 – $inlinecount

The $inlinecount=allpages system query option requires the server to return a __count value alongside the result set. The TimeSheetEntryCollection GET handler does not populate the es_response_context-inlinecount field, which is the mechanism used by the IWBEP framework to inject __count into the response. As a result, the framework omits the property entirely, with no error to the caller.

Scenario 4 – POST without TimeSheetOperation

The write path for TimeSheetEntryCollection routes all POST requests through the function module HCM_CATS_MANAGE_EXEC_TIMEENTRY via the TIMEENTRY_VALIDATIONS and execution logic. The TimeSheetOperation field (cats_operation in the internal structure) controls which action is taken. When the field is absent or empty, the execution function module receives a blank operation type and performs no action. The OData layer returns HTTP 201 because the handler completes without raising an exception, even though no data was written. This is a silent failure: no warning or error message is issued.

Resolution

Apply the following workarounds for each scenario:

Scenario 1 – $orderby: apply sorting client-side

  • Do not rely on $orderby in requests to TimeSheetEntryCollection. The parameter is accepted by the framework but has no effect.
  • Retrieve the result set using supported $filter parameters (see Supported Capabilities below) and sort the entries in the consuming application after retrieval.

Scenario 2 – $filter: use ge and le instead of gt and lt

  • Replace gt with ge and lt with le in all TimeSheetDate filter expressions.
  • To express an exclusive lower boundary (e.g. all entries after 31 January 2024), use ge with the first date of the intended range:

$filter=TimeSheetDate ge datetime'2024-02-01T00:00:00'

  • For inclusive date range queries, both ge/le and BT are supported:

$filter=TimeSheetDate ge datetime'2024-01-01T00:00:00' and TimeSheetDate le datetime'2024-01-31T00:00:00'

 

Scenario 3 – $inlinecount: use $count path segment instead

  • Do not use $inlinecount=allpages. The __count property is not returned in the response.
  • To obtain the total count of matching entries, use the $count path segment as a separate request:

GET /TimeSheetEntryCollection/$count?$filter=PersonWorkAgreementExternalID eq 'EXT001' and CompanyCode eq '1000'

  • This returns a plain integer representing the total number of entries matching the filter.

Scenario 4 – POST without TimeSheetOperation: always set the field explicitly

  • Always include TimeSheetOperation in every POST request payload. The field must be set to one of the following values:

 

TimeSheetOperation value

Action performed

'C'

Create a new timesheet entry. Returns the new TimeSheetRecord key in the response.

'U'

Update an existing entry. TimeSheetRecord must be present in the payload.

'D'

Delete an existing entry. TimeSheetRecord must be present in the payload.

 

  • After every POST, verify the TimeSheetRecord value in the response. An empty or zero TimeSheetRecord indicates that no entry was processed, regardless of the HTTP status code returned.

Mandatory Fields for POST Requests:
Refer to the attached document.

Supported Capabilities of API_MANAGE_WORKFORCE_TIMESHEET:
Refer to the attached document. 

Keywords

API_MANAGE_WORKFORCE_TIMESHEET, OData V2, $orderby ignored, $filter gt lt, $inlinecount allpages, __count missing, TimeSheetOperation, silent failure, HTTP 201, POST no entry created, TimeSheetDataFields, TimeSheetEntryCollection, mandatory fields, TimeSheetIsReleasedOnSave, TimeSheetPredecessorRecord, RecordedQuantity, HoursUnitOfMeasure, PurchaseOrder, contingent worker, reversal, correction, supported capabilities, CA-TS-S4, CATS, HCM, SAP S/4HANA Cloud Public Edition. , KBA , CA-TS-S4 , Cross Application Timesheet in S/4HANA , Bug Filed

Product

SAP S/4HANA Cloud Public Edition all versions

Attachments

KBA_Timesheet API.docx