Kontakt & Service
Jetzt Beratung vereinbaren

In wenigen Schritten einen Beratungs­termin mit unseren Experten buchen.

Anwender Helpdesk

Hilfestellung bei Problemen in Ihren SAP-Systemen.

Schulungen

Unser Schulungsangebot. Jetzt informieren!

Webinare

Unser Webinarangebot. Jetzt informieren!

Kapselung Mapping SAP

News & Wissen Funktionalitäten steuern durch Kapselung und Mapping

Häufig ist es erforderlich, dass neue oder erweiterte Funktionalitäten nur für definierte Fälle gültig sind. Anhand verschiedener Kriterien wird entschieden, welche Funktionalität in welchem Fall durchlaufen werden muss und somit aktiviert sein soll. Dabei können die Kriterien stark variieren: Jedes Land hat seine eigenen Gesetze, jedes Unternehmen, jede Lagerstruktur und jeder Produktionsprozess ist anders und so weiter. Damit eine Steuerung der Funktionalitäten im SAP-System erfolgen werden kann, möchte man sie kapseln.

Im Klartext bedeutet das: Der Programmcode darf nur durchlaufen werden, wenn eine Bedingung erfüllt ist. Das kann man jetzt im Programm fest verdrahten, indem man z. B. bei einer gesetzlichen Regelung den Buchungskreis abfragt in Form von:

If BKPF-BUKRS = ‚1000‘.

  Funktion XY

ENDIF.

Diese Form der Implementierung wählt man in der Regel, wenn es schnell gehen soll (also wie immer) oder klar ist, dass die Funktion XY definitiv nur für den Sonderfall Buchungskreis 1000 gültig sein darf.

Was ist, wenn es mehrere Organisationseinheiten betrifft und eventuell welche hinzukommen oder wegfallen? Oder die Bedingung komplexer ist: In dem einen Fall betrifft es eine ganze Einkaufsorganisation, im anderen Fall die Kombination mit Einkäufergruppen oder - noch komplexer - die zusätzliche Abhängigkeit der Materialart?

If ( EKKO-EKORG = ‚1000‘ )

  OR

  ( EKKO-EKORG = ‚2000‘ AND EKKO-EKGRP = ‘100’ )

  OR

  ( EKKO-EKORG = ‚2000‘ AND EKKO-EKGRP = ‘105’ AND MARA_MTART = ‘ROH’ ).

   Funktion XY

ENDIF.

Was ist, wenn die Implementierung der Funktion XY an mehreren Stellen im Programmcode erfolgen muss? Dann müsste man diese Bedingung an allen Stellen einbauen und im Änderungsfall auch sämtliche Stellen pflegen (das geht erfahrungsgemäß schief).

Was ist, wenn man die Funktion XY kurzfristig abschalten muss? Man hat erst im Produktivsystem bemerkt, dass da ein Fehler in der Funktion XY enthalten ist (bestenfalls kein Programmabbruch). Bis so ein Fehler analysiert, gefunden und behoben ist, kann einige Zeit vergehen, in der ein Prozess dann nicht funktioniert.

Eventuell möchte man zur vereinfachten Fehleranalyse nur eine bestimmte Funktion analysieren, sprich debuggen. Dazu sollte es möglich sein, am Start der Funktion einen BREAK-POINT zu setzen und das in Abhängigkeit eines Users (also dem Programmierer).

Aus der Komplexität der möglichen Bedingungen und der damit verbundenen Felder ergibt sich eine große Anzahl von Feldern, die in der Bedingung berücksichtigt werden müssen. Hier eine nicht vollständige Aufzählung von Feldern aus den Bereichen FI, MM und SD:

  • BUKRS            Buchungskreis
  • KOKRS            Kostenrechnungskreis
  • WERKS           Werk
  • LGORT            Lager
  • EKORG           Einkaufsorganisation
  • EKGRP            Einkäufergruppe
  • VKORG           Verkäufergruppe
  • VTWEG           Vertriebsweg
  • ...

Aufgrund dieser Vielfältigkeit der Bedingungen wird eine Kapselung oft für jedes Modul separat gemacht, also eine Kapselung für den Bereich Vertrieb und eine für den Bereich Einkauf und so weiter. Man hat also die gleiche Funktionalität nach Bereichen getrennt. Das erhöht weder die Transparenz noch die Pflege dieser generellen Funktionalität der Kapselung.

Zusammenfassung der Anforderungen

Aus den oben beschriebenen Problemen ergeben sich folgende Anforderungen an eine Kapselung von Funktionen:

  • Flexibilität
  • Erweiterbar
  • Leicht zu pflegen
  • Aktivierung / Deaktivierung
  • Userabhängiger BREAK-POINT
  • Funktion / Methode zur Abfrage der Kapselung

Umsetzung

Damit alle benötigten Informationen zur Kapselung abgefragt werden können, ist eine Tabelle notwendig. Diese Tabelle muss direkt Im System zu pflegen sein. Dies ist eine Notwendigkeit, um schnell eingreifen zu können, sollte es notwendig sein, eine Funktion mal eben zu deaktivieren.

Zu der Tabelle ist der Pflegedialog zu generieren. Für die Pflege dieser Tabelle mit SM30 sollte eine Transaktion angelegt werden, die im Berechtigungskonzept eingebaut werden kann.

Die Tabelle sollte an die Änderungshistorie angehängt werden, damit die Revisoren auch ihren Spaß haben.

Zur Abfrage der Tabelle braucht man noch einen Funktionsbaustein oder eine Methode, um die Bedingungen prüfen zu können.

Lösung 1: Fixe Felder

Bei dieser Lösung wird eine Tabelle angelegt, die als Schlüsselfelder alle möglichen Felder einer Bedingung enthält.

Im einfachsten Fall ist das nur ein Feld, wie in diesem Beispiel.

Im Programm wird dann einfach diese Funktion abgefragt:

Lösung 2: Variable Felder

Bei dieser Lösung wird nicht von Kapselung gesprochen, sondern von einer ACTIVITY.

Diese Lösung vereint vieles, was bei einer Kapselung benötigt wird:

  • Flexibilität
  • Anpassbar
  • Aktivierung eines Breakpoints

DDIC-Objekte

Für diese Lösung sind drei Tabellen und eine Struktur erforderlich:

1. ZCA_ACTIVITY    Aktivitäten

Die Tabelle ZCA_ACTIVITY enthält die Bezeichnung einer Aktivität, ein Kennzeichen ob sie generell aktiv ist und einen User-Namen, für den der Break-Point gesetzt wird, falls aktiviert. Das Feld SORT dient hier nur der optischen Zusammenfassung von mehreren Aktivitäten. Es hat KEINE funktionale Auswirkung.

2. ZCA_ACT_FIELDS    OrgEinheiten für Aktivität

Die Tabelle ZCA_ACT_FIELDS enthält die Felder der Bedingung und die Reihenfolge, in der sie stehen. Die Felder können aus der Struktur ZCA_ACTIVITY_FIELDS entnommen werden.

3. ZCA_ACT_VALUE    Generischer Wert der OrgEinheiten für Aktivität

Diese Tabelle wird nur gefüllt, wenn es zur Aktivität auch Werte gibt, die abgefragt werden sollen. Hier werden die Werte ohne Abstand in der Reihenfolge, wie in ZCA_ACT_FIELD definiert, eingetragen.

Struktur: ZCA_ACTIVITY_FIELDS    Available Activity-fields

In dieser Struktur sind die Felder hinterlegt, die der Kapselung dienen sollen. Sollte ein zusätzliches Feld benötigt werden, kann dieses hier angelegt und aktiviert werden.

Wichtig ist das Feld NO_FIELD_SPEC: Dieses Feld wird in der Methode benutzt, um zu kennzeichnen, dass die Aktivität keine zusätzlichen Bedingungen hat.

View-Cluster

Die Tabellen sind in einem View-Cluster zusammengefügt, in dem eine Aktivität gepflegt werden kann. Hier ein Beispiel für eine Aktivität, die nach Werk und Lagerort gesteuert werden soll:

In diesem Beispiel wird die Aktivität TEST_WERK_LAGER angelegt und aktiviert. An dieser Stelle muss das Aktivkennzeichen gesetzt werden, wenn die Aktivität generell aktiv sein soll.

In der Tabelle Felder werden die Felder eingetragen, für die diese Aktivität abgefragt werden soll. In diesem Beispiel sind das WERKS und LGORT.

In der Tabelle Werte werden alle möglichen Kombinationen eingetragen, für die diese Aktivität aktiv ist.

In diesem Beispiel wäre die Aktivität für das Werk WERK und Lagerort LAGR aktiv, sowie für Werk 2000 mit dem Lager 1300.

Alle anderen Kombinationen von Werk und Lagerort wären NICHT aktiv.

Wichtig: Es ist keine Maskierung möglich; alle zu aktivierenden Werte müssen in voller Länge eingetragen werden.

Was nicht geht:

  • *1200
  • 200010*

Sollte es Werte geben, die nicht das ganze Feld füllen, sind Leerzeichen einzufügen. Für das Werk 123 mit dem Lagerort 1000 muss dann 123 1000 eingetragen werden.

Kombinationen, die hier nicht aufgeführt sind oder nicht das Aktivkennzeichen haben, werden als inaktiv gewertet.

Methode

Mit der Methode zcl_ca_activity_manager=>is_activ kann eine Aktivität abgefragt werden.

Die Abfrage einer Aktivität ohne Felder erfolgt folgendermaßen:

Die Abfrage einer Aktivität mit den Feldern WERKS und LGORT erfolgt so:

Lösung 3: Einer für alles

Es soll eine Tabelle geben, mit der alle denkbaren Konstellationen abgebildet werden können - auch solche, die man heute noch nicht kennt -, ohne dass eine Änderung der Tabelle notwendig wird. Zusätzlich soll es möglich sein, diese Tabelle auch für ein Datenmapping zu nutzen.

Zu diesem Zweck wird eine Tabelle mit den folgenden Schlüsselfeldern angelegt:

  • User
  • Objektname
  • Laufende Nummer

Mit dem Feld User ist es möglich, userabhängige Einträge zu machen; dieses ist z. B. zu Testzwecken sehr hilfreich. Berechtigungen sollte man damit nicht steuern. Mit dem Wert * sind alle User abgedeckt.

Das Feld Objektname enthält den Schlüssel für die zu kapselnden Funktionen oder den zu mappenden Wert. Dabei wurde das Feld bewusst 20-stellig angelegt, um flexible, sprechende Schlüssel generieren zu können, z. B.:

  • MV45AFZZ_SAVE            Kapselung eines Userexits
  • SD000000001                Kapselung einer Erweiterung im SD
  • EKPO_EDI_1001_2100    dynamische Kapselung mit Werk und Lagerort
  • WERKS_1200                   dynamisches Mapping des Werks 1200

Das Feld Laufende Nummer dient nur der Eindeutigkeit des Keys, falls zu einem Schlüssel mehrere Werte möglich sein sollen.

Die Umsetzung ist klassisch mit Funktionsbausteinen und als OO-Lösung implementiert worden.

Objekte

  • Packet:                           ZBC
  • Tabelle:                          ZBC_ACTIV_VALUE
  • Funktionsgruppe:         ZBC_AKTIV, ZBC_TABLE
  • Funktionsbausteine:    ZBC_AKTIV, ZBC_VALUE
  • Klasse:                            ZCL_ACTIV_VALUE
  • Methode:                       IS_OBJ_ACTIVE

MAPPING_VALUE

Tabelle

Zur Tabelle gibt es einen Pflegeview, mit dem die Werte gepflegt werden können. Der Pflegeview ist NICHT an das Transportsystem angebunden. Die Werte müssen im System selber erstellt werden. So ist es möglich, kurzfristig reagieren zu können, wenn z. B. Funktionen deaktiviert oder zusätzliche Organisationseinheiten eingebunden werden sollen.

Funktionsbausteine

ZBC_ACTIV  Kapselung

Funktionsbaustein ZBC_ACTIV

  • Importparameter          IV_OBJ_NAME
  • Exportparameter          EV_ACTIV

EV_ACTIV hat den Wert „X", wenn der Schlüssel aktiv ist.

FUNCTION zbc_activ.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*"  IMPORTING
*"     REFERENCE(IV_OBJ_NAME) TYPE  ZZ_OBJ_NAME
*"  EXPORTING
*"     REFERENCE(EV_ACTIV) TYPE  ZZ_ACTIV
*"----------------------------------------------------------------------

CLEAR ev_activ.

*--------------------------------------------------------------------*
* lesen Kennzeichen "AKTIV"
*
SELECT activ FROM zbc_activ_value UP TO 1 ROWS
INTO ev_activ
WHERE ( uname  = sy-uname OR uname = '*' )
AND obj_name = iv_obj_name
AND activ    = 'X'.
EXIT.
ENDSELECT.

ENDFUNCTION.

ZBC_VALUE Datenmapping

Funktionsbaustein: ZBC_VALUE

  • Importparameter: IV_OBJ_NAME
  • Tables: ET_VALUES

In der Tabelle ET_VALUES werden die aktiven Werte zum Schlüssel zurückgegeben. Da die Tabelle im Funktionsbaustein nicht definiert ist, kann das im rufenden Programm durchgeführt werden.

Beispiel (Daten):

Programmausschnitt:

REPORT  zz_test                                 .

DATA:
lt_werks  TYPE STANDARD TABLE OF werks_d.

FIELD-SYMBOLS: <wert> TYPE ANY.

CALL METHOD zcl_activ_value=>mapping_value
EXPORTING
iv_obj_name = 'TEST'
IMPORTING
et_values   = lt_werks.

LOOP AT lt_werks ASSIGNING <wert>.
WRITE: /5 <wert>.
ENDLOOP.

Ergebnis / Liste mit User CP_PRZTHO:

Coding FuBa:

FUNCTION zbc_value.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*"  IMPORTING
*"     VALUE(IV_OBJ_NAME) TYPE  ZZ_OBJ_NAME
*"  TABLES
*"      ET_VALUES OPTIONAL
*"----------------------------------------------------------------------

* lesen Werte zum Objekt
SELECT value FROM zbc_activ_value
INTO TABLE et_values
WHERE ( uname  = sy-uname OR uname = '*' )
AND obj_name = iv_obj_name
AND activ    = 'X'.

ENDFUNCTION.

ZBC_INSERT Anlegen Datensatz

Dieser Funktionsbaustein legt einen neuen Datensatz in der Tabelle ZBC_VALUE_INSERT an. Der FuBa kann in UPDATE TASK gestartet werden.

Sinn dieses FuBa ist das Anlegen von Mappingdaten, z. B. bei der Datenmigration.

Für diesen Zweck ist es sinnvoll, das Feld LFDNR immer leer zu lassen, um einen eindeutigen Schlüssel zu bekommen.

Der FuBa hat nur ein Importparameter:

IS_ACTIV_VALUE  vom Typ der Tabelle ZBC_ACTIV_VALUE

Wird das Feld UNAME leer gelassen, ergänzt der FuBa dieses Feld mit *.

Beispiel:

Der Kunde 10004711 wird migriert und bekommt die neue Partnernummer 10000112, dann könnte man folgenden Datensatz anlegen:

  • IS_ACTIV_VALUE-UNAME = ‘’
  • IS_ACTIV_VALUE-OBJ_NAME = ‘OLB_KUNNR_10004711’
  • IS_ACTIV_VALUE-VALUE = ‘100000112’
  • IS_ACTIV_VALUE-active = ‘X’

Der FuBa würde dann folgenden Datensatz anlegen:

Coding FuBa:

function zbc_insert.
*"----------------------------------------------------------------------
*"*"Verbuchungsfunktionsbaustein:
*"
*"*"Lokale Schnittstelle:
*"  IMPORTING
*"     VALUE(IS_ACTIV_VALUE) TYPE  ZBC_ACTIV_VALUE
*"----------------------------------------------------------------------

* User setzen
if is_activ_value-uname is initial.
is_activ_value-uname = '*'.
endif.

* schreiben Datensatz
insert zbc_activ_value from is_activ_value.

endfunction.

ZCL_ACTIV_VALUE Klasse

Methoden:

  • IS_OBJ_ACTIVE          prüfen, ob Objekt aktiv ist
  • MAPPING_VALUE       zu mappende Werte lesen

IS_OBJ_ACTIVE

Der importing-Parameter enthält das zu prüfende Objekt.

Der returning-Parameter EV_ACTIV hat den Wert X, wenn das Objekt aktiv ist.

METHOD is_obj_active .

CLEAR ev_activ.

*--------------------------------------------------------------------*
* lesen Kennzeichen "AKTIV"
*
SELECT activ FROM zbc_activ_value UP TO 1 ROWS
INTO ev_activ
WHERE ( uname  = sy-uname OR uname = '*' )
AND obj_name = iv_obj_name
AND activ    = 'X'.
EXIT.
ENDSELECT.

ENDMETHOD.

Beispiel:

In der Bedingung 925 sollen nur die Lagerorte 2100, 2150 und 2160 im Werk 1000 zugelassen werden. Zu diesem Zweck werden in der Tabelle diese Einträge gemacht. Der Schlüssel besteht aus drei Teilen, die durch ‚_‘ getrennt werden, Schlüsselwort ‚EKPO_EDI‘, WERK und Lagerort. In der Bedingung wird dann zu den aktuellen Daten der Schlüssel aufgebaut und das Aktivitätskennzeichen abgefragt.

*   Aufbau Schlüssel für Aktivitätsabfrage
CONCATENATE 'EKPO_EDI'
ls_item-werks
ls_item-lgort
INTO lv_obj_name SEPARATED BY '_'.

*   Abfrage Werk/Lagerort aktiv
CALL METHOD zcl_activ_value=>is_obj_active
EXPORTING
iv_obj_name = lv_obj_name
RECEIVING
ev_activ    = lv_aktiv.

*   Aktivität prüfen
IF lv_aktiv <> 'X'.
lv_return = 4.
EXIT.
ENDIF.

MAPPING_VALUE

Der importing-Parameter enthält das zu mappende Objekt.

Der exporting Parameter ist als Tabelle mit Typ ANY definiert. Der Parameter kann / muss im rufenden Programm definiert werden.

Beispiel (Daten):

Rufendes Programm:

REPORT  zz_test                                 .

DATA:
lt_werks  TYPE STANDARD TABLE OF werks_d.

FIELD-SYMBOLS: <wert> TYPE ANY.

CALL METHOD ZCL_ACTIV_VALUE=>mapping_value
EXPORTING
iv_obj_name = 'TEST'
IMPORTING
ET_VALUES   = lt_werks.

LOOP AT lt_werks ASSIGNING <wert>.

WRITE: /5 <wert>.
ENDLOOP.

Ergebnis mit dem User CP_PRZTHO:

Dokumentation

Eine Dokumentation ist in diesem Fall sehr wichtig, um den Überblick zu behalten und schnell Änderungen an Funktionen vornehmen zu können.

Jede Kapselung sollte in Excel dokumentiert werden. Dabei ist es wichtig festzuhalten, welche Funktionalität gekapselt wird und an welchen Stellen dies überall abgefragt wird. Als Beispiel kann ein Ausschnitt der Dokumentation zum Lösungsansatz 2 dienen: Tabelle von Kapselung Userexits.

 

Stand: 26. Juli 2021
Newsletter Setzen Sie auf fundiertes Wissen aus allen Bereichen unserer Branche. Regelmäßig und stets aktuell.
Beratende Person
Kontakt Haben Sie Fragen oder wünschen weitere Informationen? Unsere Experten beraten Sie gerne.