ABAP Cloud - Migration (Beispiel)
In diesem Artikel schauen wir uns einmal im Beispiel eine Migration eines Reports von TIER-3 nach ABAP Cloud an.
Inhaltsverzeichnis
In den letzten Artikeln hatten wir uns vor allem die Theorie von ABAP Cloud angeschaut, wie das 3-TIER Modell aufgebaut ist und Software Komponenten zur Struktur beitragen. In diesem Artikel soll es einmal um die Praxis gehen.
Einleitung
Im heutigen Beispiel verwenden wir einen einfachen Report, den wir Richtung ABAP Cloud migrieren wollen. Reports kann man in zwei Richtungen migrieren, da sie im klassischen ABAP zwei Aufgaben übernehmen:
- Online-Ausführung mit Ergebnis
- Batch-Ausführung zur Hintergrundverarbeitung
Für das gezeigte Beispiel und die Testdaten verwenden wir eine Cloud Appliance Library von SAP in der Version S/4 HANA 2022. Möchtest du unser Beispiel nachstellen, findest du dort die entsprechenden Testdaten.
Use Case
Daher müssen wir zuvor festlegen, was eigentlich der Einsatzzweck ist. In unserem Beispiel verwenden wir den Report für die Hintergrundverarbeitung und planen diesen normalerweise als Job in der Nacht ein. Der Report sieht wie folgt aus, es ist dabei nur eine rudimentäre Implementierung und Ausgabe vorhanden:
REPORT zfi_book_finance_document.
START-OF-SELECTION.
DATA(go_document) = NEW zcl_book_fi_document_app( ).
DATA(gs_document) = go_document->book( ).
IF gs_document IS INITIAL.
cl_demo_output=>display( go_document->mo_log->get_messages_flat( ) ).
ELSE.
cl_demo_output=>display( go_document->get_document( gs_document ) ).
ENDIF.
Dabei ruft dieser für die Verarbeitung eine globale Klasse auf, die unsere eigentliche Logik enthält. Es gibt eine Methode zum Erzeugen der FI Belege und eine Methode, die den Beleg anhand der Daten liest und die Informationen zurückgibt.
CLASS zcl_book_fi_document_app DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES: BEGIN OF ts_document,
belnr TYPE bkpf-belnr,
bukrs TYPE bkpf-bukrs,
gjahr TYPE bkpf-gjahr,
END OF ts_document.
TYPES ts_header TYPE bkpf.
DATA mo_log TYPE REF TO zif_application_log READ-ONLY.
METHODS constructor.
METHODS book
RETURNING VALUE(rs_result) TYPE ts_document.
METHODS get_document
IMPORTING is_document TYPE ts_document
RETURNING VALUE(rs_result) TYPE ts_header.
ENDCLASS.
CLASS zcl_book_fi_document_app IMPLEMENTATION.
METHOD constructor.
mo_log = zcl_application_log=>create( ).
ENDMETHOD.
METHOD book.
DATA ls_header TYPE bapiache09.
DATA lt_accountgl TYPE STANDARD TABLE OF bapiacgl09.
DATA lt_currencyamount TYPE STANDARD TABLE OF bapiaccr09.
DATA ld_key TYPE bapiache09-obj_key.
DATA lt_return TYPE zif_application_log=>tt_message.
ls_header = VALUE #( comp_code = '1710'
doc_type = 'SA'
doc_date = '20240101'
pstng_date = sy-datum
ref_doc_no_long = |Test: { sy-uname }|
username = sy-uname ).
lt_accountgl = VALUE #( ( itemno_acc = 1 gl_account = '0011002080' )
( itemno_acc = 2 gl_account = '0070200000' costcenter = '0017101101' ) ).
lt_currencyamount = VALUE #( currency = 'EUR'
( itemno_acc = 1 amt_doccur = '65.99' )
( itemno_acc = 2 amt_doccur = '-65.99' ) ).
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
EXPORTING
documentheader = ls_header
IMPORTING
obj_key = ld_key
TABLES
accountgl = lt_accountgl
currencyamount = lt_currencyamount
return = lt_return.
mo_log->add_msg_bapi( it_bapiret = lt_return ).
IF line_exists( lt_return[ type = 'E' ] ) OR line_exists( lt_return[ type = 'W' ] ).
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
rs_result = ld_key.
ENDIF.
ENDMETHOD.
METHOD get_document.
SELECT SINGLE FROM bkpf
FIELDS *
WHERE bukrs = @is_document-bukrs
AND belnr = @is_document-belnr
AND gjahr = @is_document-gjahr
INTO @rs_result.
ENDMETHOD.
ENDCLASS.
Dabei verwenden wir den Funktionsbaustein BAPI_ACC_DOCUMENT_POST zum Erzeugen der Belege und die Tabelle BKPF, zum Lesen der Informationen.
Grundstruktur
Im ersten Schritt bauen wir uns die Grundstruktur der drei TIERs auf, am Ende sollte die Struktur entsprechend unserer Skizze aussehen.
Aufbau TIER-1
Im ersten Schritt bauen wir die Grundstruktur auf, wie wir sie bereits im letzten Artikel beschrieben haben. Die Software Komponente hatten wir bereits angelegt, diese verwendet "ABAP for Cloud". Dazu legen wir nun das passende Strukturpaket mit dem gleichen Namen an.
Im zweiten Schritt ordnen wir die Software Komponente zu und den entsprechenden Transport Layer. Da wir hier auf dem CAL System unterwegs sind und nicht transportieren, lassen wir den Layer leer.
Das TIER-1 Paket sieht nun wie folgt aus, hierbei handelt es sich um ein Strukturpaket mit der Software Komponente ZFI_T1_BNK und der Sprachversion "ABAP for Cloud Development", die es aus den Einstellungen der Software Komponente erhält.
Zum Abschluss vom ersten TIER legen wir noch ein Entwicklungspaket an, wo wir später unsere Entwicklung abbilden werden.
Aufbau TIER-2
Im zweiten TIER legen wir der Einfachheit direkt ein Entwicklungspaket mit dem Namen der Software Komponente an und kennzeichnen es als TIER-2. Hier kannst du auch dem Pattern von TIER-1 folgen und erst das passende Strukturpaket anlegen, wäre aber etwas mehr Arbeit. So kannst du die Zuordnung zur passenden Software Komponente ableiten.
Da wir das Paket unter dem Paket ZCA_TIER2 angelegt haben, ist die passende Software Komponente direkt vorbelegt. Die Komponente verwendet allerdings die Sprachversion "Standard ABAP", da wir hier unsere nicht freigegebenen Wrapper anlegen wollen.
Migration Logik
Im ersten Schritt legen wir uns eine neue Klasse an, die die Logik der alten Klasse übernimmt. Wir erstellen hier eine ausführbare Klasse, um schnell erste Ergebnisse sehen zu können und um die Reportlogik zu übernehmen.
In die MAIN Methode übernehmen wir die Logik aus dem Report. Dabei muss die Klasse durch die neue Klasse ersetzt werden. Ebenfalls müssen wir die Ausgabe leicht verändern, damit diese nun das OUT Objekt der MAIN Methode verwendet.
DATA(go_document) = NEW zcl_finance_document_new( ).
DATA(gs_document) = go_document->book( ).
IF gs_document IS INITIAL.
out->write( go_document->mo_log->get_messages_flat( ) ).
ELSE.
out->write( go_document->get_document( gs_document ) ).
ENDIF.
Nachdem wir nun die gesamte Logik aus der Klasse ZCL_BOOK_FI_DOCUMENT_APP übernommen haben, können wir allerdings noch nicht aktivieren und erhalten zahlreiche Fehlermeldungen.
Weder der BAPI, noch die Tabelle, sind zur Nutzung in ABAP Cloud freigegeben. Der Compiler lässt uns damit die Klasse nicht aktivieren und wir müssen zuerst einmal die Fehler bearbeiten.
Wrapper
Wie können wir nun die Daten der BKPF lesen? Wenn es keine freigegebene API von SAP gibt, können wir uns einen Wrapper bauen.
Core Data Service
Dazu legen wir einen Core Data Service für die Tabelle an. Hier ist wichtig, dass wir den Wrapper in TIER-2 anlegen.
Dabei erzeugen wir eine einfache Struktur mit einigen Feldern der BKPF. Würden wir einen echten Wrapper erstellen, dann würden wir auch die Feldnamen in die englischen Langnamen überführen, damit wir das Objekt mehr an den Standard heranführen.
@EndUserText.label: 'FI Header (Wrapper)'
define view entity ZFI_I_FinanceDocumentHeader
as select from bkpf
{
key bukrs,
key gjahr,
key belnr,
blart,
bldat,
budat,
cpudt,
cputm,
wwert,
usnam,
tcode,
bvorg,
xblnr,
dbblg,
stblg,
stjah,
bktxt,
waers,
kursf
}
Nachdem wir den CDS angelegt und aktiviert haben, müssen wir diesen noch freigeben, damit wir ihn in TIER-1 verwenden können. In Eclipse findest du im View "Properties" im Reiter "API State" den passenden Button.
Wir möchten einen C1 Contract erstellen und das Objekt für "Use in Cloud Development" freigeben, um es in unserer ABAP Cloud Anwendung verwenden zu können. Der Status sollte dabei auf "Released" stehen.
Im Anschluss können wir noch einmal den "API State" validieren und sehen nun den neuen Contract für das Objekt.
Austausch der Tabelle
Nun können wir beginnen, in der Klasse ZCL_FINANCE_DOCUMENT_NEW die BKPF Aufrufe durch den neuen Core Data Service auszutauschen.
TYPES: BEGIN OF ts_document,
belnr TYPE ZFI_I_FinanceDocumentHeader-belnr,
bukrs TYPE ZFI_I_FinanceDocumentHeader-bukrs,
gjahr TYPE ZFI_I_FinanceDocumentHeader-gjahr,
END OF ts_document.
TYPES ts_header TYPE ZFI_I_FinanceDocumentHeader.
Zum Abschluss können wir nun auch den SELECT anpassen, um wieder ein Ergebnis in der Klasse zu erhalten und damit die Fehlermeldungen loszuwerden.
SELECT SINGLE FROM ZFI_I_FinanceDocumentHeader
FIELDS *
WHERE bukrs = @is_document-bukrs
AND belnr = @is_document-belnr
AND gjahr = @is_document-gjahr
INTO @rs_result.
BAPI
Im letzten Schritt wollen wir noch den BAPI loswerden, hier könnten wir auch einen Wrapper bauen, doch zuerst einmal sollten wir prüfen, ob es nicht schon ein Nachfolgeobjekt gibt.
Nachfolger
Über den Cloudification Browser oder den Cloudification Repository Viewer können wir prüfen, ob es bereits heute einen definierten Nachfolger für den Funktionsbaustein BAPI_ACC_DOCUMENT_POST gibt und werden auch fündig:
Hierbei handelt es sich um das RAP Objekt I_JOURNALENTRYTP, welches den BAPI ablöst.
Dokumentation
Wie funktioniert nun eigentlich das RAP Objekt? Hier stellt SAP eine Dokumentation per Knowledge Transfer Document (KTD) zur Verfügung. Schauen wir uns die Behavior für unser RAP Objekt I_JOURNALENTRYTP an, dann erkennen wir im oberen Teil einen Link zur Navigation.
Mit einem Klick auf "Open Documentation" laden wir im KTD, hier können wir die Dokumentation zum Objekt anschauen. Dabei unterteilt sich das Objekt in die verschiedenen Bereiche, uns interessiert vor allem der Bereich der Aktionen "POST" und "REVERSE", für das Buchen und Stornieren.
In diesem Fall gibt uns die Dokumentation einen schönen Überblick über die Struktur des Aufrufs und einige Beispiele zur Implementierung des Objekts im Coding.
RAP Objekt
Implementieren wir als einmal das RAP Objekt um den BAPI in unserer Klasse abzulösen. Bei dem POST handelt es sich um eine Aktion, dass heißt wir müssen vor dem Aufruf erst einmal die Struktur mit allen Daten befüllen, die wir dann an das RAP Objekt übergeben.
DATA lt_new TYPE TABLE FOR ACTION IMPORT i_journalentrytpJournalEntry~Post.
INSERT VALUE #(
%cid = to_upper( cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ) )
%param = VALUE #(
companycode = '1710'
createdbyuser = sy-uname
accountingdocumenttype = 'SA'
documentdate = '20240101'
postingdate = cl_abap_context_info=>get_system_date( )
DocumentReferenceID = |RAP: { sy-uname }|
_glitems = VALUE #(
( glaccountlineitem = '1' glaccount = '0011002080' _currencyamount = VALUE #( ( journalentryitemamount = '-100.55' currency = 'EUR' ) ) )
( glaccountlineitem = '2' glaccount = '0070200000' _currencyamount = VALUE #( ( journalentryitemamount = '100.55' currency = 'EUR' ) ) ) ) ) )
INTO TABLE lt_new.
Wir definieren uns eine interne Tabelle mit dem Datentyp der Aktion und befüllen dann die geforderte Struktur. Die %CID befüllen wir mit einer eindeutigen ID für unseren Prozess, über %PARAM geben wir dann den Inhalt der Buchung mit. Damit befinden sich alle Daten in der internen Tabelle. Nun können wir die Aktion am RAP Objekt aufrufen.
MODIFY ENTITIES OF i_journalentrytp
ENTITY journalentry
EXECUTE post FROM lt_new
FAILED DATA(ls_failed_deep)
REPORTED DATA(ls_reported_deep).
Erhalten wir eine Fehlermeldung, dann ist die Struktur FAILED befüllt und wir können über REPORTED die Fehlermeldungen in unser Log übernehmen.
LOOP AT ls_reported_deep-journalentry INTO DATA(ls_entry).
mo_log->add_msg_text( ls_entry-%msg->if_message~get_text( ) ).
ENDLOOP.
Ist alle in der Prüfung sauber durchlaufen worden, dann können wir den Beleg auf der Datenbank anlegen lassen. Dazu müssen wir einen COMMIT ENTIRIES aufrufen und erhalten wieder über REPORTED die angelegte Belegnummer.
COMMIT ENTITIES BEGIN
RESPONSE OF i_journalentrytp
REPORTED DATA(lt_commit_reported).
DATA(ls_commit) = lt_commit_reported-journalentry[ 1 ].
rs_result-belnr = ls_commit-AccountingDocument.
rs_result-bukrs = ls_commit-CompanyCode.
rs_result-gjahr = ls_commit-FiscalYear.
COMMIT ENTITIES END.
Struktur
Nachdem nun alle Objekte aktiviert wurden, sollte die Architektur wie folgt aussehen. Es existiert nun die Klasse in TIER-1 und wir haben einen Wrapper auf TIER-2, der die Tabelle zum Lesen für TIER-1 zur Verfügung stellt.
Finale Klasse
Zum Abgleich noch einmal die finale Klasse mit allen Änderungen und Erweiterungen. Die Klasse konnte nun aktiviert werden und kann in TIER-1 verwendet werden.
CLASS zcl_finance_document_new DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ts_document,
belnr TYPE ZFI_I_FinanceDocumentHeader-belnr,
bukrs TYPE ZFI_I_FinanceDocumentHeader-bukrs,
gjahr TYPE ZFI_I_FinanceDocumentHeader-gjahr,
END OF ts_document.
TYPES ts_header TYPE ZFI_I_FinanceDocumentHeader.
DATA mo_log TYPE REF TO zif_application_log READ-ONLY.
METHODS constructor.
METHODS book
RETURNING VALUE(rs_result) TYPE ts_document.
METHODS get_document
IMPORTING is_document TYPE ts_document
RETURNING VALUE(rs_result) TYPE ts_header.
ENDCLASS.
CLASS zcl_finance_document_new IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(go_document) = NEW zcl_finance_document_new( ).
DATA(gs_document) = go_document->book( ).
IF gs_document IS INITIAL.
out->write( go_document->mo_log->get_messages_flat( ) ).
ELSE.
out->write( go_document->get_document( gs_document ) ).
ENDIF.
ENDMETHOD.
METHOD constructor.
mo_log = zcl_application_log=>create( ).
ENDMETHOD.
METHOD book.
DATA lt_new TYPE TABLE FOR ACTION IMPORT i_journalentrytpJournalEntry~Post.
INSERT VALUE #(
%cid = to_upper( cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ) )
%param = VALUE #(
companycode = '1710'
createdbyuser = sy-uname
accountingdocumenttype = 'SA'
documentdate = '20240101'
postingdate = cl_abap_context_info=>get_system_date( )
DocumentReferenceID = |RAP: { sy-uname }|
_glitems = VALUE #(
( glaccountlineitem = '1' glaccount = '0011002080' _currencyamount = VALUE #( ( journalentryitemamount = '-100.55' currency = 'EUR' ) ) )
( glaccountlineitem = '2' glaccount = '0070200000' _currencyamount = VALUE #( ( journalentryitemamount = '100.55' currency = 'EUR' ) ) ) ) ) )
INTO TABLE lt_new.
MODIFY ENTITIES OF i_journalentrytp
ENTITY journalentry
EXECUTE post FROM lt_new
FAILED DATA(ls_failed_deep)
REPORTED DATA(ls_reported_deep).
IF ls_failed_deep IS INITIAL.
COMMIT ENTITIES BEGIN
RESPONSE OF i_journalentrytp
REPORTED DATA(lt_commit_reported).
DATA(ls_commit) = lt_commit_reported-journalentry[ 1 ].
rs_result-belnr = ls_commit-AccountingDocument.
rs_result-bukrs = ls_commit-CompanyCode.
rs_result-gjahr = ls_commit-FiscalYear.
COMMIT ENTITIES END.
ELSE.
LOOP AT ls_reported_deep-journalentry INTO DATA(ls_entry).
mo_log->add_msg_text( ls_entry-%msg->if_message~get_text( ) ).
ENDLOOP.
ENDIF.
ENDMETHOD.
METHOD get_document.
SELECT SINGLE FROM ZFI_I_FinanceDocumentHeader
FIELDS *
WHERE bukrs = @is_document-bukrs
AND belnr = @is_document-belnr
AND gjahr = @is_document-gjahr
INTO @rs_result.
ENDMETHOD.
ENDCLASS.
Application Log
In unserem Beispiel verwenden wir bereits eine ABAP Cloud Application Log mit den neuen Klassen. Deshalb beschreiben wir in diesem Beispiel die Logik nicht einmal neu. Wenn du mit den neuen Klassen eine TIER-1 Re-Use Komponente aufbaust, dann kannst du diese auch normal in deinen TIER-3 Anwendungen verwenden.
Hinweis: Aktuell können TIER-3 Komponenten und Anwendungen jedes TIER-1 Objekt verwenden, es erfolgt keine Überprüfung des C1 Contracts.
Application Job
Im nächsten Schritt wollen wir einen Job anlegen, da unser alter Report als Job genutzt wurde. Dazu verwenden wir das neue Konzept der Application Jobs.
Anlage
Im ersten Schritt legen wir uns ein neues Unterpaket an, um alle Job-relevanten-Objekte in einem Paket zu haben.
Als zweiten Schritt benötigen wir die eigentliche Jobklasse, die bei der Ausführung des Jobs gestartet wird. Diese Klasse benötigt die beiden Interfaces IF_APJ_DT_EXEC_OBJECT und IF_APJ_RT_EXEC_OBJECT.
Nun können wir in der EXECUTE Methode die eigentliche Logik implementieren. Wir rufen unsere Belegklasse auf, Buchen den FI Beleg, geben eine zusätzliche Meldung ins Log aus und speichern die Meldung dann am Job. GET_PARAMETERS benötigen wir in unserem Beispiel nicht, da wir keine Eingaben von außen erwarten. Die vollständige Jobklasse sieht nun wie folgt aus:
CLASS zcl_finance_job DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_apj_dt_exec_object.
INTERFACES if_apj_rt_exec_object.
ENDCLASS.
CLASS zcl_finance_job IMPLEMENTATION.
METHOD if_apj_dt_exec_object~get_parameters.
ENDMETHOD.
METHOD if_apj_rt_exec_object~execute.
DATA(go_document) = NEW zcl_finance_document_new( ).
DATA(gs_document) = go_document->book( ).
go_document->mo_log->add_msg_text(
|BELNR: { gs_document-belnr }, BUKRS: { gs_document-bukrs }, GJAHR: { gs_document-gjahr }| ).
DATA(lo_header) = cl_bali_header_setter=>create(
object = 'ZFI_LOG'
subobject = 'DOC'
external_id = cl_abap_context_info=>get_system_date( ) && cl_abap_context_info=>get_system_time( ) ).
go_document->mo_log->save( id_save_with_job = abap_true
io_header = lo_header ).
ENDMETHOD.
ENDCLASS.
Job
Im nächsten Schritt müssen wir noch den Katalog und das Template für den Job anlegen. Wenn du nach Job suchst, findest du bei der Anlage die beiden Objekte.
Zuerst benötigen wir den Katalog und ordnen dort die Klasse zu.
Im nächsten Schritt generieren wir das Template und nehmen den Katalog aus dem Schritt zuvor als Referenz.
Test
Testen wir den neuen Job und gehen dazu in die App "Application Jobs", dort planen wir den Job einmalig ein und schauen uns das Ergebnis im Log an.
Im zweiten Schritt schauen wir uns in Eclipse (Data Preview) den erzeugten Beleg über den Core Data Service an.
Der Test war so weit erfolgreich, die Komponenten in ABAP Cloud funktionieren und liefern uns das gewünschte Ergebnis.
Struktur
Die neue Struktur sieht entsprechend mit den neuen Objekten wie folgt aus, dabei haben wir mittlerweile TIER-3 leer gelassen, da alle Objekte erfolgreich nach TIER-1 und 2 migriert wurden.
Auflösung Wrapper
Im letzten Schritt möchten wir den Wrapper von TIER-2 auflösen. Hier gehen wir einmal davon aus, dass ein freigegebenes Objekt ausgeliefert wurde. In diesem Fall gibt es für die Tabelle einen entsprechenden freigegebenen Core Data Service, den wir nun nutzen können. Solche Freigaben passieren im Moment per Upgrade des Systems, in der Zukunft kann dies allerdings auch per Hinweis erfolgen, wenn nur noch alle zwei Jahre Releases anstehen.
Nachfolger
Der Nachfolger zur BKPF lässt sich im Moment über zwei Weg ermitteln, zum einen kannst du die Tabelle in den ABAP Development Tools öffnen und in den View "Properties" navigieren, hier findest du unter "API State" die Information, wenn sie im System hinterlegt ist.
Hast du noch ein älteres Release und es gibt noch keine Information zu einem Nachfolger, dann kannst du dir die Informationen über das Cloudification Repository holen. Dafür gibt es den Viewer von SAP und einen Viewer von uns. In beiden erhalten wir jeweils den Nachfolger für die Tabelle.
Austausch
Da es nun einen Nachfolger für unseren Wrapper gibt, haben wir in diesem Fall zwei Möglichkeiten:
- Austausch Wrapper - Wir tauschen unseren Wrapper an allen Aufrufstellen aus und löschen den Wrapper im Anschluss, da er nicht mehr benötigt wird.
- Anpassung Wrapper - Wir passen unseren Wrapper an und verwenden das freigegebene Objekt, anstatt direkt die Tabelle wie vorher.
Hier solltest du von Fall zu Fall unterscheiden. Je öfter der Wrapper verwendet wird, desto eher lohnt es sich Variante 2 zu verwenden und nur den Inhalt des Wrappers einmal zu ändern. In diesem Beispiel setzen wir ebenfalls auf die zweite Variante und tauschen nur den Inhalt. Beim Ändern des freigegebenen Objekts erhalten wir eine Warnung, die wir aber nur bestätigen müssen.
Nun ändern wir die Datenquelle im Core Data Service und müssen nun die englischen Langnamen, auf die deutschen Kurzbezeichnungen mappen. In diesem Fall wäre das Mapping vorher um einiges sinnvoller gewesen.
define view entity ZFI_I_FinanceDocumentHeader
as select from I_JournalEntry
{
key CompanyCode as bukrs,
key AccountingDocument as belnr,
key FiscalYear as gjahr,
AccountingDocumentType as blart,
DocumentDate as bldat,
PostingDate as budat,
FiscalPeriod as monat,
AccountingDocumentCreationDate as cpudt,
CreationTime as cputm,
LastManualChangeDate as aedat,
LastAutomaticChangeDate as upddt,
ExchangeRateDate as wwert,
AccountingDocCreatedByUser as usnam,
TransactionCode as tcode,
IntercompanyTransaction as bvorg,
DocumentReferenceID as xblnr,
RecurringAccountingDocument as dbblg,
ReverseDocument as stblg,
ReverseDocumentFiscalYear as stjah,
AccountingDocumentHeaderText as bktxt,
TransactionCurrency as waers,
ExchangeRate as kursf
}
Zum Abschluss nur noch das Objekt aktivieren.
Verschieben
Da unser Wrapper nun bereit für ABAP Cloud ist, können wir diesen in ein entsprechendes TIER-1 Paket verschieben. Bevor wir ihn allerdings verschieben können, müssen wir die Sprachversion des Objekts ändern. Im "Properties" View im Reiter "General" können wir die Sprachversion über den "Edit" Button anpassen, im Anschluss noch einmal das Objekt aktivieren.
Mit einem Rechts-Klick auf das Objekt im "Project Explorer" kannst du im Menü die Funktion "Change Package Assignment ..." wählen.
Im anschließenden Dialog nur noch das Zielpaket eingeben und die Aktion ausführen. Ist das Objekt so weit ABAP Cloud Ready, wird es auch entsprechend verschoben und wir sind fertig.
Struktur
TIER-2 ist nun ebenfalls leer und unsere Anwendung wurde komplett mit ABAP Cloud umgesetzt. So einfach wird es nicht immer sein, der zweite TIER kann mehr oder weniger groß ausfallen, je nachdem welches Modul zum Einsatz kommt. In einigen Fällen kann es auch vorkommen, dass Objekte aus TIER-2 niemals nach TIER-1 kommen und immer dort stehen bleiben.
Zusammenfassung
Was haben wir für die Migration des Codings nun alles gemacht, hier eine kurze Zusammenfassung.
- Anlage der Struktur für die TIER-1 Komponenten
- Erstellung eines Wrappers und Freigabe für TIER-1
- Migration des Codings und Austausch nicht freigegebener Objekte
- Erstellung des Jobs
- Migration des Wrappers (möglich nach Release)
Fazit
Das Beispiel ist relativ einfach gehalten, um die verschiedenen Schritte so einfach wie möglich darzustellen. Sie sollen einen Einblick in die Arbeit mit ABAP Cloud ermöglichen und dir das Thema auf praktische Art und Weise näherbringen.