Document ABAP product division mapping reports

This commit is contained in:
2026-05-28 14:43:13 +02:00
parent da0f39235c
commit c638529dd0
8 changed files with 458 additions and 5 deletions
@@ -70,6 +70,70 @@ Sinnvolle technische Bausteine:
- Export-/Excel-Spalten fuer die drei neuen Klassifikationen.
- Pruefansicht fuer nicht zugeordnete Materialnummern.
## Nachtrag 2026-05-28 SAP-/ABAP-Zielbild
Nach weiterer Analyse mit Andreas-/SAP-Kontext ist das fuehrende Zielbild:
- SAP TR AG bleibt Quelle der Wahrheit fuer die Artikelzuordnung.
- Die Dashboard-App baut die KEDR-/KE30-Ableitungslogik nicht direkt in C# nach.
- Stattdessen wird eine flache Referenztabelle aus SAP bereitgestellt:
- `MATNR`
- `MAKTX`
- `PAPH1`
- `PAPH1_TEXT`
- `WWPFA`
- `WWPFA_TEXT`
- `WWPSP`
- `WWPSP_TEXT`
- `IS_ASSIGNED`
- Das Dashboard mappt spaeter Umsatzzeilen ueber `Material`/`MATNR` gegen diese Referenz.
- Falls die Materialnummer nicht in der Referenz enthalten ist oder keine eindeutige Ableitung existiert, wird die Zeile unter `Nicht zugeordnet` gefuehrt.
SAP-Felder / Annahmen:
- Materialnummer: `MATNR`
- Produkthierarchie aus Vertriebssicht: `MVKE-PRODH`
- CO-PA Merkmal fuer erste Produkthierarchieebene: `PAPH1`
- Produktfamilie: `WWPFA`
- Produktsparte: `WWPSP`
- Reale Ableitung kommt aus CO-PA/KEDR und ist in `CE11000` sichtbar.
ABAP-Artefakte wurden als Arbeitsstand im Repo abgelegt:
| Datei | Zweck |
| --- | --- |
| `docs/abap/ZCL_PRODSPARTE_PROVIDER.abap` | Globale Provider-Klasse fuer ALV und spaeter OData |
| `docs/abap/Z_PRODSPARTE_REPORT.abap` | ALV-Testreport, ruft Provider-Klasse |
| `docs/abap/Z_PRODSPARTE_MAP_BUILD.abap` | Baut `ZPRODSPARTE_MAP` aus eindeutigen CO-PA-Kombinationen |
| `docs/abap/README_PRODSPARTE.md` | Hinweise zu DDIC-Objekten und Pruefpunkten |
Vorgeschlagene SAP-Architektur:
1. `Z_PRODSPARTE_MAP_BUILD` liest eindeutige Kombinationen `PAPH1 -> WWPFA -> WWPSP` aus `CE11000`.
2. Mehrdeutige `PAPH1` werden protokolliert und nicht in die Mapping-Tabelle geschrieben.
3. Eindeutige Zuordnungen werden in `ZPRODSPARTE_MAP` geschrieben.
4. `ZCL_PRODSPARTE_PROVIDER` liest verkaufsrelevante Materialien aus `MVKE`, Texte aus `MAKT`/`T179T`/`T25A0`/`T25A1` und verbindet sie mit `ZPRODSPARTE_MAP`.
5. `Z_PRODSPARTE_REPORT` dient als ALV-Test.
6. Ein spaeterer SAP-Gateway/OData-Service ruft dieselbe Provider-Klasse auf.
Bewusst korrigierte Punkte im ABAP-Arbeitsstand:
- Provider-Logik ist global auslagerbar, nicht nur lokale Reportklasse.
- `MAKT` wird per `LEFT OUTER JOIN` gelesen, damit Materialien ohne Text nicht verschwinden.
- `VTWEG` ist optionaler Selektionsparameter.
- Bei mehreren Vertriebswegen gewinnt aktuell bewusst der kleinste `VTWEG`; dies ist noch fachlich zu bestaetigen.
- Fallback setzt technischen Code `UNASS`, Text `Nicht zugeordnet` und `IS_ASSIGNED = abap_false`.
- Mapping-Build schreibt die Tabelle nicht leer, falls keine eindeutigen Saetze aufgebaut wurden.
Noch zu pruefen:
- Ist `PAPH1 = MVKE-PRODH(5)` im Trafag-System exakt korrekt?
- Sind `T25A0` und `T25A1` die richtigen Text-/Customizingtabellen fuer Produktfamilie und Produktsparte?
- Ist `CE11000` der richtige CO-PA-Einzelposten fuer den relevanten Ergebnisbereich?
- Ist der Fallback-Code `UNASS` in Feld `WWPSP` zulaessig/lang genug?
- Soll `VTWEG` zwingend vorgegeben werden, statt den kleinsten Vertriebsweg zu verwenden?
- Welche VKORG ist fuer TR AG im produktiven Lauf massgebend?
## Offene Fragen Fuer Andreas / Kendra
| Frage | Warum wichtig |
@@ -86,4 +150,3 @@ Sinnvolle technische Bausteine:
## Abgrenzung
Dieser Task ist keine Finance-Soll/Ist-Regel. Die Klassifikation kann spaeter Finance- und Management-Auswertungen ergaenzen, sollte aber fachlich getrennt von Net-Sales-Abgrenzungen bleiben.
@@ -0,0 +1,49 @@
# ABAP Produktsparten-Mapping
Stand: 2026-05-28
## Dateien
| Datei | Zweck |
| --- | --- |
| `ZCL_PRODSPARTE_PROVIDER.abap` | Wiederverwendbare Provider-Klasse fuer ALV und spaeter OData |
| `Z_PRODSPARTE_REPORT.abap` | Schlanker ALV-Testreport |
| `Z_PRODSPARTE_MAP_BUILD.abap` | Baut `ZPRODSPARTE_MAP` aus eindeutigen CO-PA-Kombinationen |
## Benoetigte SAP-Objekte
- Transparente Tabelle `ZPRODSPARTE_MAP`
- `MANDT`
- `PAPH1`
- `WWPFA`
- `WWPSP`
- `CRDATE`
- `CRUSER`
- Klasse `ZCL_PRODSPARTE_PROVIDER`
- Report `Z_PRODSPARTE_REPORT`
- Report `Z_PRODSPARTE_MAP_BUILD`
Optional fuer Gateway/DDIC:
- Struktur `ZSTR_PRODSPARTE_OUT`
- Tabellentyp `ZTT_PRODSPARTE_OUT`
## Gepruefte Anpassungen Gegenueber Erstentwurf
- Provider-Logik aus Report in globale Klasse ausgelagert.
- `MAKT` als `LEFT OUTER JOIN`, damit Materialien ohne Text nicht verloren gehen.
- `VTWEG` als optionaler Parameter.
- Bei mehreren Vertriebswegen gewinnt bewusst der kleinste `VTWEG`.
- Fallback setzt technischen Code `UNASS`, Text `Nicht zugeordnet` und `IS_ASSIGNED = abap_false`.
- `gt_ambig` im Mapping-Build ist korrekt als `ty_combo` typisiert.
- `p_erkrs` wurde entfernt, weil der Report fix aus `CE11000` liest.
- Leerschreiben von `ZPRODSPARTE_MAP` wird verhindert, wenn keine eindeutigen Saetze aufgebaut wurden.
## Noch Fachlich/Technisch Zu Pruefen
- Ist `PAPH1 = MVKE-PRODH(5)` im Trafag-System exakt korrekt?
- Sind `T25A0` fuer Produktfamilie und `T25A1` fuer Produktsparte die richtigen Texttabellen?
- Ist `CE11000` der richtige CO-PA-Einzelposten fuer den relevanten Ergebnisbereich?
- Ist Fallback-Code `UNASS` in Feld `WWPSP` lang genug/zulässig?
- Soll `VTWEG` zwingend selektiert werden statt "kleinster VTWEG gewinnt"?
@@ -0,0 +1,137 @@
CLASS zcl_prodsparte_provider DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES: BEGIN OF ty_out,
matnr TYPE matnr,
maktx TYPE maktx,
paph1 TYPE ce11000-paph1,
paph1_text TYPE vtext,
wwpfa TYPE ce11000-wwpfa,
wwpfa_text TYPE bezek,
wwpsp TYPE ce11000-wwpsp,
wwpsp_text TYPE bezek,
is_assigned TYPE abap_bool,
END OF ty_out.
TYPES tt_out TYPE STANDARD TABLE OF ty_out WITH DEFAULT KEY.
METHODS get_data
IMPORTING
iv_vkorg TYPE vkorg
iv_vtweg TYPE vtweg OPTIONAL
iv_spras TYPE spras DEFAULT sy-langu
iv_fallback TYPE bezek DEFAULT 'Nicht zugeordnet'
RETURNING
VALUE(rt_out) TYPE tt_out.
ENDCLASS.
CLASS zcl_prodsparte_provider IMPLEMENTATION.
METHOD get_data.
TYPES: BEGIN OF ty_base,
matnr TYPE mvke-matnr,
vtweg TYPE mvke-vtweg,
prodh TYPE mvke-prodh,
maktx TYPE makt-maktx,
END OF ty_base.
DATA lt_base TYPE STANDARD TABLE OF ty_base WITH DEFAULT KEY.
IF iv_vtweg IS INITIAL.
SELECT mvke~matnr,
mvke~vtweg,
mvke~prodh,
makt~maktx
FROM mvke
LEFT OUTER JOIN makt
ON makt~matnr = mvke~matnr
AND makt~spras = @iv_spras
INTO TABLE @lt_base
WHERE mvke~vkorg = @iv_vkorg
AND mvke~prodh <> @space. "#EC CI_NOFIELD
ELSE.
SELECT mvke~matnr,
mvke~vtweg,
mvke~prodh,
makt~maktx
FROM mvke
LEFT OUTER JOIN makt
ON makt~matnr = mvke~matnr
AND makt~spras = @iv_spras
INTO TABLE @lt_base
WHERE mvke~vkorg = @iv_vkorg
AND mvke~vtweg = @iv_vtweg
AND mvke~prodh <> @space. "#EC CI_NOFIELD
ENDIF.
IF lt_base IS INITIAL.
RETURN.
ENDIF.
"Falls mehrere Vertriebswege gelesen werden, gewinnt bewusst der kleinste VTWEG.
SORT lt_base BY matnr vtweg.
DELETE ADJACENT DUPLICATES FROM lt_base COMPARING matnr.
SELECT paph1, wwpfa, wwpsp
FROM zprodsparte_map
INTO TABLE @DATA(lt_map). "#EC CI_NOWHERE
SORT lt_map BY paph1.
SELECT prodh, vtext
FROM t179t
INTO TABLE @DATA(lt_h)
WHERE spras = @iv_spras. "#EC CI_NOFIELD
SORT lt_h BY prodh.
SELECT wwpfa, bezek
FROM t25a0
INTO TABLE @DATA(lt_fam)
WHERE spras = @iv_spras. "#EC CI_NOFIELD
SORT lt_fam BY wwpfa.
SELECT wwpsp, bezek
FROM t25a1
INTO TABLE @DATA(lt_spa)
WHERE spras = @iv_spras. "#EC CI_NOFIELD
SORT lt_spa BY wwpsp.
LOOP AT lt_base INTO DATA(ls_base).
DATA(ls_out) = VALUE ty_out(
matnr = ls_base-matnr
maktx = ls_base-maktx
paph1 = ls_base-prodh(5)
wwpsp = 'UNASS'
wwpsp_text = iv_fallback
is_assigned = abap_false ).
READ TABLE lt_h INTO DATA(ls_h)
WITH KEY prodh = ls_base-prodh BINARY SEARCH.
IF sy-subrc = 0.
ls_out-paph1_text = ls_h-vtext.
ENDIF.
READ TABLE lt_map INTO DATA(ls_m)
WITH KEY paph1 = ls_out-paph1 BINARY SEARCH.
IF sy-subrc = 0.
ls_out-wwpfa = ls_m-wwpfa.
ls_out-wwpsp = ls_m-wwpsp.
ls_out-is_assigned = abap_true.
READ TABLE lt_fam INTO DATA(ls_f)
WITH KEY wwpfa = ls_m-wwpfa BINARY SEARCH.
IF sy-subrc = 0.
ls_out-wwpfa_text = ls_f-bezek.
ENDIF.
READ TABLE lt_spa INTO DATA(ls_s)
WITH KEY wwpsp = ls_m-wwpsp BINARY SEARCH.
IF sy-subrc = 0.
ls_out-wwpsp_text = ls_s-bezek.
ENDIF.
ENDIF.
APPEND ls_out TO rt_out.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
@@ -0,0 +1,120 @@
*&---------------------------------------------------------------------*
*& Report Z_PRODSPARTE_MAP_BUILD
*&---------------------------------------------------------------------*
*& Zweck: Einmal-/periodischer Lauf. Zieht die eindeutige Zuordnung
*& PAPH1 -> WWPFA (Produktfamilie) -> WWPSP (Produktsparte)
*& aus den CO-PA-Einzelposten CE11000 und schreibt sie in
*& ZPRODSPARTE_MAP.
*&
*& Quelle der Wahrheit: CO-PA-Belege, in denen KEDR bereits abgeleitet hat.
*& PAPH1 mit mehreren Familie/Sparte-Kombinationen wird protokolliert und
*& nicht geschrieben.
*&
*& Hinweis: Dieser Report ist bewusst fix fuer CE11000 geschrieben.
*& Falls der Ergebnisbereich variabel sein soll, muss die CE1xxxx-Tabelle
*& dynamisch aus ERKRS gebildet werden.
*&---------------------------------------------------------------------*
REPORT z_prodsparte_map_build.
PARAMETERS p_test TYPE abap_bool DEFAULT 'X' AS CHECKBOX.
TYPES: BEGIN OF ty_combo,
paph1 TYPE ce11000-paph1,
wwpfa TYPE ce11000-wwpfa,
wwpsp TYPE ce11000-wwpsp,
END OF ty_combo.
TYPES: BEGIN OF ty_map,
paph1 TYPE ce11000-paph1,
wwpfa TYPE ce11000-wwpfa,
wwpsp TYPE ce11000-wwpsp,
cnt TYPE i,
END OF ty_map.
DATA gt_combo TYPE SORTED TABLE OF ty_combo
WITH UNIQUE KEY paph1 wwpfa wwpsp.
DATA gt_map TYPE STANDARD TABLE OF ty_map WITH DEFAULT KEY.
DATA gt_ambig TYPE STANDARD TABLE OF ty_combo WITH DEFAULT KEY.
START-OF-SELECTION.
SELECT DISTINCT paph1, wwpfa, wwpsp
FROM ce11000
INTO TABLE @gt_combo
WHERE paph1 <> @space
AND wwpfa <> @space
AND wwpsp <> @space. "#EC CI_NOFIELD
IF gt_combo IS INITIAL.
WRITE: / 'Keine Kombinationen in CE11000 gefunden. Abbruch.'.
RETURN.
ENDIF.
LOOP AT gt_combo INTO DATA(ls_combo).
READ TABLE gt_map INTO DATA(ls_map)
WITH KEY paph1 = ls_combo-paph1.
IF sy-subrc <> 0.
ls_map = VALUE ty_map(
paph1 = ls_combo-paph1
wwpfa = ls_combo-wwpfa
wwpsp = ls_combo-wwpsp
cnt = 1 ).
APPEND ls_map TO gt_map.
ELSEIF ls_map-wwpfa <> ls_combo-wwpfa
OR ls_map-wwpsp <> ls_combo-wwpsp.
ls_map-cnt = ls_map-cnt + 1.
MODIFY gt_map FROM ls_map TRANSPORTING cnt WHERE paph1 = ls_combo-paph1.
APPEND ls_combo TO gt_ambig.
ENDIF.
ENDLOOP.
IF gt_ambig IS NOT INITIAL.
WRITE: / '=== WARNUNG: mehrdeutige PAPH1 (mehrere Familie/Sparte) ==='.
WRITE: / 'Diese werden NICHT in die Mapping-Tabelle geschrieben:'.
ULINE.
LOOP AT gt_ambig INTO ls_combo.
WRITE: / ls_combo-paph1, 12 ls_combo-wwpfa, 22 ls_combo-wwpsp.
ENDLOOP.
ULINE.
ENDIF.
DATA lt_insert TYPE STANDARD TABLE OF zprodsparte_map WITH DEFAULT KEY.
LOOP AT gt_map INTO ls_map WHERE cnt = 1.
APPEND VALUE zprodsparte_map(
paph1 = ls_map-paph1
wwpfa = ls_map-wwpfa
wwpsp = ls_map-wwpsp
crdate = sy-datum
cruser = sy-uname ) TO lt_insert.
ENDLOOP.
WRITE: / '=== Eindeutige Zuordnungen ==='.
WRITE: / 'PAPH1', 12 'Familie', 22 'Sparte'.
ULINE.
LOOP AT lt_insert INTO DATA(ls_insert).
WRITE: / ls_insert-paph1, 12 ls_insert-wwpfa, 22 ls_insert-wwpsp.
ENDLOOP.
ULINE.
WRITE: / 'Eindeutige Saetze :', lines( lt_insert ).
WRITE: / 'Mehrdeutige PAPH1 :', lines( gt_ambig ).
IF lt_insert IS INITIAL.
WRITE: / 'Keine eindeutigen Saetze, Tabelle wird nicht geloescht.'.
RETURN.
ENDIF.
IF p_test = abap_true.
WRITE: / 'TESTLAUF - keine DB-Aenderung. Haken entfernen zum Schreiben.'.
RETURN.
ENDIF.
DELETE FROM zprodsparte_map. "#EC CI_NOWHERE
INSERT zprodsparte_map FROM TABLE lt_insert.
IF sy-subrc = 0.
COMMIT WORK.
WRITE: / lines( lt_insert ), 'Saetze in ZPRODSPARTE_MAP geschrieben.'.
ELSE.
ROLLBACK WORK.
WRITE: / 'Fehler beim Schreiben, sy-subrc=', sy-subrc.
ENDIF.
@@ -0,0 +1,40 @@
*&---------------------------------------------------------------------*
*& Report Z_PRODSPARTE_REPORT
*&---------------------------------------------------------------------*
*& Zweck: ALV-Testreport fuer die flache Referenztabelle:
*& MATNR, MAKTX, PAPH1, PAPH1_TEXT,
*& WWPFA, WWPFA_TEXT, WWPSP, WWPSP_TEXT, IS_ASSIGNED.
*&
*& Kernlogik liegt in ZCL_PRODSPARTE_PROVIDER->GET_DATA( ).
*& Ein spaeterer SAP-Gateway/OData-Service soll dieselbe Methode nutzen.
*&---------------------------------------------------------------------*
REPORT z_prodsparte_report.
PARAMETERS p_vkorg TYPE vkorg OBLIGATORY.
PARAMETERS p_vtweg TYPE vtweg.
PARAMETERS p_spras TYPE spras DEFAULT sy-langu.
PARAMETERS p_fallb TYPE bezek DEFAULT 'Nicht zugeordnet'.
START-OF-SELECTION.
DATA(lo_provider) = NEW zcl_prodsparte_provider( ).
DATA(lt_result) = lo_provider->get_data(
iv_vkorg = p_vkorg
iv_vtweg = p_vtweg
iv_spras = p_spras
iv_fallback = p_fallb ).
IF lt_result IS INITIAL.
MESSAGE 'Keine Daten - VKORG/VTWEG pruefen.' TYPE 'I'.
RETURN.
ENDIF.
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lo_alv)
CHANGING
t_table = lt_result ).
lo_alv->get_functions( )->set_all( abap_true ).
lo_alv->get_columns( )->set_optimize( abap_true ).
lo_alv->display( ).
@@ -8,6 +8,7 @@ Stand: 2026-05-27
- Zentrale Persistenz ueber `CentralSalesRecords`.
- Finance-Auswertung und zentrale Excel sollen dieselbe Regelengine verwenden.
- Produktsparten-Mapping ist als eigene Mapping-Schicht vorgesehen, nicht als versteckte Finance-Regel.
- Produktsparten-Referenz soll ueber SAP/ABAP bzw. Gateway als flache Tabelle geliefert werden.
- Diagramme und Anwenderdokus existieren fuer Keyuser-Prozess und technische Architektur.
## Rohquellen Nur Bei Bedarf
@@ -6,9 +6,10 @@ Stand: 2026-05-27
- Neue Anforderung: Artikel aus dem Group Sales Report sollen anhand der TR-AG-Zuordnung klassifiziert werden.
- Ziel-Felder: `Produkthierarchie`, `Produktfamilie`, `Produktsparte`.
- Produkthierarchie kommt direkt aus TR-AG-Artikelstammdaten.
- Produktfamilie und Produktsparte kommen danach ueber separate Mapping-Tabelle.
- Nicht gefundene Materialnummern laufen unter `Sonstige/ohne Zuordnung`.
- SAP TR AG bleibt Quelle der Wahrheit.
- Dashboard soll KEDR-/KE30-Ableitung nicht in C# nachbauen.
- ABAP/Gateway soll eine flache Referenz liefern: `MATNR -> PAPH1 -> WWPFA -> WWPSP`.
- Nicht gefundene oder nicht eindeutig ableitbare Materialnummern laufen unter `Nicht zugeordnet`.
## Aktueller Code-Stand
@@ -17,6 +18,21 @@ Stand: 2026-05-27
- SAP-Seed-Mapping nutzt aktuell `Z.Matnr` -> `Material` und `Z.Prodh` -> `ProductGroup`.
- Zu klaeren: Ist `Z.Prodh` fachlich die Produkthierarchie?
## ABAP-Arbeitsstand
- `docs/abap/ZCL_PRODSPARTE_PROVIDER.abap`: Provider fuer ALV und spaeter OData.
- `docs/abap/Z_PRODSPARTE_REPORT.abap`: ALV-Testreport.
- `docs/abap/Z_PRODSPARTE_MAP_BUILD.abap`: baut `ZPRODSPARTE_MAP` aus `CE11000`.
- `docs/abap/README_PRODSPARTE.md`: DDIC- und Pruefhinweise.
## SAP-Zielbild
- `Z_PRODSPARTE_MAP_BUILD` liest reale CO-PA-Ableitungen aus `CE11000`.
- Eindeutige `PAPH1 -> WWPFA -> WWPSP` werden in `ZPRODSPARTE_MAP` gespeichert.
- Mehrdeutige PAPH1 werden protokolliert und nicht geschrieben.
- `ZCL_PRODSPARTE_PROVIDER` liest `MVKE-PRODH`, Texte und Mapping.
- OData-Service ruft spaeter dieselbe Provider-Klasse.
## Offene Punkte Fuer Sitzung
- Quelle und Format des TR-AG-Artikelstamms.
@@ -25,8 +41,10 @@ Stand: 2026-05-27
- Matching-Regeln: exakt, Prefix, Range, Prioritaet.
- Historisierung der Zuordnung fuer reproduzierbare Reports.
- Pruefansicht fuer nicht zugeordnete Artikel.
- `PAPH1 = MVKE-PRODH(5)` fachlich/technisch bestaetigen.
- Richtige Texttabellen fuer `WWPFA`/`WWPSP` bestaetigen.
- VKORG/VTWEG fuer TR-AG-Referenzlauf bestaetigen.
## Rohquelle Nur Bei Bedarf
- Detaildoku: `docs/PRODUCT_SPARTEN_MAPPING_2026-05-27.md`