Found and fixed the issue! It was a combination of problems with the CDS join condition, ObjectModel annotation, and dashboard data refresh timing.
1. CDS Join Condition Problem:
The left outer join was correct syntactically, but the renewal status table uses a compound key (ContractID + RenewalPeriod), not just ContractID. My join was only matching on ContractID, which caused multiple rows per contract or no match when the period wasn’t specified. Fixed join:
left outer join ZI_RenewalStatus as _Renewal
on Contract.ContractID = _Renewal.ContractID
and _Renewal.RenewalPeriod = 'CURRENT'
The ‘CURRENT’ filter ensures we only get active renewal tracking records.
2. ObjectModel Annotation Fix:
I was missing proper association metadata. Added this to the CDS view:
@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
association [0..1] to ZI_RenewalStatus as _Renewal
on $projection.ContractID = _Renewal.ContractID
The [0..1] cardinality is important - it tells the analytics framework that each contract has at most one current renewal status. Without this, the dashboard aggregation logic was confused about how to handle the relationship.
3. Dashboard Data Refresh Configuration:
The dashboard was using a cached dataset that only refreshed nightly. I updated the tile configuration in the Fiori launchpad designer to use real-time data refresh:
- Changed refresh mode from ‘scheduled’ to ‘on-load’
- Set the cache duration to 0 (no caching for renewal data)
- Added date parameter binding to ensure the 90-day filter is applied at query time
I also had to regenerate the OData service metadata after changing the CDS view annotations. Used transaction /IWFND/MAINT_SERVICE to clear the service cache.
The renewal tracking section now displays all 47 contracts correctly. The key learning was that dashboard associations need explicit cardinality and association type annotations - the analytics framework doesn’t infer these automatically like it does for regular CDS view consumption.
One additional fix: I added @Analytics.query: true to the parent view to ensure it’s properly registered as an analytical query. This improved dashboard performance significantly because it enables proper aggregation at the database level rather than in the application layer.
This draft is based on general SAP S/4HANA knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.