This is a test message to test the length of the message box.
Login
ABAP RAP Komplexe Entität
Erstellt von Software-Heroes

RAP - Komplexe Entität

212

Schauen wir uns einmal eine RAP Anwendung mit zwei Entitäten an und wie diese miteinander verbunden sind. Dabei gehen wir vor allem auf die Unterschiede ein.

Werbung


Bereits vor einer Weile haben wir uns eine einfache Entität angeschaut und wie wir diese komplett auf RAP aufbauen. In diesem Artikel schauen wir uns einmal an, was die Unterschiede sind, wenn wir mehr als eine Entität in eine Anwendung einbauen. Wenn du mehr zum Aufbau von einfachen Entitäten wissen willst, dann beginne am besten am Anfang der Serie.

 

Einleitung

Wir hatten uns bereits intensiv angeschaut, wie wir eine RAP Anwendung anhand einer Entität aufbauen und was wir alles benötigen. In dieser kleinen Serie werden wir uns den Aufbau von komplexen Anwendungen anschauen, in dem wir Rechnungen und Positionen in einer Anwendung zusammenführen. Dabei werden wir wieder mit dem Datenmodell auf unserer CDS-Reihe arbeiten.

 

Datenmodell

Wir möchten die beiden Entitäten Rechnung und Position zusammen in eine App bringen und bearbeitbar machen, dazu sieht das Datenmodell wie folgt aus:

 

Die Entität für Material benötigen wir, da die Mengeneinheit benötigt wird und diese nur am Material verfügbar ist. Wie immer erzeugen wir dazu eine Interface Schicht und setzen für die Applikation den Consumption Layer oben drauf.

 

CDS

Die erste Anpassung gibt es bereits auf der Ebene der Datenmodellierung. Zwischen den Entitäten benötigen wir Verknüpfungen, da wir später von den Rechnungen auf die Positionen navigieren wollen und weil diese beiden Objekte zusammengehören. Schauen wir uns dazu die beiden Schichten einmal genauer an.

 

Interface

Auf der Ebene der Interfaces verbinden wir die Rechnungen mit den Positionen. Dazu legen wir vom Root Knoten eine "Composition" Richtung Position an, der View sieht damit wie folgt aus:

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface for ZBS_DMO_INVOICE'
define root view entity ZBS_R_RAPCInvoice
  as select from zbs_dmo_invoice
  composition [0..*] of ZBS_I_RAPCPosition as _Position
{
  key document as Document,
      doc_date as DocDate,
      doc_time as DocTime,
      partner  as Partner,
      _Position
}

 

Auf Positionsebene müssen wir nun eine "Association To Parent" anlegen, damit machen wir deutlich, dass hier eine Beziehung nach oben existiert. Die zweite Assoziation ist für die Einheit, die wir für die Daten benötigen.

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface for ZBS_DMO_POSITION'
define view entity ZBS_I_RAPCPosition
  as select from zbs_dmo_position
  association     to parent ZBS_R_RAPCInvoice as _Invoice  on $projection.Document = _Invoice.Document
  association [1] to ZBS_I_RAPCMaterial       as _Material on $projection.Material = _Material.Material
{
  key document            as Document,
  key pos_number          as PositionNumber,
      material            as Material,
      @Semantics.quantity.unitOfMeasure : 'Unit'
      quantity            as Quantity,
      _Material.StockUnit as Unit,
      price               as Price,
      currency            as Currency,
      _Invoice

}

 

Consumption

Auf der Consumption Ebene sieht es so ähnlich aus, hier werden aber die Beziehungen anders definiert. Dazu fügen wir hinter der Assoziation einen "Redirect to Composition Child" in der Wurzel-Entität ein.

@EndUserText.label: 'Consumption for ZBS_R_RAPCINVOICE'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
define root view entity ZBS_C_RAPCInvoice
  provider contract transactional_query
  as projection on ZBS_R_RAPCInvoice as Invoice
{
  key Document,
      DocDate,
      DocTime,
      Partner,
      _Position : redirected to composition child ZBS_C_RAPCPosition
}

 

Bei den Positionen benötigen wir einen "Redirect To Parent", also zur Rechnung. Die Beziehungen dienen im späteren Service für die Navigation zwischen den Entitäten.

@EndUserText.label: 'Consumption for ZBS_I_RAPCPOSITION'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
define view entity ZBS_C_RAPCPosition
  as projection on ZBS_I_RAPCPosition as Position
{
  key Document,
  key PositionNumber,
      Material,
      Quantity,
      Unit,
      Price,
      Currency,
      _Invoice : redirected to parent ZBS_C_RAPCInvoice
}

 

Verhaltensdefinition

Wie sieht es nun mit der Verwaltung der Verhaltensimplementierung aus? Hier benötigst du zwei Definitionen, für jede Entität eine. Besonderheiten die man hier beachten sollte wären:

  • Anlage der Position geschieht über die Assoziation der Rechnung und nicht direkt über die Position.
  • Assoziationen werden in den Entitäten bekannt gegeben.
  • Sperren und berechtigen auf die Daten der Position, geschieht über die Rechnung.
  • Die Verhaltensimplementierung kann pro Entität implementiert werden oder über eine Klasse im Kopf der Verhaltensdefinition.

 

Die Verhaltensdefinition sieht damit wie folgt aus:

managed implementation in class zbp_bs_rapcinvoice unique;
strict ( 1 );

define behavior for ZBS_R_RAPCInvoice alias Invoice
persistent table zbs_dmo_invoice
lock master
authorization master ( instance )
{
  create;
  update;
  delete;

  field ( readonly:update ) Document;

  association _Position { create; }
  mapping for zbs_dmo_invoice
    {
      Document = document;
      Partner  = partner;
      DocDate  = doc_date;
      DocTime  = doc_time;
    }
 }

define behavior for ZBS_I_RAPCPosition alias Position
persistent table zbs_dmo_position
lock dependent by _Invoice
authorization dependent by _Invoice
{
  update;
  delete;

  field ( readonly ) Document;
  field ( readonly:update ) PositionNumber;

  association _Invoice;
  mapping for zbs_dmo_position
    {
      Document       = document;
      PositionNumber = pos_number;
      Material       = material;
      Price          = price;
      Quantity       = quantity;
      Currency       = currency;
    }
 }

 

Das Handling der Assoziationen siehst du aber am Besten in der Projektion der Verhaltensdefinition:

projection;
strict ( 1 );

define behavior for ZBS_C_RAPCInvoice alias Invoice
{
  use create;
  use update;
  use delete;

  use association _Position { create; }
}

define behavior for ZBS_C_RAPCPosition alias Position
{
  use update;
  use delete;

  use association _Invoice;
}

 

Service

Die Service Definition und die Service Bindung kann dann wie gewohnt angelegt werden, es sollten beide Entitäten mitgegeben werden, damit der Zugriff dafür verfügbar ist. Nach der Anlage der Bindung sollten die beiden Entitäten sichtbar sein, sowie die Verbindungen untereinander.

 

App

Die Anwendung an sich besitzt erst einmal keine Design, Felder oder Einschränkungsmöglichkeiten. Über den Fiori Elements Preview kannst du aber wie bisher, ein Grundlayout definieren, zumindest um einmal testen zu können. Eine Navigation auf die Positionen ist damit aktuell nicht möglich, dazu müssen wir erst die UI Annotationen anlegen.

 

GitHub

Die Änderungen haben wir wie immer im GitHub Repository zur Verfügung gestellt. Der Commit mit den Anpassungen hat neue Objekte im Paket ZBS_DEMO_RAP_COMPLEXE angelegt, wenn du nicht alles durchsuchen möchtest.

 

Fazit

Der Aufbau der Anwendung ist so ähnlich wie bei unserer einfachen Anwendung, allerdings sind ein paar Dinge zu beachten, zum Beispiel, dass die einzelnen Entitäten untereinander verknüpft sind. Alle Änderungen findest du wieder wie gewohnt im GitHub Repository.


Enthaltene Themen:
RAPBTPKomplexe Entität
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


RAP - Übersetzungs-App (Beispiel)

Kategorie - ABAP

Schauen wir uns einmal ein praktisches Beispiel für die Entwicklung einer RAP Anwendung im ABAP Environment an und wie du mit wenig Aufwand eine App erstellst.

02.08.2024

RAP - Custom Entity Wertehilfe (Deep Dive)

Kategorie - ABAP

Mit der Custom Entity hast du in RAP die meisten Freiheiten in der Entwicklung von ABAP Cloud Anwendungen, doch wie sieht es mit potentiellen Fehlern aus?

12.07.2024

RAP - Deep Action in OData v4

Kategorie - ABAP

In diesem Artikel schauen wir uns einmal Aktionen mit tiefen Strukturen an, wie wir sie erzeugen und Daten an einen API Endpunkt übergeben können.

24.05.2024

BTP - Anbindung On-Premise (Consumption Model v2)

Kategorie - ABAP

In diesem Artikel wollen wir noch einmal einen Update zur Anbindung von On-Premise Systemen geben und wie dies mit einem Communication Arrangement durchgeführt wird.

15.12.2023

RAP - App Count anzeigen (Kachel)

Kategorie - ABAP

In diesem Beispiel geht es um die Anzeige eines Zählers auf der Kachel einer Fiori Elements Anwendung und wie sich so etwas umsetzen lässt.

06.10.2023