Las anotaciones CDS extienden los CDS Views con metadatos para renderizado de UI, generación de OData, búsqueda y analítica. Son centrales para Fiori Elements y el modelo de programación RAP.
Categorías de anotaciones
| Categoría | Prefijo | Descripción |
|---|---|---|
| UI | @UI | Diseño de interfaz |
| OData | @OData | Propiedades OData |
| Semantics | @Semantics | Significado semántico |
| Search | @Search | Comportamiento de búsqueda |
| Analytics | @Analytics | Propiedades analíticas |
| ObjectModel | @ObjectModel | Metadatos del modelo de objetos |
Anotaciones UI
Configuración UI básica
@EndUserText.label: 'Pedidos'@Metadata.allowExtensions: truedefine view entity ZC_Order as projection on ZI_Order{ @UI.facet: [{ id: 'OrderHeader', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Cabecera del pedido', position: 10 }, { id: 'OrderItems', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Posiciones', 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}Información de cabecera
@UI.headerInfo: { typeName: 'Pedido', typeNamePlural: 'Pedidos', title: { type: #STANDARD, value: 'OrderId' }, description: { type: #STANDARD, value: 'CustomerName' }, imageUrl: 'ImageUrl'}define view entity ZC_OrderFacets y secciones
@UI.facet: [ { id: 'GeneralInfo', purpose: #STANDARD, type: #COLLECTION, label: 'Información general', 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: 'Posiciones', position: 20, targetElement: '_Items' }, { id: 'Notes', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Notes', label: 'Notas', position: 30 }]Grupos de campos
@UI.fieldGroup: [{ qualifier: 'HeaderData', position: 10, label: 'Número de pedido' }]OrderId,
@UI.fieldGroup: [{ qualifier: 'HeaderData', position: 20, label: 'Fecha de pedido' }]OrderDate,
@UI.fieldGroup: [{ qualifier: 'Address', position: 10, label: 'Calle' }]Street,
@UI.fieldGroup: [{ qualifier: 'Address', position: 20, label: 'Ciudad' }]City,
@UI.fieldGroup: [{ qualifier: 'Notes', position: 10, label: 'Observaciones' }]@UI.multiLineText: trueNotesAcciones y botones
@UI: { lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: 'confirmOrder', label: 'Confirmar' }, { position: 20, type: #FOR_ACTION, dataAction: 'cancelOrder', label: 'Cancelar', criticality: #NEGATIVE }], identification: [{ position: 100, type: #FOR_ACTION, dataAction: 'confirmOrder', label: 'Confirmar pedido' }]}OrderId,Tipos de DataField
" Campo estándar@UI.lineItem: [{ position: 10, type: #STANDARD }]OrderId,
" Con navegación@UI.lineItem: [{ position: 20, type: #WITH_NAVIGATION_PATH, targetElement: '_Customer'}]CustomerId,
" Como 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,
" Progreso@UI.lineItem: [{ position: 50, type: #AS_DATAPOINT}]@UI.dataPoint: { visualization: #PROGRESS, targetValue: 100, criticality: 'ProgressCriticality'}CompletionPercentAnotaciones Semantics
" Importes y monedas@Semantics.amount.currencyCode: 'Currency'TotalAmount,
@Semantics.currencyCode: trueCurrency,
" Cantidades y unidades@Semantics.quantity.unitOfMeasure: 'Unit'Quantity,
@Semantics.unitOfMeasure: trueUnit,
" Campos del sistema@Semantics.user.createdBy: trueCreatedBy,
@Semantics.user.lastChangedBy: trueChangedBy,
@Semantics.systemDateTime.createdAt: trueCreatedAt,
@Semantics.systemDateTime.lastChangedAt: trueChangedAt,
" Email y teléfono@Semantics.eMail.address: trueEmail,
@Semantics.telephone.type: [#WORK]PhoneNumber,
" Nombre@Semantics.name.fullName: trueCustomerName,
" Dirección@Semantics.address.street: trueStreet,
@Semantics.address.city: trueCity,
@Semantics.address.country: trueCountryAnotaciones Search
@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}Anotaciones OData
@OData.publish: true@OData.entityType.name: 'Order'@OData.entitySet.name: 'Orders'define view entity ZC_Order
" Navegaciones@OData.navigable: true_Customer,
" Actions@OData.operation.name: 'confirmOrder'Anotaciones Analytics
@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}Anotaciones ObjectModel
@ObjectModel: { modelCategory: #BUSINESS_OBJECT, compositionRoot: true, transactionalProcessingEnabled: true, writeActivePersistence: 'ZORDERS', semanticKey: ['OrderId'], representativeKey: 'OrderId'}define view entity ZI_Order
" Relación de texto@ObjectModel.text.element: ['StatusText']Status,
@ObjectModel.text.association: '_StatusText'_StatusText
" Clave foránea@ObjectModel.foreignKey.association: '_Customer'CustomerId,
" Transitorio (no persistente)@ObjectModel.virtualElement: true@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_ORDER_VIRTUAL'CalculatedFieldMetadata Extensions
" Archivo de anotaciones separado@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: 'Específico del cliente', position: 100 }] _root;}Criticality (colores de semáforo)
" Estado con Criticality@UI.lineItem: [{ criticality: 'StatusCriticality' }]Status,
" Campo Criticality calculadocase Status when 'O' then 2 -- Amarillo (Open) when 'C' then 3 -- Verde (Confirmed) when 'X' then 1 -- Rojo (Cancelled) else 0 -- Neutralend as StatusCriticality,
" Valores de Criticality:" 0 = Neutral (Gris)" 1 = Negative (Rojo)" 2 = Critical (Amarillo/Naranja)" 3 = Positive (Verde)" 5 = New Item (Azul) - solo para ciertos contextosValue Helps
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_Customer', element: 'CustomerId' }, additionalBinding: [{ element: 'CustomerName', localElement: 'CustomerName', usage: #RESULT }]}]CustomerId,
" Con filtro@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' );}Referencia de anotaciones
| Anotación | Valores | Descripción |
|---|---|---|
| @UI.importance | #HIGH, #MEDIUM, #LOW | Prioridad de columna |
| @UI.hidden | true/false | Ocultar campo |
| @Aggregation.default | #SUM, #AVG, #MIN, #MAX, #COUNT | Agregación por defecto |
| @Analytics.dataCategory | #DIMENSION, #CUBE, #FACT | Categoría analítica |
| @Search.ranking | #HIGH, #MEDIUM, #LOW | Prioridad de búsqueda |
Mejores prácticas
- Metadata Extensions: Mantener anotaciones UI separadas
- Usar Semantics: Para monedas, cantidades, campos del sistema
- Labels consistentes: Usar EndUserText.label
- Criticality: Para resaltado visual
- Search: Hacer campos importantes buscables
- Value Helps: Ayudas de entrada amigables
Temas relacionados
- CDS Views - Fundamentos de Core Data Services
- Servicios OData - Servicios web RESTful
- AMDP - Procedimientos de base de datos
- Verificación de autorizaciones - Access Control