Background
In a previous blog post, one scenario of auto-populating the External Actual Transfer of Control Date was discussed. Today we continue with another variation — this time in the context of 5MQ (Sell from Stock with Valuated Stock in Transit), where the date source and trigger are different.
The business requirement here has two parts:
- When an outbound delivery is created, default the External Planned Transfer of Control Date to 9999-12-31 — this keeps the POD window open indefinitely and prevents it from expiring before billing takes place.
- When the delivery is saved after billing, automatically populate the External Actual Transfer of Control Date from the corresponding Billing Document Date (posting date of the billing document).
Both fields are sap:updatable="false" in the standard OData API (API_OUTBOUND_DELIVERY_SRV), so BAdI-based extensibility is the only viable path.
The two fields in question on the outbound delivery Shipment tab:
- External Planned Transfer of Control Date (
INTCOEXTPLNDTRANSFOFCTRLDTETME) - External Actual Transfer of Control Date (
INTCOEXTACTLTRANSFOFCTRLDTETME)
Enhancement Points
BAdI 1 — LE_SHP_MODIFY_HEAD (Key User Extensibility)
Purpose: Default the Planned Transfer of Control Date to 9999-12-31 at delivery creation.
Entry point: Custom Logic app (#CustomLogic-develop) — Key User Extensibility, no transport required.
Implementation:
delivery_document_out = delivery_document_in.
DATA lv_max_ts TYPE timestamp.
lv_max_ts="99991231000000".
IF delivery_document_in-intcoextplndtransfofctrldtetme IS INITIAL.
delivery_document_out-intcoextplndtransfofctrldtetme = lv_max_ts.
ENDIF.
This BAdI operates under a FUNCTIONAL transactional contract — no database reads allowed, which is fine here since we only need a field assignment.
BAdI 2 — LE_SHP_SAVE_DOCUMENT_PREPARE (Key User Extensibility)
Purpose: Populate the Actual Transfer of Control Date from the billing document date when the delivery is saved.
Entry point: Custom Logic app (#CustomLogic-develop) — same as above.
Why not LE_SHP_MODIFY_HEAD for this? LE_SHP_MODIFY_HEAD enforces a FUNCTIONAL contract at runtime — any SELECT statement raises a transactional contract violation error. LE_SHP_SAVE_DOCUMENT_PREPARE does not have this restriction and allows reads against standard CDS views.
Implementation:
delivery_document_out = delivery_document_in.
DATA lv_max_ts TYPE timestamp.
lv_max_ts="99991231000000".
delivery_document_out-intcoextplndtransfofctrldtetme = lv_max_ts.
CHECK delivery_document_in-shippingpoint="1311" OR
delivery_document_in-shippingpoint="1320".
CHECK delivery_document_in-intcoextactltransfofctrldtetme IS INITIAL.
SELECT SINGLE t~billingdocumentdate
FROM i_billingdocument AS t
INNER JOIN i_billingdocumentitem AS i
ON i~billingdocument = t~billingdocument
WHERE i~referencesddocument = @delivery_document_in-deliverydocument
AND i~referencesddocumentcategory = 'J'
AND t~billingdocumentiscancelled = ''
INTO @DATA(lv_billing_date).
IF sy-subrc = 0 AND lv_billing_date IS NOT INITIAL.
DATA(lv_date_str) = |{ lv_billing_date DATE = RAW }|.
DATA lv_timestamp TYPE timestamp.
lv_timestamp = |{ lv_date_str }000000|.
delivery_document_out-intcoextactltransfofctrldtetme = lv_timestamp.
ENDIF.
Design notes:
- Scoped to specific Shipping Points — adjust
shippingpointvalues to match your configuration CHECK IS INITIALon the Actual date ensures idempotency — the date is only set once and won't be overwritten on subsequent savesReferenceSDDocumentCategory = 'J'filters for outbound deliveries in the document flow- Date-to-timestamp conversion uses string template syntax;
CONVERT DATE ... INTO TIME STAMPis not available in the Custom Logic environment - No custom tables or Z CDS views required — standard CDS views
I_BillingDocumentandI_BillingDocumentItemare sufficient
Test Result
Outbound delivery 80000325, Shipping Point 1311/1320, with an existing billing document dated 05/28/2026:
before
after
The Actual Transfer of Control Date matches the billing document date. The Planned date remains 9999-12-31 as expected.
One thing need to mention, after billing is completed and the invoice has a posting date, it is still necessary to manually trigger an outbound delivery update in order for the update to be successful.
Summary
Requirement BAdI Contract Approach
| Default Planned date to 9999-12-31 | LE_SHP_MODIFY_HEAD |
FUNCTIONAL | Direct field assignment |
| Populate Actual date from billing | LE_SHP_SAVE_DOCUMENT_PREPARE |
No restriction | SELECT on I_BillingDocument + I_BillingDocumentItem |
Both implementations are maintained entirely in the Custom Logic Fiori app — no developer extensibility, no transport requests.
The features covered in this article are based on SAP S/4HANA Cloud, Public Edition 2602, please refer to the latest information for changes in subsequent versions.
Hope you LIKE it if it addresses your issue. After that, please feel free to comment after following my account and I will reply ASAP.



