Você está na página 1de 57

PLANTÃO DE IMPLANTAÇÃO

RELATÓRIOS
GATEWAY + SAPUI5
Sumário
Sumário ................................................................................................................................................ 2
Definições .............................................................................................................................................. 3
Criar novo Projeto .................................................................................................................................. 5
Definindo Uma Entidade ........................................................................................................................ 7
Publicação do Serviço ............................................................................................................................ 9
Atualizando os Metadados .................................................................................................................. 12
Leitura de lista: Método GET_ENTITYSET ............................................................................................. 14
Leitura de chave primária: Método GET_ENTITY ................................................................................. 18
Criando o Aplicativo FrontEnd ............................................................................................................. 20
Adição de dados na página de detalhes ............................................................................................... 29
Implementação de Filtros .................................................................................................................... 31
Implementação de Ordenação............................................................................................................. 35
Implementação da Paginação .............................................................................................................. 39
Adicionando Associações no Modelo OData ........................................................................................ 43
Implementando Expansões (Cliente/vendas) ...................................................................................... 46
Consumindo as Relações no UI5 (Cliente/vendas) ............................................................................... 50
Deploy da aplicação no servidor – Report ABAP .................................................................................. 53

#MIGRESUACARREIRA
2
Definições

SAP Gateway é uma ferramenta que permite que o desenvolvedor ABAP crie
webservices que podem ser consumidos externamente por qualquer tecnologia
FrontEnd que consuma serviços do protocolo OData. o SAP Gateway na posição de
servidor SAP foi o primeiro nome do atual Front-End Server.

OData é um protocolo de comunicação aberto baseado em princípios REST. O PI


também suporta protocolo OData, mas a diferença é que agora o serviço é gerado
direto do ABAP para a web, sem precisar fazer uma segunda transformação no PI.

outra diferença é que o foco do PI é integração Business-to-Business, ou seja, de


sistema com sistema. Enquanto que o foco do Gateway é integração Business-to-
Consumer, ou seja, sistema com usuário de dispositivos móveis.

SAPUI5 é um framework para desenvolvimento de aplicativos FrontEnd que rodam


em browser e dispositivos móveis.
A SAP percebeu que a interface do usuário (IU) está mais suscetível a mudanças hoje
do que nunca. As necessidades e demandas do usuário estão em evolução e podem
mudar a composição e o design de um aplicativo. Por isso o BackEnd deve ser
desenvolvido e mantido separadamente do FrontEnd e deve haver uma divisão clara
de responsabilidades.
Com base na teoria acima, a SAP criou um kit de ferramentas de desenvolvimento
baseado em HTML5, SAPUI5, que incentiva uma experiência de usuário consistente.

#MIGRESUACARREIRA
3
DEFINIÇÃO E
PUBLICAÇÃO
DO SERVIÇO
ODATA

#MIGRESUACARREIRA
4
Criar novo Projeto

Transação SEGW
Criar Projeto
Indicar:
- Nome
- Descrição
- Pacote
Salvar.

Clicar em Gerar objetos


• Não mudar os valores da tela exibida

#MIGRESUACARREIRA
5
Na pasta Runtime Artifacts, vão ser geradas as Classes:
• MPC: Model Provider Class
Encarregada da definição do modelo. NÃO MODIFICAR.

• DPC: Data Provider Class


Encarregada do tratamento de operações e retorno de informações de negócio.
NÃO MODIFICAR.

• MPC_EXT e DPC_EXT:
Classes herdeiras das indicadas acima. Nelas redefinimos o comportamento,
inserindo a lógica que queremos.

#MIGRESUACARREIRA
6
Definindo Uma Entidade

Transação SEGW
Pelo Wizard: Clique com botão direito em Data Model > Create > Entity Type
(ou manual: clicar duas vezes em Entity Types e clicar em Anexar linha )

Name: Cliente
Marcar ‘Create Related Entity Set’

Expandir pasta Entity Types > Cliente > Properties

#MIGRESUACARREIRA
7
Clicar em Inserir Linha e adicionar os registros abaixo:

Name IS Key EDM Core Type ML ABAP Field


ID X Edm.String 10 ID
Nome Edm.String 30 NOME
Telefone Edm.String 16 TELEFONE
UF Edm.String 3 UF
Email Edm.String 40 EMAIL
Status Edm.String 1 STATUS

Clicar duas vezes em Entity Sets, Marcar EntitySet com Addressable

Gravar e Gerar

#MIGRESUACARREIRA
8
Publicação do Serviço

Transação /IWFND/MAINT_SERVICE (cuidado com a ‘/’ no inicio)


Inserir Serviço

Indicamos:
- Alias do Sistema: LOCAL
- Nome Serviço Técnico: (nome do objeto gerado dentro da pasta “Runtime
Artifacts” no Passo 1, que termina com _SRV e é do tipo “registered service”)

Como consultar Registered Service na Tela da SEGW

#MIGRESUACARREIRA
9
Na MAINT_SERVICE, selecionar a entrada.
Clicar ‘Inserir serviços selecionados’.
OK (várias vezes)
Voltar para tela inicial
Filtrar pelo nome do serviço.

Clicar em Chamar browser ou SAP Gateway Client acessa no serviço (cuidado, só


acessar pela porta 5200 com protocolo HTTPS e 8000 padrão).

Vai ser gerado um link no seguinte padrão. Ajuste os termos entre <> para os dados
do seu ambiente.
http://<host>:<porta>/sap/opu/odata/sap/<nome_serviço>_SRV/

Caso o ambiente tenha mais de um mandate, ajuste o ambiente no fim da URL


http://<host>:<porta>/sap/opu/odata/sap/<nome_serviço>_SRV/?sap-client=xxx

#MIGRESUACARREIRA
10
No final da URL , a interrogação (?) indica que serão informados parâmetros
adicionais.
Os parâmetros adicionais são concatenados por ‘e comercial’ (&)

Veja a diferença entre os links


http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/?sap-
client=200

http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/?$format=xml&sap-
client=200
http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/?$format=json&sap-
client=200

Guarde o link dos Metadados - definição de atributos do serviço:


https://lnl-s4h.opustech.com.br:5200/sap/opu/odata/sap/ZLOJA_SRV/$metadata?sap-client=200
http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/$metadata?sap-client=200

Alguns parâmetros são precedidos de cifrão ($), como os parâmetros de query


Filtro: ClienteSet?$filter=UF eq 'MG'

Ordenação: ClienteSet?$orderby=ID desc

Contagem: ClienteSet/$count

Paginação: ClienteSet/?$skip=2&$top=2

#MIGRESUACARREIRA
11
Atualizando os Metadados

Quando adicionamos novas entidades no projeto e clicamos em gerar, se acessamos


os metadados pode ser que não tenha mudado nada.
Geralmente os metadados dos serviços OData de forma de ter uma melhor
performance, trabalham com cache em dois níveis.
- Cache na definição do serviço do lado backend.
- Cache na instancia do serviço do lado frontend.

Sempre que for modificada a definição de um serviço devemos atualizar o cache dos
dois níveis.
• Backend:
• Transação /IWBEP/CACHE_CLEANUP
• Executamos para todos os modelos.

• Frontend:
• Transação /IWFND/CACHE_CLEANUP
• Por modelo: O nome do ‘Registered Model’ (pasta runtime artifacts do projeto
na SEGW)
• Cleanup Cache para todos modelos: manter flag ativo

Se acessamos aos metadados de nosso serviço vamos conseguir ver a mudança.


http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/$metadata?sap-
client=200

#MIGRESUACARREIRA
12
IMPLEMENTAÇÃO
DO SERVIÇO
ODATA

#MIGRESUACARREIRA
13
Leitura de lista: Método GET_ENTITYSET

Acessar coleção pelo browser usando URL


http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet?sap-client=200

Vai aparecer um erro

O erro basicamente indica que o método CLIENTESET_GET_ENTITYSET não está


implementado.

Acessamos Transação SEGW


• Pasta Service Implementation >
ClienteSet > GetEntitySet
• Botão direito > Go To ABAP Workbench

Para toda Entidade que definimos, é gerado de forma automática 5 métodos ABAP
na classe DPC: Create, Update, Delete, GetEntity e GetEntitySet.

#MIGRESUACARREIRA
14
Com a classe DPC_EXT vamos na SE24 e buscamos o método
CLIENTESET_GET_ENTITYSET.

Se entramos no método vemos que a implementação por default é a geração de uma


exceção de método não implementado.

Redefinimos o método para colocar a nossa lógica:

SELECT *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET.

Após mudanças testamos novamente:


http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet?sap-client=200

#MIGRESUACARREIRA
15
A consulta ao serviço odata também pode ser feito usando a transação
/IWFND/GW_CLIENT - SAP Gateway Client
Nesta tela é informada a url do serviço, sem informar host e porta

#MIGRESUACARREIRA
16
Para melhorar a performance, o serviço OData permite especificar as colunas para
serem selecionadas.

Exemplo: coloque na url o parâmetro ClienteSet?$select=ID,Nome


http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet?$select=ID,
Nome&sap-client=200

No código ABAP, coloque o seguinte trecho

data(lt_select_mandt) = IO_TECH_REQUEST_CONTEXT->get_select_with_mandtry_fields( ) .

SELECT (lt_select_mandt)
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET.

Execute a url e veja a diferença. Só serão exibidas as colunas informadas

#MIGRESUACARREIRA
17
Leitura de chave primária: Método GET_ENTITY

Acessar 1 registro específico pelo browser usando URL


http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet('000000025
7')?sap-client=200
Vai aparecer um erro

O erro é relacionado com a falta de implementação do método


CLIENTESET_GET_ENTITY. Basicamente, o método GET_ENTITY é responsável por
retornar os dados da entidade considerando o campo chave.
Primeiro implementamos a busca de Clientes pelo campo chave, redefinindo método
CLIENTESET_GET_ENTITY

O campo chave está nos parâmetros de entrada do método. Pode ser obtido o nome
interno ou externo da propriedade da entidade OData

Redefinimos o método para colocar a nossa lógica:

MODO 1: NOMES INTERNOS


DATA: LS_ENTITY TYPE ZCL_ZLOJA_MPC=>TS_CLIENTE.
IO_TECH_REQUEST_CONTEXT->GET_CONVERTED_KEYS(
IMPORTING
ES_KEY_VALUES = LS_ENTITY).

SELECT SINGLE *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF ER_ENTITY
WHERE ID EQ LS_ENTITY-ID.

#MIGRESUACARREIRA
18
MODO 2: NOMES EXTERNOS

READ TABLE IT_KEY_TAB


WITH KEY NAME = 'ID'
REFERENCE INTO DATA(LV_REF_KEY).

READ TABLE IT_KEY_TAB


WITH KEY NAME = 'ID'
INTO DATA(LV_KEY).

SELECT SINGLE *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF ER_ENTITY
WHERE ID EQ LV_KEY-VALUE.

Agora temos como resultado apenas o registro com a chave especificada

#MIGRESUACARREIRA
19
Criando o Aplicativo FrontEnd

Criamos um App para o serviço gerado, usando Visual Studio Code.


O VSCode necessita da instalação do SAP Fiori Tools.
Para usar SAP Business application Studio, configurar SAP Cloud
Connector

No VSCode aperte F1 > digite Fiori > selecione Open Application Generator

Escolher tipo de aplicativo SAPUI5 Freestyle

Escolher o floorplan Worklist

#MIGRESUACARREIRA
20
#MIGRESUACARREIRA
21
Em Data Source, selecione Connect to a System

Em System, serão exibidos os Sistemas cadastrados


Caso não tenha nenhum sistema cadastrado , selecione New System

Em System type, selecione ABAP On Premise

#MIGRESUACARREIRA
22
Coloque o host e porta https do ambiente (o mesmo host e porta do launchpad)

Informe suas credenciais e clique em login

Em Service, escolha o serviço OData gerado, podendo digitar o nome para filtrar

#MIGRESUACARREIRA
23
Em Object collection selecione a entidade criada no serviço
Em Object collection key informe o campo chave da entidade
Em Object ID selecione uma propriedade significativa da entidade, que não seja o
campo chave
Em number e unit of measure não informe nada. Informe se tiver criado as
respectivas propriedades no serviço

#MIGRESUACARREIRA
24
Em Project atributes , coloque as informações do aplicativo

Verifique a versão mínima, e ajuste se necessário.


Confira se o ambiente da sua empresa não tem uma vesão mais antiga do que a
suportada no VS Code

Para conferir versão do UI5 SDK no ambiente da empresa, use este


link, ajustando o host e porta:
http://lnl-
s4h.opustech.com.br:8000/sap/public/bc/ui5_ui5/index.html

#MIGRESUACARREIRA
25
Opcionalmente, você pode informar as configurações de de deploy e launchpad

Nas opções de deploy é informado o nome da aplicação bsp, o pacote abap, a


request e a descrição

#MIGRESUACARREIRA
26
Em FPL configuration é informado o objeto semântico e ação para configurações do
launchpad

A IDE vai instalar todos os módulos

Depois que o projeto for gerado, clique na opção run e debug, e clique em run

#MIGRESUACARREIRA
27
OPERAÇÕES DE
LEITURA E
QUERY

#MIGRESUACARREIRA
28
Adição de dados na página de detalhes

Vamos adicionar um formulário simples na view Object


No cabeçalho da view adicionamos os namespaces dos componentes a serem
usados
Na seção de “content” adicionamos um “form”

<mvc:View controllerName="cris.controller.Object"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core"
xmlns:semantic="sap.f.semantic">
...
<semantic:content>
<VBox>
<f:Form id="FormDisplay354" editable="false">
<f:title>
<core:Title text="Detalhes" />
</f:title>
<f:layout>
<f:ResponsiveGridLayout labelSpanXL="3" labelSpanL="3" labelSpanM="3" labelSpanS="12"
adjustLabelSpan="false" emptySpanXL="4" emptySpanL="4" emptySpanM="4" emptySpanS="0" columnsXL="1"
columnsL="1" columnsM="1" singleContainerFullSize="false" />
</f:layout>
<f:formContainers>
<f:FormContainer>
<f:formElements>
<f:FormElement label="ID">
<f:fields>
<Text text="{ID}" />
</f:fields>
</f:FormElement>
<f:FormElement label="Nome">
<f:fields>
<Text text="{Nome}" />
</f:fields>
</f:FormElement>
<f:FormElement label="Telefone">
<f:fields>
<Text text="{Telefone}" />
</f:fields>
</f:FormElement>
<f:FormElement label="UF">
<f:fields>
<Text text="{UF}" />
#MIGRESUACARREIRA
29
</f:fields>
</f:FormElement>
<f:FormElement label="Email">
<f:fields>
<Text text="{Email}" />
</f:fields>
</f:FormElement>
</f:formElements>
</f:FormContainer>
</f:formContainers>
</f:Form>
</VBox>
</semantic:content>
</semantic:SemanticPage>
</mvc:View>

#MIGRESUACARREIRA
30
Implementação de Filtros

Se testamos o filtro pelo nome do cliente verificamos que o mesmo não está
funcionando. Temos que implementar a lógica para aplicar o filtro no backend.

Na view temos a declaração do filtro e seu evento

#MIGRESUACARREIRA
31
No Controller vemos a implementação do método de busca.
Nele vemos que o filtro está sendo passado para a propriedade Nome

A efetivação da chamada ao backend se dá em métodos relacionados a


funcionalidade de “data binding”

Veja exemplos de parâmetros de filtros usando a URL:

ClienteSet?$filter=substringof('carne', Nome) eq true


ClienteSet?$filter=substringof('carne', Nome)
ClienteSet?$filter=substringof('carne', Nome) and UF eq 'MG'
ClienteSet?$filter=substringof('carne', Nome) or substringof('Wal', Nome)
ClienteSet?$filter=substringof('carne', Nome) or substringof('Wal', Nome)&$format=json

ClienteSet?$filter=UF eq 'MG'

Confira a sintaxe das operações de Leitura do serviço OData


https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

#MIGRESUACARREIRA
32
Para implementar o filtro, no método CLIENTESET_GET_ENTITYSET temos que
obter os filtros passados pelo FrontEnd e aplicar na consulta ao banco de dados.

Os dados podem ser obtidos através dos parâmetros de entrada do método na


classe ABAP.

MODO 1 CLASSE ACESSÓRIA – ENTENDE TODOS OS FILTROS


DATA(LS_where) = IO_TECH_REQUEST_CONTEXT->get_osql_where_clause( ).

SELECT *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET
WHERE (LS_WHERE).

MODO 2 MANUAL – NECESSITA CRIAR CADA FILTRO MANUALMENTE


DATA:
LR_NOME TYPE RANGE OF ZTAB_CLIENTES-NOME.

LOOP AT IT_FILTER_SELECT_OPTIONS REFERENCE INTO DATA(LV_FILTER).

CASE LV_FILTER->PROPERTY.
WHEN 'Nome'.

LOOP AT LV_FILTER->SELECT_OPTIONS REFERENCE INTO DATA(LV_OPTIONS).


APPEND INITIAL LINE TO LR_NOME REFERENCE INTO DATA(LV_NOME).

MOVE-CORRESPONDING LV_OPTIONS->* TO LV_NOME->*.

ENDLOOP.

WHEN OTHERS.
ENDCASE.

ENDLOOP.

SELECT *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET
WHERE NOME IN LR_NOME .

#MIGRESUACARREIRA
33
Após mudanças no backend, nosso filtro deve estar funcionando.

Como funciona o contador no cabeçalho da tabela?


O componente da tabela tem um evento chamado updateFinished

Este evento tem como parâmetro o numero total de linhas da tabela.


Este total é atribuído ao titulo

#MIGRESUACARREIRA
34
Implementação de Ordenação

A ordenação da lista é um parâmetro que existe na view, informada ao definir os itens


da lista.

É possível estar a ordenação na URL com as seguintes opções:


ClienteSet?$orderby=Nome asc

ClienteSet?$orderby=ID desc

Vamos tratar a ordenação no backend.


Para isso no método CLIENTESET_GET_ENTITYSET temos que obter os campos
pelos quais ordenar. Estes campos estão nos parâmetros de entrada do método.

#MIGRESUACARREIRA
35
MODO 1 CLASSE ACESSÓRIA
“MONTAGEM DOS FILTROS
...
"ORDENAÇÃO
DATA: LV_DB_ORDERBY TYPE STRING.
DATA(LT_ORDERBY) = IO_TECH_REQUEST_CONTEXT->GET_ORDERBY( ).

LOOP AT LT_ORDERBY REFERENCE INTO DATA(LS_ORDERBY).

IF LS_ORDERBY->ORDER EQ 'desc'.

DATA(LV_SORT_ORDER) = 'DESCENDING'.
ELSE.
LV_SORT_ORDER = 'ASCENDING'.
ENDIF.

CONCATENATE
LV_DB_ORDERBY
LS_ORDERBY->PROPERTY
LV_SORT_ORDER

INTO LV_DB_ORDERBY SEPARATED BY SPACE.

ENDLOOP.

SELECT *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET WHERE
NOME IN LR_NOME
ORDER BY (LV_DB_ORDERBY) .

#MIGRESUACARREIRA
36
MODO 2 MANUAL
“MONTAGEM DOS FILTROS
...

LOOP AT IT_ORDER REFERENCE INTO DATA(LV_REF_ORDER)."tabela de campos a serem ordenados

CASE LV_REF_ORDER->PROPERTY.
WHEN 'Nome'.
DATA(LV_DB_FIELD) = 'NOME'.
ENDCASE.

DATA(LV_ORDER) = LV_REF_ORDER->ORDER.

TRANSLATE LV_ORDER TO UPPER CASE.

CASE LV_ORDER.
WHEN 'DESC'.
DATA(LV_DB_ORDER) = 'DESCENDING'.
WHEN OTHERS.
LV_DB_ORDER = 'ASCENDING'.
ENDCASE.

CONCATENATE
LV_DB_FIELD
LV_DB_ORDER
INTO
DATA(LV_ORDER_BY)
SEPARATED BY
SPACE.

ENDLOOP.

SELECT *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET
WHERE NOME IN LR_NOME.
WHERE NOME IN LR_NOME
ORDER BY (LV_ORDER_BY).

Você também pode simplesmente concatenar ‘ENDING’ no parâmetro de


ordenação!!!

#MIGRESUACARREIRA
37
Após mudanças no backend, a ordenação vai estar funcionando.

#MIGRESUACARREIRA
38
Implementação da Paginação

A paginação o serve para melhorar a performance da lista. Por exemplo, se nossa


tabela tivesse meio milhão de registros, a cada solicitação ao backend estaríamos
sempre retornando meio milhão de registros.

Na paginação temos que considerar:


• Vai existir uma request que vai solicitar o total de registros.
http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet/$count

• Vai existir uma request que vai solicitar a página


http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet/?$skip=2&$top=2

O tamanho da página depende dos atributos do controle UI5.

#MIGRESUACARREIRA
39
Para implementar a paginação, no método CLIENTESET_GET_ENTITYSET temos que
obter os dados de paginação. Estes campos estão nos parâmetros de entrada do
método.
MODO 1 – PARA USO EM TABELAS
POR CAUSA DO “UP TO X ROWS”
“MONTAGEM DOS FILTROS
...
* CONTAGEM
IF IO_TECH_REQUEST_CONTEXT->HAS_COUNT( ) = ABAP_TRUE.

SELECT COUNT(*)
FROM ZTAB_CLIENTES
INTO @DATA(LV_COUNT)
WHERE NOME IN @LR_NOME.

ES_RESPONSE_CONTEXT-COUNT = LV_COUNT.

ELSE.

DATA(LV_UP_TO) = IS_PAGING-TOP + IS_PAGING-SKIP.

SELECT *
FROM ZTAB_CLIENTES
UP TO LV_UP_TO ROWS

INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET


WHERE NOME IN LR_NOME
ORDER BY (LV_ORDER_BY).

IF IS_PAGING-SKIP > 0.
DELETE ET_ENTITYSET FROM 1 TO IS_PAGING-SKIP.
ENDIF.

#MIGRESUACARREIRA
40
MODO 2 – PARA USO EM BAPIS
PORQUE BAPI RETORNA A LISTA INTEIRA
“MONTAGEM DOS FILTROS
...

DATA: LT_CLIENTES TYPE TABLE OF ZTAB_CLIENTES.

SELECT *
FROM ZTAB_CLIENTES
INTO CORRESPONDING FIELDS OF TABLE LT_CLIENTES WHERE
NOME IN LR_NOME
ORDER BY (LV_DB_ORDERBY) .

DATA(LV_INICIO) = 1.

IF IS_PAGING-SKIP IS NOT INITIAL.


LV_INICIO = IS_PAGING-SKIP + 1.
ENDIF.

IF IS_PAGING-TOP IS INITIAL.
DATA(LV_FIM) = LINES( LT_CLIENTES ).
ELSE.
LV_FIM = LV_INICIO + IS_PAGING-TOP - 1.
ENDIF.

LOOP AT LT_CLIENTES INTO DATA(LS_CLIENTE)


FROM LV_INICIO TO LV_FIM.
APPEND INITIAL LINE TO ET_ENTITYSET REFERENCE INTO DATA(LS_ENTITY).
MOVE-CORRESPONDING LS_CLIENTE TO LS_ENTITY->*.
ENDLOOP.

ENDIF.

Após mudanças no backend, a paginação deveria estar funcionando com uma


performance melhor.

#MIGRESUACARREIRA
41
ASSOCIAÇÕES E
NAVEGAÇÃO
NO SERVIÇO
ODATA

#MIGRESUACARREIRA
42
Adicionando Associações no Modelo OData

Associações, o também relações, definem a cardinalidade entre entidades. Vamos


adicionar as seguintes relações no nosso modelo:
Cliente [1..N] Venda
Venda [1..1] Cliente

• Transação SEGW.
• Criamos a Entidade

Venda (criar EntitySet por default: VendaSet)

• Informamos as seguintes propriedades:


ABAP
IS EDM Core
Name Precision Scale ML ABAP Field Type
Key Type
Editor
IDVenda X Edm.String 10 ID
DataCriacao Edm.DateTime DATA_CRIACAO DATS
Descricao Edm.String 40 DESCRICAO
Cliente Edm.String 10 CLIENTE_ID
ValorLiquido Edm.Decimal 15 2 VALOR_LIQUIDO
CriadoPor Edm.String 12 CRIADO_POR

! Atenção para ajuste de tipo no ABAP


• Clicar no botão na coluna ABAP Type
• Escolher mode 2 Explict assignment

#MIGRESUACARREIRA
43
• Informar Associated Type como DATS
• Continuar

Vamos criar a associação

• Duplo clique na pasta Associations do


Data Model:
• Criamos as seguintes entradas:
• ClienteToVendas, Cliente, 1, Venda N
• Referential Constraints:

• VendaToCliente, Venda, 1, Cliente 1


• Referential Constraints:

#MIGRESUACARREIRA
44
• Na entidade Cliente, adicionamos em
Navigation Properties o registro:
• Name vendas
• Relationship Name ClienteToVendas
• ABAP Field Name VENDAS

• Na entidade Venda, adicionamos em


Navigation Properties o registro:
• Name cliente
• Relationship Name VendaToCliente
• ABAP Field Name CLIENTE

Gravamos e Geramos.
Verificamos que os metadados foram atualizados .

#MIGRESUACARREIRA
45
Implementando Expansões (Cliente/vendas)

Antes de implementar as relações, precisamos implementar o comportamento


individual da entidade.
rimeiro implementamos a busca de Vendas redefinindo método
VENDASET_GET_ENTITYSET

"SELEÇÃO DE CAMPOS
DATA(LT_SELECT) = IO_TECH_REQUEST_CONTEXT->GET_SELECT_WITH_MANDTRY_FIELDS( ).

"FILTRO DE CAMPOS
DATA(LV_WHERE) = IO_TECH_REQUEST_CONTEXT->GET_OSQL_WHERE_CLAUSE_CONVERT( ).

SELECT (LT_SELECT)
FROM ZTAB_VENDAS_CAB
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET
WHERE (LV_WHERE)

ORDER BY ID .

http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/VendaSet/$count

http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/VendaSet/?$filter=substringof('milho',
Descricao)

Na URL, a partir da entidade ClienteSet, navegamos para vendas


http://lnl-s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet('0000000001')/vendas

Na lista de vendas do Cliente estão vindo todas as Vendas da tabela do banco de


dados. O erro não aparece no debug, mas é um erro de funcionalidade.
http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet('00000000
01')/vendas/$count

#MIGRESUACARREIRA
46
Para corrigir, devemos adaptar o método VENDASET_GET_ENTITYSET já
implementado.

"DEFINIR ESTRUTURA PARA COLETAR CAMPOS CHAVE DA ENTIDADE ORIGEM


DATA: LS_CLIENTE TYPE ZCL_ZMONITORVENDAS_MPC=>TS_CLIENTE.

DATA(LV_ENTITYSET) = IO_TECH_REQUEST_CONTEXT-
>GET_SOURCE_ENTITY_SET_NAME( ).

"SELEÇÃO DE CAMPOS
DATA(LT_SELECT) = IO_TECH_REQUEST_CONTEXT-
>GET_SELECT_WITH_MANDTRY_FIELDS( ).
"FILTRO DE CAMPOS
DATA(LV_WHERE) = IO_TECH_REQUEST_CONTEXT-
>GET_OSQL_WHERE_CLAUSE_CONVERT( ).

IF LV_ENTITYSET = 'ClienteSet'.

"IMPLEMENTAÇÃO DA NAVEGAÇÃO
IO_TECH_REQUEST_CONTEXT->GET_CONVERTED_SOURCE_KEYS(
IMPORTING
ES_KEY_VALUES = LS_CLIENTE
).

SELECT (LT_SELECT) FROM ZTAB_VENDAS_CAB


INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET
WHERE CLIENTE_ID EQ LS_CLIENTE-ID
ORDER BY ID.

ELSE.
"IMPLEMENTAÇÃO TRADICIONAL

SELECT (LT_SELECT)
FROM ZTAB_VENDAS_CAB
INTO CORRESPONDING FIELDS OF TABLE ET_ENTITYSET
WHERE (LV_WHERE)

ORDER BY ID .

ENDIF.

#MIGRESUACARREIRA
47
Caso existam múltiplas navegações para a mesma associação, verificar a
propriedade de navegação no parâmetro de entrada
IT_NAVIGATION_PATH.
Exemplo: a associação Vendas-Cliente pode ter as navegações ‘emissor”,
“recebedor”, “pagador”, onde cada navegação vai trazer um tipo de cliente
diferente, mas são todos da entidade cliente.

Após implementar as mudanças vemos que o funcionamento é o esperado:


http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet('000000000
1')/vendas/$count

http://lnl-
s4h.opustech.com.br:8000/sap/opu/odata/sap/ZLOJA_SRV/ClienteSet('000000000
1')/vendas

#MIGRESUACARREIRA
48
ASSOCIAÇÕES E
NAVEGAÇÃO
NO SAPUI5

#MIGRESUACARREIRA
49
Consumindo as Relações no UI5 (Cliente/vendas)

Na view Object, adicionamos a lista de todas as Vendas do Cliente exibido. O


importante aqui é informar a propriedade de navegação da SEGW na propriedade
items do List
...
</f:Form>

<List
growing="true"
growingScrollToLoad="true"
growingThreshold="20"
id="vendasListCliente"
headerText="{i18n>vendaListCliente}"
class="sapUiResponsiveMargin"
width="auto"
items="{
path : 'vendas',
sorter: {
path: 'DataCriacao',
descending: true
}
}">
<items>
<ObjectListItem
title="{Descricao}"
number="{ValorLiquido}"
numberState="{= ${ValorLiquido} > 500 ? 'Error' : 'Success' }"
>

<attributes>
<ObjectAttribute text="{IDVenda}" />
<ObjectAttribute
text="{
path: 'DataCriacao',
type: 'sap.ui.model.type.Date',
formatOptions:
{
style: 'short',
UTC: true
}
}"
/>
</attributes>
</ObjectListItem>
</items>
</List>
</VBox>

#MIGRESUACARREIRA
50
DEPLOY DO APP
NO SERVIDOR

#MIGRESUACARREIRA
51
Deploy da aplicação no servidor – Report ABAP

Para fazer deploy usando o SAP GUI, existe na transação SE38 o report
/UI5/UI5_REPOSITORY_LOAD

• Transação se38
• Programa /UI5/UI5_REPOSITORY_LOAD
• Parâmetros seleção:
• Informar o nome da aplicação a criar/atualizar.
• Selecionar <Carregar>
• Ajustar fins de linha
• <F8>

Com este report você também pode baixar o código fonte de um


aplicativo no servidor, e eliminar aplicativos

#MIGRESUACARREIRA
52
• Indicar o caminho completo até pasta webapp, contendo os arquivos do app

#MIGRESUACARREIRA
53
• Rolar a tela até o final
• clicar em <Clicar aqui para upload>

• Informar uma descrição


• Informar Pacote
• Informar em Code page Externo: UTF-8

• Informar Request e avançar

#MIGRESUACARREIRA
54
Se tudo correr bem, o upload será encerrado.

O id da aplicação deve ser único no servidor, caso esteja duplicado,


será acusado duplicidade

#MIGRESUACARREIRA
55
• Indexar a App utilizando o seguinte programa na SE38:
/UI5/APP_INDEX_CALCULATE

Clique em Executar

#MIGRESUACARREIRA
56
#MIGRESUACARREIRA
57

Você também pode gostar