CDS - Parâmetros, Filtros e Views Parametrizadas
Parâmetros em CDS Views
Parâmetros permitem criar views dinâmicas que filtram ou calculam dados baseados em valores fornecidos em runtime.
Sintaxe Básica
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Customer by Country'
define view entity ZI_CustomerByCountry
with parameters
P_Country : land1
as select from kna1 as Customer
{
key Customer.kunnr as CustomerId,
Customer.name1 as CustomerName,
Customer.land1 as Country,
Customer.ort01 as City
}
where
Customer.land1 = $parameters.P_Country
Consumindo View com Parâmetros
" Consulta ABAP
SELECT FROM ZI_CustomerByCountry( P_Country = 'DE' )
FIELDS CustomerId,
CustomerName,
City
INTO TABLE @DATA(lt_customers).
LOOP AT lt_customers INTO DATA(ls_customer).
WRITE: / ls_customer-CustomerId,
ls_customer-CustomerName,
ls_customer-City.
ENDLOOP.
Múltiplos Parâmetros
View com Vários Parâmetros
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Orders by Date Range'
define view entity ZI_SalesOrderByDateRange
with parameters
P_DateFrom : abap.dats,
P_DateTo : abap.dats,
P_Currency : waers
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.kunnr as CustomerId,
@Semantics.currencyCode: true
SalesOrder.waers as Currency,
// Associação
_Customer
}
where
SalesOrder.erdat >= $parameters.P_DateFrom
and SalesOrder.erdat <= $parameters.P_DateTo
and SalesOrder.waers = $parameters.P_Currency
and _Customer.Country = $parameters.P_Country
Consumo do Dashboard
" ABAP Report
REPORT z_sales_dashboard.
PARAMETERS: p_from TYPE dats OBLIGATORY,
p_to TYPE dats OBLIGATORY,
p_curr TYPE waers DEFAULT 'EUR',
p_land TYPE land1 DEFAULT 'PT'.
START-OF-SELECTION.
SELECT FROM ZI_SalesDashboardParam(
P_DateFrom = @p_from,
P_DateTo = @p_to,
P_Currency = @p_curr,
P_Country = @p_land )
FIELDS Year,
Quarter,
CustomerSegment,
NetValue,
TotalValue
INTO TABLE @DATA(lt_dashboard).
" Processar resultados
LOOP AT lt_dashboard INTO DATA(ls_line).
WRITE: / ls_line-Year,
ls_line-Quarter,
ls_line-CustomerSegment,
ls_line-NetValue,
ls_line-TotalValue.
ENDLOOP.
Performance com Parâmetros
Push-Down com Parâmetros
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Optimized Parametrized View'
define view entity ZI_OptimizedParamView
with parameters
P_SalesOrg : vbak.vkorg
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.netwr as NetValue
}
where
SalesOrder.vkorg = $parameters.P_SalesOrg -- Filtro no banco de dados
Performance
Parâmetros aplicados no WHERE são processados no banco de dados (push-down), melhorando drasticamente a performance.
Exercícios Práticos
Exercício 1: View Parametrizada Básica
Crie uma view de materiais filtrada por: - Tipo de material (obrigatório) - Data de criação (intervalo)
Exercício 2: Window Functions
Crie uma view que mostre: - Top 10 clientes por faturamento - Ranking por país - Número sequencial de pedidos por cliente
Exercício 3: Dashboard Completo
Implemente um dashboard parametrizado com: - Filtros de data (obrigatórios) - Filtro de país (opcional) - Agregações por mês e trimestre - Categorização de clientes - Window functions para ranking
Exercício 4: Union de Dados
Combine dados de clientes (KNA1) e fornecedores (LFA1) em uma única view com: - ID unificado - Tipo de parceiro - Endereço completo
Resumo do Módulo CDS
Conceitos Fundamentais
✅ CDS View Entities vs CDS Views
✅ Anotações técnicas e semânticas
✅ Nomenclatura e boas práticas
Associações e Joins
✅ Diferença entre associações e joins
✅ Cardinalidades
✅ Path expressions
✅ Propagação de associações
Anotações e Metadata
✅ Anotações UI
✅ Anotações Analytics
✅ Metadata Extensions
✅ Separation of Concerns
Funções e Expressões
✅ Funções de texto, data e matemáticas
✅ CASE expressions
✅ Agregações
✅ Type casting
Parâmetros e Filtros
✅ Views parametrizadas
✅ Session variables
✅ Window functions
✅ Subqueries e UNION
Recursos Adicionais
Documentação SAP
Best Practices
- Use View Entities para novos desenvolvimentos
- Prefira associações sobre joins
- Implemente Metadata Extensions para UI
- Use parâmetros para views reutilizáveis
- Documente suas views com @EndUserText
Próximos Passos
- Praticar com exemplos reais
- Integrar com SAP Fiori
- Criar serviços OData
- Implementar autorização (DCL)
- Otimizar performance com HANA
Conclusão
Parabéns! Você completou o tutorial completo de CDS. Continue praticando e explorando as capacidades avançadas do Core Data Services.Semantics.amount.currencyCode: 'Currency' SalesOrder.netwr as NetValue,
SalesOrder.waers as Currency
} where SalesOrder.erdat >= $parameters.P_DateFrom and SalesOrder.erdat <= $parameters.P_DateTo and SalesOrder.waers = $parameters.P_Currency
### Uso em ABAP
```abap
DATA: lv_date_from TYPE dats,
lv_date_to TYPE dats.
lv_date_from = sy-datum - 30.
lv_date_to = sy-datum.
SELECT FROM ZI_SalesOrderByDateRange(
P_DateFrom = @lv_date_from,
P_DateTo = @lv_date_to,
P_Currency = 'EUR' )
FIELDS SalesOrderId,
CreationDate,
NetValue,
Currency
INTO TABLE @DATA(lt_orders).
Parâmetros com Valores Padrão
Definindo Valores Default
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Products with Optional Filter'
define view entity ZI_ProductsFiltered
with parameters
P_ProductType : mtart,
@Environment.systemField: #SYSTEM_DATE
P_ValidOn : abap.dats
as select from mara as Product
{
key Product.matnr as ProductId,
Product.mtart as ProductType,
Product.ersda as CreationDate,
Product.meins as BaseUnit
}
where
Product.mtart = $parameters.P_ProductType
System Fields como Parâmetros
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Current Language Texts'
define view entity ZI_ProductText
with parameters
@Environment.systemField: #SYSTEM_LANGUAGE
P_Language : spras
as select from makt
{
key matnr as ProductId,
spras as Language,
maktx as ProductDescription
}
where
spras = $parameters.P_Language
Session Variables
Variáveis de Sistema Disponíveis
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Orders with Session Info'
define view entity ZI_OrdersWithSessionInfo
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.kunnr as CustomerId,
// Data atual do sistema
$session.system_date as CurrentDate,
// Língua de logon
$session.system_language as SystemLanguage,
// Cliente (mandante)
$session.client as Client,
// Usuário
$session.user as CurrentUser,
// Dias desde criação
dats_days_between(
SalesOrder.erdat,
$session.system_date
) as DaysSinceCreation
}
Filtro por Data Atual
define view entity ZI_CurrentMonthOrders
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.netwr as NetValue
}
where
substring(SalesOrder.erdat, 1, 6) =
substring($session.system_date, 1, 6)
Parâmetros em Associações
Propagação de Parâmetros
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Order with Items by Date'
define view entity ZI_SalesOrderFiltered
with parameters
P_DateFrom : abap.dats
as select from vbak as SalesOrder
association [0..*] to ZI_SalesOrderItem as _Items
on $projection.SalesOrderId = _Items.SalesOrderId
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.kunnr as CustomerId,
_Items
}
where
SalesOrder.erdat >= $parameters.P_DateFrom
View Consumidora com Parâmetros
define view entity ZC_SalesOrderWithDetails
with parameters
P_DateFrom : abap.dats,
P_Country : land1
as select from ZI_SalesOrderFiltered(
P_DateFrom: $parameters.P_DateFrom
) as SalesOrder
association [0..1] to ZI_CustomerByCountry as _Customer
on $projection.CustomerId = _Customer.CustomerId
and _Customer.P_Country = $parameters.P_Country
{
key SalesOrder.SalesOrderId,
SalesOrder.CreationDate,
SalesOrder.CustomerId,
_Customer.CustomerName,
_Customer.Country,
_Customer,
_Items
}
UNION e UNION ALL
Combinar Múltiplas Fontes
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'All Business Partners'
define view entity ZI_AllBusinessPartners
as select from kna1 as Customer
{
key kunnr as PartnerId,
name1 as PartnerName,
'Customer' as PartnerType,
land1 as Country
}
union all
select from lfa1 as Vendor
{
key lifnr as PartnerId,
name1 as PartnerName,
'Vendor' as PartnerType,
land1 as Country
}
UNION com Transformação
define view entity ZI_CombinedAddresses
as select from kna1 as Customer
{
kunnr as PartnerId,
concat('C-', kunnr) as PartnerCode,
name1 as Name,
stras as Street,
ort01 as City,
land1 as Country,
'Customer' as Type
}
union
select from lfa1 as Vendor
{
lifnr as PartnerId,
concat('V-', lifnr) as PartnerCode,
name1 as Name,
stras as Street,
ort01 as City,
land1 as Country,
'Vendor' as Type
}
WHERE Clause Avançada
Múltiplas Condições
define view entity ZI_ComplexFilter
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.kunnr as CustomerId,
SalesOrder.netwr as NetValue,
SalesOrder.waers as Currency
}
where
SalesOrder.erdat >= '20240101'
and (
SalesOrder.netwr >= 10000
or SalesOrder.kunnr in ( '0001000000', '0001000001' )
)
and SalesOrder.waers = 'EUR'
Operadores IN e NOT IN
define view entity ZI_EuropeanCustomers
as select from kna1 as Customer
{
key Customer.kunnr as CustomerId,
Customer.name1 as CustomerName,
Customer.land1 as Country,
Customer.ort01 as City
}
where
Customer.land1 in ( 'DE', 'FR', 'ES', 'IT', 'PT', 'NL', 'BE' )
and Customer.loevm <> 'X' -- Não marcado para eliminação
Operadores LIKE
define view entity ZI_CustomerNameSearch
as select from kna1 as Customer
{
key Customer.kunnr as CustomerId,
Customer.name1 as CustomerName,
Customer.ort01 as City
}
where
Customer.name1 like '%GMBH%'
or Customer.name1 like '%LTD%'
or Customer.name1 like '%SA%'
Subqueries (EXISTS e IN)
EXISTS
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Customers with Orders'
define view entity ZI_CustomersWithOrders
as select from kna1 as Customer
{
key Customer.kunnr as CustomerId,
Customer.name1 as CustomerName,
Customer.land1 as Country,
Customer.ort01 as City
}
where exists (
select from vbak as SalesOrder
where SalesOrder.kunnr = Customer.kunnr
and SalesOrder.erdat >= '20240101'
)
NOT EXISTS
define view entity ZI_CustomersWithoutOrders
as select from kna1 as Customer
{
key Customer.kunnr as CustomerId,
Customer.name1 as CustomerName,
Customer.land1 as Country
}
where not exists (
select from vbak as SalesOrder
where SalesOrder.kunnr = Customer.kunnr
)
IN com Subquery
define view entity ZI_HighValueCustomers
as select from kna1 as Customer
{
key Customer.kunnr as CustomerId,
Customer.name1 as CustomerName,
Customer.land1 as Country
}
where Customer.kunnr in (
select SalesOrder.kunnr
from vbak as SalesOrder
where SalesOrder.netwr >= 100000
)
Window Functions
RANK e DENSE_RANK
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Customer Ranking by Revenue'
define view entity ZI_CustomerRanking
as select from vbak as SalesOrder
{
key SalesOrder.kunnr as CustomerId,
@Semantics.amount.currencyCode: 'Currency'
sum(SalesOrder.netwr) as TotalRevenue,
SalesOrder.waers as Currency,
// Ranking (valores iguais recebem mesma posição, próximo é saltado)
rank( ) over(
partition by SalesOrder.waers
order by sum(SalesOrder.netwr) descending
) as RevenueRank,
// Dense Rank (sem saltar posições)
dense_rank( ) over(
partition by SalesOrder.waers
order by sum(SalesOrder.netwr) descending
) as DenseRevenueRank
}
group by
SalesOrder.kunnr,
SalesOrder.waers
ROW_NUMBER
define view entity ZI_OrdersWithRowNumber
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.kunnr as CustomerId,
SalesOrder.erdat as CreationDate,
SalesOrder.netwr as NetValue,
// Número sequencial
row_number( ) over(
partition by SalesOrder.kunnr
order by SalesOrder.erdat descending
) as OrderSequence
}
Filtrar por Window Function
define view entity ZI_LatestOrderPerCustomer
as select from ZI_OrdersWithRowNumber
{
key SalesOrderId,
CustomerId,
CreationDate,
NetValue
}
where
OrderSequence = 1 -- Apenas o pedido mais recente
Parâmetros com Validação
View com Filtro Obrigatório
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Order - Mandatory Date'
define view entity ZI_SalesOrderMandatory
with parameters
@Consumption.filter.mandatory: true
P_CreationDate : abap.dats
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.erdat as CreationDate,
SalesOrder.kunnr as CustomerId,
SalesOrder.netwr as NetValue
}
where
SalesOrder.erdat = $parameters.P_CreationDate
Parâmetros com Lista de Valores
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Orders by Document Type'
define view entity ZI_OrdersByDocType
with parameters
@Consumption.valueHelpDefinition: [{
entity: {
name: 'I_SalesDocumentType',
element: 'SalesDocumentType'
}
}]
P_DocType : vbak.auart
as select from vbak as SalesOrder
{
key SalesOrder.vbeln as SalesOrderId,
SalesOrder.auart as DocumentType,
SalesOrder.erdat as CreationDate,
SalesOrder.netwr as NetValue
}
where
SalesOrder.auart = $parameters.P_DocType
Exemplo Completo: Dashboard Parametrizado
```abap @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Sales Dashboard - Parametrized' @Analytics.dataCategory: #CUBE define view entity ZI_SalesDashboardParam with parameters @Consumption.filter.mandatory: true @Consumption.filter.selectionType: #INTERVAL P_DateFrom : abap.dats,
@Consumption.filter.mandatory: true
@Consumption.filter.selectionType: #INTERVAL
P_DateTo : abap.dats,
@Consumption.defaultValue: 'EUR'
@Consumption.valueHelpDefinition: [{
entity: {
name: 'I_Currency',
element: 'Currency'
}
}]
P_Currency : waers,
@Consumption.filter.selectionType: #SINGLE
@Consumption.valueHelpDefinition: [{
entity: {
name: 'I_Country',
element: 'Country'
}
}]
P_Country : land1
as select from vbak as SalesOrder
association [0..1] to ZI_Customer as _Customer on $projection.CustomerId = _Customer.CustomerId { // Dimensões @Analytics.dimension: true key SalesOrder.vbeln as SalesOrderId,
@Analytics.dimension: true SalesOrder.kunnr as CustomerId,
@Analytics.dimension: true SalesOrder.erdat as CreationDate,
@Analytics.dimension: true cast(substring(SalesOrder.erdat, 1, 6) as abap.char(6)) as YearMonth,
@Analytics.dimension: true cast(substring(SalesOrder.erdat, 1, 4) as abap.numc(4)) as Year,
@Analytics.dimension: true case cast(substring(SalesOrder.erdat, 5, 2) as abap.numc(2)) when 1 then 'Q1' when 2 then 'Q1' when 3 then 'Q1' when 4 then 'Q2' when 5 then 'Q2' when 6 then 'Q2' when 7 then 'Q3' when 8 then 'Q3' when 9 then 'Q3' when 10 then 'Q4' when 11 then 'Q4' when 12 then 'Q4' else 'Unknown' end as Quarter,
@Analytics.dimension: true _Customer.Country,
@Analytics.dimension: true _Customer.City,
@Analytics.dimension: true case when SalesOrder.netwr >= 100000 then 'VIP' when SalesOrder.netwr >= 50000 then 'Premium' when SalesOrder.netwr >= 10000 then 'Standard' else 'Basic' end as CustomerSegment,
// Medidas @Analytics.measure: true @Aggregation.default: #SUM @Semantics.amount.currencyCode: 'Currency' SalesOrder.netwr as NetValue,
@Analytics.measure: true @Aggregation.default: #SUM @Semantics.amount.currencyCode: 'Currency' SalesOrder.netwr * 0.23 as VATAmount,
@Analytics.measure: true @Aggregation.default: #SUM @Semantics.amount.currencyCode: 'Currency' SalesOrder.netwr * 1.23 as TotalValue,
@