Finanzplandaten importieren in S/4 / Budgetierung auf Kostenstellen
Über die FIORI-App "Finanzplandaten importieren" können Plandaten in die ACDOCP geladen werden. Zu den Plandaten gehören seit Release 1909 (on premise) auch Budgets auf Kostenstellen, eine Funktionalität, die seit Ewigkeiten von Kunden nachgefragt und nun endlich seitens SAP ausgeliefert wurde. Hiermit können also bereitgestellte Plandaten ins System geladen und z.B. über die App "Multidimensionale Bilanz" den Ist-Werten gegenüber gestellt werden.
Für erweiterte Planungsfunktionalitäten ist eine dedizierte Planungslösung notwendig, also bspw. SAP Analytics Cloud (SAC) bzw. embedded BPC. Das o.g. Szenario eignet sich also insbesondere dann, wenn die Plandaten überwiegend aus externen Quellen stammen. Es kann ohne weitere Lizensierung (fast) out of the Box verwendet werden, lediglich etwas Customizing ist vonnöten...
IMG: Controlling - Controlling Allgemein – Planung - Kategorie für Planung pflegen
Hier werden die sog. Plankategorien ausgeprägt, welche in etwa den Planversionen in der klassischen SAP Planungswelt entsprechen. SAP liefert hier bereits eine gewisse Anzahl von Kategorien aus, die ggf. als Kopiervorlage dienen können. Für die Budgetierung auf Kostenstellen kann die Plankategorie BUDGET02 verwendet werden. Für gewöhnliche Planzahlen stellt SAP die Kategorie PLN bereit.
Um die Daten über die Finanzplanungs-App importieren und ggf. löschen zu können, müssen natürlich die entsprechenden Optionen ausgewählt werden. In der IMG-Doku zur o.g. Aktivität finden sich detaillierte Ausführungen zu den einzelnen Einstellungen.
Sollen lediglich reine Plandaten importiert werden, war's das schon. Die folgenden IMG-Aktivitäten sind nur für Budgets notwendig. Offenbar ist die Funktionalität "Budgetierung auf Kostenstellen" unter großem Zeitdruck entstanden, so dass nicht mal Zeit war, alle IMG Knoten zu benamsen...;-):
IMG: Controlling - Controlling Allgemein – Planung - Knotentext wurde nicht gefunden - Budgetprüfungen für Kategorien festlegen
Mit der vorgenannten IMG Aktivität kann bei Budget-Kategorien die Verfügbarkeits- sowie die Konsistenzprüfung aktiviert werden. Das weiteren ist das Profil für die Budgetverfügbarkeitskontrolle auszuprägen:
IMG: Controlling – Kostenstellenrechnung – Etatverwaltung - Profil für Budgetverfügbarkeitskontrolle für Kostenstellen pflegen...
In diesem Abschnitt können je Sachkontenhierarchie/Sachkontengruppe/Vorgangsgruppe Toleranzen und die entsprechende Systemreaktion (Fehler/Warnung) konfiguriert werden. Weitere Infos finden sich in der ausführlichen Dokumentation zur IMG-Aktivität.
Für die Budgetierung auf Kostenstellen muss nun das definierte Verfügbarkeitsprofil im Kostenstellenstammsatz hinterlegt werden.
ACHTUNG: dies ist im Dialog nur mit der FIORI-App zur Kostenstellenpflege möglich, nicht mit der klassischen GUI-Transaktion KS02. Aber: über die Massenänderungs- bzw. Sammelbearbeitungsfunktion KS12N können die budgetrelevanten Daten versorgt werden. Insofern besteht Hoffnung, das in einem der kommenden Feature-Packs bzw. Releases, die KS02 entsprechend ertüchtigt wird.
Im Reiter Steuerung im Bereich Budgetverfügbarkeitskontrolle sind die Eingabefelder für die Budgetierung zu finden:
- Budgettragende Kostenstelle
- Verfügbarkeitsprofil
- Budgetverfügbarkeitskontrolle aktiv
Anschließend können die Plan- bzw. Budgetdaten importiert werden. Die App Finanzplandaten importieren ist praktisch selbsterklärend. Zunächst wird die Vorlage generiert, anschließend geeignet mit Daten befüllt und abschließend wieder hochgeladen. Die Daten werden in der ACDOCP gespeichert.
Als Trennzeichen für die CSV-Datei sollte ";" gewählt werden. Auf diese Weise kann die Vorlage ohne weiteres Zutun in Excel geöffnet werden und die einzelnen Felder sind dabei in getrennten Spalten angeordnet.
Je nach ausgewähltem Planungsgebiet werden automatisch die zu befüllenden Spalten inklusive Feldnamen und Überschrift konfiguriert.
Buchungstext in Abgrenzungsbelege des Accruals Management einfügen
Über das Customizing des Accruals Management hat man (abgesehen von der Belegart und natürlich der zu bebuchenden Konten) keinerlei weiteren Einfluß auf den Inhalt der erzeugten FI-Belege.
Typischerweise ist das ARAP-Konto jedoch mit Feldstatusgruppe „Text obligatorisch“ versehen, was meist auch nicht geändert werden soll. Dies führt unweigerlich zu einem Fehler in der Buchungsschnittstelle, da der Buchungstext im Standard nicht befüllt wird.
Damit die automatischen Buchungen aus der ACE trotzdem durchgehen, kann mithilfe einer Implementierung zum BadI BADI_ACE_DOCUMENT_SCHEMA_CUST ein Buchungstext zugeführt werden (s. auch Hinweis 2769936).
Im nachfolgenden Beispiel-Coding wird der Text aus dem Stammsatz des Abgrenzungsobjektes gelesen und in den Buchungstext eingefüllt.
METHOD if_ace_document_schema_badi~change_calculated_schema.
“Subklasse zum IF_ACE_MDO_SUBOBJ
DATA: lo_subobj_acac TYPE REF TO cl_acac_mdo_subobj,
l_text TYPE acac_text.
CHECK ct_schema_calculated[] IS NOT INITIAL.
* Buchungstext aus Beschreibung des Abgrenzungsobjekts holen...
TRY.
"Objekt erzeugen, Subklasse casten
lo_subobj_acac ?= ct_schema_calculated[ 1 ]-o_item->mo_subobj.
"Entsprechendes Subklassen-Atrribut holen
l_text = lo_subobj_acac->ms_acac_obj_header-text.
"Text in die Buchungspos. einfüllen
LOOP AT ct_schema_calculated
ASSIGNING FIELD-SYMBOL(<lf_schema_calculated>).
<lf_schema_calculated>-sgtxt = l_text.
ENDLOOP.
CATCH cx_root.
ENDTRY.
ENDMETHOD.
Pivot-Browser - eigene Aktionen
Der Pivot-Browser (PIVB) ist ein neues Ausgabe-Framework der SAP, welches die Anzeige beliebiger (strukturierter) Dateninhalte in Tabellenform ermöglicht. Die Art der Darstellung der Daten ist dabei an das bekannte ALV-Grid angelehnt. Im Unterschied zum ALV geht der Funktionsumfang des Pivot-Browsers jedoch über die reine Aufbereitung und Anzeige der Daten hinaus. Auch die Datenbeschaffung (HANA-optimiert) sowie die Behandlung von Benutzerinteraktionen ist in das Framework integriert.
Details hierzu finden sich in den PDF-Anhängen zum Hinweis 2100879 - Pivot Browser: Dokumentation
Einige der im Standard ausgelieferten Funktionalitäten, die auf dem Pivot-Browser basieren, sind die Einzelpostenbrowser in der S/4 Finanzbuchhaltung:
| Transaktion | Funktion / Beschreibung |
|---|---|
| FAGLL03H | Sachkonteneinzelposten-Browser (ledgerspezifisch) |
| FBL3H | Sachkonteneinzelposten-Browser (einfach) |
| FBL1H | Kreditoren-Einzelposten |
| FBL5H | Debitoren-Einzelposten |
Während der Anzeige-Bereich (links) weitestgehend identisch zum bekannten ALV funktioniert, ist der Interaktionsbereich (rechts) ein neu gestaltetes Element im Pivot-Browser.
Im Bereich Spalten können die anzuzeigenden Felder ausgewählt werden. Bei den o.g. FI-Einzelpostenbrowsern stehen gegen Ende der Liste auch Stammdatenfelder und Bezeichnungen zur Verfügung. So kann bspw. zur Kostenstelle die entsprechende Kostenstellenbezeichnung in die Anzeige geholt werden, ohne wie bei den klassischen Einzelpostenlisten (FBLxN) den Feldvorrat erweitern und die Inhalte per BTE/BADI nachlesen zu müssen.
Der Bereich Layouts enthält alle verfügbaren Anzeigelayouts und ermöglicht deren Verwaltung wie unter ALV bekannt (entsprechende Berechtigung vorausgesetzt).
Interessant ist der Bereich Aktionen, in dem für den aktuellen Anzeigevorrat verfügbare Benutzeraktionen dargestellt sind. Diese können in einer (max. zweistufigen) Baumstruktur angeordnet werden, um so gewisse Interaktionen zu gruppieren.
Sie ahnen es wahrscheinlich schon, dieser Bereich lässt sich modifikationsfrei beliebig erweitern und mit kundenspezifischen Aktionen spicken...
Weiter unten möchte ich ein Beispiel für eine solche kundeneigene Aktion zeigen, das die Erzeugung von Abgrenzungsobjekten der Accrual Engine bzw. des Accruals Management (ab S/4 1809) direkt aus den Einzelpostenbrowsern der Finanzbuchhaltung ermöglicht.
Die einzelnen Anwendungen des Pivot-Browsers werden als Erweiterungsimplementierung des Erweiterungsspots PIVB registriert. Für die EP-Browser im FI (s.o.) ist dies die Implementierung FAGL_LIB_PIVB. In ihr wiederum werden die Implementierungen zur BadI-Definition FAGL_LIB gerufen, zu der auch kundeneigene Implementierungen angelegt werden können.
Für die Aktionen sind die beiden Interface-Methoden SIDEBAR_ACTIONS_SET und SIDEBAR_ACTIONS_HANDLE relevant. In ersterer kann der "Aktionsbaum" um kundeneigene Aktionen erweitert werden, in der zweitgenannten Methode wird dann die eigentliche Aktion ausgestaltet.
Fügen wir also zunächst eine Aktion in einem kundeneigenen Ordner hinzu:
METHOD if_fagl_lib~sidebar_actions_set.
* Kundeneigene Aktionen im Einzelpostenbrowser
TYPE-POOLS: icon.
* Neuer Ordner am Ende anfügen
APPEND INITIAL LINE TO c_menu-t_folder_level1 ASSIGNING FIELD-SYMBOL(<lf_folder>).
<lf_folder>-folder_key = 'ZZACE'.
<lf_folder>-folder_text = 'Abgrenzungsobjekt'.
* Aktion in den neuen Ordner einfügen
APPEND INITIAL LINE TO <lf_folder>-t_item_level2 ASSIGNING FIELD-SYMBOL(<lf_menuitem>).
<lf_menuitem>-item_key = 'ZZACE_CREATE'.
<lf_menuitem>-text = 'Abgrenzungsobjekt anlegen'.
<lf_menuitem>-icon = icon_fencing.
ENDMETHOD.
...und nun kann die Aktion, die mit der ID ZZACE_CREATE angelegt wurde, ausgestaltet werden.
METHOD if_fagl_lib~sidebar_actions_handle.
* Kundeneigene Aktionen im Einzelpostenbrowser
DATA: l_checker TYPE i.
DATA: ls_bseg TYPE bseg.
DATA: ls_bkpf TYPE bkpf.
l_checker = 0.
CASE i_navigate_item_key.
WHEN 'ZZACE_CREATE'. "Abgrenzungsobjekt anlegen
IF it_outtab_selected_rows[] IS NOT INITIAL. "Mind. eine Zeile selektiert?
LOOP AT it_column ASSIGNING FIELD-SYMBOL(<lf_col>) WHERE fieldname = 'BUKRS' OR "Felder Bukrs, Belnr, Gjahr und Buzei in Liste?
fieldname = 'BELNR' OR
fieldname = 'GJAHR' OR
fieldname = 'BUZEI'.
IF <lf_col>-is_invisible = abap_false.
ADD 1 TO l_checker.
ENDIF.
ENDLOOP.
IF l_checker < 4.
MESSAGE 'Bitte mind. BUKRS BELNR GJAHR BUZEI in Anzeige holen' TYPE 'I'.
EXIT.
ELSE.
"Belegdaten nachlesen
READ TABLE it_outtab INDEX it_outtab_selected_rows[ 1 ]-row_id ASSIGNING FIELD-SYMBOL(<lf_row>).
MOVE-CORRESPONDING <lf_row> TO ls_bseg.
SELECT SINGLE * FROM bkpf INTO ls_bkpf
WHERE bukrs = ls_bseg-bukrs
AND belnr = ls_bseg-belnr
AND gjahr = ls_bseg-gjahr.
SELECT SINGLE * FROM bseg INTO ls_bseg
WHERE bukrs = ls_bkpf-bukrs
AND belnr = ls_bkpf-belnr
AND gjahr = ls_bkpf-gjahr
AND buzei = ls_bseg-buzei.
IF sy-subrc = 0.
"Aufruf Generierungsprogramm f. Abgrenzungsobjekte
ls_bseg-dmbtr = abs( ls_bseg-dmbtr ). "Abgrenzungsbetrag muss positiv sein
IF ls_bseg-koart NE 'S'. "Kontokorrente (FBL1H)
SUBMIT zacac_d_trans_s4 AND RETURN VIA SELECTION-SCREEN
WITH p_check = 'X'
WITH p_efdate = sy-datum
WITH p_powip = 'X'
WITH so_acmth = 'LINEAR'
WITH so_acpst = ls_bkpf-budat
WITH so_belnr = ls_bkpf-belnr
WITH so_bukrs = ls_bkpf-bukrs
WITH so_gjahr = ls_bkpf-gjahr
WITH p_amnt = ls_bseg-dmbtr
WITH p_text = ls_bseg-sgtxt.
ELSE. "FAGLL03H, FBL3H
SUBMIT zacac_d_trans_s4 AND RETURN VIA SELECTION-SCREEN
WITH p_check = 'X'
WITH p_efdate = sy-datum
WITH p_powoip = 'X' "Bei Sachkontenposten - OHNE Eröffnungbuchung als Default
WITH p_powip = space
WITH so_acmth = 'LINEAR'
WITH so_acpst = ls_bkpf-budat
WITH so_belnr = ls_bkpf-belnr
WITH so_bukrs = ls_bkpf-bukrs
WITH so_buzei = ls_bseg-buzei
WITH so_gjahr = ls_bkpf-gjahr
WITH p_amnt = ls_bseg-dmbtr
WITH p_text = ls_bseg-sgtxt.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDCASE.
ENDMETHOD.
Da der Pivot-Browser HANA optimiert ist, werden nur die Spalten gelesen, die auch im aktuellen Layout benötigt werden. Dies ist ein wesentlicher Unterschied zu den klassischen EP-Listen, die immer alle Spalten eines Postens lesen, unabhängig von deren Verwendung in der Anzeige.
D.h., es muss zunächst geprüft werden, ob die für die weitere Verarbeitung benötigten Felder auch zur Verfügung stehen!
Im weiteren Verlauf dieses Beispiels wird eine angepasste Z-Kopie des Demo-Reports ACAC_D_TRANS_EXAMPLE_S4 gerufen, der aus einem vorgegebenen Belegvorrat Abgrenzungsobjekte im Accruals Management generiert. Für die "alte" Accrual Engine (vor S/4 1809) wäre dies der Report ACAC_DATA_TRANSFER_EXAMPLE.
Erweiterung der WE/RE-Kontenfindung
Sind die Anforderungen an die WE/RE-Kontenfindung durch das Standardcustomizing (Vorgang ‚WRX’) nicht zu bedienen, kann eine sog. Kontomodifikation verwendet werden, die über die SAP-Erweiterung LMR1M002 (User Exit) bestelldatenabhängig gesetzt werden kann. Im Customizing werden dann die WE/RE-Konten in Abhängigkeit von der im Userexit versorgten Kontomodifikation in folgender Form gesetzt:
|
Kontomodifikation |
WE/RE Konto |
Bezeichnung |
|
YY1 |
<…..> |
WE/RE Konto 1 |
|
YY2 |
<…..> |
WE/RE Konto 2 |
|
… |
<…..> |
… |
Kontomodifikation - WE/RE-Konto
IMG: Finanzwesen > Hauptbuch > Geschäftsvorfälle > Integration > Materialwirtschaft > Konten für Materialwirtschaft hinterlegen (Vorgang WRX)
Ein konkreter Anwendungsfall könnte z.B. sein, dass im Rahmen der buchungskreisübergreifenden Umlagerung (Szenario ‚Cross Company Nachschub') für die internen Wareneingänge und Rechnungen ein separates WE/RE-Konto gefunden werden soll:
Beispielcoding:
Funktionsbaustein EXIT_SAPLKONT_011, Include ZXM08U18
* WE/RE-Kontenfindung anhand Bestellart
select single bsart into l_bsart from ekko where ebeln = i_wrxmod-ebeln.
if l_bsart = ‘UB’.
e_konto_modif = ‚YCC’. „Cross Company
else.
e_konto_modif = space. „Normalfall
endif.
Ausweis von Nettoumsätzen von Debitoren und Kreditoren
Zwei, drei mal wurde in den letzen Jahren in den einschlägigen deutschsprachigen FICO-Foren nach einer Auswertung von Nettoumsätzen von Debitoren bzw. Kreditoren gefragt. Da der SAP Standard sich hierbei eher bedeckt hält, lief es meist auf einen Z-Report hinaus.
Eine Lösung, die in die einschlägigen EP-Listen (FBLxN) integriert ist, hat FICO-Forum User Frank Thielemann freundlicherweise zur Verfügung gestellt:
Es handelt sich um einen Ansatz, der die Erweiterungsmöglichkeiten der EP-Listen via Business Transaction Event (BTE) nutzt. Alternativ kann auch das BadI FAGL_ITEMS_CH_DATA herhalten. Details hierzu siehe hier, Abschnitt "Hinzufügen eigener Felder".
Pimp my Batchman
Was sich anhört wie der Titel meines gefloppten Rap-Albums, ist in Wahrheit ein Upgrade des beliebten CO-Superhelden BATCHMAN, mit dem CO-Belege aus externen Dateien ins System geladen werden können. Mein Kollege Markus Läller hat hierzu den von SAP ausgelieferten schwachbrüstigen Schummeldiesel rausgerissen und durch ein bärenstarkes 5.0-Liter V8-Aggregat ersetzt.
Im Vergleich zur Standardauslieferung hat der aufgepumpte Batchman folgendes zu bieten:
- Natives Excel-Format kann ohne vorherige Konvertierung ins CSV-Format verwendet werden
- Vorlagen auf das Wesentliche reduziert und übersichtlich
- Keine führenden Nullen in der Uploaddatei für Stammdaten benötigt
- Zahlenformate mit Dezimalpunkt oder -komma unterstützt
- Kostenrechnungskreis wird auf Defaultwert gesetzt, sofern nicht gefüllt
- User wird automatisch gesetzt (SY-UNAME)
- Automatischer Belegsplit, wenn maximal zulässige Zeilenanzahl überschritten wird
Der Download-Link zu den im folgenden beschriebenen, vereinfachten Excel-Vorlagen findet sich weiter hinten in diesem Artikel.
Wer den BATCHMAN noch gar nicht kennt, kann sich hier mit der Standardauslieferung vertraut machen.
Unterstützte Datenübernahmen
Manuelle Kostenverrechnung
Mit Hilfe der manuellen Kostenverrechnung können Kosten umgebucht werden. Dabei wird ein Senderobjekt (z.B. eine Kostenstelle) entlastet und ein Empfängerobjekt (z.B. eine andere Kostenstelle/ein Auftrag) belastet. Dies ist als Ergänzung der maschinellen Verfahren für die Kostenverrechnung (Umlage, Verteilung) zu verstehen, bei denen nicht mit festen Regeln gearbeitet werden kann.
Im SAP Standard wird die manuelle Kostenverrechnung mit der Transaktion KB15N durchgeführt. Mittels der Transaktion BATCHMAN können Massendaten unter Zuhilfenahme folgender Vorlage gebucht werden:
Die Vorlage besitzt folgenden Aufbau:
Allgemein
Die Spalte A darf nicht verändert werden. Hier stehen die Strukturdaten, die dynamisch die Zeileninformationen aufbauen. Neben den Strukturen stehen die Felder, die in den Strukturen enthalten sind .
Die Daten werden ab Zeile 4 übernommen, d.h. die Zeile 3 (leer) darf nicht gelöscht werden.
Es dürfen maximal 9999 Zeilen angegeben werden (inklusive Leerzeilen).
Belegkopf
Das Feld DOC_NO stellt die Verbindung zwischen Belegkopf und Belegposition her. Somit es möglich, 1 bis n Belege zu erzeugen.
Im Feld DOC_HDR_TX kann ein Belegkopftext angegeben werden.
In den Feldern Belegdatum und Buchungsdatum können Angaben gemacht werden. Bleiben die Felder leer, wird das Systemdatum (=Tagesdatum) übernommen.
Im Feld TRANS_CURR muss die Transaktionswährung angegeben werden.
Belegposition
Das Feld DOC_NO stellt die Verbindung zwischen Belegkopf und Belegposition her. Somit es es möglich, 1 bis n Belege zu erzeugen.
Im Feld COST_ELEM ist die umzubuchende Kostenart anzugeben. Die Kostenart darf ohne führende Nullen angegeben werden.
Im Feld VALUE_TCUR muss der Wert der Buchung angegeben werden. Dezimalstellen können mit Punkt oder Komma angegeben werden.
Im Feld SEND_CCTR ist die abgebende SAP Kostenstelle anzugeben. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Im Feld REC_CCTR ist die empfangende SAP Kostenstelle anzugeben, sofern kein echter Auftrag kontiert werden soll. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Sofern ein Auftrag kontiert werden soll, ist das Feld REC_ORDER mit der SAP Auftragsnummer zu füllen. Die Auftragsnummer darf ohne führende Nullen angegeben werden.
Im Feld SEG_TEXT kann ein Positionstext angegeben werden.
Manuelle Umbuchung Kosten
Mittels der Funktion manuelle Umbuchung Kosten können Primärkosten umgebucht werden. Die Originalkostenart bleibt immer erhalten. Die Funktion wurde vorwiegend konzipiert, um Fehlbuchungen zu korrigieren. Es ist im Einzelfall zu entscheiden, ob wirklich im CO umgebucht werden sollte oder doch lieber die Buchung im Finanzwesen zu korrigieren ist.
Wichtig: Anders als bei der manuellen Kostenverrechnung wird das abgebende Objekt (z.B. die Kostenstelle) nicht mit Entlastungskennzeichen gebucht, sondern mit negativem Belastungskennzeichen.
Im SAP Standard wird die manuelle Umbuchung der Kosten mit der Transaktion KB11N durchgeführt.
Die Vorlage besitzt folgenden Aufbau:
Allgemein
Die Spalte A darf nicht verändert werden. Hier stehen die Strukturdaten, die dynamisch die Zeileninformationen aufbauen. Neben den Strukturen stehen die Felder, die in den Strukturen enthalten sind .
Die Daten werden ab Zeile 4 übernommen, d.h. die Zeile 3 (leer) darf nicht gelöscht werden.
Es dürfen maximal 9999 Zeilen angegeben werden (inklusive Leerzeilen).
Belegkopf
Das Feld DOC_NO stellt die Verbindung zwischen Belegkopf und Belegposition her. Somit es möglich, 1 bis n Belege zu erzeugen.
Im Feld DOC_HDR_TX kann ein Belegkopftext angegeben werden.
In den Feldern Belegdatum und Buchungsdatum können Angaben gemacht werden. Bleiben die Felder leer, wird das Systemdatum (=Tagesdatum) übernommen.
Im Feld TRANS_CURR muss die Transaktionswährung angegeben werden.
Belegposition
Das Feld DOC_NO stellt die Verbindung zwischen Belegkopf und Belegposition her. Somit es es möglich, 1 bis n Belege zu erzeugen.
Im Feld COST_ELEM ist die umzubuchende Kostenart anzugeben. Die Kostenart darf ohne führende Nullen angegeben werden.
Im Feld VALUE_TCUR muss der Wert der Buchung angegeben werden. Dezimalstellen können mit Punkt oder Komma angegeben werden.
Im Feld SEND_CCTR ist die abgebende SAP Kostenstelle anzugeben. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Im Feld REC_CCTR ist die empfangende SAP Kostenstelle anzugeben, sofern kein echter Auftrag kontiert werden soll. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Sofern ein Auftrag kontiert werden soll, ist das Feld REC_ORDER mit der SAP Auftragsnummer zu füllen. Die Auftragsnummer darf ohne führende Nullen angegeben werden.
Im Feld SEG_TEXT kann ein Positionstext angegeben werden.
Interne Leistungsverrechnung
Bei der direkten Leistungsverrechnung wird die erbrachte betriebliche Leistung gemessen, erfasst und verrechnet. Hierfür müssen im System die entsprechenden (messbaren) Bezugsgrößen (= Maßgrößen für die Kostenverursachung) angelegt sein. In der Kostenstellenrechnung werden sie als Leistungsarten bezeichnet. Eine Leistungsverrechnung erfolgt beispielsweise durch das Rückmelden von Arbeitsvorgängen bzw. durch Kontieren der Leistung. Hierbei wird die erbrachte Leistung mit dem Tarif der Leistungsart multipliziert.
Dies erfordert auf den entsprechenden Kostenstellen eine Planung der Leistungsarten mit manuell zu setzendem Tarif.
Im SAP Standard wird die Leistungsverrechnung mit der Transaktion KB21N durchgeführt. Mittels der Transaktion BATCHMAN können Massendaten unter zur Hilfenahme folgender Vorlage gebucht werden:
Allgemein
Die Spalte A darf nicht verändert werden. Hier stehen die Strukturdaten, die dynamisch die Zeileninformationen aufbauen. Neben den Strukturen stehen die Felder, die in den Strukturen enthalten sind .
Die Daten werden ab Zeile 4 übernommen, d.h. die Zeile 3 (leer) darf nicht gelöscht werden.
Es dürfen maximal 9999 Zeilen angegeben werden (inklusive Leerzeilen).
Belegkopf
Im Feld DOC_HDR_TX kann ein Belegkopftext angegeben werden.
In den Feldern Belegdatum und Buchungsdatum können Angaben gemacht werden. Bleiben die Felder leer, wird das Systemdatum (=Tagesdatum) übernommen.
Belegposition
Im Feld ACTTYPE ist Leistungsart anzugeben. Die Leistungsart darf ohne führende Nullen angegeben werden.
Im Feld ACTVTY_QTY muss die geleistete Menge angegeben werden. Die Leistungseinheit wird aus dem Leistungsartenstammsatz ermittelt und nicht eingebbar.
Im Feld SEND_CCTR ist die abgebende SAP Kostenstelle anzugeben. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Im Feld REC_CCTR ist die empfangende SAP Kostenstelle anzugeben, sofern kein echter Auftrag kontiert werden soll. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Sofern ein Auftrag kontiert werden soll, ist das Feld REC_ORDER mit der SAP Auftragsnummer zu füllen. Die Auftragsnummer darf ohne führende Nullen angegeben werden.
Im Feld SEG_TEXT kann ein Positionstext angegeben werden.
Statistische Kennzahl
Statistische Kennzahlen können für Kennzahlenbildungen im Berichtswesen sowie als Bezugsbasis für periodenbezogene Verrechnungen erfasst werden. Dies erfolgt ebenfalls im Rahmen einer vorgangsbezogenen Verrechnung im Controlling.
Im SAP Standard werden statistische Kennzahlen mit der Transaktion KB31N gebucht. Mittels der Transaktion BATCHMAN können Massendaten unter zur Hilfenahme folgender Vorlage gebucht werden:
Allgemein
Die Spalte A darf nicht verändert werden. Hier stehen die Strukturdaten, die dynamisch die Zeileninformationen aufbauen. Neben den Strukturen stehen die Felder, die in den Strukturen enthalten sind .
Die Daten werden ab Zeile 4 übernommen, d.h. die Zeile 3 (leer) darf nicht gelöscht werden.
Es dürfen maximal 9999 Zeilen angegeben werden (inklusive Leerzeilen).
Belegkopf
Im Feld DOC_HDR_TX kann ein Belegkopftext angegeben werden.
In den Feldern Buchungsdatum können Angaben gemacht werden. Sofern das Feld leer ist wird das Tagesdatum übernommen.
Belegposition
Im Feld STATKEYFIG ist die statistische Kennzahl anzugeben. Die Kennzahl darf ohne führende Nullen angegeben werden.
Im Feld STAT_QTY muss der Wert/die Menge angegeben werden. Dezimalstellen können mit Komma und Punkt abgetrennt werden.
Im Feld REC_CCTR ist die empfangende SAP Kostenstelle anzugeben, sofern kein echter Auftrag kontiert werden soll. Die Kostenstelle darf ohne führende Nullen angegeben werden.
Sofern ein Auftrag kontiert werden soll, ist das Feld REC_ORDER mit der SAP Auftragsnummer zu füllen. Die Auftragsnummer darf ohne führende Nullen angegeben werden.
Im Feld SEG_TEXT kann ein Positionstext angegeben werden.
Vorlagen
Nachfolgend der Download-Link zu den oben beschriebenen Excel-Templates:
https://drive.google.com/open?id=1PD1TyrMrV0ncoCvSyceVbgiOrvRi_cDD
Es handelt sich im um ein RAR-Archiv, in dem folgende Excel-Vorlagen enthalten sind:
Installation
Legen Sie in der SE24 die Klasse ZCL_IM_BATCHMAN an und betätigen Sie die Drucktaste "Quelltext-basiert".
Laden Sie anschließend das Coding der Klasse hier herunter und kopieren Sie es in den Editor ein. Aktivieren Sie die Klasse und verankern Sie diese im Customizing unter
Controlling - Kostenstellenrechnung - Istbuchungen - Datenübernahme aus Fremdsystemen - BAdI: Übernahme von externen CO-Istdaten implementieren...
Legen Sie eine BADI-Implementierung an und geben Sie als implementierende Klasse ZCL_IM_BATCHMAN vor.
Anschließend ist die Funktionalität aktiv.
Ausführung / Handhabung
In der Transaktion BATCHMAN stehen folgende Funktionen zur Verfügung:
- Ausführen der Datenübernahme
- Nachbearbeiten der Datenübernahme
- Stornieren der Datenübernahme
- Protokoll zur Datenübernahme anzeigen.
- Testen/Buchen : Die Datenübernahme kann im Testmodus und im Echtlauf ( Buchen ) gestartet werden. Im Testlauf werden alle erforderlichen Prüfungen durchgeführt, jedoch noch keine Buchungen vorgenommen.
- Warnungen ignorieren : Ist dieses Kennzeichen gesetzt, werden Belege auch dann gebucht, wenn bei der Belegprüfung Warnmeldungen auftreten. Ist das Kennzeichen nicht gesetzt, verhindert das Auftreten von Warnungen bei der Belegprüfung die Buchung des betreffenden Belegs.
- Das Feld Externe Nummernvergabe bitte nicht nutzen.
- Datenübernahme-Text : Den Datenübernahmen kann ein Text zugeordnet werden, um die Identifikation von Daten zu unterstützen.
Dateiname Buchungsdaten : Alle bei den Belegprüfungen auftretenden Nachrichten werden protokolliert. Im Echtlauf wird das Protokoll unter der Datenübernahme-Kennung gespeichert. Es kann später mit dieser Kennung gefunden und angezeigt werden (s.a. Protokoll zur Datenübernahme ). Daten, die nicht erfolgreich übernommen werden konnten, werden in einen Nachbearbeitungsvorrat gestellt. Dieser wird ebenfalls über die Kennung der Datenübernahme identifiziert. Dadurch wird gewährleistet, dass sich die Daten zwischen Einlesen und Nachbearbeitung nicht ändern.
Die externe Datenquelle kann mehrfach für die Datenübernahme verwendet werden kann. Die Reaktion der Anwendung auf die mehrfache Übernahme der gleichen Datenquelle kann über die Nachrichtensteuerung der Nachricht 001 des Arbeitsgebietes K41C eingestellt werden. Vorab eingestellt ist, dass der Hinweis auf eine bereits mit der gleichen Datenquelle durchgeführte Datenübernahme als Info-Meldung gezeigt wird, die übergangen werden kann.
Wurde die Datenübernahme im Testlauf durchgeführt, wird folgendes Protokoll ausgegeben:
Mittels Buchen kann die Buchung ausgeführt werden:
Das Ergebnis sind entsprechende Buchungsbelege, die wie folgt angezeigt werden können:
|
|
Anzeigen |
Storno |
|
Manuelle Kostenverrechnung |
KB16N |
KB17N |
|
Manuelle Umbuchung Kosten |
KB13N |
KB14N |
|
Interne Leistungsverrechnung |
KB23N |
KB24N |
|
Statistische Kennzahl |
KB33N |
KB34N |
Nachbearbeiten der Datenübernahme
Testen/Buchen: Die Nachbearbeitung kann im Testmodus oder im Echtlauf (Buchen) erfolgen.
Möglichkeiten:
· Manuelle Verarbeitung
· Halbautomatische Verarbeitung
· Automatische Verarbeitung
Welche der Optionen am besten für die Nachbearbeitung geeignet ist, hängt von der Art der aufgetretenen Fehler ab.
War zum Beispiel zum Zeitpunkt der Datenübernahme für den gewünschten Vorgang die Buchungsperiode gesperrt, sind in der Regel keine Änderungen an den zu buchenden Daten erforderlich. Der Datenübernahme kann automatisch wiederholt werden, nachdem die Periodensperre aufgehoben wurde.
Ist ein Fehler aufgetreten, der nur durch Korrigieren der übernommenen Daten behoben werden kann, kann dies halbautomatisch oder manuell geschehen. Die halbautomatische Nachbearbeitung ist geeignet, wenn Fehler auf der Ebene des Belegkopfes zu beheben sind (z.B. falsches Buchungsdatum oder falsche Referenz ). Sind einzelne Buchungszeilen falsch, wird es nötig sein, diese einzeln manuell zu korrigieren.
Warnungen Ignorieren: Ist dieses Kennzeichen gesetzt, werden Belege auch dann gebucht, wenn bei der Belegprüfung Warnmeldungen auftreten. Ist das Kennzeichen nicht gesetzt, verhindert das Auftreten von Warnungen bei der Belegprüfung die Buchung des betreffenden Belegs.
Externe Nummernvergabe: Dieses Kennzeichen bitte nicht verwenden.
Datenübernahme-ID: Dieser Parameter bestimmt, welche Datenübernahme nachbearbeitet wird.
Zunächst können die zu bearbeitenden Belege aus dem gesamten Nachbearbeitungsvorrat ausgewählt werden. Es können einzelne Belege, Beleggruppen oder alle Belege zur Nachbearbeitung ausgewählt werden.
Im halbautomatischen Modus können Informationen zum Belegkopf wie Kostenrechnungskreis, Version, Buchungsdatum, usw. korrigiert und die so berichtigten Belege automatisch gebucht werden.
Enthält eine Datenübernahme nur Belege eines Typs, werden nur die dafür relevanten Felder zur Korrektur eingeblendet. Wenn eine Datenübernahme Belege zu verschiedenen Vorgängen enthält (z.B. Leistungsverrechnung und Umbuchung von Primärkosten), werden alle Felder angezeigt, die für mindestens einen der Vorgänge geändert werden dürfen. Die korrigierten Werte werden nur dann in die Belege übernommen, wenn sie für den Vorgang des betreffenden Belegs gültige Eingaben sind. Wird zum Beispiel die Version geändert, wird der Wert nicht in Belege zur Umbuchung von Primärkosten übernommen.
Stornieren der Datenübernahme
Die Anwendung erlaubt es, Datenübernahme-Läufe komplett zu stornieren. Wurden einzelne Belege aus dem Lauf bereits manuell storniert, wird eine entsprechende Fehlermeldung ausgegeben, und es werden nur die noch nicht stornierten Belege zum Übernahmelauf storniert.
Testen/Stornieren : Die Stornierung kann im Testmodus oder im Echtlauf (Stornieren) erfolgen.
Warnungen ignorieren : Ist dieses Kennzeichen gesetzt, werden Belege auch dann gebucht, wenn bei der Belegprüfung Warnmeldungen auftreten. Ist das Kennzeichen nicht gesetzt, verhindert das Auftreten von Warnungen bei der Belegprüfung die Buchung des betreffenden Belegs.
Nachbearbeitungsvorrat löschen : Ist das Kennzeichen gesetzt, werden alle zum Datenübernahme-Lauf gehörenden Einträge im Nachbearbeitungsvorrat gelöscht.
Buchungsdatum für Storno : Der Storno kann mit einem Buchungsdatum versehen werden.
Zu stornierende Datenübernahme : Es werden einzelne Datenübernahmen storniert. Sie wählen hier die Datenübernahme-ID aus.
Protokoll zur Datenübernahme anzeigen.
Zu einer Datenübernahme wird das Protokoll angezeigt. In der Regel ist dies das Protokoll aus den Belegprüfungen bei der Datenübernahme. Falls die Datenübernahme nachbearbeitet worden ist, ist das Protokoll erweitert um die Nachrichten aus der Nachbearbeitung. Eine Stornierung der Datenübernahme wird ebenfalls protokolliert.
CO Umlagen - der sog. "Vorbrenner"
Umlagen im CO führen insbesondere im Bereich der Konzernumlage immer dann zu Problemen, wenn als Empfängerbezugsbasis die Gesamtkosten einer Kostenstelle herangezogen werden sollen und dazu ggfls. noch eine sehr differenzierte Funktionsbereichsdefinition mit vielen Empfängerkostenstellen vorliegt. Dies führt in Großkonzernen und Retail Gesellschaften mit vielen Filialen und damit einhergehend vielen Empfängerkostenstellen dazu, das bei Aufbau der Sender-/Empfängerbeziehungen eine interne Tabelle aufgebaut wird, die ggfls. die Speichergrenzen übersteigt und zu einem Short Dump führt.
Folgendes Programm sorgt dafür, dass die gebuchten Kostenarten (echte Buchung) auf eine statistische Kennzahl verdichtet werden.
Der Effekt bei einem Kunden war bspw., dass eine nicht lauffähige Umlage nach 1300 Sekunden durchgebucht wurde.
In diesem Zusammenhang wurde auch eine Meldung bei SAP aufgemacht und es gab diesbezüglich einen regen Austausch mit dem SAP Development Support. Lt. SAP Entwicklung ist demnach die Nutzung solcher „Vorbrenner“ in diesen Konstellationen wohl nicht unüblich.
Das nachfolgende Programm stellt einen solchen "Vorbrenner" dar.
Das Programm startet mit folgendem Selektionsbildschirm:
- Der Kostenrechnungskreis ist mit 1000 vorbelegt.
- Im Feld Kostenstellengruppe kann eine Gruppe oder Selektionsvariante angegeben werden. Es werden nur die Kostenstellen für die Fortschreibung der kumulierten Kosten berücksichtigt, die in der Gruppe enthalten sind. Dies entspricht in der Umlage der Empfängerbezugsbasis.
- Mittels der Kostenartengruppe (Gruppe/Selektionsvariante) kann auf bestimmte Kosten eingeschränkt werden, um z.B. um bereits ausgeführte Umlagen / Abrechnungen nicht als Empfängerbezugsbasis heranzuziehen. Sofern gewünscht kann das Feld leer gelassen werden und das Häkchen Gesamtkosten gesetzt werden. In diesem Fall werden alle Kosten der in der Kostenstellengruppe angegeben Kostenstellen berücksichtigt.
- Geschäftsjahr und Periode müssen angegeben werden. Unter dieser Periode erfolgt die Selektion und Fortschreibung.
- Die statistische Kennzahl ISTKOS ist die statistische Kennzahl, unter der die Kosten fortgeschrieben werden.
Coding:
*&---------------------------------------------------------------------*
*& Report ZCO_POST_COSTASSKF
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zco_post_costasskf.
* Datendeklaration
INCLUDE zco_post_costasskf_top.
* Selektionsbildschirm
INCLUDE zco_post_costasskf_sel.
START-OF-SELECTION.
IF gs_selection-kstar IS INITIAL AND p_gesam IS INITIAL.
"Fehlermeldung
ENDIF.
*Übernahme der Selektionsparameter in Struktur
gs_selection-kokrs = p_kokrs.
gs_selection-gjahr = p_gjahr.
gs_selection-perio = p_perio.
gs_selection-gesam = p_gesam.
gs_selection-verto = p_verto.
gs_selection-stagr = p_stagr.
LOOP AT s_verfr REFERENCE INTO DATA(ls_verfr).
APPEND ls_verfr->* TO gs_selection-verfr.
ENDLOOP.
IF gs_selection-koset IS INITIAL. gs_selection-koset = '0101' && gs_selection-kokrs && p_1koset. ENDIF.
IF gs_selection-kstar IS NOT INITIAL AND p_gesam IS INITIAL. gs_selection-kstar = '0102' && gs_selection-kokrs && p_1kstar. ENDIF.
* Start der Verarbeitung
DATA(lo_instance) = zcl_co_cost2statfig=>get_instance( ).
lo_instance->start( gs_selection ).
*&---------------------------------------------------------------------*
*& Include ZCO_POST_COSTASSKF_TOP
*&---------------------------------------------------------------------*
DATA: gv_kosetname TYPE c LENGTH 10,
gv_kstarname TYPE c LENGTH 10.
DATA: gs_selection TYPE zcl_co_cost2statfig=>ts_selection.
TABLES: csks.
*&---------------------------------------------------------------------*
*& Include ZCO_POST_COSTASSKF_SEL
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME TITLE TEXT-t01.
PARAMETERS: p_kokrs TYPE kokrs MATCHCODE OBJECT csh_tka01 OBLIGATORY DEFAULT 1000.
PARAMETERS: p_1koset LIKE rksb1-ksgru OBLIGATORY.
*PARAMETERS: p_2koset LIKE rgsbs-setnr MODIF ID in5.
PARAMETERS: p_1kstar LIKE rksb1-kagru.
*PARAMETERS: p_2kstar LIKE rgsbs-setnr MODIF ID in5.
PARAMETERS: p_gesam AS CHECKBOX.
SELECTION-SCREEN SKIP 1.
PARAMETERS: p_gjahr TYPE gjahr OBLIGATORY.
PARAMETERS: p_perio TYPE periode OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b01.
SELECTION-SCREEN BEGIN OF BLOCK b02 WITH FRAME TITLE TEXT-t02.
PARAMETERS: p_stagr TYPE ccss-stagr OBLIGATORY.
PARAMETERS: p_verto TYPE csks-kosar.
SELECT-OPTIONS: s_verfr FOR csks-kosar NO INTERVALS.
SELECTION-SCREEN END OF BLOCK b02.
INITIALIZATION.
* Defaultwert Datum
SELECT SINGLE lmona FROM tka01
WHERE kokrs EQ @p_kokrs
INTO @DATA(gv_periv).
CALL FUNCTION 'DATE_TO_PERIOD_CONVERT'
EXPORTING
i_date = sy-datum
* I_MONMIT = 00
i_periv = gv_periv
IMPORTING
e_buper = p_perio
e_gjahr = p_gjahr
EXCEPTIONS
input_false = 1
t009_notfound = 2
t009b_notfound = 3
OTHERS = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
* Periodenberechnung
p_perio = p_perio - 1.
IF p_perio EQ 0. p_perio = 12. ENDIF.
IF p_perio EQ 12. p_gjahr = p_gjahr - 1. ENDIF.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_1koset.
CALL FUNCTION 'K_GROUP_SELECT'
EXPORTING
class = '0101'
field_name = 'KOSTL '
table = 'CCSS '
IMPORTING
setid = gs_selection-koset
set_name = gv_kosetname
EXCEPTIONS
no_set_picked = 02.
IF sy-subrc = 0.
p_1koset = gv_kosetname.
ENDIF.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_1kstar.
CALL FUNCTION 'K_GROUP_SELECT'
EXPORTING
class = '0102'
field_name = 'KSTAR '
table = 'CCSS '
IMPORTING
setid = gs_selection-kstar
set_name = gv_kstarname
EXCEPTIONS
no_set_picked = 02.
IF sy-subrc = 0.
p_1kstar = gv_kstarname.
ENDIF.
AT SELECTION-SCREEN.
IF p_gesam EQ abap_true.
CLEAR: p_1kstar, gs_selection-kstar, gv_kstarname.
ENDIF.
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
IF screen-name = 'P_1KSTAR'.
IF p_gesam EQ abap_true.
CLEAR p_1kstar.
screen-input = '0'.
ELSE.
screen-input = '1'.
ENDIF.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
CLASS zcl_co_cost2statfig DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES: * <SIGNATURE>---------------------------------------------------------------------------------------+ * <SIGNATURE>---------------------------------------------------------------------------------------+ * <SIGNATURE>---------------------------------------------------------------------------------------+
tr_kosar TYPE RANGE OF csks-kosar .
TYPES:
BEGIN OF ts_selection.
TYPES kokrs TYPE kokrs.
TYPES koset TYPE rgsbs-setnr.
TYPES kstar TYPE rgsbs-setnr.
TYPES gesam TYPE checkbox.
TYPES gjahr TYPE gjahr.
TYPES perio TYPE periode.
TYPES verto TYPE kosar.
TYPES verfr TYPE tr_kosar.
TYPES stagr TYPE stagr.
TYPES END OF ts_selection .
TYPES BEGIN OF ts_csks.
TYPES kokrs TYPE kokrs.
TYPES kostl TYPE kostl.
TYPES datbi TYPE datbi.
TYPES bukrs TYPE bukrs.
TYPES prctr TYPE prctr.
TYPES kosar TYPE kosar.
TYPES END OF ts_csks.
TYPES tt_csks TYPE STANDARD TABLE OF ts_csks WITH DEFAULT KEY
WITH UNIQUE HASHED KEY k1 COMPONENTS kokrs kostl datbi
WITH NON-UNIQUE SORTED KEY k2 COMPONENTS kosar.
TYPES tt_cskb TYPE STANDARD TABLE OF cskb WITH DEFAULT KEY.
TYPES BEGIN OF ts_costs.
TYPES kokrs TYPE kokrs.
TYPES kostl TYPE kostl.
TYPES bukrs TYPE bukrs.
TYPES prctr TYPE prctr.
TYPES kosar TYPE kosar.
TYPES wrttp TYPE co_wrttp.
TYPES sum TYPE coep-wkgbtr.
TYPES END OF ts_costs.
TYPES tt_costs TYPE STANDARD TABLE OF ts_costs WITH DEFAULT KEY.
CLASS-METHODS get_instance
RETURNING
VALUE(ro_instance) TYPE REF TO zcl_co_cost2statfig .
METHODS start
IMPORTING
!is_selection TYPE ts_selection .
protected section.
private section.
data CV_FAILURE type ABAP_BOOL .
data GT_COSTS type TT_COSTS .
data CV_VERTO type KOSAR .
data GR_KSTAR type REP_EAPS_TAB_KSTAR_RANGE .
data GT_VERTO type TT_CSKS .
data RT_VERFR type TR_KOSAR .
data CV_GESAM type CHECKBOX .
data CV_DATAB type DATEFROM .
data CV_DATBI type DATETO .
data CV_GJAHR type GJAHR .
data CV_KOKRS type KOKRS .
data CV_PERIO type PERIODE .
class-data GO_INSTANCE type ref to ZCL_CO_COST2STATFIG .
data GT_CSKB type TT_CSKB .
data GR_KOSTL type HRPP_SEL_KOSTL .
data CV_STAGR type STAGR .
data GT_RETURN type BAPIRET2_T .
methods CALCULATE_COSTS .
methods DBSEL_CSKB
importing
!IT_KSTAR type REP_EAPS_TAB_KSTAR_RANGE
returning
value(RT_CSKB) type TT_CSKB .
methods DBSEL_CSKS
importing
!IT_KOSTL type HRPP_SEL_KOSTL
returning
value(RT_CSKS) type TT_CSKS .
methods POST_STATFIG .
methods REVERSE_STATFIGPOST .
methods SHOW_LOG .
methods SET_DATA
importing
!IS_SELECTION type TS_SELECTION .
methods SET_KOSTENARTEN
importing
!IS_SELECTION type TS_SELECTION .
methods SET_KOSTENSTELLEN
importing
!IS_SELECTION type TS_SELECTION .
methods SET_SELMAIN
importing
!IS_SELECTION type TS_SELECTION .
ENDCLASS.
CLASS ZCL_CO_COST2STATFIG IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->CALCULATE_COSTS
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD calculate_costs.
DATA: lv_tabix TYPE sy-tabix,
ls_costverto TYPE ts_costs,
lt_costverto TYPE tt_costs.
* Prüfen, ob bereits eine Fehlersituation vorliegt
CHECK cv_failure IS INITIAL.
* Select aus COEP, da hier die Daten mit Vorzeichen vorliegen
SELECT
a~kokrs, a~kostl, b~bukrs, b~prctr, b~kosar,
a~wrttp, SUM( a~wkgbtr ) AS sum "Direkte Summierung möglich, da Werte positiv und negativ vorliegen
FROM coep AS a
INNER JOIN csks AS b
ON a~kokrs EQ b~kokrs AND a~kostl EQ b~kostl
WHERE a~kokrs EQ @cv_kokrs
AND a~lednr EQ '00'
AND a~gjahr EQ @cv_gjahr
AND a~perio EQ @cv_perio
AND a~kstar IN @gr_kstar
AND a~kostl IN @gr_kostl
GROUP BY a~kokrs, b~bukrs, b~prctr, a~kostl, b~kosar, a~wrttp
INTO CORRESPONDING FIELDS OF TABLE @gt_costs.
* Buchungskreis 1003 hat Filialkostenstellen, die irrelevant sind, Nullzeilen ignorieren!
DELETE gt_costs WHERE ( bukrs = '1003' AND kosar EQ cv_verto ) OR sum IS INITIAL.
DELETE gt_costs WHERE wrttp NE '04'.
* Verdichtung
LOOP AT gt_verto REFERENCE INTO DATA(ls_verto).
CLEAR ls_costverto.
MOVE-CORRESPONDING ls_verto->* TO ls_costverto.
LOOP AT gt_costs REFERENCE INTO DATA(ls_costs)
WHERE bukrs EQ ls_verto->bukrs
AND prctr EQ ls_verto->prctr
AND
* | Instance Private Method ZCL_CO_COST2STATFIG->DBSEL_CSKB
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_KSTAR TYPE REP_EAPS_TAB_KSTAR_RANGE
* | [<-()] RT_CSKB TYPE TT_CSKB
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD dbsel_cskb.
IF cv_gesam IS INITIAL AND it_kstar IS NOT INITIAL.
SELECT kokrs, kstar, katyp FROM cskb
WHERE kokrs EQ @cv_kokrs
AND kstar IN @it_kstar
AND datbi GE @cv_datbi
INTO CORRESPONDING FIELDS OF TABLE @rt_cskb.
ELSE.
SELECT kokrs, kstar, katyp FROM cskb
WHERE kokrs EQ @cv_kokrs
AND datbi GE @cv_datbi
INTO CORRESPONDING FIELDS OF TABLE @rt_cskb.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->DBSEL_CSKS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_KOSTL TYPE HRPP_SEL_KOSTL
* | [<-()] RT_CSKS TYPE TT_CSKS
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD dbsel_csks.
SELECT kokrs, kostl, datbi, bukrs, prctr, kosar
FROM csks
WHERE kokrs EQ @cv_kokrs
AND kostl IN @it_kostl
AND datbi GE @cv_datbi
AND datab LE @cv_datab
and kosar EQ @cv_verto
INTO CORRESPONDING FIELDS OF TABLE @rt_csks.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_CO_COST2STATFIG=>GET_INSTANCE
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RO_INSTANCE TYPE REF TO ZCL_CO_COST2STATFIG
* +--------------------------------------------------------------------------------------</SIGNATURE>
method GET_INSTANCE.
IF go_instance IS INITIAL.
CREATE OBJECT go_instance.
ENDIF.
ro_instance = go_instance.
endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->POST_STATFIG
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD post_statfig.
DATA: lt_item TYPE STANDARD TABLE OF bapiskfitm WITH DEFAULT KEY,
lt_return TYPE bapiret2_t,
ls_return TYPE REF TO bapiret2,
lv_count TYPE i.
* Bei Fehler keine weitere Verarbeitung
CHECK cv_failure IS INITIAL.
* Ohne Daten keine Competition
CHECK gt_costs IS NOT INITIAL.
* Kopfdaten füllen
DATA(ls_header) = VALUE bapidochdrp( co_area = cv_kokrs
postgdate = cv_datbi
doc_hdr_tx = 'CUM_COSTS' && ' ' && cv_gjahr && '/' && cv_perio
username = sy-uname ).
* Positionsdaten füllen
LOOP AT gt_costs REFERENCE INTO DATA(ls_costs).
lv_count = lv_count + 1.
APPEND VALUE bapiskfitm( statkeyfig = cv_stagr
stat_qty = CONV smexxx( ls_costs->sum )
seg_text = ' '
rec_cctr = ls_costs->kostl ) TO lt_item.
IF lv_count = 899.
* Funktionsbaustein aufrufen
CALL FUNCTION 'BAPI_ACC_STAT_KEY_FIG_POST'
EXPORTING
doc_header = ls_header
* IGNORE_WARNINGS = ' '
* IMPORTING
* doc_no = lv_belnr
TABLES
doc_items = lt_item
return = lt_return.
* Rückgabetabelle auswerten
LOOP AT lt_return REFERENCE INTO ls_return.
IF ls_return->type CA 'AEX'.
cv_failure = abap_true.
ENDIF.
APPEND ls_return->* TO gt_return.
ENDLOOP.
* Clear
CLEAR: lv_count, lt_item, lt_return.
ENDIF.
ENDLOOP.
* Letzter Block
IF lt_item IS NOT INITIAL.
* Funktionsbaustein aufrufen
CALL FUNCTION 'BAPI_ACC_STAT_KEY_FIG_POST'
EXPORTING
doc_header = ls_header
* IGNORE_WARNINGS = ' '
* IMPORTING
* doc_no = lv_belnr
TABLES
doc_items = lt_item
return = lt_return.
* Rückgabetabelle auswerten
LOOP AT lt_return REFERENCE INTO ls_return.
IF ls_return->type CA 'AEX'.
cv_failure = abap_true.
ENDIF.
APPEND ls_return->* TO gt_return.
ENDLOOP.
* Clear
CLEAR: lv_count, lt_item, lt_return.
ENDIF.
* Fehlerprüfung
IF cv_failure NE abap_true.
* Auf Datenbank schreiben
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = abap_true.
ELSE.
* Nicht auf DB schreiben
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ENDMETHOD.
* | Instance Private Method ZCL_CO_COST2STATFIG->REVERSE_STATFIGPOST
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD reverse_statfigpost.
* Erst mal kein Storno, sondern nur Fehlermeldung ausgeben
* Selektion Kopf und Position
SELECT
a~kokrs, a~belnr,
SUM( b~smebtr ) AS wert
FROM cobk AS a
INNER JOIN coepr AS b
ON a~kokrs EQ b~kokrs
AND a~belnr EQ b~belnr
WHERE a~kokrs EQ @cv_kokrs
AND a~gjahr EQ @cv_gjahr
* AND a~versn EQ 0
AND a~vrgng EQ 'RKS'
AND a~perab EQ @cv_perio
AND a~stflg NE @abap_true
AND a~stokz NE @abap_true
AND b~stagr EQ @cv_stagr
GROUP BY a~kokrs, a~belnr
INTO TABLE @DATA(lt_cobk).
* Daten gefunden? Dann Fehler und Returntabelle füllen
LOOP AT lt_cobk REFERENCE INTO DATA(ls_cobk).
cv_failure = abap_true.
APPEND VALUE bapiret2( id = 'ZCO'
number = 5 "Bitte &1 / &2 in &3 mittels KB34N stornieren (Wert: &4).
type = 'E'
message_v1 = ls_cobk->kokrs
message_v2 = ls_cobk->belnr
message_v3 = cv_gjahr && '/' && cv_perio
message_v4 = CONV char13( ls_cobk->wert ) ) TO gt_return.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->SET_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_SELECTION TYPE TS_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD set_data.
* Datum/Kostenrechnungskreis setzen
set_selmain( is_selection ).
* Kostenstellen festlegen
set_kostenstellen( is_selection ).
* Kostenarten festlegen
set_kostenarten( is_selection ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->SET_KOSTENARTEN
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_SELECTION TYPE TS_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD set_kostenarten.
DATA: lt_setvalues TYPE TABLE OF setvalues,
lr_kstar TYPE rep_eaps_tab_kstar_range.
IF is_selection-kstar IS NOT INITIAL.
* Werte importieren
CALL FUNCTION 'G_SET_TREE_IMPORT'
EXPORTING
client = sy-mandt
setid = is_selection-kstar
* tabname = table
* fieldname = fieldname
no_descriptions = abap_true
no_rw_info = abap_true
date_from = cv_datab
date_to = cv_datbi
TABLES
* set_hierarchy =
set_values = lt_setvalues
EXCEPTIONS
set_not_found = 1
OTHERS = 3.
* Werte in Rangetabelle übernehmen
LOOP AT lt_setvalues REFERENCE INTO DATA(ls_set).
APPEND VALUE rep_eaps_str_kstar_range( sign = 'I'
option = 'BT'
low = ls_set->from
high = ls_set->to ) TO gr_kstar.
ENDLOOP.
ENDIF.
* Benötigte Daten selektieren und in Attributtabelle stellen
gt_cskb = dbsel_cskb( gr_kstar ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->SET_KOSTENSTELLEN
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_SELECTION TYPE TS_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD set_kostenstellen.
DATA: lt_setvalues TYPE TABLE OF setvalues.
CALL FUNCTION 'G_SET_TREE_IMPORT'
EXPORTING
client = sy-mandt
setid = is_selection-koset
* tabname = table
* fieldname = fieldname
no_descriptions = abap_true
no_rw_info = abap_true
date_from = cv_datab
date_to = cv_datbi
TABLES
* set_hierarchy =
set_values = lt_setvalues
EXCEPTIONS
set_not_found = 1
OTHERS = 3.
LOOP AT lt_setvalues REFERENCE INTO DATA(ls_set).
APPEND VALUE hrpp_sel_st_kostl( sign = 'I'
option = 'BT'
low = ls_set->from
high = ls_set->to ) TO gr_kostl.
ENDLOOP.
gt_verto = dbsel_csks( gr_kostl ).
ENDMETHOD.
* | Instance Private Method ZCL_CO_COST2STATFIG->SET_SELMAIN
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_SELECTION TYPE TS_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD set_selmain.
* Übernahme in globale Attribute
cv_gjahr = is_selection-gjahr.
cv_perio = is_selection-perio.
cv_kokrs = is_selection-kokrs.
cv_gesam = is_selection-gesam.
rt_verfr = is_selection-verfr.
cv_verto = is_selection-verto.
cv_stagr = is_selection-stagr.
* Datum ermitteln
SELECT SINGLE lmona FROM tka01
WHERE kokrs EQ @cv_kokrs
INTO @DATA(lv_periv).
* Anfangsdatum
CALL FUNCTION 'FIRST_DAY_IN_PERIOD_GET'
EXPORTING
i_gjahr = cv_gjahr
* I_MONMIT = 00
i_periv = lv_periv
i_poper = cv_perio
IMPORTING
e_date = cv_datab
EXCEPTIONS
input_false = 1
t009_notfound = 2
t009b_notfound = 3
OTHERS = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
* Enddatum
CALL FUNCTION 'LAST_DAY_OF_MONTHS'
EXPORTING
day_in = cv_datab
IMPORTING
last_day_of_month = cv_datbi
EXCEPTIONS
day_in_no_date = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_CO_COST2STATFIG->SHOW_LOG
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD show_log.
CALL FUNCTION 'C14ALD_BAPIRET2_SHOW'
TABLES
i_bapiret2_tab = gt_return.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_CO_COST2STATFIG->START
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_SELECTION TYPE TS_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD start.
* Wesentliche Attribute füllen
set_data( is_selection ).
* Ggfls. bisherige stat. Kennzahl stornieren
reverse_statfigpost( ).
* Kosten ermitteln und Verdichten
calculate_costs( ).
* Wert buchen
post_statfig( ).
* Protokoll ausgeben
show_log( ).
ENDMETHOD.
ENDCLASS.
Workflowbasierte Bearbeitung und Freigabe des Zahlungsvorschlags
In neueren Releases (S/4 bzw. ab SAP_FIN 617) gibt es die Funktion "Workflow-basierte Freigabe des Zahlungsvorschlags". Hiermit lassen sich (arbeitsteilige) Abarbeitungs- bzw. Fertigmeldungsszenarien für den Zahllauf (F110 bzw. F111) implementieren.
Relevante Hinweise
- 2441770 - FI-Zahlprogramm: Workflow-basierte Freigabe des Zahlungsvorschlags
Installation:
- 2418713 - F110 F111: Workflow-basierte Freigabe des Zahlungsvorschlags (Prozess-Integration zu Hinweis 2441805)
- 2441804 - F110 F111: Workflow-basierte Freigabe des Zahlungsvorschlags (Installation zu Hinweis 2441805)
- 2441805 - F110 F111: Workflow-basierte Freigabe des Zahlungsvorschlags
Mithilfe der Customizing-Transaktion F110WFR bzw. IMG: Finanzwesen - Debitoren- und Kreditorenbuchhaltung - Geschäftsvorfälle - Zahlungsausgang - Zahlungsausgang automatisch - Zahlungsvorschlagsbearbeitung - Workflow für die Zahlungsvorschlagsbearbeitung einrichten lässt sich der Workflow aktivieren und die Bearbeiterfindung ausprägen. Für dieses Beispiel richten wir eine arbeitsteilige Bearbeitung des Zahlvorschlags (nach Sachbearbeiter-Kürzeln) ein.
Aktivieren Sie den Workflow im entsprechenden zahlenden Buchungskreis und geben Sie die Zahlwege vor, für die der Workflow greifen soll.
Im Rahmen dieser Aktivität bietet das System einen einfachen Regel-Editor, mit dem in Abhängigkeit von gewissen Feldinhalten der Zahlvorschlag paketiert und entsprechende Bearbeiter (z.B. SAP-User) zugeordnet werden können.
Im vorliegenden Fall wird der Zahlvorschlag nach Sachbearbeiter-Kürzeln (01, 02) am Kreditoren- bzw. Debitorenstammsatz aufgeteilt und die Arbeitspakete werden den zuständigen Zahlvorschlagsbearbeitern zugeordnet.
Als letzter Eintrag ohne Regel ist ein Default-User eingerichtet, der den schwarzen Peter bekommt, wenn durch Anwendung der vorherigen Regeln bis dorthin kein Bearbeiter gefunden werden konnte.
Ein komplexeres Regelwerk zur Bearbeiterfindung lässt sich über die Ausgestaltung eines BAdIs implementieren. Details hierzu und weitere Informationen zu diesem Themenkreis finden sich in der Dokumentation zur IMG-Aktivität.
Über die Methode GET_WF_PACKAGE_ACTORS liessen sich bspw. die zuständigen Bearbeiter aus der Tabelle T001S (Sachbearbeiterkürzel) nachlesen und dynamisch den Arbeitspaketen zuteilen.
Der ausgelieferte Workflow (WS23200018) besteht aus folgenden Aufgaben/Schritten:
Nach dem Startereignis (Zahlungsvorschlag wurde in der F110 erstellt) werden die Arbeitspakete erstellt und an die zugeteilten Bearbeiter weitergeleitet. Die Bearbeiter haben nun entsprechende ausführbare Workpackages in ihrem SAP Business Workplace. Der weitere Ablauf kann nun wie folgt variieren:
- Der Vorschlag wird gelöscht
- Die Arbeitspakete werden von den jeweiligen Bearbeitern abgearbeitet, bis die Anzahl der offenen Pakete 0 ist, also alles bestätigt wurde
Den Status der Abarbeitung kann jederzeit in der F110 eingesehen werden über "Zahlvorschlag anzeigen"
Sofern der Zahlvorschlag vor Beginn der Abarbeitung gelöscht wurde, ist der Workflow beendet. Wurden alle Arbeitspakete durch die jeweiligen Bearbeiter bestätigt, wird der Zahlvorschlag vom System gesperrt und die Abschlußarbeiten nach Workflow eingeleitet. In der Standardauslieferung wird hierbei der Zahllauf inkl. Zahlungsträgererstellung und Druck angestossen.
Die einzelnen Schritte und deren konkrete Ausgestaltung sind in einem Default-BadI (FI_PAYMENT_PROPOSAL_WF) implementiert, welches von SAP ausgeliefert wird. Nachfolgend ein kurzer Überblick über die ausgelieferten Funktionalitäten:
| Methode | Ausgelieferte Funktionalität |
| CHECK_WF_ACTIVE | Es wird geprüft, ob der Workflow im Cust. für den entsprechenden zahlenden Buchungskreis und Zahlweg aktiviert ist. |
| DELETE_WF_PACKAGES | Wird der Zahlungsvorschlag gelöscht, werden alle erstellten Arbeitspakete mitgelöscht. |
| GET_WF_PACKAGE_1 | Paketierung des Zahlungsvorschlages gemäß Regeleditor im Customizing, wenn die regelnden Felder im Zahlungskopf enthalten sind (REGUH) |
| GET_WF_PACKAGE_2 | Paketierung des Zahlungsvorschlages gemäß Regeleditor im Customizing, wenn die regelnden Felder in der Zahlungsposition enthalten sind (REGUP) |
| GET_WF_PACKAGE_ACTORS | Zuteilung des Bearbeiters zum jeweiligen Arbeitspaket anhand der Zuordnung im Customizing (s.o.) |
| GET_WF_PACKAGE_DESCRIPTION | Generischer Aufbau der Arbeitspaketbeschreibung anhand der techn. Beschreibung des Feldnamens aus der Regel und der vorgegebenen Werte, z.B.: BUSAB = 01 wird zu "Buchhaltungs-Sachbearbeiter 01" |
| START_WF_POSTPROCESSING | Abschlußarbeiten, wenn alle Arbeitspakete bestätigt wurden: Starten des Zahllaufs inkl. Zahlungsträgererstellung und Druck |
Durch eine eigene BadI-Implementierung lassen sich alle oder einzelne Funktionen durch kundeneigenes Coding übersteuern.
Upload-Tool für Hauptbuchbelege (SAPGUI)
Update 13.04.26: Damit das Programm "fiorisiert" werden kann, muss der Zugriff auf die Excel-Datei von OLE auf einen alternativen Zugriff umgestellt werden. OLE ist nur im Kontext der SAP-GUI unterstützt, das Programm in seiner ursprünglich geposteten Form wäre als fiorisierte GUI-App nicht lauffähig. Deshalb wurde der komplette Upload auf die sog. XCO API umgestellt. Das Tool ist nun auch in der FIORI-Welt ausführbar.
Eine viel nachgefragte Funktion im FI ist die Möglichkeit, Belege in Excel aufzubereiten und unter SAP hochzuladen, z.B. für Sachkonten-Umbuchungen im Rahmen von Abschlusstätigkeiten. Unter S/4 (ab Rel. 1511) gibt es hierfür eine Fiori-App zum Upload von Hauptbuchbelegen via Excel-Template, ab Release 1809 gibt es diese auch für kreditorische Belege...
Bis dahin hilft meines Wissens tatsächlich nur eine selbstgebaute Upload-Funktion oder ggf. ein 3rd Party-Produkt.
Ein einfaches Programm inkl. Testlauf-/Prüffunktion findet sich in diesem Artikel. Hinweise zur Installation und zum Format der Quell-Datei finden sich am Ende des Codings...
*&---------------------------------------------------------------------*
*& Report ZFI_UPL_DOCUMENTS
*----------------------------------------------------------------------*
* Function : Upload documents from Excel *
*----------------------------------------------------------------------*
* Description : Upload & posting of documents via Excel *
* Author : S.Rohde Consenso Consulting *
* Date/Version : 23.01.2023 1.0
*----------------------------------------------------------------------*
* SRO190723 Enable postings in foreign currency
* SRO030226 Upgrade to S/4 & new Excel Interface
* SRO300326 Ignore negative values in Excel file, sign is determined
* by posting key only
REPORT zfi_upl_documents.
***********************************************************************
******************** GLOBAL DATA **************************************
***********************************************************************
CONSTANTS: gc_delimiter(1) TYPE c VALUE '~'.
SET EXTENDED CHECK OFF.
INCLUDE:
sbal_constants,
<icon>.
SET EXTENDED CHECK ON.
TYPES: gty_currency_amount TYPE TABLE OF bapiaccr09.
DATA:
g_s_log TYPE bal_s_log,
g_log_handle TYPE balloghndl,
g_t_log_handle TYPE bal_t_logh,
g_s_display_profile TYPE bal_s_prof.
DATA: g_dummy TYPE c.
DATA: data_tab TYPE TABLE OF string.
TYPES: BEGIN OF gty_xl_sheet,
col_a TYPE string,
col_b TYPE string,
col_c TYPE string,
col_d TYPE string,
col_e TYPE string,
col_f TYPE string,
col_g TYPE string,
col_h TYPE string,
col_i TYPE string,
col_j TYPE string,
col_k TYPE string,
col_l TYPE string,
col_m TYPE string,
col_n TYPE string,
col_o TYPE string,
col_p TYPE string,
col_q TYPE string,
col_r TYPE string,
col_s TYPE string,
col_t TYPE string,
col_u TYPE string,
col_v TYPE string,
col_w TYPE string,
col_x TYPE string,
col_y TYPE string,
col_z TYPE string,
END OF gty_xl_sheet.
TYPES: gtt_it_xl TYPE STANDARD TABLE OF gty_xl_sheet WITH DEFAULT KEY.
TYPES: BEGIN OF tax_item,
mwskz TYPE mwskz,
direct_tax TYPE abap_bool,
basis TYPE fwbas,
bashw TYPE hwbas,
steuer TYPE fwste,
steuhw TYPE hwste,
END OF tax_item.
DATA: git_taxitems TYPE TABLE OF tax_item,
gs_taxitem TYPE tax_item.
TYPES: BEGIN OF gty_doc,
doc(20) TYPE c,
bschl TYPE bschl,
umskz TYPE umskz,
bukrs TYPE bukrs,
newko TYPE rf05a-newko,
mwskz TYPE mwskz,
wrbtr(15) TYPE c,
waers TYPE waers,
netto TYPE c,
dmbtr(15) TYPE c,
kostl TYPE kostl,
sgtxt TYPE sgtxt,
blart TYPE blart,
bldat(10) TYPE c,
budat(10) TYPE c,
xblnr TYPE xblnr,
bumon TYPE bumon,
bktxt TYPE bktxt,
zuonr TYPE dzuonr,
netdt(10) TYPE c,
bewar TYPE bseg-bewar,
aufnr TYPE aufnr,
prctr TYPE prctr,
kidno TYPE bseg-kidno,
zterm TYPE bseg-zterm,
END OF gty_doc.
DATA: git_docs TYPE TABLE OF gty_doc,
gs_doc TYPE gty_doc.
DATA: gs_t001 TYPE t001,
g_rc TYPE sy-subrc.
DATA: g_tabix TYPE sytabix.
* Interface data for BAPI
DATA:
* Returnparameters of BAPIs
g_obj_type TYPE bapiache09-obj_type, "Object type
* Object key will be populated with Document number
* NNNNNNNNNNYYYYBBBB N = Doc Number, Y = Fiscal Year, B = Company code
g_obj_key TYPE bapiache09-obj_key, "Object key
g_obj_sys TYPE bapiache09-obj_sys, "log. System
* Document header
gs_documentheader TYPE bapiache09,
* G/L account item
git_accountgl TYPE TABLE OF bapiacgl09,
gs_accountgl TYPE bapiacgl09,
* AR item
git_accountrec TYPE TABLE OF bapiacar09,
gs_accountrec TYPE bapiacar09,
* AP items
git_accountpay TYPE TABLE OF bapiacap09,
gs_accountpay TYPE bapiacap09,
* Tax items
git_accounttax TYPE TABLE OF bapiactx09,
gs_accounttax TYPE bapiactx09,
* Amount information
git_currencyamount TYPE TABLE OF bapiaccr09,
gs_currencyamount TYPE bapiaccr09,
* BAPI mesages
git_return TYPE TABLE OF bapiret2,
gs_return TYPE bapiret2.
DATA:
g_itemno TYPE posnr_acc. "Line item number
*&---------------------------------------------------------------------*
*& SELECTION-SCREEN
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME TITLE TEXT-b01.
PARAMETERS: pa_fnam LIKE rlgrap-filename OBLIGATORY.
" PARAMETERS: pa_shtyp TYPE zde_shtyp DEFAULT '2' NO-DISPLAY.
SELECTION-SCREEN END OF BLOCK b01.
SELECTION-SCREEN BEGIN OF BLOCK b02 WITH FRAME TITLE TEXT-b02.
PARAMETERS: pa_test AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b02.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR pa_fnam.
PERFORM f4_filename.
*-----------------------------------------------------------------------
START-OF-SELECTION.
*-----------------------------------------------------------------------
CLEAR git_return[].
PERFORM init_protocol.
PERFORM upload_data.
PERFORM precheck_data CHANGING g_rc.
IF g_rc = 0.
PERFORM process_data.
ENDIF.
PERFORM add_msg_to_prot.
PERFORM log_display.
*&---------------------------------------------------------------------*
*& Form F4_FILENAME
*&---------------------------------------------------------------------*
*& F4 Help Excel-file
*&---------------------------------------------------------------------*
FORM f4_filename .
CALL FUNCTION 'FAA_FILE_F4'
EXPORTING
i_default_extension = 'XLS'
IMPORTING
e_filename = pa_fnam
EXCEPTIONS
interface_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
PERFORM msg_add USING probclass_high.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form UPLOAD_DATA
*&---------------------------------------------------------------------*
*& Upload Excel spreadsheet & structurize data
*&---------------------------------------------------------------------*
FORM upload_data .
DATA: lt_bin_data TYPE w3mimetabtype.
DATA: lt_sheet_data TYPE gtt_it_xl.
DATA: l_fnam TYPE string.
l_fnam = pa_fnam.
CALL METHOD cl_gui_frontend_services=>gui_upload
EXPORTING
filename = l_fnam
filetype = 'BIN'
CHANGING
data_tab = lt_bin_data.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
* solix -> xstring
DATA(lv_xsts_xlsx) = cl_bcs_convert=>solix_to_xstring( it_solix = lt_bin_data ).
* Excel-Dokument
DATA(o_xl) = xco_cp_xlsx=>document->for_file_content( lv_xsts_xlsx )->read_access( ).
* 1. Sheet
DATA(o_sheet) = o_xl->get_workbook( )->worksheet->at_position( 1 ).
IF abap_true = o_sheet->exists( ).
DATA(o_sel_pattern) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( )->get_pattern( ).
CLEAR lt_sheet_data[].
DATA(o_result) = o_sheet->select( o_sel_pattern
)->row_stream(
)->operation->write_to( REF #( lt_sheet_data )
)->set_value_transformation( xco_cp_xlsx_read_access=>value_transformation->string_value
)->if_xco_xlsx_ra_operation~execute( ).
IF abap_true = o_result->succeeded.
LOOP AT lt_sheet_data ASSIGNING FIELD-SYMBOL(<ls_sheet>).
CHECK sy-tabix > 1.
gs_doc-doc = <ls_sheet>-col_a.
gs_doc-bschl = <ls_sheet>-col_b.
gs_doc-umskz = <ls_sheet>-col_c.
gs_doc-bukrs = <ls_sheet>-col_d.
gs_doc-newko = <ls_sheet>-col_e.
gs_doc-mwskz = <ls_sheet>-col_f.
gs_doc-wrbtr = <ls_sheet>-col_g.
gs_doc-waers = <ls_sheet>-col_h.
gs_doc-netto = <ls_sheet>-col_i.
gs_doc-dmbtr = <ls_sheet>-col_j.
gs_doc-kostl = <ls_sheet>-col_k.
gs_doc-sgtxt = <ls_sheet>-col_l.
gs_doc-blart = <ls_sheet>-col_m.
gs_doc-bldat = <ls_sheet>-col_n.
gs_doc-budat = <ls_sheet>-col_o.
gs_doc-xblnr = <ls_sheet>-col_p.
gs_doc-bumon = <ls_sheet>-col_q.
gs_doc-bktxt = <ls_sheet>-col_r.
gs_doc-zuonr = <ls_sheet>-col_s.
gs_doc-netdt = <ls_sheet>-col_t.
gs_doc-bewar = <ls_sheet>-col_u.
gs_doc-aufnr = <ls_sheet>-col_v.
gs_doc-prctr = <ls_sheet>-col_w.
gs_doc-kidno = <ls_sheet>-col_x.
gs_doc-zterm = <ls_sheet>-col_y.
APPEND gs_doc TO git_docs.
ENDLOOP.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form INIT_PROTOCOL
*&---------------------------------------------------------------------*
*& Initialize application protocol
*&---------------------------------------------------------------------*
FORM init_protocol .
* create a log
g_s_log-extnumber = 'Document-Upload'(ext).
CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log = g_s_log
IMPORTING
e_log_handle = g_log_handle
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
*--------------------------------------------------------------------
* FORM ADD_MSG_TO_PROT
*--------------------------------------------------------------------
FORM add_msg_to_prot.
DATA:
l_s_msg TYPE bal_s_msg,
l_context TYPE bal_s_ex01.
DATA:
l_s_return LIKE LINE OF git_return.
LOOP AT git_return INTO l_s_return.
* define data of message for Application Log
l_s_msg-msgty = l_s_return-type.
l_s_msg-msgid = l_s_return-id.
l_s_msg-msgno = l_s_return-number.
l_s_msg-msgv1 = l_s_return-message_v1.
l_s_msg-msgv2 = l_s_return-message_v2.
l_s_msg-msgv3 = l_s_return-message_v3.
l_s_msg-msgv4 = l_s_return-message_v4.
* add this message to log file
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
* I_LOG_HANDLE =
i_s_msg = l_s_msg
EXCEPTIONS
log_not_found = 0
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDLOOP.
ENDFORM.
FORM log_display.
DATA:
l_s_display_profile TYPE bal_s_prof,
l_s_fcat TYPE bal_s_fcat.
* get standard display profile
CALL FUNCTION 'BAL_DSP_PROFILE_SINGLE_LOG_GET'
IMPORTING
e_s_display_profile = l_s_display_profile
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
* for display variants add report id
l_s_display_profile-disvariant-report = sy-repid.
* when you use also other ALV lists in your report,
* please specify a handle to distinguish between the display
* variants of these different lists, e.g:
l_s_display_profile-disvariant-handle = 'LOG'.
* show log file with modified output profile
* - we specify the display profile since we created our own
* - we do not specify any filter (like I_S_LOG_FILTER, ...,
* I_T_MSG_HANDLE) since we want to display all messages available
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXPORTING
* I_S_LOG_FILTER =
* I_T_LOG_CONTEXT_FILTER =
* I_S_MSG_FILTER =
* I_T_MSG_CONTEXT_FILTER =
* I_T_LOG_HANDLE =
* I_T_MSG_HANDLE =
i_s_display_profile = l_s_display_profile
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
*--------------------------------------------------------------------
* FORM MSG_ADD_FREE_TEXT
*--------------------------------------------------------------------
FORM msg_add_free_text USING VALUE(i_text) TYPE c.
* add this message to log file
CALL FUNCTION 'BAL_LOG_MSG_ADD_FREE_TEXT'
EXPORTING
* I_LOG_HANDLE =
i_msgty = 'S'
i_text = i_text
EXCEPTIONS
log_not_found = 0
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form INIT
*&---------------------------------------------------------------------*
*& Initialization
*&---------------------------------------------------------------------*
FORM init .
CLEAR: git_accountgl[],
git_accountpay[],
git_accountrec[],
git_accounttax[],
git_currencyamount[],
git_taxitems[].
CLEAR: g_itemno, gs_documentheader.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form POST_DOCUMENT
*&---------------------------------------------------------------------*
*& Post document
*&---------------------------------------------------------------------*
FORM post_document .
DATA: l_error TYPE abap_bool VALUE abap_false.
DATA: lit_return TYPE TABLE OF bapiret2.
*-----------------------------------------------------------------------
* BAPI-Call
*-----------------------------------------------------------------------
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST' "#EC CI_USAGE_OK[2628704]
EXPORTING
documentheader = gs_documentheader "#EC CI_USAGE_OK[2438131]
IMPORTING
obj_type = g_obj_type
obj_key = g_obj_key
obj_sys = g_obj_sys
TABLES
accountgl = git_accountgl
accountreceivable = git_accountrec
accountpayable = git_accountpay
accounttax = git_accounttax
currencyamount = git_currencyamount
return = lit_return.
LOOP AT lit_return TRANSPORTING NO FIELDS
WHERE type = 'A' OR type = 'E'.
l_error = abap_true.
ENDLOOP.
IF l_error = abap_false.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
APPEND LINES OF lit_return TO git_return.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CHECK_DOCUMENT
*&---------------------------------------------------------------------*
*& check document (Test mode)
*&---------------------------------------------------------------------*
FORM check_document .
DATA: lit_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_ACC_DOCUMENT_CHECK' "#EC CI_USAGE_OK[2438131]
EXPORTING
documentheader = gs_documentheader "#EC CI_USAGE_OK[2628704]
TABLES
accountgl = git_accountgl
accountreceivable = git_accountrec
accountpayable = git_accountpay
accounttax = git_accounttax
currencyamount = git_currencyamount
return = lit_return.
APPEND LINES OF lit_return TO git_return.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form PROCESS_DATA
*&---------------------------------------------------------------------*
*& map excel data to BAPI structure & post / check documents
*&---------------------------------------------------------------------*
FORM process_data .
DATA: l_netto TYPE wrbtr,
l_nethw TYPE dmbtr,
l_brutto TYPE wrbtr,
l_bruthw TYPE dmbtr,
l_steuer TYPE fwste,
l_steuhw TYPE hwste,
l_basis TYPE fwbas,
l_bashw TYPE hwbas.
DATA: l_mwskz TYPE skb1-mwskz,
ls_bsl TYPE tbsl.
*-----------------------------------------------------------------------
* Items
*-----------------------------------------------------------------------
LOOP AT git_docs INTO gs_doc.
AT NEW doc.
PERFORM init.
*-----------------------------------------------------------------------
* document header
*-----------------------------------------------------------------------
READ TABLE git_docs INDEX sy-tabix INTO DATA(ls_doc).
CLEAR gs_documentheader.
gs_documentheader-bus_act = 'RFBU'.
gs_documentheader-username = sy-uname.
gs_documentheader-comp_code = ls_doc-bukrs.
PERFORM _convert_date_xlsx USING ls_doc-bldat.
gs_documentheader-doc_date = ls_doc-bldat.
PERFORM _convert_date_xlsx USING ls_doc-budat.
gs_documentheader-pstng_date = ls_doc-budat.
IF gs_doc-bumon IS NOT INITIAL AND ls_doc-bumon NE space.
gs_documentheader-fis_period = ls_doc-bumon.
ENDIF.
gs_documentheader-ref_doc_no = ls_doc-xblnr.
gs_documentheader-header_txt = ls_doc-bktxt.
gs_documentheader-doc_type = ls_doc-blart.
SELECT SINGLE * FROM t001 INTO gs_t001 WHERE bukrs = ls_doc-bukrs.
ENDAT.
g_tabix = sy-tabix.
ADD 1 TO g_itemno.
"begin of insertion SRO300326
gs_doc-wrbtr = abs( gs_doc-wrbtr ).
gs_doc-dmbtr = abs( gs_doc-dmbtr ).
"end of insertion SRO300326
SELECT SINGLE * FROM tbsl INTO ls_bsl WHERE bschl = gs_doc-bschl.
IF sy-subrc NE 0.
MESSAGE e034(f5) WITH gs_doc-bschl INTO g_dummy.
PERFORM msg_add USING probclass_high.
CONTINUE.
ENDIF.
CASE ls_bsl-koart.
WHEN 'S'.
CLEAR: gs_accountgl, gs_currencyamount.
CLEAR: l_brutto, l_bruthw.
gs_accountgl-itemno_acc = g_itemno.
PERFORM _convert USING gs_doc-newko gs_accountgl-gl_account 'HKONT'.
gs_accountgl-item_text = gs_doc-sgtxt.
IF gs_doc-kostl IS NOT INITIAL.
PERFORM _convert USING gs_doc-kostl gs_accountgl-costcenter 'KOSTL'.
ENDIF.
IF gs_doc-prctr IS NOT INITIAL.
PERFORM _convert USING gs_doc-prctr gs_accountgl-profit_ctr 'PRCTR'.
ENDIF.
IF gs_doc-aufnr IS NOT INITIAL.
PERFORM _convert USING gs_doc-aufnr gs_accountgl-orderid 'AUFNR'.
ENDIF.
gs_accountgl-alloc_nmbr = gs_doc-zuonr.
gs_accountgl-tax_code = gs_doc-mwskz.
gs_accountgl-cshdis_ind = abap_true.
IF gs_doc-wrbtr IS NOT INITIAL.
PERFORM _convert USING gs_doc-wrbtr l_brutto 'WRBTR'.
ENDIF.
IF gs_doc-dmbtr IS NOT INITIAL AND gs_doc-waers NE gs_t001-waers.
PERFORM _convert USING gs_doc-dmbtr l_bruthw 'DMBTR'.
ENDIF.
"Net amounts provided? --> Calculate gross-amounts
IF gs_doc-netto = abap_true.
PERFORM calculate_grossamounts USING gs_documentheader-comp_code gs_doc-waers gs_doc-mwskz
CHANGING l_brutto l_bruthw.
ENDIF.
IF ls_bsl-shkzg = 'H'.
MULTIPLY l_brutto BY -1.
MULTIPLY l_bruthw BY -1.
ENDIF.
* GL account taxable?
CLEAR l_mwskz.
SELECT SINGLE mwskz FROM skb1 INTO l_mwskz
WHERE saknr = gs_accountgl-gl_account
AND bukrs = gs_documentheader-comp_code. "#EC CI_DB_OPERATION_OK[2431747]
IF sy-subrc = 0 AND l_mwskz IS INITIAL.
"no tax allowed? --> clear tax code (same behaviour as FIORI app)
CLEAR: gs_doc-mwskz, gs_accountgl-tax_code.
ENDIF.
CLEAR: l_steuer, l_netto, l_basis, l_steuhw, l_nethw, l_bashw.
* with tax?
IF gs_doc-mwskz IS NOT INITIAL.
IF l_mwskz = '>' OR l_mwskz = '<'. "Direct Tax
CALL FUNCTION 'RE_CALCULATE_BASE_AMOUNT'
EXPORTING
i_taxam = l_brutto
i_mwskz = gs_doc-mwskz
i_waers = gs_doc-waers
i_bukrs = gs_documentheader-comp_code
IMPORTING
e_fwbas = l_basis.
l_steuer = l_netto = l_brutto.
IF gs_doc-waers NE gs_t001-waers.
CALL FUNCTION 'RE_CALCULATE_BASE_AMOUNT'
EXPORTING
i_taxam = l_bruthw
i_mwskz = gs_doc-mwskz
i_waers = gs_t001-waers
i_bukrs = gs_documentheader-comp_code
IMPORTING
e_fwbas = l_bashw.
l_steuhw = l_nethw = l_bruthw.
ENDIF.
ELSE.
CALL FUNCTION 'CALCULATE_TAX_FROM_GROSSAMOUNT'
EXPORTING
i_bukrs = gs_documentheader-comp_code
i_mwskz = gs_doc-mwskz
i_waers = gs_doc-waers
i_wrbtr = l_brutto
IMPORTING
e_fwste = l_steuer
EXCEPTIONS
OTHERS = 16.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO g_dummy.
PERFORM msg_add USING probclass_high.
ENDIF.
l_netto = l_brutto - l_steuer.
l_basis = l_netto.
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
CALL FUNCTION 'CALCULATE_TAX_FROM_GROSSAMOUNT'
EXPORTING
i_bukrs = gs_documentheader-comp_code
i_mwskz = gs_doc-mwskz
i_waers = gs_t001-waers
i_wrbtr = l_bruthw
IMPORTING
e_fwste = l_steuhw
EXCEPTIONS
OTHERS = 16.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO g_dummy.
PERFORM msg_add USING probclass_high.
ENDIF.
l_nethw = l_bruthw - l_steuhw.
l_bashw = l_nethw.
ENDIF.
ENDIF.
*-----------------------------------------------------------------------
* collect corresponding tax line for each taxable GL account
*-----------------------------------------------------------------------
CLEAR gs_taxitem.
gs_taxitem-mwskz = gs_doc-mwskz.
gs_taxitem-steuer = l_steuer.
gs_taxitem-steuhw = l_steuhw.
gs_taxitem-basis = l_basis.
gs_taxitem-bashw = l_bashw.
IF l_mwskz = '>' OR l_mwskz = '<'. "Direct Tax
gs_taxitem-direct_tax = abap_true.
ELSE.
gs_taxitem-direct_tax = abap_false.
ENDIF.
COLLECT gs_taxitem INTO git_taxitems.
ELSE.
l_netto = l_brutto.
l_nethw = l_bruthw.
ENDIF.
IF NOT ( l_mwskz = '>' OR l_mwskz = '<' ). "Direct Tax
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '00'. "transaction (foreign) currency
ENDIF.
gs_currencyamount-itemno_acc = gs_accountgl-itemno_acc.
gs_currencyamount-currency = gs_doc-waers.
gs_currencyamount-amt_doccur = l_netto. "#EC CI_FLDEXT_OK[2610650]
APPEND: gs_accountgl TO git_accountgl,
gs_currencyamount TO git_currencyamount.
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '10'. "local currency
gs_currencyamount-itemno_acc = gs_accountgl-itemno_acc.
gs_currencyamount-currency = gs_t001-waers.
gs_currencyamount-amt_doccur = l_nethw. "#EC CI_FLDEXT_OK[2610650]
APPEND: gs_currencyamount TO git_currencyamount.
ENDIF.
ENDIF.
WHEN 'D'.
CLEAR: gs_accountrec, gs_currencyamount.
gs_accountrec-itemno_acc = g_itemno. "Positionsidentifier
PERFORM _convert USING gs_doc-newko gs_accountrec-customer 'KUNNR'.
gs_accountrec-item_text = gs_doc-sgtxt. "Belegtext
gs_accountrec-alloc_nmbr = gs_doc-zuonr. "Zuordnung
gs_accountrec-sp_gl_ind = gs_doc-umskz. "SHB-KZ
gs_accountrec-paymt_ref = gs_doc-kidno. "Zahlungsreferenz
IF gs_doc-netdt IS NOT INITIAL.
PERFORM _convert_date_xlsx USING gs_doc-netdt.
gs_accountrec-bline_date = gs_doc-netdt.
ENDIF.
IF gs_doc-zterm IS NOT INITIAL.
gs_accountrec-pmnttrms = gs_doc-zterm.
ELSE.
SELECT SINGLE zterm FROM knb1 INTO gs_accountrec-pmnttrms
WHERE kunnr = gs_accountrec-customer
AND bukrs = gs_doc-bukrs.
ENDIF.
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '00'. "transaction (foreign) currency
ENDIF.
gs_currencyamount-itemno_acc = gs_accountrec-itemno_acc.
gs_currencyamount-currency = gs_doc-waers.
IF gs_doc-wrbtr IS NOT INITIAL.
PERFORM _convert USING gs_doc-wrbtr l_brutto 'WRBTR'.
IF ls_bsl-shkzg = 'H'.
MULTIPLY l_brutto BY -1.
ENDIF.
ENDIF.
gs_currencyamount-amt_doccur = l_brutto. "#EC CI_FLDEXT_OK[2610650]
APPEND: gs_accountrec TO git_accountrec,
gs_currencyamount TO git_currencyamount.
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '10'. "local currency
gs_currencyamount-itemno_acc = gs_accountrec-itemno_acc.
gs_currencyamount-currency = gs_t001-waers.
IF gs_doc-dmbtr IS NOT INITIAL.
PERFORM _convert USING gs_doc-dmbtr l_bruthw 'DMBTR'.
IF ls_bsl-shkzg = 'H'.
MULTIPLY l_bruthw BY -1.
ENDIF.
ENDIF.
gs_currencyamount-amt_doccur = l_bruthw. "#EC CI_FLDEXT_OK[2610650]
APPEND gs_currencyamount TO git_currencyamount.
ENDIF.
WHEN 'K'.
CLEAR: gs_accountpay, gs_currencyamount.
gs_accountpay-itemno_acc = g_itemno. "Positionsidentifier
PERFORM _convert USING gs_doc-newko gs_accountpay-vendor_no 'LIFNR'.
gs_accountpay-item_text = gs_doc-sgtxt. "Belegtext
gs_accountpay-alloc_nmbr = gs_doc-zuonr. "Zuordnung
gs_accountpay-sp_gl_ind = gs_doc-umskz. "SHB-KZ
gs_accountpay-paymt_ref = gs_doc-kidno. "Zahlungsreferenz
IF gs_doc-netdt IS NOT INITIAL.
PERFORM _convert_date_xlsx USING gs_doc-netdt.
gs_accountpay-bline_date = gs_doc-netdt.
ENDIF.
IF gs_doc-zterm IS NOT INITIAL.
gs_accountpay-pmnttrms = gs_doc-zterm.
ELSE.
SELECT SINGLE zterm FROM lfb1 INTO gs_accountpay-pmnttrms
WHERE lifnr = gs_accountpay-vendor_no
AND bukrs = gs_doc-bukrs.
ENDIF.
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '00'. "transaction (foreign) currency
ENDIF.
gs_currencyamount-itemno_acc = gs_accountpay-itemno_acc.
gs_currencyamount-currency = gs_doc-waers.
IF gs_doc-wrbtr IS NOT INITIAL.
PERFORM _convert USING gs_doc-wrbtr l_brutto 'WRBTR'.
IF ls_bsl-shkzg = 'H'.
MULTIPLY l_brutto BY -1.
ENDIF.
ENDIF.
gs_currencyamount-amt_doccur = l_brutto. "#EC CI_FLDEXT_OK[2610650]
APPEND: gs_accountpay TO git_accountpay,
gs_currencyamount TO git_currencyamount.
IF gs_doc-waers NE gs_t001-waers AND gs_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '10'. "local currency
gs_currencyamount-itemno_acc = gs_accountpay-itemno_acc.
gs_currencyamount-currency = gs_t001-waers.
IF gs_doc-dmbtr IS NOT INITIAL.
PERFORM _convert USING gs_doc-dmbtr l_bruthw 'DMBTR'.
IF ls_bsl-shkzg = 'H'.
MULTIPLY l_bruthw BY -1.
ENDIF.
ENDIF.
gs_currencyamount-amt_doccur = l_bruthw. "#EC CI_FLDEXT_OK[2610650]
APPEND gs_currencyamount TO git_currencyamount.
ENDIF.
ENDCASE.
AT END OF doc.
READ TABLE git_docs INDEX g_tabix INTO ls_doc.
*-----------------------------------------------------------------------
* Prepare collected tax lines & attach to current document
*-----------------------------------------------------------------------
LOOP AT git_taxitems INTO gs_taxitem.
ADD 1 TO g_itemno.
CLEAR: gs_accounttax, gs_currencyamount.
gs_accounttax-itemno_acc = g_itemno.
gs_accounttax-tax_code = gs_taxitem-mwskz.
gs_accounttax-direct_tax = gs_taxitem-direct_tax.
IF ls_doc-waers NE gs_t001-waers AND ls_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '00'.
ENDIF.
gs_currencyamount-itemno_acc = gs_accounttax-itemno_acc.
gs_currencyamount-currency = ls_doc-waers.
gs_currencyamount-amt_doccur = gs_taxitem-steuer. "#EC CI_FLDEXT_OK[2610650]
gs_currencyamount-amt_base = gs_taxitem-basis. "#EC CI_FLDEXT_OK[2610650]
APPEND: gs_accounttax TO git_accounttax,
gs_currencyamount TO git_currencyamount.
IF ls_doc-waers NE gs_t001-waers AND ls_doc-dmbtr IS NOT INITIAL.
gs_currencyamount-curr_type = '10'.
gs_currencyamount-itemno_acc = gs_accounttax-itemno_acc.
gs_currencyamount-currency = gs_t001-waers.
gs_currencyamount-amt_doccur = gs_taxitem-steuhw. "#EC CI_FLDEXT_OK[2610650]
gs_currencyamount-amt_base = gs_taxitem-bashw. "#EC CI_FLDEXT_OK[2610650]
APPEND: gs_currencyamount TO git_currencyamount.
ENDIF.
ENDLOOP.
PERFORM round_amounts USING g_itemno CHANGING git_currencyamount.
*-----------------------------------------------------------------------
* Post / Check document
*-----------------------------------------------------------------------
IF pa_test IS INITIAL.
PERFORM post_document.
ELSE.
PERFORM check_document.
ENDIF.
ENDAT.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form _CONVERT
*&---------------------------------------------------------------------*
*& Convert excel data to SAP format
*&---------------------------------------------------------------------*
*& --> in/out input / output
*& --> Dtel data element that determines the conversion
*&---------------------------------------------------------------------*
FORM _convert USING in out VALUE(dtel).
DATA: l_btr TYPE wrbtr.
IF dtel = 'WRBTR' OR dtel = 'DMBTR' AND in CO '0123456789 .'.
l_btr = in. "#EC CI_FLDEXT_OK[2610650]
out = l_btr. "#EC CI_FLDEXT_OK[2610650]
EXIT.
ENDIF.
CALL FUNCTION 'RS_CONV_EX_2_IN_DTEL'
EXPORTING
input_external = in "#EC CI_FLDEXT_OK[2610650]
dtel = dtel
IMPORTING
output_internal = out. "#EC CI_FLDEXT_OK[2610650]
IF sy-subrc <> 0.
MESSAGE a600(fr) WITH 'ERROR'(f03) sy-subrc 'at conversion'(f04) dtel.
ENDIF.
ENDFORM.
*--------------------------------------------------------------------
* FORM MSG_ADD
*--------------------------------------------------------------------
FORM msg_add USING VALUE(i_probclass) TYPE bal_s_msg-probclass.
DATA:
l_s_msg TYPE bal_s_msg.
* define data of message for Application Log
l_s_msg-msgty = sy-msgty.
l_s_msg-msgid = sy-msgid.
l_s_msg-msgno = sy-msgno.
l_s_msg-msgv1 = sy-msgv1.
l_s_msg-msgv2 = sy-msgv2.
l_s_msg-msgv3 = sy-msgv3.
l_s_msg-msgv4 = sy-msgv4.
l_s_msg-probclass = i_probclass.
* add this message to log file
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
* I_LOG_HANDLE =
i_s_msg = l_s_msg
EXCEPTIONS
log_not_found = 0
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form PRECHECK_DATA
*&---------------------------------------------------------------------*
* Precheck Data, whether local currency is consistently provided
*----------------------------------------------------------------------*
FORM precheck_data CHANGING p_rc.
DATA: l_mix(2) TYPE c.
LOOP AT git_docs INTO gs_doc.
AT NEW doc.
READ TABLE git_docs INDEX sy-tabix INTO DATA(ls_doc).
SELECT SINGLE * FROM t001 INTO gs_t001 WHERE bukrs = ls_doc-bukrs.
CLEAR l_mix.
ENDAT.
"Doc is given in foreign currency
IF gs_doc-waers NE gs_t001-waers.
IF gs_doc-dmbtr IS NOT INITIAL OR gs_doc-dmbtr CO '0,. '.
l_mix(1) = 'X'.
ELSE.
l_mix+1(1) = 'X'.
ENDIF.
ENDIF.
IF l_mix = 'XX'.
"sometimes amount in LC is provided and sometimes not within same document
"--> ERROR
p_rc = 4.
MESSAGE e800(f5) INTO g_dummy.
PERFORM msg_add USING probclass_high.
EXIT.
ELSE.
p_rc = 0.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form _convert_date_xlsx
*&---------------------------------------------------------------------*
*& Datumsformat Excel in anständiges Datum umwandeln.
*&---------------------------------------------------------------------*
FORM _convert_date_xlsx CHANGING p_date TYPE char10.
DATA: lv_days TYPE i,
lv_date TYPE datum.
CHECK p_date IS NOT INITIAL.
CHECK p_date CO ' 0123456789.'.
lv_days = trunc( p_date ) - 2.
lv_date = '19000101'.
ADD lv_days TO lv_date.
p_date = lv_date.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form calculate_grossamounts
*&---------------------------------------------------------------------*
*& Calculate gross amounts from net amounts
*&---------------------------------------------------------------------*
*& --> p_bukrs
*& --> p_WAERS
*& --> p_MWSKZ
*& <-- p_BRUTTO
*& <-- p_BRUTHW
*&---------------------------------------------------------------------*
FORM calculate_grossamounts USING p_bukrs TYPE bukrs
p_waers TYPE waers
p_mwskz TYPE mwskz
CHANGING p_netto TYPE wrbtr
p_nethw TYPE dmbtr.
DATA: lt_mwdat TYPE TABLE OF rtax1u15,
l_fwste TYPE bset-fwste.
* transaction currency
CALL FUNCTION 'CALCULATE_TAX_FROM_NET_AMOUNT'
EXPORTING
i_bukrs = p_bukrs
i_mwskz = p_mwskz
i_waers = p_waers
i_wrbtr = p_netto
IMPORTING
e_fwste = l_fwste
TABLES
t_mwdat = lt_mwdat
EXCEPTIONS
OTHERS = 15.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
ADD l_fwste TO p_netto.
ENDIF.
CHECK p_nethw NE 0.
* company code currency
CALL FUNCTION 'CALCULATE_TAX_FROM_NET_AMOUNT'
EXPORTING
i_bukrs = p_bukrs
i_mwskz = p_mwskz
i_waers = p_waers
i_wrbtr = p_nethw
IMPORTING
e_fwste = l_fwste
TABLES
t_mwdat = lt_mwdat
EXCEPTIONS
OTHERS = 15.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
ADD l_fwste TO p_nethw.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form round_amounts
*&---------------------------------------------------------------------*
*& elimnate rounding differences
*&---------------------------------------------------------------------*
*& --> p_ITEMNO
*& <-- p_CURRENCY_AMOUNT
*&---------------------------------------------------------------------*
FORM round_amounts USING p_itemno TYPE posnr_acc
CHANGING p_currencyamount TYPE gty_currency_amount.
DATA: diff_00 TYPE bapidoccur,
diff_10 TYPE bapidoccur,
diff TYPE bapidoccur.
DATA: tabix_00 LIKE sy-tabix,
tabix_10 LIKE sy-tabix,
tabix LIKE sy-tabix.
LOOP AT p_currencyamount INTO DATA(ls_curr) WHERE curr_type = '00'.
ADD ls_curr-amt_doccur TO diff_00.
ENDLOOP.
LOOP AT p_currencyamount INTO ls_curr WHERE curr_type = '10'.
ADD ls_curr-amt_doccur TO diff_10.
ENDLOOP.
LOOP AT p_currencyamount INTO ls_curr WHERE curr_type = ' '.
ADD ls_curr-amt_doccur TO diff.
ENDLOOP.
CHECK diff <> 0 OR diff_00 <> 0 OR diff_10 <> 0.
READ TABLE p_currencyamount TRANSPORTING NO FIELDS WITH KEY itemno_acc = p_itemno
curr_type = '00'.
IF sy-subrc = 0.
tabix_00 = sy-tabix.
ENDIF.
READ TABLE p_currencyamount TRANSPORTING NO FIELDS WITH KEY itemno_acc = p_itemno
curr_type = '10'.
IF sy-subrc = 0.
tabix_10 = sy-tabix.
ENDIF.
READ TABLE p_currencyamount TRANSPORTING NO FIELDS WITH KEY itemno_acc = p_itemno
curr_type = ' '.
IF sy-subrc = 0.
tabix = sy-tabix.
ENDIF.
IF diff_00 <> 0.
p_currencyamount[ tabix_00 ]-amt_doccur = p_currencyamount[ tabix_00 ]-amt_doccur - diff_00.
ENDIF.
IF diff_10 <> 0.
p_currencyamount[ tabix_10 ]-amt_doccur = p_currencyamount[ tabix_10 ]-amt_doccur - diff_10.
ENDIF.
IF diff <> 0.
p_currencyamount[ tabix ]-amt_doccur = p_currencyamount[ tabix ]-amt_doccur - diff.
ENDIF.
ENDFORM.
Hinweise zur Installation:
Textelemente:
001 Verarbeitung der Datei
B01 Excel-Datei auswählen
B02 Testlauf ohne Buchen
Selektionstexte:
PA_FNAM Name der Datei
PA_TEST Testlauf - nur prüfen
Link zur Excel-Vorlage, die mit dem oben stehenden Programm verarbeitet werden kann.
https://drive.google.com/open?id=13XQEsF9yEa1wv6DE6SPn5zPNm8D9p9n-
Hinweis: die Vorlage ist an das Template für die S/4-FIORI-App "Hauptbuchbelege hochladen" angepasst. Es versteht sich wohl von selbst, dass Anpassungen am Programm gemacht werden müssen, wenn das Template abgeändert wird.
Kontenfindung für buchungskreisübergreifende CO Umlagen
Grundsätzlich ist ja möglich, CO Umlagen buchungskreisübergreifend zu definieren, wenn die beteiligten Buchungskreise einem Kostenrechnungskreis zugeordnet sind. Dabei werden ohne weiteres Zutun die im Rahmen der CO-FI Integration im Customizing der Finanzbuchhaltung hinterlegten Buchnungskreisverrechnungskonten (Vorgang BUV) angebucht. Dies ist nicht immer gewünscht, weil Umlagen im CO zumeist nur interne Werteflüsse abbilden und keine echten Intercompany-Geschäftsvorfälle darstellen.
In den Hinweisen 2483347 bzw. 2457163 wird das Vorgehen beschrieben, wie für Umlagekostenarten eine dedizierte Kontenfindung abseits der 'normalen' Buchungskreisverrechnungskonten eingestellt werden kann.
/image%2F1473637%2F20170207%2Fob_adae32_profilbild.png)
























