CDS Annotations erweitern CDS Views um Metadaten für UI-Rendering, OData-Generierung, Suche und Analytik. Sie sind zentral für Fiori Elements und das RAP-Programmiermodell.
Annotation-Kategorien
| Kategorie | Präfix | Beschreibung |
|---|---|---|
| UI | @UI | Oberflächengestaltung |
| OData | @OData | OData-Eigenschaften |
| Semantics | @Semantics | Semantische Bedeutung |
| Search | @Search | Suchverhalten |
| Analytics | @Analytics | Analytische Eigenschaften |
| ObjectModel | @ObjectModel | Objektmodell-Metadaten |
UI-Annotations
Grundlegende UI-Konfiguration
@EndUserText.label: 'Bestellungen'@Metadata.allowExtensions: truedefine view entity ZC_Order as projection on ZI_Order{ @UI.facet: [{ id: 'OrderHeader', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Bestellkopf', position: 10 }, { id: 'OrderItems', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Positionen', position: 20, targetElement: '_Items' }]
@UI: { lineItem: [{ position: 10, importance: #HIGH }], identification: [{ position: 10 }], selectionField: [{ position: 10 }] } key OrderId,
@UI: { lineItem: [{ position: 20, importance: #HIGH }], identification: [{ position: 20 }], selectionField: [{ position: 20 }] } CustomerId,
@UI: { lineItem: [{ position: 30, importance: #MEDIUM }], identification: [{ position: 30 }] } OrderDate,
@UI: { lineItem: [{ position: 40, importance: #HIGH, criticality: 'StatusCriticality' }], identification: [{ position: 40 }], selectionField: [{ position: 30 }] } Status,
@UI: { lineItem: [{ position: 50, importance: #HIGH }], identification: [{ position: 50 }] } @Semantics.amount.currencyCode: 'Currency' TotalAmount,
Currency,
@UI.hidden: true StatusCriticality,
_Items}Header-Informationen
@UI.headerInfo: { typeName: 'Bestellung', typeNamePlural: 'Bestellungen', title: { type: #STANDARD, value: 'OrderId' }, description: { type: #STANDARD, value: 'CustomerName' }, imageUrl: 'ImageUrl'}define view entity ZC_OrderFacets und Sections
@UI.facet: [ { id: 'GeneralInfo', purpose: #STANDARD, type: #COLLECTION, label: 'Allgemeine Informationen', position: 10 }, { id: 'HeaderData', parentId: 'GeneralInfo', type: #FIELDGROUP_REFERENCE, targetQualifier: 'HeaderData', position: 10 }, { id: 'AddressData', parentId: 'GeneralInfo', type: #FIELDGROUP_REFERENCE, targetQualifier: 'Address', position: 20 }, { id: 'ItemsTable', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Positionen', position: 20, targetElement: '_Items' }, { id: 'Notes', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Notes', label: 'Notizen', position: 30 }]Field Groups
@UI.fieldGroup: [{ qualifier: 'HeaderData', position: 10, label: 'Bestellnummer' }]OrderId,
@UI.fieldGroup: [{ qualifier: 'HeaderData', position: 20, label: 'Bestelldatum' }]OrderDate,
@UI.fieldGroup: [{ qualifier: 'Address', position: 10, label: 'Straße' }]Street,
@UI.fieldGroup: [{ qualifier: 'Address', position: 20, label: 'Stadt' }]City,
@UI.fieldGroup: [{ qualifier: 'Notes', position: 10, label: 'Bemerkungen' }]@UI.multiLineText: trueNotesAktionen und Buttons
@UI: { lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: 'confirmOrder', label: 'Bestätigen' }, { position: 20, type: #FOR_ACTION, dataAction: 'cancelOrder', label: 'Stornieren', criticality: #NEGATIVE }], identification: [{ position: 100, type: #FOR_ACTION, dataAction: 'confirmOrder', label: 'Bestellung bestätigen' }]}OrderId,DataField-Typen
" Standard-Feld@UI.lineItem: [{ position: 10, type: #STANDARD }]OrderId,
" Mit Navigation@UI.lineItem: [{ position: 20, type: #WITH_NAVIGATION_PATH, targetElement: '_Customer'}]CustomerId,
" Als URL@UI.lineItem: [{ position: 30, type: #WITH_URL, url: 'WebLink'}]DocumentLink,
" Rating@UI.lineItem: [{ position: 40, type: #AS_DATAPOINT}]@UI.dataPoint: { visualization: #RATING, targetValue: 5}Rating,
" Progress@UI.lineItem: [{ position: 50, type: #AS_DATAPOINT}]@UI.dataPoint: { visualization: #PROGRESS, targetValue: 100, criticality: 'ProgressCriticality'}CompletionPercentSemantics Annotations
" Beträge und Währungen@Semantics.amount.currencyCode: 'Currency'TotalAmount,
@Semantics.currencyCode: trueCurrency,
" Mengen und Einheiten@Semantics.quantity.unitOfMeasure: 'Unit'Quantity,
@Semantics.unitOfMeasure: trueUnit,
" Systemfelder@Semantics.user.createdBy: trueCreatedBy,
@Semantics.user.lastChangedBy: trueChangedBy,
@Semantics.systemDateTime.createdAt: trueCreatedAt,
@Semantics.systemDateTime.lastChangedAt: trueChangedAt,
" E-Mail und Telefon@Semantics.eMail.address: trueEmail,
@Semantics.telephone.type: [#WORK]PhoneNumber,
" Name@Semantics.name.fullName: trueCustomerName,
" Adresse@Semantics.address.street: trueStreet,
@Semantics.address.city: trueCity,
@Semantics.address.country: trueCountrySearch Annotations
@Search.searchable: truedefine view entity ZC_Order{ @Search.defaultSearchElement: true @Search.fuzzinessThreshold: 0.8 @Search.ranking: #HIGH key OrderId,
@Search.defaultSearchElement: true @Search.ranking: #MEDIUM CustomerName,
@Search.defaultSearchElement: true @Search.ranking: #LOW Description}OData Annotations
@OData.publish: true@OData.entityType.name: 'Order'@OData.entitySet.name: 'Orders'define view entity ZC_Order
" Navigationen@OData.navigable: true_Customer,
" Actions@OData.operation.name: 'confirmOrder'Analytics Annotations
@Analytics.dataCategory: #CUBEdefine view entity ZI_SalesAnalytics{ @Analytics.dimension: true @ObjectModel.text.element: ['CustomerName'] CustomerId,
CustomerName,
@Analytics.dimension: true SalesOrg,
@Analytics.dimension: true @Semantics.calendar.yearMonth: true CalendarYearMonth,
@Analytics.measure: true @Aggregation.default: #SUM @Semantics.amount.currencyCode: 'Currency' Revenue,
@Analytics.measure: true @Aggregation.default: #SUM Quantity,
@Analytics.measure: true @Aggregation.default: #AVG AveragePrice,
Currency}ObjectModel Annotations
@ObjectModel: { modelCategory: #BUSINESS_OBJECT, compositionRoot: true, transactionalProcessingEnabled: true, writeActivePersistence: 'ZORDERS', semanticKey: ['OrderId'], representativeKey: 'OrderId'}define view entity ZI_Order
" Text-Beziehung@ObjectModel.text.element: ['StatusText']Status,
@ObjectModel.text.association: '_StatusText'_StatusText
" Fremdschlüssel@ObjectModel.foreignKey.association: '_Customer'CustomerId,
" Transient (nicht persistent)@ObjectModel.virtualElement: true@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_ORDER_VIRTUAL'CalculatedFieldMetadata Extensions
" Separate Annotation-Datei@Metadata.layer: #CUSTOMERannotate view ZC_Order with{ @UI.lineItem: [{ position: 10, importance: #HIGH }] @UI.identification: [{ position: 10 }] OrderId;
@UI.lineItem: [{ position: 20 }] @UI.hidden: true InternalField;
@UI.facet: [{ id: 'CustomSection', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Custom', label: 'Kundenspezifisch', position: 100 }] _root;}Criticality (Ampel-Farben)
" Status mit Criticality@UI.lineItem: [{ criticality: 'StatusCriticality' }]Status,
" Berechnetes Criticality-Feldcase Status when 'O' then 2 -- Gelb (Open) when 'C' then 3 -- Grün (Confirmed) when 'X' then 1 -- Rot (Cancelled) else 0 -- Neutralend as StatusCriticality,
" Criticality-Werte:" 0 = Neutral (Grau)" 1 = Negative (Rot)" 2 = Critical (Gelb/Orange)" 3 = Positive (Grün)" 5 = New Item (Blau) - nur für bestimmte KontexteValue Helps
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_Customer', element: 'CustomerId' }, additionalBinding: [{ element: 'CustomerName', localElement: 'CustomerName', usage: #RESULT }]}]CustomerId,
" Mit Filter@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_Status' }, qualifier: 'StatusVH', useForValidation: true}]@Consumption.filter: { selectionType: #SINGLE, multipleSelections: false}StatusAccess Control
@AccessControl.authorizationCheck: #CHECK@AccessControl.privilegedAssociations: ['_Admin']define view entity ZI_Order
" DCL (Data Control Language)@EndUserText.label: 'Order Access Control'@MappingRole: truedefine role ZI_ORDER_DCL { grant select on ZI_Order where ( SalesOrg ) = aspect pfcg_auth( V_VBAK_VKO, VKORG, ACTVT = '03' ) and ( CustomerId ) = aspect pfcg_auth( Z_CUSTOMER, KUNNR, ACTVT = '03' );}Annotation-Referenz
| Annotation | Werte | Beschreibung |
|---|---|---|
| @UI.importance | #HIGH, #MEDIUM, #LOW | Spalten-Priorität |
| @UI.hidden | true/false | Feld verstecken |
| @Aggregation.default | #SUM, #AVG, #MIN, #MAX, #COUNT | Standard-Aggregation |
| @Analytics.dataCategory | #DIMENSION, #CUBE, #FACT | Analytik-Kategorie |
| @Search.ranking | #HIGH, #MEDIUM, #LOW | Such-Priorität |
Best Practices
- Metadata Extensions: UI-Annotations separat halten
- Semantics nutzen: Für Währungen, Mengen, Systemfelder
- Konsistente Labels: EndUserText.label verwenden
- Criticality: Für visuelle Hervorhebung
- Search: Wichtige Felder durchsuchbar machen
- Value Helps: Benutzerfreundliche Eingabehilfen
Verwandte Themen
- CDS Views - Core Data Services Grundlagen
- OData Services - RESTful Web Services
- AMDP - Database Procedures
- Berechtigungsprüfungen - Access Control