ABAP Cloud in S/4HANA Public Cloud: Entwicklung & Extensibility

kategorie
ABAP Cloud
Veröffentlicht
autor
Johannes

ABAP Cloud in S/4HANA Public Cloud ermöglicht Unternehmen, das SAP-Standardsystem um eigene Geschäftslogik zu erweitern - ohne den Clean Core zu gefährden. Dieser Artikel erklärt die Besonderheiten, verfügbaren APIs und praktischen Einsatzszenarien.

S/4HANA Public Cloud vs. BTP ABAP Environment

SAP bietet zwei Umgebungen für ABAP Cloud-Entwicklung:

AspektS/4HANA Public CloudBTP ABAP Environment
BezeichnungEmbedded SteampunkSteampunk
ZweckStandard erweiternNeue Apps entwickeln
DatenhaltungIm S/4HANA-SystemEigene Datenbank
APIsS/4HANA Released APIsBTP Released APIs
ExtensibilityOn-StackSide-by-Side
DeploymentTeil von S/4HANAEigene BTP-Instanz
UpdatesQuartalsweise durch SAPSelbst gesteuert
LizenzierungS/4HANA Cloud LizenzSeparate BTP-Lizenz

Wann S/4HANA Public Cloud wählen?

S/4HANA Public Cloud Extensibility ist ideal für:

  • Erweiterungen des Standards ohne separate Infrastruktur
  • Zugriff auf S/4HANA-Daten ohne Integration
  • Schnelle Time-to-Value durch direkten Zugang zu Geschäftsdaten
  • Konsistente User Experience innerhalb einer Systemlandschaft

Wann BTP ABAP Environment?

BTP ABAP Environment passt besser für:

  • Komplett neue Anwendungen ohne S/4HANA-Abhängigkeit
  • Side-by-Side-Extensions mit eigener Datenbank
  • Multi-Cloud-Szenarien (AWS, Azure, GCP)
  • Unabhängige Release-Zyklen vom S/4HANA-Kernsystem

Architektur in S/4HANA Public Cloud

3-System-Landschaft

S/4HANA Public Cloud nutzt eine feste 3-System-Landschaft:

┌─────────────────────────────────────────────────────────┐
│ SAP-verwaltete Landschaft │
├─────────────────┬─────────────────┬─────────────────────┤
│ Development │ Test │ Production │
│ (DEV) │ (TST/QAS) │ (PRD) │
├─────────────────┼─────────────────┼─────────────────────┤
│ Entwicklung │ Integrations- │ Produktiver │
│ & Unit Tests │ tests │ Betrieb │
├─────────────────┼─────────────────┼─────────────────────┤
│ ABAP Cloud │ Transportierte │ Transportierte │
│ Entwickler │ Objekte testen │ Objekte aktiv │
└─────────────────┴─────────────────┴─────────────────────┘
│ │ │
└───── Transport ─────► Transport ──┘
(automatisiert über SAP-Prozesse)

Transportwesen

Der Transport in S/4HANA Public Cloud unterscheidet sich vom On-Premise-Modell:

AspektS/4HANA Public CloudOn-Premise
TransportsteuerungSAP-verwaltetEigenverantwortlich
TransportrouteDEV → TST → PRD (fest)Frei konfigurierbar
Release-ZyklusMit SAP-UpdatesIndividuell
KonfliktprüfungAutomatisiertManuell
ZurücksetzenEingeschränktFlexibel

Software Component Konzept

Entwicklungsobjekte werden in Software Components organisiert:

" Software Component Struktur
" /NAMESPACE/COMPONENT_NAME
" Beispiel-Struktur:
" ZEXT_SALES
" ├── ZEXT_SALES_CDS " CDS Views
" ├── ZEXT_SALES_BP " Behavior Pools
" ├── ZEXT_SALES_IF " Interfaces
" └── ZEXT_SALES_CL " Klassen

Software Components werden über Adaptation Transport Organizer (ATO) verwaltet:

  1. Clone Repository: Software Component aus Git klonen
  2. Pull: Änderungen vom Remote-Repository holen
  3. Checkout: Branch für Entwicklung auschecken
  4. Release: Änderungen freigeben und transportieren

Verfügbare APIs und Einschränkungen

Released APIs in S/4HANA Public Cloud

S/4HANA Public Cloud stellt eine kuratierte Menge an APIs bereit:

" Prüfen, ob eine API released ist:
" In ADT: Rechtsklick → Properties → API State
" Released APIs haben:
" - Stability Contract: Released
" - Visibility: Public
" - Cloud-Kompatibilität: Ja

Kategorien von Released APIs

KategorieBeispieleVerwendung
RAP BOsI_BusinessPartner, I_SalesOrderGeschäftsobjekte lesen/ändern
CDS ViewsI_Product, I_CostCenterDaten abfragen
BAPI-WrapperCL_BAPI_* KlassenLegacy-Funktionen nutzen
XCO LibraryXCO_CP_*, XCO_CDSMetadaten & Generierung
ABAP Cloud APIsCL_ABAP_, CL_HTTP_Basis-Funktionen

Wichtige Einschränkungen

" ❌ Nicht erlaubt in S/4HANA Public Cloud:
" Direkte Tabellenzugriffe auf SAP-Tabellen
SELECT * FROM mara INTO TABLE @lt_mara. " Verboten!
" Nicht freigegebene Funktionsbausteine
CALL FUNCTION 'BAPI_MATERIAL_GET_DETAIL'. " Verboten!
" Klassische ALV-Reports
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'. " Verboten!
" SAP GUI-Transaktionen
CALL TRANSACTION 'MM03'. " Verboten!
" ✅ Stattdessen Released APIs nutzen:
" CDS Views für Datenabfrage
SELECT * FROM I_Product
WHERE Product = @lv_product
INTO TABLE @DATA(lt_products).
" RAP für Geschäftslogik
DATA(lo_product) = cl_product_api=>create_instance( ).
lo_product->get_details( EXPORTING iv_product = lv_product
IMPORTING es_details = ls_details ).
" OData Services für Integration
" → Fiori Elements Apps nutzen

API-Verfügbarkeit prüfen

CLASS zcl_api_checker DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS zcl_api_checker IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
" XCO nutzen, um API-Status zu prüfen
DATA(lo_class) = xco_cp_abap_repository=>object->clas->for( 'CL_ABAP_RANDOM' ).
IF lo_class->exists( ).
DATA(lv_api_state) = lo_class->content(
)->get_api_state(
)->get_release_state( ).
out->write( |API State: { lv_api_state }| ).
ENDIF.
" CDS View prüfen
DATA(lo_view) = xco_cp_cds=>view( 'I_PRODUCT' ).
IF lo_view->exists( ).
out->write( 'I_PRODUCT ist verfügbar' ).
ENDIF.
ENDMETHOD.
ENDCLASS.

Developer Extensibility in Public Cloud

Extensibility-Optionen

S/4HANA Public Cloud bietet mehrere Extensibility-Ebenen:

┌─────────────────────────────────────────────────┐
│ Extensibility-Pyramide │
├─────────────────────────────────────────────────┤
│ ▲ Custom Applications (RAP Business Objects) │
│ │ ───────────────────────────────────────── │
│ │ Behavior Extensions (RAP Erweiterungen) │
│ │ ───────────────────────────────────────── │
│ │ CDS View Extensions (Felderweiterungen) │
│ │ ───────────────────────────────────────── │
│ │ BAdI Implementations (Geschäftslogik) │
│ │ ───────────────────────────────────────── │
│ ▼ Key User Extensibility (No-Code) │
└─────────────────────────────────────────────────┘
Komplexität ▲ ▼ Einfachheit

BAdI-Implementierungen

Released BAdIs ermöglichen Erweiterungen der Standardlogik:

CLASS zcl_badi_salesorder DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
" BAdI für Sales Order Erweiterung
INTERFACES if_sd_sales_order_create.
ENDCLASS.
CLASS zcl_badi_salesorder IMPLEMENTATION.
METHOD if_sd_sales_order_create~validate.
" Eigene Validierung bei Auftragsanlage
LOOP AT it_sales_order_item ASSIGNING FIELD-SYMBOL(<ls_item>).
" Prüfe Mindestbestellmenge für bestimmte Kunden
IF <ls_item>-sold_to_party IN lr_vip_customers
AND <ls_item>-order_quantity < 100.
APPEND VALUE #(
item_number = <ls_item>-item_number
message = 'VIP-Kunden: Mindestbestellmenge 100 Stück'
severity = 'E'
) TO ct_messages.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

RAP Behavior Extensions

Standard-RAP-Business-Objects können erweitert werden:

" Behavior Extension für I_SalesOrderTP
" (wenn von SAP für Erweiterung freigegeben)
extension using interface /sap/bc/i_salesordertp_ext
implementation in class zbp_ext_salesorder unique;
extend behavior for SalesOrder
{
" Zusätzliche Validierung
validation validateCustomPriority on save
{ field CustomerPriority; }
" Zusätzliche Determination
determination setDefaultPriority on modify
{ field SoldToParty; }
" Zusätzliche Action
action ( features : instance ) escalatePriority result [1] $self;
}
CLASS zbp_ext_salesorder DEFINITION
PUBLIC ABSTRACT FINAL
FOR BEHAVIOR OF i_salesordertp_ext.
ENDCLASS.
CLASS zbp_ext_salesorder IMPLEMENTATION.
METHOD validateCustomPriority.
" Eigene Validierungslogik
READ ENTITIES OF i_salesordertp_ext IN LOCAL MODE
ENTITY SalesOrder
FIELDS ( CustomerPriority SoldToParty )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_orders).
LOOP AT lt_orders ASSIGNING FIELD-SYMBOL(<ls_order>).
IF <ls_order>-CustomerPriority IS INITIAL.
APPEND VALUE #(
%tky = <ls_order>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Kundenpriorität muss gepflegt werden'
)
) TO reported-salesorder.
APPEND VALUE #( %tky = <ls_order>-%tky ) TO failed-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD setDefaultPriority.
" Standardpriorität basierend auf Kunde setzen
READ ENTITIES OF i_salesordertp_ext IN LOCAL MODE
ENTITY SalesOrder
FIELDS ( SoldToParty CustomerPriority )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_orders).
LOOP AT lt_orders ASSIGNING FIELD-SYMBOL(<ls_order>)
WHERE CustomerPriority IS INITIAL.
" Prüfe Kundenkategorie
SELECT SINGLE CustomerClassification
FROM I_Customer
WHERE Customer = @<ls_order>-SoldToParty
INTO @DATA(lv_classification).
DATA(lv_priority) = SWITCH #( lv_classification
WHEN 'A' THEN 'HIGH'
WHEN 'B' THEN 'MEDIUM'
ELSE 'LOW'
).
MODIFY ENTITIES OF i_salesordertp_ext IN LOCAL MODE
ENTITY SalesOrder
UPDATE FIELDS ( CustomerPriority )
WITH VALUE #( (
%tky = <ls_order>-%tky
CustomerPriority = lv_priority
) ).
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Custom RAP Business Objects

In S/4HANA Public Cloud können eigene RAP Business Objects erstellt werden:

Beispiel: Kundenanfragen-Management

Schritt 1: Datenbanktabelle definieren

@EndUserText.label : 'Customer Inquiries'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
define table zinquiry {
key client : abap.clnt not null;
key inquiry_id : sysuuid_x16 not null;
customer : kunnr;
inquiry_type : abap.char(4);
subject : abap.char(100);
description : abap.string(0);
priority : abap.char(1);
status : abap.char(2);
created_by : abap.uname;
created_at : timestampl;
changed_by : abap.uname;
changed_at : timestampl;
}

Schritt 2: CDS View mit Annotationen

@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: 'Customer Inquiry'
define root view entity ZI_Inquiry
as select from zinquiry
association [0..1] to I_Customer as _Customer
on $projection.Customer = _Customer.Customer
{
key inquiry_id as InquiryId,
customer as Customer,
inquiry_type as InquiryType,
subject as Subject,
description as Description,
priority as Priority,
status as Status,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.lastChangedBy: true
changed_by as ChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
changed_at as ChangedAt,
_Customer
}

Schritt 3: Behavior Definition

managed implementation in class zbp_i_inquiry unique;
strict ( 2 );
with draft;
define behavior for ZI_Inquiry alias Inquiry
persistent table zinquiry
draft table zinquiry_d
lock master total etag ChangedAt
authorization master ( instance )
etag master ChangedAt
{
create;
update;
delete;
field ( readonly ) InquiryId, CreatedBy, CreatedAt, ChangedBy, ChangedAt;
field ( mandatory ) Customer, InquiryType, Subject;
determination setInquiryId on save { create; }
determination setDefaultStatus on modify { create; }
validation validateCustomer on save { field Customer; }
validation validatePriority on save { field Priority; }
action ( features : instance ) escalate result [1] $self;
action ( features : instance ) close result [1] $self;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft action Resume;
draft determine action Prepare;
mapping for zinquiry corresponding
{
InquiryId = inquiry_id;
Customer = customer;
InquiryType = inquiry_type;
Subject = subject;
Description = description;
Priority = priority;
Status = status;
CreatedBy = created_by;
CreatedAt = created_at;
ChangedBy = changed_by;
ChangedAt = changed_at;
}
}

Schritt 4: Behavior Implementation

CLASS zbp_i_inquiry DEFINITION
PUBLIC ABSTRACT FINAL
FOR BEHAVIOR OF zi_inquiry.
PRIVATE SECTION.
CONSTANTS:
BEGIN OF gc_status,
open TYPE c LENGTH 2 VALUE '01',
in_process TYPE c LENGTH 2 VALUE '02',
escalated TYPE c LENGTH 2 VALUE '03',
closed TYPE c LENGTH 2 VALUE '04',
END OF gc_status.
ENDCLASS.
CLASS zbp_i_inquiry IMPLEMENTATION.
METHOD setInquiryId.
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
FIELDS ( InquiryId )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
DATA lt_inquiries_update TYPE TABLE FOR UPDATE zi_inquiry.
LOOP AT lt_inquiries ASSIGNING FIELD-SYMBOL(<ls_inquiry>)
WHERE InquiryId IS INITIAL.
TRY.
DATA(lv_uuid) = cl_system_uuid=>create_uuid_x16_static( ).
CATCH cx_uuid_error.
CONTINUE.
ENDTRY.
APPEND VALUE #(
%tky = <ls_inquiry>-%tky
InquiryId = lv_uuid
%control-InquiryId = if_abap_behv=>mk-on
) TO lt_inquiries_update.
ENDLOOP.
MODIFY ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
UPDATE FIELDS ( InquiryId )
WITH lt_inquiries_update.
ENDMETHOD.
METHOD setDefaultStatus.
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
FIELDS ( Status )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
DATA lt_inquiries_update TYPE TABLE FOR UPDATE zi_inquiry.
LOOP AT lt_inquiries ASSIGNING FIELD-SYMBOL(<ls_inquiry>)
WHERE Status IS INITIAL.
APPEND VALUE #(
%tky = <ls_inquiry>-%tky
Status = gc_status-open
%control-Status = if_abap_behv=>mk-on
) TO lt_inquiries_update.
ENDLOOP.
MODIFY ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
UPDATE FIELDS ( Status )
WITH lt_inquiries_update.
ENDMETHOD.
METHOD validateCustomer.
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
FIELDS ( Customer )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
" Sammle alle Kunden für Massenprüfung
DATA lt_customers TYPE SORTED TABLE OF kunnr WITH UNIQUE KEY table_line.
LOOP AT lt_inquiries ASSIGNING FIELD-SYMBOL(<ls_inquiry>).
INSERT <ls_inquiry>-Customer INTO TABLE lt_customers.
ENDLOOP.
" Prüfe Existenz über Released CDS View
SELECT Customer
FROM I_Customer
WHERE Customer IN @lt_customers
INTO TABLE @DATA(lt_valid_customers).
" Validiere
LOOP AT lt_inquiries ASSIGNING <ls_inquiry>.
IF NOT line_exists( lt_valid_customers[ Customer = <ls_inquiry>-Customer ] ).
APPEND VALUE #(
%tky = <ls_inquiry>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = |Kunde { <ls_inquiry>-Customer } existiert nicht|
)
) TO reported-inquiry.
APPEND VALUE #( %tky = <ls_inquiry>-%tky ) TO failed-inquiry.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD validatePriority.
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
FIELDS ( Priority )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
LOOP AT lt_inquiries ASSIGNING FIELD-SYMBOL(<ls_inquiry>).
IF <ls_inquiry>-Priority NOT IN VALUE #( ( 'H' ) ( 'M' ) ( 'L' ) ).
APPEND VALUE #(
%tky = <ls_inquiry>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Priorität muss H (Hoch), M (Mittel) oder L (Niedrig) sein'
)
) TO reported-inquiry.
APPEND VALUE #( %tky = <ls_inquiry>-%tky ) TO failed-inquiry.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD escalate.
" Status auf Eskaliert setzen
MODIFY ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
UPDATE FIELDS ( Status Priority )
WITH VALUE #( FOR key IN keys (
%tky = key-%tky
Status = gc_status-escalated
Priority = 'H' " Automatisch hohe Priorität
%control-Status = if_abap_behv=>mk-on
%control-Priority = if_abap_behv=>mk-on
) ).
" Ergebnis zurückgeben
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
result = VALUE #( FOR inquiry IN lt_inquiries (
%tky = inquiry-%tky
%param = inquiry
) ).
ENDMETHOD.
METHOD close.
MODIFY ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
UPDATE FIELDS ( Status )
WITH VALUE #( FOR key IN keys (
%tky = key-%tky
Status = gc_status-closed
%control-Status = if_abap_behv=>mk-on
) ).
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
result = VALUE #( FOR inquiry IN lt_inquiries (
%tky = inquiry-%tky
%param = inquiry
) ).
ENDMETHOD.
METHOD get_instance_features.
READ ENTITIES OF zi_inquiry IN LOCAL MODE
ENTITY Inquiry
FIELDS ( Status )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_inquiries).
result = VALUE #( FOR inquiry IN lt_inquiries (
%tky = inquiry-%tky
" Escalate nur möglich wenn nicht schon eskaliert oder geschlossen
%action-escalate = COND #(
WHEN inquiry-Status = gc_status-escalated OR inquiry-Status = gc_status-closed
THEN if_abap_behv=>fc-o-disabled
ELSE if_abap_behv=>fc-o-enabled
)
" Close nur möglich wenn nicht schon geschlossen
%action-close = COND #(
WHEN inquiry-Status = gc_status-closed
THEN if_abap_behv=>fc-o-disabled
ELSE if_abap_behv=>fc-o-enabled
)
) ).
ENDMETHOD.
ENDCLASS.

Praktisches Beispiel: Integration mit Standard

Ein häufiges Szenario ist die Integration eigener Objekte mit S/4HANA-Standard:

Kundenanfragen mit Kundenstamm verknüpfen

CLASS zcl_inquiry_customer_integration DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ty_customer_inquiries,
customer_id TYPE kunnr,
customer_name TYPE bu_name1st,
open_inquiries TYPE i,
avg_resolution TYPE i,
END OF ty_customer_inquiries.
METHODS get_customer_inquiry_stats
RETURNING VALUE(rt_stats) TYPE STANDARD TABLE OF ty_customer_inquiries.
ENDCLASS.
CLASS zcl_inquiry_customer_integration IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(lt_stats) = get_customer_inquiry_stats( ).
out->write( 'Kundenanfragen-Statistik:' ).
out->write( '─────────────────────────────────────────────' ).
LOOP AT lt_stats ASSIGNING FIELD-SYMBOL(<ls_stat>).
out->write( |Kunde: { <ls_stat>-customer_name }| ).
out->write( | Offene Anfragen: { <ls_stat>-open_inquiries }| ).
out->write( | Ø Bearbeitungszeit: { <ls_stat>-avg_resolution } Tage| ).
out->write( '' ).
ENDLOOP.
ENDMETHOD.
METHOD get_customer_inquiry_stats.
" Kombiniere eigene Tabelle mit S/4HANA Kundenstamm
SELECT
i~customer AS customer_id,
c~CustomerName AS customer_name,
COUNT( CASE WHEN i~status <> '04' THEN 1 END ) AS open_inquiries,
AVG( DATS_DAYS_BETWEEN(
i~created_at,
CASE WHEN i~status = '04' THEN i~changed_at ELSE @sy-datum END
) ) AS avg_resolution
FROM zinquiry AS i
INNER JOIN I_Customer AS c ON i~customer = c~Customer
GROUP BY i~customer, c~CustomerName
INTO TABLE @rt_stats.
ENDMETHOD.
ENDCLASS.

OData Service für Fiori App

" Service Definition
@EndUserText.label: 'Inquiry Service'
define service ZUI_INQUIRY_O4 {
expose ZC_Inquiry as Inquiry;
}
" Consumption View mit UI-Annotationen
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@UI.headerInfo: {
typeName: 'Kundenanfrage',
typeNamePlural: 'Kundenanfragen',
title: { value: 'Subject' },
description: { value: 'Customer' }
}
define view entity ZC_Inquiry
as projection on ZI_Inquiry
{
@UI.facet: [{
id: 'GeneralInfo',
type: #IDENTIFICATION_REFERENCE,
label: 'Allgemeine Informationen',
position: 10
}]
@UI.lineItem: [{ position: 10 }]
@UI.identification: [{ position: 10 }]
key InquiryId,
@UI.lineItem: [{ position: 20 }]
@UI.identification: [{ position: 20 }]
@UI.selectionField: [{ position: 10 }]
@Consumption.valueHelpDefinition: [{ entity: { name: 'I_Customer', element: 'Customer' } }]
Customer,
@UI.lineItem: [{ position: 30 }]
@UI.identification: [{ position: 30 }]
@UI.selectionField: [{ position: 20 }]
InquiryType,
@UI.lineItem: [{ position: 40 }]
@UI.identification: [{ position: 40 }]
Subject,
@UI.identification: [{ position: 50 }]
Description,
@UI.lineItem: [{ position: 50, criticality: 'PriorityCriticality' }]
@UI.identification: [{ position: 60 }]
@UI.selectionField: [{ position: 30 }]
Priority,
@UI.lineItem: [{ position: 60, criticality: 'StatusCriticality' }]
@UI.identification: [{ position: 70 }]
@UI.selectionField: [{ position: 40 }]
Status,
@UI.lineItem: [{ position: 70 }]
CreatedAt,
CreatedBy,
ChangedAt,
ChangedBy,
" Criticality für Semantic Coloring
case Priority
when 'H' then 1 " Rot
when 'M' then 2 " Gelb
else 3 " Grün
end as PriorityCriticality,
case Status
when '03' then 1 " Eskaliert = Rot
when '01' then 2 " Offen = Gelb
when '02' then 2 " In Bearbeitung = Gelb
else 3 " Geschlossen = Grün
end as StatusCriticality,
_Customer
}

Best Practices für S/4HANA Public Cloud

DO: Empfohlene Praktiken

✅ Nur Released APIs verwenden
✅ Software Components für Modularität nutzen
✅ Unit Tests schreiben (ABAP Unit)
✅ Clean ABAP Guidelines befolgen
✅ Dokumentation in ABAP Doc pflegen
✅ Feature Control für Actions nutzen
✅ Authorization Checks implementieren

DON’T: Zu vermeidende Praktiken

❌ Direkte Zugriffe auf SAP-Tabellen
❌ Nicht freigegebene APIs verwenden
❌ Hardcoded System-IDs oder Mandanten
❌ Synchrone HTTP-Aufrufe in Transaktionen
❌ Lange laufende Prozesse ohne Background Processing
❌ Komplexe Logik ohne Modularisierung

Checkliste vor dem Transport

PrüfpunktErledigt
ATC-Prüfung bestanden (ABAP Cloud Variante)
Unit Tests vorhanden und erfolgreich
Authorization Checks implementiert
Keine nicht-freigegebenen APIs
Dokumentation aktuell
Performance-Tests durchgeführt

Weiterführende Themen