Quantcast
Channel: Module Archive - Tricktresor
Viewing all 32 articles
Browse latest View live

Anzeige des Belegflusses

$
0
0

Der weitgehend unbekannte Transaktionscode ALO1 (Buchstabe O, nicht Null) zeigt vollständige Belegflüsse für Einkaufs-, Material- Vertriebs- und FI-Belege an. Das klappt sowohl Richtung Belegvorgänger als auch für die Nachfolger. Daneben bietet die ALO1 Reporting-Möglichkeiten für diese Belegarten und ist in der Lage, die Daten auch aus Archiven zu lesen.

Im Einstiegsbild kann ausgewählt werden, über welchen Belegtyp man mit der Suche beginnen möchte.

Transaktion ALO1

Über die nun dargestellte Liste kann in die Einzelansicht des Belegflusses verzweigt werden.

ALO1 - belegfluss

Achtung: Die Selektion kann durchaus etwas länger dauern...

Adresse im Kundenauftrag geändert?

$
0
0

In einem Kundenauftrag kann die Adresse eines Partners geändert werden. Häufig werden zum Beispiel in der Adresse des Warenempfängers noch zusätzliche Informationen hinterlegt. Technisch gesehen steht in der Partnertabelle VBPA die Adressnummer aus dem Kundenstamm. Wird die Adresse geändert, bekommt der Partner eine neue Adressnummer. Diese Adressnummer verweist - wie auch die Adresse der Stammdaten - auf einen Eintrag in der Tabelle ADRC.

Änderungsbelege Fehlanzeige?

Möchte man die Änderungen eines Partner aus dem Kundenauftrag nachvollziehen, so funktioniert dies leider nicht über die aus dem Auftrag wählbare Anzeige der Änderungen im Menü Umfeld - Änderungen. Warum man sich hier nicht auf die Anzeige der Änderungen verlassen kann, sondern sich einen Tricks bedienen muss, wird ein Geheimnis der SAP bleiben.

Änderungen ermitteln

Um die Partneränderungen zu ermitteln, musst du zuerst die Adressnummer (Feld ADRNR) aus der Tabelle VBPA zum Auftrag ermitteln. Also: SE16n aufrufen, Belegnummer eingeben, auf gewünschte Partnerart einschränken (WE für Warenempfänger) und die Adressnummer - oder -nummern bei unterschiedlichen Partnern auf Positionseben -  in die Zwischenablage kopieren.

Mit diesen Adressnummern "im Gepäck" musst du erst einmal den genauen Objektwert ermitteln. Der Objektwert (OBJECTID) ist die Nummer, für die eine Änderung gespeichert wird. Zu der OBJECTID benötigst du noch das Änderungsbelegobjekt (OBJECTCLAS) ADRESSE.

Normalerweise ist der Objektwert gleich dem Objekt selbst, also z.B. der Nummer des Auftrags. Im Falle der Adressnummer wird jedoch noch die Adressgruppe. Die Adressnummer ist zwar auch ohne die Adressgruppe eindeutig, sie wird jedoch im Änderungsbeleg benötigt.

Also: Mit SE16n in die Tabelle CDHDR schauen, hier am Beispiel der Adressnummer 9001234567:

OBJECTCLAS ADRESSE
OJBECTID   *9001234567

Das Ergebnis kann zum Beispiel den Objektwert BP  9001234567 (Gruppe BP) oder SD019001234567 (Gruppe SD01) ergeben.

Diese Nummer benötigst du nun, um die Änderungsbelege zu dieser Adressnummer anzeigen zu lassen: Rufe Report RSSCD200 auf:

RSSCD200

 

Nach Start des Reports - und sofern Änderungen vorhanden sind - siehst du die Liste mit den Änderungen.

Wenn du dir nicht sicher bist, ob die Adresse geändert wurde: Das Adresskennzeichen (Feld VBAP-ADRDA) sagt dir, ob es sich bei der Adressnummer um die Adressnummer des Stammsatzes handelt (ADRDA = D) oder ob die Adresse nachträglich geändert wurde (ADRDA = E). Je nach Konfiguration und Anwendung können auch andere Kennzeichen verwendet werden. Diese sind in der Werthilfe zum Feld ADRDA hinterlegt.

FI-Beleg mit Umsatzsteuer buchen

$
0
0

Ausnahmsweise mal ein Ausflug in die Welt der Finanzbuchhaltung. Für mich ein Rotes Tuch mit Sieben Siegeln aus einem böhmischen Dorf... Ich werde trotzdem versuchen, den Sachverhalt nicht nur syntaktisch sondern auch inhaltlich korrekt wiederzugeben. Aus diesem Grund werde ich mich bewusst so schwammig wie möglich ausdrücken und Fachtermini wie "Erlöskonto", "Bilanz" oder "Buchungsschlüssel" vermeiden.

Aufgabe

Buchen eines FI-Beleges mit Umsatzsteuer. Es soll ein Bruttobetrag auf ein Konto und der zugehörige Nettobetrag auf ein Gegenkonto gebucht werden. Die Umsatzsteuer soll auf das richtige Umsatzsteuerkonto gebucht werden.

Hilfsmittel

Dass nur der BAPI_ACC_DOCUMENT_POST für diese Zwecke infrage kommt, war mir immerhin schnell klar. Wie man mit diesem Baustein bucht, habe ich ebenfalls schnell heraus gefunden. Eine Herausforderung war die Buchung der Umsatzsteuer. Von der irrigen Annahme, der Baustein könnte die Umsatzsteuer selber rechnen, habe ich mich schnell verabschieden müssen. Die Umsatzsteuer muss dem Baustein übergeben werden.

Um die Umsatzsteuer zu berechnen, helfen diese beiden Bausteine:

  • CALCULATE_TAX_FROM_NET_AMOUNT
  • CALCULATE_TAX_FROM_GROSSAMOUNT

Desweiteren notwendig ist eine Buchungsperiode. Diese lässt sich zwar auch einfach aus dem Datum errechnen, aber der Baustein CON_FIN_CURRENT_PERIOD_GET_2 hilft ebenfalls weiter. Da der Baustein sich auf den MM-Periodenverschieber bezieht, bin ich mir nicht sicher, ob der Baustein wirklich sinnvoll ist, aber in meinem Fall funktioniert er.

Beleg

Dieser Beleg kommt bei so einer Buchung heraus:

Beleg

Coding

REPORT.
PARAMETERs p_bukrs type bukrs DEFAULT '1000'.

START-OF-SELECTION.

  DATA ls_header TYPE bapiache09.
  DATA lt_return TYPE STANDARD TABLE OF bapiret2.
  DATA ls_return TYPE bapiret2.
  DATA lt_acc_gl TYPE STANDARD TABLE OF bapiacgl09.
  DATA ls_acc_gl LIKE LINE OF lt_acc_gl.
  DATA lt_cur_am TYPE STANDARD TABLE OF bapiaccr09.
  DATA ls_cur_am LIKE LINE OF lt_cur_am.
  DATA lt_acc_tx TYPE STANDARD TABLE OF bapiactx09.
  DATA ls_acc_tx LIKE LINE OF lt_acc_tx.
  data lv_period type POPER.
  data lv_year   type BDATJ.
*== aktuelle Periode ermitteln
  CALL FUNCTION 'CON_FIN_CURRENT_PERIOD_GET_2'
    EXPORTING
      id_bukrs                 = p_bukrs
   IMPORTING
     ED_CURRENT_YEAR          = lv_year
     ED_CURRENT_PERIOD        = lv_period
   EXCEPTIONS
     INTERNAL_ERROR           = 1
     OTHERS                   = 2.

*== Header
  ls_header-bus_act           = 'RFBU'.               "Betriebswirtschaftlicher Vorgang
  ls_header-username          = 'ICH'.                "Name des Benutzers
  ls_header-header_txt        = 'Test'.               "Belegkopftext
  ls_header-comp_code         = p_bukrs.              "Buchungskreis
  ls_header-doc_date          = sy-datum.             "Belegdatum im Beleg
  ls_header-pstng_date        = sy-datum.             "Buchungsdatum im Beleg
  ls_header-trans_date        = sy-datum.             "Umrechnungsdatum
  ls_header-fisc_year         = lv_year.              "Geschäftsjahr
  ls_header-fis_period        = lv_period.            "Geschäftsmonat
  ls_header-doc_type          = 'SB'.                 "Belegart
  ls_header-vatdate           = sy-datum.             "Steuermeldedatum


*== Buchungszeile Haben
  ls_acc_gl-itemno_acc        = 1.                    "Positionsnummer des Rechnungswesenbeleges
  ls_acc_gl-gl_account        = '0000184040'.         "Sachkonto der Hauptbuchhaltung
  ls_acc_gl-item_text         = 'Postext Haben'.      "Positionstext
  ls_acc_gl-acct_key          = space.                "Vorgangsschlüssel
  ls_acc_gl-acct_type         = 'S'.                  "Kontoart
  ls_acc_gl-costcenter        = ''.
  ls_acc_gl-value_date        = sy-datum.
  APPEND ls_acc_gl TO lt_acc_gl.

*== Buchungszeile Soll
  ls_acc_gl-itemno_acc        = 2.                    "Positionsnummer des Rechnungswesenbeleges
  ls_acc_gl-gl_account        = '0000420000'.         "Sachkonto der Hauptbuchhaltung
  ls_acc_gl-item_text         = 'Postext Soll'  .     "Positionstext
  ls_acc_gl-acct_key          = space.                "Vorgangsschlüssel
  ls_acc_gl-acct_type         = 'S'.                  "Kontoart
  ls_acc_gl-costcenter        = ''.
  ls_acc_gl-value_date        = sy-datum.
  ls_acc_gl-orderid           = 'XYZ'.                "Falls notwendig
  APPEND ls_acc_gl TO lt_acc_gl.

*== Haben Bruttobetrag
  ls_cur_am-itemno_acc        = 1.
  ls_cur_am-currency          = 'EUR'.
  ls_cur_am-currency_iso      = 'EUR'.
  ls_cur_am-amt_doccur        = '11.90-'.
  ls_cur_am-curr_type         = '00'.
  APPEND ls_cur_am TO lt_cur_am.

*== Soll Nettobetrag
  ls_cur_am-itemno_acc        = 2.
  ls_cur_am-currency          = 'EUR'.
  ls_cur_am-currency_iso      = 'EUR'.
  ls_cur_am-amt_doccur        = '10.00'.
  ls_cur_am-curr_type         = '00'.
  APPEND ls_cur_am TO lt_cur_am.

*== Soll Steuerbetrag
  ls_cur_am-itemno_acc        = 3.
  ls_cur_am-currency          = 'EUR'.
  ls_cur_am-currency_iso      = 'EUR'.
  ls_cur_am-amt_doccur        = '01.90'.
  ls_cur_am-amt_base          = '10.00'.
  ls_cur_am-curr_type         = '00'.
  APPEND ls_cur_am TO lt_cur_am.

*== Steuerinformation
  ls_acc_tx-itemno_acc        = 3.
  ls_acc_tx-tax_code          = 'AA'.
  ls_acc_tx-cond_key          = 'MWAS'.
  APPEND ls_acc_tx TO lt_acc_tx.

*== Beleg buchen
  CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
    EXPORTING
      documentheader = ls_header
    TABLES
      accountgl      = lt_acc_gl
      accounttax     = lt_acc_tx
      currencyamount = lt_cur_am
      return         = lt_return.

*== Protokoll
  LOOP AT lt_return INTO ls_return.
    WRITE: / ls_return-row,
             ls_return-message,
           / ls_return-type,
             ls_return-id,
             ls_return-number,
             ls_return-message_v1.
  ENDLOOP.

*== Commit work
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
    IMPORTING
      return = ls_return.

Neuigkeiten

Januar 2015: SAP hat den Hinweis 2070697 zu den BAPIs BAPI_ACC_DOCUMENT_POST + BAPI_ACC_DOCUMENT_CHECK veröffentlicht:

Symptom

Es wird immer Steuer 0 errechnet oder nichtabzugsfähige Beträge werden nicht verteilt bei Verwendung der Methode gemäß Hinweis 1873588.

Ursache und Voraussetzungen

Mit Hinweis 1873588 wurde eine Methode zur Verfügung gestellt zur Ableitung der Steuerdaten für BAPIs. Die Methode soll das Füllen der Steuerdaten für die BAPIs bapi_acc_document_post und bapi_acc_document_check erleichtern, und zwar ursprünglich für die Ermittlung der Parameter für die zeilenweise Steuer mit Hinweis 1873588, weil hier grundlegende Änderungen im SAP Standard vorgenommen worden sind. Mit diesem Hinweis wird die Methode erweitert für die Berechnung von Steuern (VAT, Sales und Use Tax) inklusive Nichtabzugsfähigkeit und Anzahlungen. Es kann nun ein Gesamtsteuerbetrag für den Beleg vorgegeben werden, der dann entsprechend der berechneten Steuern verteilt wird. Ein neuer Parameter wurde eingeführt, mit dem der Methode mitgeteilt werden kann, dass der Belegsaldo die fehlende Steuer ist, die verteilt werden soll. Eine Berechnung wird nur für Belege durchgeführt, die keine Mischbelege sind, d.h. z.B. Belege mit Anzahlungen und steuerrelevanten Aufwandpositionen in einem Beleg werden nicht unterstützt. Steuern für Indien und Brasilien werden nicht durch diese Methode unterstützt. Direkte Steuern (DIRECT_TAX='X') werden ebenfalls nicht unterstützt.

Des weiteren sind alle Änderungen inklusive der Änderungen des Hinweises 1873588 auch für SAPKH60000-60404 verfügbar, d.h. die Änderungen sind mit diesem Hinweis runtergezogen worden, wobei die zeilenweise Übergabe der Steuern erst ab SAPKH60405 möglich ist, weil die BAPIS mit SAPKH60405 um den Parameter ITEMNO_TAX erweitert worden sind. Die Serviceklasse ist somit ab SAPKH60000 verfügbar und wird in allen Enhancementpacks ab SAPKH60000 gleich gehalten. Zudem wird der Funktionsbaustein FI_TAX_SERVICES_CALCULATE angeboten, der RFC-fähig ist. Dieser kann über RFC aufgerufen werden und ruft im SAP-System anschließend die obengenannte  Methode FI_TAX_SERVICES=>CALCULATE auf und gibt die Parameter zurück.

Lösung

Korrektur

MM Konditionen lieferantenabhängig umbenennen

$
0
0

Oftmals wird vom Einkauf ein Blumenstrauß an Konditionen gefordert um diverse Zusatzkosten oder Rabatte erfassen zu können.
Sägekostenzuschlag, Anbruchzuschlag, Maut, Sonderkosten, Rüstkosten, Sonderrüstkosten, "China-Verpackung", 10-Jahres-Rabatt, Verhandelter Preis, Angebotspreis, Messepreis, Messerabatt  usw. usw. usw.
Bei jedem Lieferanten werden diese Konditionen unterschiedlich benannt.

Technisch sind diese meistens absolut identisch ausgeprägt und im schlimmsten Fall auch noch prozentual, absolut und mengenbezogen multipliziert angelegt.

Eine kaum bekannte und gut versteckte Funktion im Einkaufsinfosatz (ME12) ermöglicht die Umbenennung von Konditionen.
Genau das richtige Werkzeug um diese Anforderung abzudecken ohne das Kalkschema unnötig aufzublähen.

Ablauf:

MM_Kurztext Kondition1
Im Infosatz --> Konditionen --> eine Kondition erfassen (funktioniert natürlich auch mit dem PB00 Preis)

MM_Kurztext Kondition2
Zusätz --> Kurztext zur Konditionsart

MM_Kurztext Kondition3 MM_Kurztext Kondition4
Dort "Neue Einträge" aus dem Menü anwählen und die Kondition entsprechend umbenennen.

MM_Kurztext Kondition5
Im Infosatz sieht man sofort das gewünschte Ergebnis.

MM_Kurztext Kondition6
Entsprechend wird der neue Konditions-Kurztext in der Bestellung und je nach Formular auch auf dem Papier angezeigt.

Tipps am Rande:

Modul Transaktion Funktion
MM m/03 Konditionstabelle anlegen
MM m/04 Konditionstabelle ändern
MM m/05 Konditionstabelle pflegen
MM m/06 Konditionsarten MM pflegen
MM m/07 Zugriffsfolgen
MM m/08 MM Kalkulationsschema
SD vok0 Im Menü dieser Transaktion findet sich so ziemlich alles zu SD Konditionen.
Gibt es leider nicht für die MM Seite :-(

 

AWI 18.11.2014

Partner und ihre Tücken

$
0
0

Partner im SD-Umfeld sind sehr vielfältig. Es gibt verschiedene Partnerrollen (PARVW), die je Belegart in einem Partnerschema eingebunden werden können. Die Partnerrollen sind einer Partnerart zugeordnet (NRART). Möchte man Programme schreiben, die nicht auf eine Partnerrolle oder eine Partnerart eingeschränkt sind, dann stehen einige Hilfsmittel zur Verfügung. Man muss sie nur kennen...

Partnerrollen

In der Tabelle in der die Partner zu einem SD-Beleg gespeichert werden (Tabelle VBPA), gibt es für jede Partnerart ein eigenes Feld:

  • KUNNR - Kundennummer (Auftraggeber, Rechnungsempfänger, Regulierer, ...)
  • LIFNR - Lieferantennummer (Spediteur, Zollagent, Rechnungssteller, ...)
  • PERNR - Personalnummer (Verkäufer, zuständiger Mitarbeiter, ...)
  • PARNR - Ansprechpartner (Ansprechpartner, Qualitätszeugnisempfänger, ...)

Partnerarten

Möchte man wissen, welches Feld man bei welcher Partnerrolle ansprechen soll, dann muss man wissen, welche Partnerart eine Partnerrolle hat.

Die einzelnen Partnerarten können sein:

  • KU - Kunde
  • LI - Lieferanten
  • PE - Personalnummer
  • AP - Ansprechpartner
  • US - Benutzer
  • weitere

In der Partnerartentabelle TVAP steht genau, welche Partnerart gegen welche Tabelle geprüft werden kann.

Tools

Im Folgenden ein paar Tools, die im Umfeld von "Partnern" hilfreich sein können.

Partnerart ermitteln

Mithilfe des Funktionsbausteins MM_PARTNER_TYPE kann die Partnerart (KU, LI, PE etc.) ermittelt werden. Er greift auf die Tabelle TPAR zu und liefert die Partnerart (NRART) zurück

Anzeige eines Partners

Unabhängig von der Partnerrolle und Partnerart kann der Funktionsbaustein SD_PARTNER_DISPLAY dazu verwendet werden, um die Partnerdaten anzuzeigen.

 

Customizing übersetzen

$
0
0

Neuer Rollout - Neues Glück.
Spätestens beim ersten internationalen Rollout kommt die Frage auf welche Customizing Objekte zu übersetzen sind.
In der SPRO ist - etwas versteckt - eine sehr nützliche Standard-Funktion.

Spro übersetzung

uebersetzung2

 

 

GLD Entwicklung

$
0
0

Oftmals die Gretchenfrage als MMler.
Wie ist es dazu gekommen, dass der gleitende Durchschnittspreis (GLD) eines Materials sich verändert hat? Welcher Materialbeleg ist schuld daran?

Einflussfaktoren gibt es viele. Die üblichen Verdächtigen sind:

  • Bestellungen
  • Rechnungen
  • Retourenbestellungen
  • Gutschriften
  • Umbewertungen
  • "wilde MIGO Buchungen" mit Wertangabe (ja das geht...)
  • Umlagerungen "Werk an Werk"
  • ...

Die Transaktion S_P00_07000139 aus dem Thailändischen Steuerrecht (?) zeigt wenigstens halbwegs, wie und mit welchem Beleg sich der GLD verändert hat.

S_P00_07000139

gld_entwicklung

 

1--> 2 --> 3Wert und Menge ergeben den GLD
4-->5 Bestandswert reduziert um Buchungswert ergibt den neuen GLD

Im Layoutlayoutkann man sich noch diverse Zusatzinformationen einblenden lassen.

Tabellen rund um das Thema GLD:

MBEW Materialbewertung
MBEWH Materialbewertung Historie
QBEW Projektbestand
EBEW Kundeneinzel- / Transitbestand

sinnvolle OSS Hinweise zur Transaktion:

1327549
1175356

Bankleitzahlen einlesen

$
0
0

Mal wieder ein Thema aus dem FI-Bereich. Diesmal geht es um die Aktualisierung der Bankleitzahlen. Die Bundesbank bietet die aktuellen Bankleitzahlen zum Download an. Weitere Infos gibt es hier.

Das Einlesen der Bankleitzahlen ist dabei gar nicht die größte Herausforderung, sondern das Finden der aktuellen Bankleitzahlendatei. Markus Völker hat hierfür eine kleine Klasse geschrieben, mit der

  1. die URL der Bankleitzahlendatei ermittelt wird
  2. Die Bankleitzahlen ins SAP-System eingelesen werden

Verbesserungspotential

Die Klasse ermittelt und liest die Bankleitzahlen ein. Eventuelle wäre es jedoch wünschenswert zu sehen, welche und wie viele Debitoren von den Änderungen betroffen sind. Es müsste dafür eine Prüfung gegen die Tabelle KNBK gemacht werden.

Proxy

Falls du dich mit User und Kennwort am Proxy anmelden musst, dann muss du nach der Methode cl_http_client=>create_by_url den folgenden Aufruf einbauen:

lo_client->propertytype_logon_popup = http_client->co_disabled.
call method lo_client->authenticate
     exporting
        username  = 'myProxyUser'
        password  = 'myProxyPassword'.

Dementsprechend muss der CONSTRUCTOR um die beiden Parameter username und password erweitert werden.

Coding

REPORT  zrep_bbank_vs_bnka.
**&---------------------------------------------------------------------*
**& Report  ZREP_BBANK_VS_BNKA
**&
**&---------------------------------------------------------------------*
**& Dieser Report demonstriert die Benutzung der Klasse lcl_cmp_bnka_to_bbank
**& Author: Markus Völker
**&---------------------------------------------------------------------*


PARAMETERS p_proxy TYPE string LOWER CASE DEFAULT '123.100.100.88'.
PARAMETERS p_pport TYPE string            DEFAULT `80`.


CLASS lcl_cmp_bnka_to_bbank DEFINITION.
  PUBLIC SECTION.

    TYPES:
      BEGIN OF mts_bnka_result,
             status TYPE char01,
             bankl  TYPE bankl,
      END OF mts_bnka_result .
    TYPES:
      mtt_bnka_result TYPE STANDARD TABLE OF mts_bnka_result WITH DEFAULT KEY .

**Vergleiche:
**http://www.bundesbank.de/Redaktion/DE/Downloads/Aufgaben/Unbarer_Zahlungsverkehr/Bankleitzahlen/merkblatt_bankleitzahlendatei.pdf?__blob=publicationFile
    TYPES:
      BEGIN OF mts_bundesbank,
        blz(8), "Bankleitzahl
        merkmal(1), "Merkmal, ob bankleitzahlführender Zahlungsdienstleister ("1") oder nicht ("2")
        bezeichnung(58), "Bezeichnung des Zahlungsdienstleisters
        plz(5), "Postleitzahl
        ort(35), "Ort
        kurzbezeichnung(27), "Kurzbezeichnung des Zahlungsdienstleisters mit Ort
        pan(5), "Institutsnummer für PAN
        bic(11), "Business Identifier Code (BIC)
        pz(2), "Kennzeichen für Prüfzifferberechnungsmethode
        datensatz(6), "Nummer des Datensatzes
        aenderungs(1), "Änderungskennzeichen
        blz_loesch(1), "Hinweis auf eine beabsichtigte Bankleitzahllöschung
        nach_blz(8), "Hinweis auf Nachfolge-Bankleitzahl
        knz_iban(6), "Kennzeichen für die IBAN-Regel
      END OF mts_bundesbank .
    TYPES:
      mtt_bundesbank TYPE STANDARD TABLE OF mts_bundesbank WITH DEFAULT KEY .

    CONSTANTS  mc_bank_changes  TYPE char01 VALUE 'C'.     "#EC NOTEXT "Die Bank ist zur Änderung vorgesehen
    CONSTANTS  mc_bank_correct  TYPE char01 VALUE 'O'.     "#EC NOTEXT "Die Bank ist in Ordnung
    CONSTANTS  mc_bank_missing  TYPE char01 VALUE 'M'.     "#EC NOTEXT "Die Bank existiert nicht mehr
    CLASS-DATA mv_proxy_host    TYPE string .              "Proxy IP
    CLASS-DATA mv_proxy_service TYPE string .              "Proxy Port
    DATA       mt_bbank_datei   TYPE mtt_bundesbank .      "Datei der Bundesbank

    METHODS constructor
      IMPORTING
        iv_proxy_host    TYPE string OPTIONAL
        iv_proxy_service TYPE string OPTIONAL .
    METHODS set_bbank_file
      IMPORTING
        iv_path        TYPE csequence OPTIONAL
      EXPORTING
        ev_subrc       TYPE sy-subrc
        ev_err_message TYPE string.
    TYPE-POOLS abap .
    METHODS compare_bbank_with_bnka
      IMPORTING
        iv_with_missing      TYPE flag DEFAULT abap_true
        iv_with_changes      TYPE flag DEFAULT abap_true
        iv_with_correct      TYPE flag DEFAULT abap_true
      RETURNING
        VALUE(rt_result_tab) TYPE mtt_bnka_result .
  PROTECTED SECTION.
    METHODS get_bbank_file_from_web
      EXPORTING
        ev_subrc       TYPE sy-subrc
        ev_err_message TYPE string
        et_filetab     TYPE table .

ENDCLASS.

CLASS lcl_cmp_bnka_to_bbank IMPLEMENTATION.


* ---------------------------------------------------------------------------------------+
* | Instance Public Method COMPARE_BBANK_WITH_BNKA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_WITH_MISSING                TYPE        FLAG (default =ABAP_TRUE)
* | [--->] IV_WITH_CHANGES                TYPE        FLAG (default =ABAP_TRUE)
* | [--->] IV_WITH_CORRECT                TYPE        FLAG (default =ABAP_TRUE)
* | [<-()] RT_RESULT_TAB                  TYPE        MTT_BNKA_RESULT
* +--------------------------------------------------------------------------------------
  METHOD compare_bbank_with_bnka.

    DATA: lt_bnka  TYPE TABLE OF bnka,
          lv_subrc TYPE sy-subrc.

    FIELD-SYMBOLS: <bnka>   TYPE bnka,
                   <bbank>  TYPE mts_bundesbank,
                   <result> TYPE mts_bnka_result.

    DEFINE append_result.
      append initial line to rt_result_tab assigning <result>.
      <result>-status = &1.
      <result>-bankl  = &2.
    END-OF-DEFINITION.

* Wenn wir noch keine Daten haben, holen wir halt welche
    IF mt_bbank_datei IS INITIAL.
      set_bbank_file( IMPORTING ev_subrc = lv_subrc ).
      IF lv_subrc <> 0.
        RETURN.
      ENDIF.
    ENDIF.

* Alle Banken holen
    SELECT * FROM bnka INTO TABLE lt_bnka WHERE banks = 'DE'.

* Vergleich der Daten
*/--------------------------------------------------------------------------------\
    LOOP AT lt_bnka ASSIGNING <bnka>.
*   Lese die Vergleichsdaten
      READ TABLE mt_bbank_datei ASSIGNING  WITH KEY blz = <bnka>-bnklz.  "#EC WARNOK.
      IF sy-subrc <> 0.
*     Die Bank existiert nicht mehr
        append_result mc_bank_missing <bnka>-bankl.
      ELSEIF -blz_loesch = '1'.
*     Die Bank ist zum Löschen vorgemerkt
        append_result mc_bank_changes <bnka>-bankl.
      ELSE.
*     Keine Veränderungen festzustellen
        append_result mc_bank_correct <bnka>-bankl.
      ENDIF.
    ENDLOOP.
*\--------------------------------------------------------------------------------/

* Lösche ungewünschtes
*/--------------------------------------------------------------------------------\
    IF iv_with_missing = abap_false.
      DELETE rt_result_tab WHERE status = mc_bank_missing.
    ENDIF.
    IF iv_with_changes = abap_false.
      DELETE rt_result_tab WHERE status = mc_bank_changes.
    ENDIF.
    IF iv_with_correct = abap_false.
      DELETE rt_result_tab WHERE status = mc_bank_correct.
    ENDIF.
*\--------------------------------------------------------------------------------/

  ENDMETHOD.                                               "compare_bbank_with_bnka


* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZZ_CMP_BNKA_TO_BBANK->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_PROXY_HOST                  TYPE        STRING(optional)
* | [--->] IV_PROXY_SERVICE               TYPE        STRING(optional)
* +--------------------------------------------------------------------------------------
  METHOD constructor.
* Das hier ist nur die Erinnerung, eventuell einen Proxy setzen zu müssen
    mv_proxy_host    = iv_proxy_host .
    mv_proxy_service = iv_proxy_service.
  ENDMETHOD.                                               "constructor


* ---------------------------------------------------------------------------------------+
* | Instance Protected Method GET_BBANK_FILE_FROM_WEB
* +-------------------------------------------------------------------------------------------------+
* | [<---] EV_SUBRC                       TYPE        SY-SUBRC
* | [<---] EV_ERR_MESSAGE                 TYPE        STRING
* | [<---] ET_FILETAB                     TYPE        TABLE
* +--------------------------------------------------------------------------------------
  METHOD get_bbank_file_from_web.
* Hole die Datei der Bundesbank per HTTP
    DATA: lv_url     TYPE string,
          lv_datvon  TYPE d,
          lv_datbis  TYPE d,
          lo_http    TYPE REF TO if_http_client,
          lv_recdata TYPE xstring,
          lt_tmpbin  TYPE TABLE OF raw256,
          lv_tmplen  TYPE i.

*******************
* DATUMSBERECHNUNG
*******************

*     Monat/Jahr von:
*/--------------------------------------------------------------------------------\
    lv_datvon = sy-datum.
    DO.
      lv_datvon = cl_hrpad_date_computations=>subtract_months_from_date( start_date = lv_datvon               " Datum von dem Monate subtrahiert werden
                                                                         months     = 1  ).                   " Anzahl Monate
      IF lv_datvon+4(2) MOD 3 = 0.
        EXIT.
      ENDIF.
    ENDDO.
*     Tag von ...
    lv_datvon+6(2) = '01'.
    DO.
*      Finde den ersten Samstag im Monat ...
      IF cl_hrpad_date_computations=>get_weekday_number( lv_datvon ) = 6.            "Samstag
        EXIT.
      ENDIF.
      lv_datvon = lv_datvon + 1.
    ENDDO.
    lv_datvon = lv_datvon + 2.                             "Wir brauchen aber den Montag
*\--------------------------------------------------------------------------------/
*     Monat/Jahr bis:
*/--------------------------------------------------------------------------------\
    lv_datbis = sy-datum.
    DO.
      IF lv_datbis+4(2) MOD 3 = 0.
        EXIT.
      ENDIF.
      lv_datbis = cl_hrpad_date_computations=>add_months_to_date( start_date = lv_datbis               " Datum von dem Monate subtrahiert werden
                                                                  months     = 1  ).                   " Anzahl Monate
    ENDDO.
*     Tag von ...
    lv_datbis+6(2) = '01'.
    DO.
*      Finde den ersten Samstag im Monat ...
      IF cl_hrpad_date_computations=>get_weekday_number( lv_datbis ) = 6.            "Samstag
        EXIT.
      ENDIF.
      lv_datbis = lv_datbis + 1.
    ENDDO.
    lv_datbis = lv_datbis + 1.                             "geht bis Sonntag
*\--------------------------------------------------------------------------------/

* URL Zusammenbauen
*/--------------------------------------------------------------------------------\
    lv_url =    'http://www.bundesbank.de/Redaktion/DE/Downloads/Aufgaben/Unbarer_Zahlungsverkehr/Bankleitzahlen/' ##no_text
             && |{ lv_datbis(4) }_{ lv_datbis+4(2) }_{ lv_datbis+6(2) }/blz_{ lv_datvon(4) }_{ lv_datvon+4(2) }_{ lv_datvon+6(2) }_txt.txt?__blob=publicationFile|.
*\--------------------------------------------------------------------------------/

*******************
* HTTP - Verbindung
*******************
* Erstellen des Verbindungsobjekts
    cl_http_client=>create_by_url( EXPORTING url           = lv_url
                                             proxy_host    = mv_proxy_host               " logische Destination (Wird bei Funktionsaufruf angegeben)
                                             proxy_service = mv_proxy_service            " Portnummer
                                   IMPORTING
                                             client        = lo_http ).             " HTTP Client Abstraction

* Request senden
    lo_http->send( EXCEPTIONS OTHERS = 1 ).
    IF sy-subrc <> 0.
      lo_http->get_last_error( IMPORTING code    = ev_subrc
                                         message = ev_err_message ).
      RETURN.
    ENDIF.

* Daten annehmen
    lo_http->receive( EXCEPTIONS OTHERS = 1 ).
    IF sy-subrc <> 0.
      lo_http->get_last_error( IMPORTING code    = ev_subrc
                                         message = ev_err_message ).
      RETURN.
    ENDIF.

* Datei reinladen...
    lv_recdata = lo_http->response->get_data( ).
    IF lv_recdata IS INITIAL.
      ev_subrc = 1024.
      RETURN.
    ENDIF.

* Daten in eine "Datei" - Tabelle konvertieren
*/--------------------------------------------------------------------------------\
    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer        = lv_recdata
      IMPORTING
        output_length = lv_tmplen
      TABLES
        binary_tab    = lt_tmpbin.

    CALL FUNCTION 'SCMS_BINARY_TO_TEXT'
      EXPORTING
        input_length = lv_tmplen
      TABLES
        binary_tab   = lt_tmpbin
        text_tab     = et_filetab.
*\--------------------------------------------------------------------------------/

  ENDMETHOD.                                               "GET_BBANK_FILE_FROM_HTML


* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZZ_CMP_BNKA_TO_BBANK->SET_BBANK_FILE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_PATH                        TYPE        CSEQUENCE(optional)
* | [<---] EV_SUBRC                       TYPE        SY-SUBRC
* | [<---] EV_ERR_MESSAGE                 TYPE        STRING
* | [EXC!] FAILED_VIA_UPLOAD
* +--------------------------------------------------------------------------------------
  METHOD set_bbank_file.

    DATA: lt_filetab TYPE TABLE OF char512.
    FIELD-SYMBOLS:  <file>  TYPE char512,
                    <bbank> TYPE mts_bundesbank.

    IF iv_path IS NOT INITIAL AND cl_gui_frontend_services=>file_exist( iv_path ) = abap_true.
*   Datei einfach vom Frontend hochladen
      cl_gui_frontend_services=>gui_upload( EXPORTING
                                              filename = iv_path               " Name der Datei
                                            CHANGING
                                              data_tab = lt_filetab            " Übergabetabelle für Datei-Inhalt
                                            EXCEPTIONS
                                              OTHERS   = 1 ).
      ev_subrc = sy-subrc.
    ELSE.
*   Datei per HTTP holen
      me->get_bbank_file_from_web( IMPORTING ev_subrc       = ev_subrc
                                             ev_err_message = ev_err_message
                                             et_filetab     = lt_filetab ).
    ENDIF.

* Wenn die Datei leer ist machen wir hier nichts
    IF lt_filetab IS INITIAL.
      RETURN.
    ENDIF.

* In die richtige Struktur kippen:
    LOOP AT lt_filetab ASSIGNING <file>.
      APPEND INITIAL LINE TO mt_bbank_datei ASSIGNING <bbank>.
      <bbank> = <file>.
    ENDLOOP.
  ENDMETHOD.                                               "set_bbank_file
ENDCLASS.

DATA gr_bbank  TYPE REF TO lcl_cmp_bnka_to_bbank.
DATA gv_subrc  TYPE sy-subrc.
DATA gv_err    TYPE string.
DATA gt_result TYPE lcl_cmp_bnka_to_bbank=>mtt_bnka_result.
FIELD-SYMBOLS  TYPE lcl_cmp_bnka_to_bbank=>mts_bnka_result.


START-OF-SELECTION.

* Objekt instanziieren
  CREATE OBJECT gr_bbank
    EXPORTING
      iv_proxy_host    = p_proxy                           " logische Destination
      iv_proxy_service = p_pport.                          " Portnummer

* Datei innerhalb der Klasse organisieren
  gr_bbank->set_bbank_file( IMPORTING
                             ev_subrc       = gv_subrc     " Rückgabewert von ABAP-Anweisungen
                             ev_err_message = gv_err       " Error - Message
                           ).
  IF gv_subrc <> 0.
    WRITE: / gv_err.
    RETURN.
  ENDIF.

* Vergleich der Daten aus der Bundesbank und SAP holen
  gt_result = gr_bbank->compare_bbank_with_bnka( ).

* primitive Ausgabe... :)
  LOOP AT gt_result ASSIGNING .
    CASE -status.
      WHEN lcl_cmp_bnka_to_bbank=>mc_bank_missing.
        WRITE: / 'MISSING'.
      WHEN lcl_cmp_bnka_to_bbank=>mc_bank_changes.
        WRITE: / 'CHANGING'.
      WHEN lcl_cmp_bnka_to_bbank=>mc_bank_correct.
        WRITE: /  'OK'.
    ENDCASE.
    WRITE: 12 '|', -bankl.
  ENDLOOP.

High Definition SAP? Ein Jahr später

$
0
0

Vor ziemlich genau einem Jahr habe ich mich darüber ausgelassen, dass der SAPGUI mit einer Auflösung größer als FullHD leider nicht zu verwenden ist: High Definition SAP? Ein Erfahrungsbericht
Jetzt, ein Jahr später, führt die SAP im SAPGUI das SAP Blue Crystal Design ein:
Blue Crystal Design
SAP Blue Crystal is a new visual design theme which succeeds Corbu. It provides a consistent design that allows users to seamlessly experience SAP GUI and NWBC elements. It is the standard theme of Fiori applications and comes with a new color palette and icons which are better scalable. The background texture has a stroke pattern in white and light blue with a gradient layer.

SAP-Note 2022335

Hat sich was geändert?

Die SAP hat tatsächlich nachgebessert und für das Blue Crystal Design die Icons komplett neu gebaut. Ich persönlich finde das Design extrem unübersichtlich und hässlich. Leider wurden die Icons für das Signature Theme nicht überarbeitet.
Leider sind jedoch nach wie vor Elemente vergessen worden.
Folgend ein paar Screenshots mit hoher Auflösung und dem neuen SAP Blue Crystal Design.

Der erste Blick gilt der SE80. Hier ist gut erkennbar, dass zwar die Icons gut skaliert wurden, der Auswahlbereich links oben jedoch immer noch nicht korrekt skaliert wird.

SAP Blue Crystal Design - SE24

 

Ich wollte es kaum glauben: Das Calendar-Control wurde gar nicht angepasst:

SAP Blue Crystal Design - Calendar

 

Das ALV-Grid sieht ordentlich aus. Die Icons finde ich jedoch gelinde gesagt schrecklich.

SAP Blue Crystal Design - ALV Grid

 

Im Tree-Control-Demo sieht man, dass die "Anfasser" für die Ordner immer noch extrem klein sind.

SAP Blue Crystal Design - Tree

 

Die Dynamischen Dokument werden gut skaliert. Allerdings nur der Text. Die Icons sind so klein, dass sie kaum zu erkennen sind.

SAP Blue Crystal Design - HTML

 

 

The background texture has a stroke pattern in white and light blue with a gradient layer. Hier in vierfacher Vergrößerung. Mich hat der schraffierte Hintergrund sofort irritiert:

SAP Crystal Design - Hintergrund

 

Das SAP-Logon ebenfalls mit einem sehr kleinen "Auf- und Zuklapper":

 

SAPlogon

 

 

Zuguter letzt bin ich  noch über die F4-Eingabehilfe gestolpert. Hier funktioniert das Skalieren so gar nicht.

f4

 

Fazit

Ich werde weiterhin mit meiner auf FullHD runter skalierten Auflösung arbeiten und weiterhin das Signature Theme verwenden. Schließlich will ich mit dem SAPGUI arbeiten...

Ach so: Für alle, die an der genauen Info über den SAPGUI-Patch interessiert sind:

SAPLOGON Info

MAIN MODULE INFORMATION:
saplogon.exe
SAP Logon für Windows
740 Final Release
7400.1.3.1104
1588321

MD04 Start/Freigabedatum anzeigen

$
0
0

In der Bedarfs/Bestandsliste stehen alle Banfen und Planaufträge. Schön nach Datum sortiert mit dem Hinweis wann das Material im Werk sein soll.
Speziell bei plangesteuerter Disposition - mit Bedarfen in der Zukunft - stellt sich aber oftmals die Frage wann man denn die Banf in eine Bestellung umwandeln muss.

Hierzu kann man die im Standard ausgeblendete Spalte "Start-/Freigabedatum" einblenden lassen.
Dort steht dann das Datum des Bedarfstermins minus der Wiederbeschaffungszeit, also der Tag an dem die Banf spätestens umgesetzt werden soll.

MD04

Zum Einblenden muss man mit dem Mauszeiger genau zwischen 2 Spalten bis sich der Mauszeiger von "verschieben/Größe ändern" zu "einblenden" ändert.
(2 parallele Balken mit Pfeilen nach links und rechts) (neben dem Feld "Dispoelement"). Dieses Vorgehen muss 2 mal wiederholt werden, bis die Spalte "Start-/Freigabedatum" erscheint.

Danach kann das Layout gespeichert werden.

Layout speichern MD04

wie immer "aktivieren" und schon wird die Spalte dauerhaft eingeblendet.

Layout aktivieren

Kleiner Trick - große Hilfe :-)

AWI, 06/2015

Transaktionen

MD04

Kundenfelder in BAPI-Struktur füllen

$
0
0

Das Befüllen von Kundeneigenen Feldern in einem BAPI stellt einen häufig vor Probleme. Ich stelle dir hier eine kurze Doku mit Beispielcoding vor, um Kundenfelder korrekt und beschwerdefrei übergeben zu können.
Als Beispiel verwenden ich den BAPI_SALESORDER_CREATEFROMDAT2 zum Anlegen von Kundenaufträgen.

Vorbedingung BAPE_VBAK

Alle kundeneigenen Felder, die mittels APPEND an die Kopfstruktur VBAK angehängt wurden, müssen ebenfalls in einem APPEND an die Struktur BAPE_VBAK appendiert werden. Hierbei ist es wichtig, dass die Felder zeichenartig sein müssen! Es dürfen also keine Felder vom Typ FLOAT, DEC oder INT verwendet werden! Entweder müssen diese Felder außen vor gelassen werden (sie können dann nicht mittels BAPI geändert werden), oder es muss ein eigenes zeichenartiges Datenelement spezielle für den BAPI angelegt werden.

Beispiel

Die Umwandlung einer Struktur in einen "Container" braucht man immer, wenn man Kundenfelder in BAPIs verwenden möchte. In vielen BAPIs gibt es einen EXTENSION-Parameter, dem alle Kundenfelder übergeben werden. In diesem speziellen Fall ist es die Übergabetabelle EXTENSIONIN.

Die Anweisung zum Füllen der EXTENSIONIN sieht klassischerweise in etwa so aus:

DATA ls_bape_vbak  TYPE bape_vbak.
DATA ls_extension  TYPE bapiparex.
DATA lt_extensions TYPE STANDARD TABLE OF bapiparex.

ls_bape_vbak-zzfeld1    = '1'.
ls_bape_vbak-zzfeld2    = 'ABCD'.

ls_extension-structure  = 'BAPE_VBAK'.
ls_extension+30(960)    = ls_bape_vbak. "(bapiparex-valuepart1 - 4)
APPEND ls_extension TO lt_extensions.

Abgesehen davon, dass die Unterteilung der Kundenfelder in VALUEPART1 bis VALUEPART4 absoluter Schwachsinn ist, ist es unter Unicode nicht mehr einfach möglich, die Strukturen zuzuweisen. Im ABAP-Editor erhälst du dann die Meldung:

"LS_EXTENSION+30(960)" und "LS_BAPE_VBAK" sind in einem
Unicode-Programm nicht ineinander konvertierbar.

Casting notwendig

Entweder bedient man sich des Tricks mit dem X-Casting oder man verwendet die entsprechende Klasse von SAP: CL_ABAP_CONTAINER_UTILITIES.
Mit dieser Klasse - und speziell der Methode FILL_CONTAINER_C - ist es möglich, die typgerechte Umwandlung vorzunehmen.
CALL METHOD cl_abap_container_utilities=>fill_container_c
  EXPORTING
    im_value     = ls_bape_vbak
  IMPORTING
    ex_container = ls_extension+30(960)
  EXCEPTIONS
    illegal_parameter_type = 1
    OTHERS = 2.

Projektsystem: Hierarchie PSP-Element ändern

$
0
0

Eine Projektstruktur ist zwangsläufig eine Hierarchie. Einzelne PSP-Elemente können ebenfalls hierarchisch angeordnet sein. Eine einfache Struktur sieht beispielsweise so aus:

2016-05-26_17-26-05

Die Projektstruktur wird im SAP-Standard mit der Transaktion CJ20n bearbeitet.
Mit dem kleinen Hierarchieänderungsprogramm soll die Struktur nun dahingehend geändert werden, dass das PSP-Element 43 unter das PSP-Element Nummer 42 gehängt wird. Der Aufruf sieht folgendermaßen aus:

2016-05-26_18-30-54

Die Übergabetabelle LT_HIERARCHY:

2016-05-26_18-32-09

Das Ergebnis ist glücklicherweise wie erwartet:

2016-05-26_17-27-35

Hinweis

Wenn die Hierarchie geändert werden soll, dann kann dies leider nicht beliebig passieren. In jedem Fall muss immer die Hierarchie aller beteiligten PSP-Elemente definiert werden. Soll das PSP-Element Nummer 43 wieder "heraufgestuft" werden, dann müssen Nr. 42 und Nr. 43 jeweils mit "UP = P-0000004"  und "DOWN = space" an den Baustein übergeben werden. Nr. 4 muss ebenfalls übergeben werden. Hier der Aufruf für Nr. 43. Eigentlich müsste auch hier Nr. 42 berücksichtigt werden, da es ebenfalls beteiligt ist, denn es "verliert" ja sein Kind:

2016-05-26_18-36-46

Dies ist das Ergebnis:

2016-05-26_17-41-13

Wie du siehst, ist die Reihenfolge vertauscht: Erst kommt Element 43, danach 42. Eine Sortierung gibt es nicht. Die "Geschwister" müssen genau definiert werden (LEFT und RIGHT). Soll die Reihenfolge anders herum sein, also erst 42, dann 43, dann muss die Übergabetabelle folgendermaßen aussehen:

2016-05-26_17-53-09

Die Geschwister müssen nicht immer definiert werden. Manchmal funktioniert eine Operation jedoch nur dann, wenn auch die Geschwister korrekt angegeben werden.

Am besten ist es, die Hierarchie 100%ig genau zu definieren. Wann sich der Baustein unvollständigen Definitionen tolerant verhält und wann nicht, ist für mich nicht nachvollziehbar.

Fehler "Wurzelelement der Hierarchie darf nicht verschoben werden"

Fehler 469(CJ)

Bei der Änderung der Hierarchie müssen alle beteiligten Elemente definiert werden! Wenn aus der Ausgangsposition "43 ist 42 untergeordnet" die Änderung "42 ist 43 untergeordnet" erfolgen soll, dann muss das ROOT-Element P-0000004 erwähnt werden. Das passiert in dem Demoprogramm, allerdings zeige ich den Fehler hier auf, weil er nicht auf die Fehlerursache schließen lässt.

2016-05-26_18-21-16

Code

 PARAMETERS p_projn  TYPE ps_pspid DEFAULT 'K-0000001'.
 PARAMETERS p_root   TYPE ps_posid DEFAULT 'P-0000004'.
 PARAMETERS p_parent TYPE ps_posid DEFAULT 'P-00000042'.
 PARAMETERS p_child  TYPE ps_posid DEFAULT 'P-00000043'.
 
 START-OF-SELECTION.
 
   PERFORM go.
 
 *&---------------------------------------------------------------------*
 *&      Form  go
 *&---------------------------------------------------------------------*
 FORM go.
 
   DATA ls_project_def      TYPE bapi_project_definition.
   DATA ls_project_def_upd  TYPE bapi_project_definition_up.
   DATA lt_messages         TYPE STANDARD TABLE OF bapi_meth_message.
   DATA ls_message          TYPE bapi_meth_message.
   DATA ls_return           TYPE bapireturn1.
   DATA lt_methods          TYPE STANDARD TABLE OF bapi_method_project.
   DATA ls_method           TYPE bapi_method_project.
   DATA lt_hierarchy        TYPE STANDARD TABLE OF bapi_wbs_hierarchie.
   DATA ls_hierarchy        TYPE bapi_wbs_hierarchie.
 
   ls_project_def-project_definition p_projn.
 
 
   ls_method-method     'Create'.
   ls_method-objecttype 'WBS-Hierarchy'.
   APPEND ls_method TO lt_methods.
 
 
   CLEAR ls_method.
   ls_method-method     'SaveAndWait'.
   APPEND ls_method TO lt_methods.
 
   CLEAR ls_hierarchy.
   ls_hierarchy-project_definition p_projn.
   ls_hierarchy-wbs_element        p_root.
   ls_hierarchy-down               p_parent.
   APPEND ls_hierarchy TO lt_hierarchy.
 
 
   CLEAR ls_hierarchy.
   ls_hierarchy-project_definition p_projn.
   ls_hierarchy-wbs_element        p_parent.
   ls_hierarchy-down               p_child.
   ls_hierarchy-up                 p_root.
   APPEND ls_hierarchy TO lt_hierarchy.
 
   IF p_child IS NOT INITIAL.
     CLEAR ls_hierarchy.
     ls_hierarchy-project_definition p_projn.
     ls_hierarchy-wbs_element        p_child.
     ls_hierarchy-up                 p_parent.
     APPEND ls_hierarchy TO lt_hierarchy.
   ENDIF.
 
 
   CALL FUNCTION 'BAPI_PROJECT_MAINTAIN'
     EXPORTING
       i_project_definition     ls_project_def
       i_project_definition_upd ls_project_def_upd
     IMPORTING
       return                   ls_return
     TABLES
       e_message_table          lt_messages
       i_method_project         lt_methods
       i_wbs_hierarchie_table   lt_hierarchy.
 
   WRITE/ ls_return-message.
   LOOP AT lt_messages INTO ls_message.
     WRITE/ ls_message-message_text.
   ENDLOOP.
 
   CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
     EXPORTING
       wait abap_true.
 
 ENDFORM.                    "go

Selektion für MD04/ MD06 + MS04/06 eingrenzen

$
0
0

Je nach Größe und aufkommen in Werk und Dispobereich dauert die Auswertung in den Transaktionen recht lange. Die Standardselektion erlaubt es leider nur sehr begrenzt die Ergebnismenge einzugrenzen – Select-Options vermisst man gänzlich. Der Benutzer wird oft gezwungen die komplette Liste aufzubauen und anschließend mit Filtern die Datenmenge einzugrenzen.
Zum Glück bietet die SAP uns hier die Möglichkeit die Situation mittels BAdI MD_EXCLUDE_MATERIAL zu verbessern. Der BAdI erlaubt es im Einstiegsbild einen zusätzlichen Reiter „Zusatzselektion“ einzubinden und dort ein eigenes Dynpro mit einem Selektionsbild einzubinden.

Link zur SAP-Doku

https://help.sap.com/erp_hcm_ias_2013_01/helpdata/de/45/188147e1235d79e10000000a11466f/content.htm

„SAP empfiehlt, sich stark an der Beispielimplementierung zu orientieren und einen speziellen kundenspezifischen Report analog dem Report RMD07_BADI_SCREEN_EXTENSION01 mit Selektionsscreen 347 und Auswahl-Formroutine zu definieren. Der Selektions-Subscreen muss dann in der Screen-Erweiterung den leeren Subscreen 347 ersetzen, während die Auswahl-Formroutine innerhalb der Methode EXCLUDE_MATERIAL_EVAL aufgerufen werden muss.“

Demoreport der SAP

Report RMD07_BADI_SCREEN_EXTENSION01

Beispiel

Beispielsweise könnte das wie folgt aussehen:

Erweiterung der Selektionsoptionen bei MD04

Erweiterung der Selektionsoptionen bei MD04

Vor der Auswertung der Dispositionsdaten wird dann für jedes Material im Dispobereich die BAdI-Methode gerufen und die Möglichkeit gegeben das Material aus der Auswertung auszuschließen.
Unbefriediegend dabei ist, dass die „Speichern“ Funktion des Standards die Eingabewert im Subscreen nicht mit speichert und entsprechend beim Start der Transaktion nicht wiederherstellt. Zum Glück erlaubt uns das Sel-Screen Eventing die entsprechenden Zeitpunkte ebenfalls abzuhandeln und das so zu ermöglichen. *** Einmalig beim Start der Transaktion gespeicherte Daten wiederherstellen via FuBa RS_SUPPORT_SELECTIONS

CASE sy-ucomm. 
  WHEN 'YES'. 
*** Wiederherstellen Selektionsbild via FuBa RS_SUPPORT_SELECTIONS wenn 
*** der Benutzer zurück aus der Auswertung kommt. 
  WHEN 'SAVP'. 
*** Speichern des Selektionsbild via FuBa RS_REFRESH_FROM_SELECTOPTIONS 
*** und RS_CHANGE_CREATED_VARIANT_255 bzw. RS_CREATE_VARIANT_255 
ENDCASE.

Preisfindung im Kundenauftrag von außen anstossen

$
0
0

In diesem Beitrag zeige ich dir, wie du die Preisfindung eines Kundenauftrags neu ausführen lassen kannst. Das grundsätzliche Verfahren sieht so aus:

  1. Userexit in SAPMV45A anpassen
  2. Parameter setzen
  3. BAPI aufrufen
  4. Parameter zurücknehmen

Um die Preisfindung von außen triggern zu können, musst du Änderungen im Programm SAPMV45A durchführen. Zuerst benötigst du jedoch die Möglichkeit, einen Parameter zur Laufzeit zu setzen, der dann im SAPMV45A abgefragt werden kann. Das kann gut über eine der beiden Methoden erfolgen:

  1. EXPORT TO MEMORY und IMPORT FROM MEMORY
  2. Öffentliches Attribut der eigenen globalen Klasse

Anlage der globalen Klasse

Als erstes musst du eine Klasse anlegen mit der die neue Preisfindung durchgeführt werden soll. In meinem Beispiel heißt sie ZCL_SD_NP (New Pricing).

Lege das öffentliche Klassenattribut KNPRS vom Typ KNPRS an (static). Das ist die Preisfindungsart, mit der die Art der neuen Preisfindung gesteuert werden kann.

Quelltext (relevanter Teil ) in MV45AFZB:

FORM userexit_new_pricing_vbap CHANGING new_pricing.
  IF zcl_sd_np=>knprs IS NOT INITIAL.  
     new_pricing = zcl_sd_np=>knprs.
   ENDIF.
ENDFORM.                    "USEREXIT_NEW_PRICING_VBAP
FORM userexit_new_pricing_vbkd CHANGING new_pricing.
  IF zcl_sd_np=>knprs IS NOT INITIAL. 
     new_pricing = zcl_sd_np=>knprs.
   ENDIF.
ENDFORM.                    "USEREXIT_NEW_PRICING_VBKD

Quelltext Klasse

Nun brauchen wir noch die Methode TRIGGER_NEW_PRICING

DATA: 
  ls_bapisdh1x  TYPE bapisdh1x,
  lt_pos        TYPE STANDARD TABLE OF bapisditm WITH NON-UNIQUE DEFAULT KEY,
  lt_posx       TYPE STANDARD TABLE OF bapisditmx WITH NON-UNIQUE DEFAULT KEY,
  lt_return     TYPE bapiret2_t.
FIELD-SYMBOLS: 
  <ls_pos>      LIKE LINE OF lt_pos,
  <ls_posx>     LIKE LINE OF lt_posx.


CLEAR ct_bapiret2.
knprs = iv_knprs.
*--------------------------------------------------------------------*
* Get all positions to be redermined
*--------------------------------------------------------------------*
SELECT posnr AS itm_number werks AS plant
INTO CORRESPONDING FIELDS OF TABLE lt_pos
FROM vbap
WHERE vbeln = iv_vbeln_va.

LOOP AT lt_pos ASSIGNING <ls_pos>.
APPEND INITIAL LINE TO lt_posx ASSIGNING <ls_posx>.
<ls_posx>-itm_number = <ls_pos>-itm_number.
<ls_posx>-updateflag = 'U'.
ENDLOOP.

ls_bapisdh1x-updateflag = 'U'.
CALL FUNCTION 'BAPI_SALESORDER_CHANGE'
  EXPORTING
    salesdocument    = iv_vbeln_va
    order_header_inx = ls_bapisdh1x
  TABLES
    return           = ct_bapiret2
    order_item_in    = lt_pos
    order_item_inx   = lt_posx
  EXCEPTIONS
    ERROR_MESSAGE = 1.

CLEAR knprs.  " Only once

TRY.
    DATA(ls_return) = ct_bapiret2[ type = 'E' ].
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
    RAISE EXCEPTION TYPE zcx_my_exception.
  CATCH CX_SY_ITAB_LINE_NOT_FOUND.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
ENDTRY.

Durch Aufruf der Methode ZCL_SD_NP=>TRIGGER_NEW_PRICING( … ) kannst du nun einen Beleg dazu bewegen, eine neue Preisfindung durchzuführen.

Der Beitrag Preisfindung im Kundenauftrag von außen anstossen erschien zuerst auf Tricktresor.

Komponenten einem Fertigungsauftrag hinzufügen

$
0
0

Für den Fertigungsaufträge sind die BAPIs leider sehr rar gesät und man muss auf andere Bausteine ausweichen. Um einem Auftrag Komponenten hinzuzufügen, habe ich nur den Baustein CO_XT_COMPONENT_ADD gefunden. Die CO_XT-Funktionsbausteine sind zwar prinzipiell „extern“ und in der Funktionsgruppe „APIs Fertigungsauftrag“, jedoch sind die Bausteine allesamt sehr mit Vorsicht zu genießen.

Das folgende Coding fügt einem Fertigungsauftrag eine Komponente (Materialnummer) hinzu.

Code

"Lokale Daten
DATA ls_return TYPE coxt_bapireturn.
DATA lt_return TYPE coxt_t_bapireturn.
DATA lv_error_occurred TYPE boolean.
DATA ls_resbd_created TYPE resbd.
DATA lt_resbt_exp TYPE STANDARD TABLE OF resbb.
DATA lv_posnr TYPE positionno.

DATA ls_quan TYPE coxt_s_quantity.
DATA ls_stor_loc TYPE coxt_s_storage_location.
DATA ls_stor_loc_x TYPE coxt_s_storage_locationx.

ls_quan-quantity    = menge.
ls_quan-uom         = meins.

ls_stor_loc-werks   = werks.
ls_stor_loc-lgort   = lgort.
ls_stor_loc_x-werks = abap_true.
ls_stor_loc_x-lgort = abap_true.

"Komponente hinzufügen
CALL FUNCTION 'CO_XT_COMPONENT_ADD'
  EXPORTING
    is_order_key         = aufnr
    i_material           = matnr
    is_requ_quan         = ls_quan
    i_operation          = 1
    is_storage_location  = ls_stor_loc
    is_storage_locationx = ls_stor_loc_x
    i_postp              = 'L' "Lagerposition
    i_posno              = lv_posnr
  IMPORTING
    es_bapireturn        = ls_return
    e_error_occurred     = lv_error_occurred
    es_resbd_created     = ls_resbd_created
  TABLES
    resbt_exp            = lt_resbt_exp.

IF lv_error_occurred = abap_false.
*== PRE-Commit
  CALL FUNCTION 'CO_XT_ORDER_PREPARE_COMMIT'
    TABLES
      et_bapireturn = lt_return.

"Keine Fehler!
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
ELSE.
"Fehlerbehandlung
ENDIF.

Fehlende Positionsnummer

Der Baustein hat leider einen kleinen Schönheitsfehler: Die Positionsnummer (RSB-POSNR) wird leider nicht gesetzt und kann auch nicht ohne weiteres geändert werden. Um die Positionsnummer trotzdem ändern zu können, habe ich zwei Lösungen gefunden:

  1. Die Änderung der internen Tabelle RESB_BT  über einen Dirty-Assign
  2. Änderung über die Standardbausteine
    • CO_BT_RESB_READ_WITH_KEY
    • CO_BT_RESB_GET_LAST_POSNR
    • CO_BT_RESB_UPDATE

Die Änderung muss nach dem CO_XT_COMPONENT_ADD und vor dem Commit erfolgen.

Positionsnummer ändern über Dirty-Assign

*--------------------------------------------------------------------*
* set item number
*--------------------------------------------------------------------*
  TYPES: BEGIN OF ts_resb_bt.
    INCLUDE TYPE resbb.
    TYPES: indold LIKE sy-tabix,
    no_req_upd LIKE sy-datar,
  END OF ts_resb_bt.

  TYPES tt_resb_bt TYPE TABLE OF ts_resb_bt.
  FIELD-SYMBOLS <lt_resb_bt> TYPE tt_resb_bt.
  FIELD-SYMBOLS <ls_resb_bt> TYPE ts_resb_bt.

  ASSIGN ('(SAPLCOBC)RESB_BT[]') TO <lt_resb_bt>.
  LOOP AT <lt_resb_bt> ASSIGNING <ls_resb_bt>.
    IF <ls_resb_bt>-posnr IS INITIAL.
      <ls_resb_bt>-posnr = CONV numc04( <ls_resb_bt>-rspos * 10 ).
    ENDIF.
  ENDLOOP.

Änderung der Positionsnummer über Funktionsbausteine

DATA resbd_exp TYPE resbd.
 DATA posnr_max TYPE tcn41-posnr_mat.
 DATA index_exp TYPE sy-tabix.
 DATA vbkz_exp  TYPE resbb-vbkz.
 DATA nfgrp_exp TYPE resbd-nfgrp.
 DATA posnr_exp TYPE resbd-posnr.

 CALL FUNCTION 'CO_BT_RESB_READ_WITH_KEY'
   EXPORTING
     rsart_imp = ls_resbd-rsart
     rsnum_imp = ls_resbd-rsnum
     rspos_imp = ls_resbd-rspos
   IMPORTING
     index_exp = index_exp " Index interner Tabellen
     posnr_exp = posnr_exp " Nummer der Stücklistenposition
     resbd_exp = resbd_exp " Reservierung/Sekundärbedarf
     nfgrp_exp = nfgrp_exp " Ein-/Auslaufdaten: Nachfolgegruppe
     vbkz_exp  = vbkz_exp " Verbuchungskennzeichen
   EXCEPTIONS
     not_found = 1
     OTHERS    = 2.

 CALL FUNCTION 'CO_BT_RESB_GET_LAST_POSNR'
   EXPORTING
     aufpl     = aufpl
     aplzl     = aplzl
   IMPORTING
     posnr_max = posnr_max. 

 resbd_exp-posnr = posnr_max + 10.

 CALL FUNCTION 'CO_BT_RESB_UPDATE'
   EXPORTING
     resb_new  = resbd_exp
     tabix_old = index_exp.

Dialog oder nicht Dialog?

Ein weiteres Problem könnte der Baustein CO_XT_ORDER_PREPARE_COMMIT machen, denn bei der Änderung des Fertigungsauftrags können Popups erscheinen, die vom Anwender bestätigt werden müssen.

Wenn man Dialoge verhindern möchte, dann muss der Update-Baustein CO_ZV_ORDER_POST direkt aufgerufen werden. Dieser hat einen Parameter NO_DIALOG, den man entsprechend mit X besetzen kann.

 

 

Der Beitrag Komponenten einem Fertigungsauftrag hinzufügen erschien zuerst auf Tricktresor.


Vorgang im Fertigungsauftrag anlegen

$
0
0

BAPIs sollten eigentlich programmtechnisch das möglich machen, was auch im Dialog möglich ist. Leider gibt es sehr viele Unterschiede zwischen BAPI und entsprechender Dialog-Transaktion.

Im Produktionsumfeld ist es so, dass ein Fertigungsauftrag gar nicht komplett mit Hilfe von BAPIs angelegt werden kann. Die Anlage bzw. Änderung muss in mehrere Schritten erfolgen. Normalerweise reicht es dem BAPI_PRODORD_CREATE unter Angabe einer Materialnummer und eines Werkes um einen Fertigungsauftrag anzulegen.

Aber natürlich gibt es immer Umstände, die eine gezielte Anlage oder Manipulation des Fertigungsauftrags notwendig machen. In diesem Beispiel zeige ich die Anlage eines Vorgangs. Hierfür gibt es leider keinen BAPI und ich verwende den Baustein CO_SE_PRODORD_CHANGE, da dieser problemlos separat aufzurufen war. Es gibt noch den Baustein CO_XT_OPERATION_CHANGE, der jedoch Vorbereitungen mit anderen CO_XT-Bausteinen benötigt.

Code

"Lokale Daten
 DATA lv_aufnr TYPE aufnr.
 DATA ls_return TYPE bapiret2.
 DATA lt_operations TYPE cose_t_operation.
 DATA ls_operation TYPE cose_s_operation.
 DATA ls_header TYPE cose_s_header.

"Vorgangsdaten
 ls_operation-standard_value_01 = data-vgw01.
 ls_operation-standard_value_01_unit = data-vge01.
 ls_operation-standard_value_02 = data-vgw02.
 ls_operation-standard_value_02_unit = data-vge02.
 ls_operation-short_text = data-vorgangstext.

 ls_operation-sequence = space.
 ls_operation-operation = data-vornr.
 ls_operation-work_center = data-arbpl.
 ls_operation-control_key = data-steus. 
 ls_operation-earliest_end_exec_date = data-endtermin.
 ls_operation-earliest_end_exec_time = '210000'.
 ls_operation-base_quantity = data-menge.
 ls_operation-dispatch_indicator = abap_false.
 ls_operation-user_field_02_character = data-xyz.

 ls_operation-standard_value_01_x = abap_true.
 ls_operation-standard_value_01_unit_x = abap_true.
 ls_operation-standard_value_02_x = abap_true.
 ls_operation-standard_value_02_unit_x = abap_true.
 ls_operation-work_center_x = abap_true.
 ls_operation-earliest_end_exec_date_x = abap_true.
 ls_operation-earliest_end_exec_time_x = abap_true.
 ls_operation-short_text_x = abap_true.
 ls_operation-base_quantity_x = abap_true.
 ls_operation-user_field_02_character_x = abap_true.
 APPEND ls_operation TO lt_operations.

 SET UPDATE TASK LOCAL.

"Anlage/ Änderung des Vorgangs
 CALL FUNCTION 'CO_SE_PRODORD_CHANGE'
   EXPORTING
     iv_order_number = lv_aufnr
     is_header = ls_header
     it_operation = lt_operations
     iv_commit = abap_true
   IMPORTING
     es_return = ls_return.
     export_werks_to_memory( space ).

 IF ls_return IS INITIAL.
   COMMIT WORK.
 ELSE.
   RAISE EXCEPTION TYPE zcx_order.
 ENDIF.

Keine Werksänderung möglich

Leider hat der verwendete Baustein eine Einschränkung, die es im Dialog nicht gibt: Es kann kein abweichendes Werk im Vorgang übergeben werden. Dies war jedoch zwingend notwendig. Ich wusste dann keine andere Möglichkeit, als an geeigneter Stelle eine Erweiterungsimplementierung zu erstellen, die das vom Baustein gefundene Default-Werk überschreibt.

Die Erweiterung habe ich im Programm LCO_SEF03 am Ende der FORM-Routine opr_set_default_values gesetzt. Vor Aufruf des Bausteins CO_SE_PROORD_CHANGE exportiere ich das zu verwendende Werk über EXPORT TO MEMORY in den SAP-Speicher. Die Erweiterungsimplementierung überschreibt das Feld gs_afvgd-werks  mittels IMPORT FROM MEMORY (sofern vorhanden). Hiermit ist nur die Anlage oder Änderung eines Vorgangs möglich. Für das Ändern mehrerer Vorgänge muss die Logik entsprechend angepasst werden und man muss in der Erweiterung prüfen, welcher Vorgang gerade bearbeitet wird.

Der Beitrag Vorgang im Fertigungsauftrag anlegen erschien zuerst auf Tricktresor.

Fertigungsauftrag rückmelden

$
0
0

Ein kurzes und knappes Code-Beispiel um eine Rückmeldung zu einem Fertigungsauftrag mit Hilfe des Bausteins BAPI_PRODORDCONF_CREATE_TT zu erfassen. Die Rückmeldedaten werden erfasst und dann dem Baustein übergeben.

Um das ganze etwas interessanter zu machen, verwende ich die neuen ABAP-740 Sprachfeatures VALUE und SWITCH…

Time Ticket füllen

append value #(
   "Rückmeldedaten füllen
    orderid        = aufnr
    operation      = vornr
    work_cntr      = arbpl
    plant          = werks
    postg_date     = sy-datum
    conf_text      = |Rückmeldung Hugo|
    yield          = gutmenge
    conf_quan_unit = 'ST'
    recordtype     = COND #( WHEN gutmenge >= gesamtmenge THEN 'L40' ELSE 'L20' )
  ) TO tickets.

Rückmeldung buchen

DATA return     TYPE bapiret1.
 DATA return_det TYPE STANDARD TABLE OF bapi_coru_return.
 DATA return_det TYPE bapi_coru_return.

 "Rückmeldung buchen
 CALL FUNCTION 'BAPI_PRODORDCONF_CREATE_TT'
   EXPORTING
     post_wrong_entries = '0'
     testrun       = abap_false
   IMPORTING
     return        = return
   TABLES
     timetickets   = tickets
     detail_return = return_det.
Wie bei allen BAPIs muss die Buchung durch ein BAPI_TRANSACTION_COMMIT bestätigt werden

Der Beitrag Fertigungsauftrag rückmelden erschien zuerst auf Tricktresor.

SimDia² als Alternative zur Programmierung?

$
0
0

Über mein Lieblings-AddOn SimDia² habe ich ja bereits mehrmals geschrieben (SAP Datenimport einfach?, Neue Version SimDia² und Logik vs. Daten). Grund dafür waren die große Funktionalität und die extrem einfache Handhabung. Beides ermöglicht es auch Endanwendern und Nicht-Informatikern, sehr schnell – also in wenigen Minuten – einen Datenaustausch zwischen Excel und SAP zu definieren und automatisch ausführen zu lassen.

Mein Problem als leidenschaftlicher Programmierer und „Datenmalträtierer“ war aber bisher immer, dass mir ein bisschen die „Anwender-Brille“ fehlte und damit entsprechende Anwendungsfälle. In meinem Arbeitsalltag habe ich nämlich mit Datenimport-Anfragen nicht wirklich zu tun (worüber ich aber ehrlicherweise gar nicht traurig bin). Und wenn doch, dann habe ich ja dieses Tool zum Extreme Customizing: ABAP. Daher ging ich bis vor kurzem davon aus, dass SimDia² vor allem ein Tool für Fachabteilungen und Endanwender zur Lösung kleinerer und einfacher Datenimport-Aufgaben ist.

Das Problem eines Entwicklers in meiner Xing-Gruppe Tricktresor  zum Thema Aufzeichnung in LSMW (Sekundärressourcen pflegen) brachte mich jedoch zu der Frage, ob und wie sich der dort geschilderte und recht komplexe Vorgang statt mit LSMW auch mit SimDia² lösen ließe. Kurz und gut: mit ein wenig Auffrischung im Umgang mit SimDia² (was mir bis dahin aus oben erwähnten Gründen etwas gefehlt hatte) ließ sich die gesamte Aufgabe schlussendlich in nur 2-3 Minuten lösen.

Aufzeichnung mit SimDia²

Im Grunde reicht es, wenn man die betreffende SAP-Transaktion gut kennt (in diesem Fall die mir bis dahin unbekannte C202) und ein wenig weiß, wie SAP tickt. Da die gesamte SimDia²-Aufzeichnung im normalen SAP GUI-Dialog stattfindet, verschwinden auch keine Registerkarten (wie teilweise beim Batchinput) und nach dem Text Planungs-Vorgang lässt sich sehr einfach in der Tabelle suchen. Der einzige Trick besteht dann noch darin, den gefundenen Vorgang zu markieren. Aber auch das verrät SAP einem nach beherztem Druck auf die rechte Maustaste:

Anschließend lassen sich die Sekundärressourcen ganz einfach ebenfalls über das Kontext-Menü  aufrufen und versorgen.

Nur für Fachabteilungen?

Ist SimDia² also „nur“ ein Tool für Fachabteilungen und Endanwender zur Lösung kleinerer Datenimport-Aufgaben? Mitnichten.

Nachdem bei mir der Knoten geplatzt war – spätestens, als ich gesehen hatte, wie einfach auch die Verarbeitung von Kopf- und Detaildaten damit ist – wurde mir klar, dass mit SimDia² eben auch komplexe Fälle abgebildet werden können. Auch solche, für die in der LSMW geballtes Entwickler-Gehirnschmalz und manchmal sogar ABAP nötig sind.

Denn auf diese Weise können – und da müssen wir Entwickler jetzt ganz stark sein😉 – auch ganz „normale“ SAP-Anwender komplexe Datenimporte durchführen. Wenn man mal kurz darüber nachdenkt, ist das doch aber gar nicht so verkehrt. Warum? Weil dadurch die Aufgaben von denjenigen erledigt werden können, die sich mit den Daten ohnehin am besten auskennen. Und wir Entwickler können uns auf das konzentrieren, wofür wir eigentlich ausgebildet wurden und bezahlt werden: komplexe Software-Lösungen entwickeln und unsere Unternehmen fit zu machen für die Zukunft. Außerdem sagt ja keiner, dass wir SimDia² nicht auch für unsere Zwecke einsetzen können, falls z. B. die Datenimporte weiterhin von der IT durchgeführt werden sollen. Wenn wir Aufgaben in ein paar Minuten erledigen können, für die vorher einige Stunden nötig waren, dann beschwert sich darüber sicher auch niemand.

SimDia²

Mehr Informationen zu SimDia² findest du auf der Homepage: http://www.ersasoft.de/

Erfahrungsberichte

Da ich selbst SimDia² in der Praxis noch nicht eingesetzt habe (ich darf zum Glück tun, wofür ich ausgebildet wurde und bezahlt werde😉), interessieren mich natürlich einschlägige Erfahrungen. Falls ihr also weitere Beispiele für mich habt, in denen ihr komplexe Datentransfers mit SimDia² erledigt habt, für die vorher eine aufwendige LSMW-Programmierung notwendig war, dann gerne immer her damit!

Tricktresor- Bonus

Sichere dir einen 5%-Rabatt auf SimDia²!

Schreibe uns eine Mail und berufe dich auf diesen Artikel im Tricktresor.

Beim Kauf von SimDia² erhältst du dann einen Nachlass von fünf Prozent!!

* indicates required field

Der Beitrag SimDia² als Alternative zur Programmierung? erschien zuerst auf Tricktresor.

Buchungsbelege erstellen

$
0
0

Folgend ein Report, der exemplarisch zeigt, wie FI-Belege gebucht werden können. Es werden Die Bausteine BAPI_ACC_DOCUMENT_CHECK und BAPI_ACC_DOCUMENT_POST verwendet.

Aktuell macht der Report gar nichts!

Die Kopf- und Positionsdaten müssen in LT_BKPF und LT_MSEG entsprechend eingefügt werden.

Vorgaben

Ich gehe davon aus, das die zu buchenden Daten in der Form Kopf/Position vorliegen. Sollte dies nicht der Fall sein, so sollten diese vorher so aufbereitet werden, da dies den Umgang beim Programmieren wesentlich vereinfacht.

Das folgende Beispiel behandelt exemplarisch eine kreditorische Buchung,
läßt sich jedoch prinzipiell ebenso auf debitorische oder Sachkonten-
buchungen übertragen.
Als Schmankerl wird ein zusätzliches Feld, welches nicht in der Sachkontenzeile
enthalten ist (LZBKZ – Landeszentralbankkennzeichen) mitgegeben und die Steuer
mit einem Steuerschema gebucht, welches zwei Steuerzeilen enthält.

Prinzipiell muss man folgendes Wissen zur Buchung von FI-Belegen wissen:

  1. Die erste Zeile des zu buchenden Beleges enthält den Betrag IMMER als Brutto-Wert! Unabhängig davon ob diese kreditorisch, debitorisch oder eine Sachkontenbuchung ist.
  2. Bei kreditorischen oder debitorischen Buchungen tauchen diese als Zeile nur ein mal als erste Zeile auf!
  3. Steuerkennzeichen MÜSSEN mitgeliefert werden sonst kann keine Steuer gebucht werden.

Kopfdaten

Wenn die Daten aus einem R3-System kommen, liegen die Daten normalerweise in der Form BUKRS/BELNR/GJAHR + Datenteil (für BKPF/BSEG) vor.
Sollte dies nicht der Fall, so erhält man normalerweise, wie in diesem Beispiel, eine laufende, eindeutige Nummer als Identifikator.
Für den Kopf auf jeden Fall müssen mitgegeben werden:

  • BUDAT – Buchungsdatum
  • BLDAT – Belegdatum
  • BUKRS – Buchungskreis
  • BLART – Belegart
  • WAERS – Währung in der gebucht werden soll (Belegwährung)

Bei Fremdwährungsbuchungen müssen zusätzlich das Feld

  • KURSF – Umrechnungskurs zur Buchungskreiswährung (Zeilentyp BAPIACCR09)
    ODER!!!!
  • WWERT – Umrechnungsdatum (Zeilentyp BAPIACHE09)

mitgegeben werden – keinesfalls beide!

Bei kreditorischen Buchungen ist z.B. auch die Referenz zu füllen

  • XBLNR – Referenznummer (Belegnummer des Lieferanten)

All diese Werte müssen bekannt sein und mitgegeben werden.

Das Buchungsdatum kann auch leer gelassen werden, dann wird aus dem Systemdatum die entsprechenden Werte für GJAHR und POPER errechnet (siehe Routine ADD_DATA_BKPF).
Ansonsten wird das mitgegebene Buchungsdatum verwendet und zur Berechnung verwendet

  • BKTXT – Kopftext (braucht man manchmal)

Positionsdaten

  • Als Mussdaten sind notwendig:
  • BUZEI fortlaufende Buchungszeilennummer.
    Kann man auch „on the fly“ erzeugen einfacher ist es, wenn sie bereits gefüllt ist. Die Buchungszeile stellt über den in jedem Segment vorhandenen Parameter ITEMNO_ACC die Verbindung bzw. die Sortierung der einzelnen Zeilen des Beleges untereinander sicher
  • KOART Kontoart
    K – Kreditorische Buchungszeile, D – Debitorische Buchungszeile,
    S – Sachkontenzeile
  • SHKZG Soll-/Haben Kennzeichen S/H
    Auch aus Fremdsystemen erhält man normalerweise dieses Kennzeichen. Es dient dazu, das Vorzeichen für die Beträge, welche dem BAPI übergeben werden, richtig zu ermitteln. Dies setzt voraus, das die Beträge (!!) immer als positive Werte übergeben werden – was im R/3 immer der Fall ist und bei Fremdsystembelegen zu 99% (SAP hat schließlich die Buchhaltung nicht erfunden 😉 )
    Habenwerte sind hierbei immmer mit -1 zu multiplizieren, Sollwerte behalten Ihr positives Vorzeichen
  • GKONT Gegenkonto
    Im Fall einer kreditorischen bzw. debitorischen Zeile die Lieferanten- bzw. Kundennummer. Im Fall einer Sachkontenzeile die Kontonummer, auf welche gebucht werden soll
  • MWSKZ Mehrwertsteuerkennzeichen
    MUSS, im Falle einer ggf. zu buchenden Steuer, mitgegeben werden. Hierüber werden die zu buchenden Steuerzeilen ermittelt
  • BRUTTO Bruttowert der Buchungszeile. Wird immer benutzt bei „Kopfzeilen“ d.h. bei kreditorische, debitorischen oder der 1. Zeile eines Sachkontenbeleges
  • NETTO Nettowert der Buchungszeile d.h. ohne Steuer
    Wird bei allen „Positionszeilen“, d.h. ab Zeile 2 des Beleges benutzt

Kontierungen

Im Beispiel habe ich Kontierungen auf Kostenstellen, Innenaufträge, SD-Belege und Anlagen vorgesehen.

  • SGTXT Positionstext (braucht man manchmal)
  • LANDL Lieferland
    Wird benötigt, wenn der Lieferant im Ausland ansässig ist – kann man aber auch durch nachlesen des Landes aus der Adresse des Lieferanten holen. Hier der Einfachheit halber in der Struktur

Schmankerl 1

  • LZBKZ Landeszentralbankkennzeichen
    Die betrifft Rechnungen von ausländischen Lieferanten die eine Sonstige Leistung i.S. des Umsatzsteuergesetzes erbracht haben. Der §13b UStG regelt unter einzelnen Punkten in welchen Fällen der Leistungsempfänger für die Leistungen die Umsatzsteuer schuldet.
    Gleichzeitig darf der Leistungsempfänger sich diesen Betrag als Vorsteuer in Abzug bringen.
    Steht in der BSEG als Feld zur Verfügung, ist aber nicht in der kreditorischen Struktur BAPIACAP09 vorhanden!!! Muß über die Tabelle extension2 des BAPI’s übergeben werden
    Ausführungen dazu in der Unterroutine für die Kreditorenzeile

Schmankerl 2

  • CO-PA Kontierung
    Bei Kontierung auf CO-PA Objekte (Ergebnisobjekte) kommt es oft genug vor, das vom Kunden nur der Vertriebsbeleg vorgegeben wird und alles andere soll ermittelt werden. Wir befinden uns nicht in der FB01 oder FB60 und können auf den Knopf „Ableitung“ drücken.
    Was also tun? Siehe hierzu die Unterroutine „ADD_COPA_LINE‘.

Coding

REPORT z_post_acc_document.

* Vorgaben
* Ich gehe davon aus, das die zu buchenden Daten in der Form
* Kopf/Position vorliegen. Sollte dies nicht der Fall sein, so sollten
* diese vorher so aufbereitet werden, da dies den Umgang beim Programmieren
* wesentlich vereinfacht.

* Das folgende Beispiel behandelt exemplarisch eine kreditorische Buchung,
* läßt sich jedoch prinzipiell ebenso auf debitorische oder Sachkonten-
* buchungen übertragen.
* Als Schmankerl wird ein zusätzliches Feld, welches nicht in der Sachkontenzeile
* enthalten ist (LZBKZ - Landeszentralbankkennzeichen) mitgegeben und die Steuer
* mit einem Steuerschema gebucht, welches zwei Steuerzeilen enthält.

* Prinzipiell múß man folgendes Wissen zur Buchung von FI-Belegen wissen:
* 1. Die erste Zeile des zu buchenden Beleges enthält den Betrag IMMER als Brutto-Wert!
*    Unabhängig davon ob diese kreditorisch, debitorisch oder eine Sachkontenbuchung ist.
* 2. Bei kreditorischen oder debitorischen Buchungen tauchen diese als Zeile nur 1mal
*    als erste Zeile auf!
* 3. Steuerkennzeichen MÜSSEN mitgeliefert werden sonst kann keine Steuer gebucht werden.

****** KOPFDATEN ********
* Wenn die Daten aus einem R3-System kommen, liegen die Daten normalerweise
* in der Form BUKRS/BELNR/GJAHR + Datenteil (für BKPF/BSEG) vor.
* Sollte dies nicht der Fall, so erhält man normalerweise, wie in diesem Beispiel,
* eine laufende, eindeutige Nummer als Identifikator.
* Für den Kopf auf jeden Fall müssen mitgegeben werden:
* - BUDAT - Buchungsdatum
* - BLDAT - Belegdatum
* - BUKRS - Buchungskreis
* - BLART - Belegart
* - WAERS - Währung in der gebucht werden soll (Belegwährung)
* Bei Fremdwährungsbuchungen müssen zusätzlich das Feld
* - KURSF - Umrechnungskurs zur Buchungskreiswährung (Zeilentyp BAPIACCR09) ODER !!!!
* - WWERT - Umrechnungsdatum (Zeilentyp BAPIACHE09)
* mitgegeben werden - keinesfalls beide !!!!!
* Bei kreditorischen Buchungen ist z.B. auch die Referenz zu füllen
* XBLNR - Referenznummer (Belegnummer des Lieferanten)
* All diese Werte müssen bekannt sein und mitgegeben werden.
* Das Buchungsdatum kann auch leer gelassen werden, dann wird aus dem Systemdatum
* die entsprechenden Werte für GJAHR und POPER errechnet (siehe Routine ADD_DATA_BKPF).
* Ansonsten wird das mitgegebene Buchungsdatum verwendet und zur Berechnung verwendet
* BKTXT - Kopftext (braucht man manchmal)
TYPES: BEGIN OF gtys_bkpf,
         id    TYPE numc10,
         bukrs TYPE bkpf-bukrs,
         gjahr TYPE bkpf-gjahr,
         poper TYPE poper,
         blart TYPE bkpf-blart,
         bldat TYPE bkpf-bldat,
         budat TYPE bkpf-budat,
         xblnr TYPE bkpf-xblnr,
         bktxt TYPE bkpf-bktxt,
         waers TYPE bkpf-waers,
         kursf TYPE bkpf-kursf,
         wwert TYPE bkpf-wwert,
       END OF gtys_bkpf,
       gtyt_bkpf TYPE STANDARD TABLE OF gtys_bkpf.

******** POSITIONSDATEN ***********
* Als Mußdaten sind notwendig:
* BUZEI  fortlaufende Buchungszeilennummer. Kann man auch "on the fly" erzeugen
*        einfacher ist es, wenn sie bereits gefüllt ist. Die Buchungszeile stellt
*        über den in jedem Segment vorhandenen Parameter ITEMNO_ACC die Verbindung
*        bzw. die Sortierung der einzelnen Zeilen des Beleges untereinander sicher
* KOART  Kontoart
*        K - Kreditorische Buchungszeile, D - Debitorische Buchungszeile,
*        S - Sachkontenzeile
* SHKZG  Soll-/Haben Kennzeichen S/H
*        Auch aus Fremdsystemen erhält man normalerweise dieses Kennzeichen
*        Es dient dazu, das Vorzeichen für die Beträge, welche dem BAPI
*        übergeben werden, richtig zu ermitteln. Dies setzt voraus, das die Beträge!!
*        immer als positive Werte übergeben werden - was im R/3 immer der Fall
*        ist und bei Fremdsystembelegen zu 99% (SAP hat schließlich die
*        Buchhaltung nicht erfunden ;-) )
*        Habenwerte sind hierbei immmer mit -1 zu multiplizieren, Sollwerte behalten
*        Ihr positives Vorzeichen
* GKONT  Gegenkonto
*        Im Fall einer kreditorischen bzw. debitorischen Zeile die
*        Lieferanten- bzw. Kundennummer. Im Fall einer Sachkontenzeile die
*        Kontonummer, auf welche gebucht werden soll
* MWSKZ  Mehrwertsteuerkennzeichen
*        MUSS, im Falle einer ggf. zu buchenden Steuer, mitgegeben werden.
*        Hierüber werden die zu buchenden Steuerzeilen ermittelt
* BRUTTO Bruttowert der Buchungszeile. Wird immer benutzt bei "Kopfzeilen" d.h.
*        bei kreditorische, debitorischen oder der 1. Zeile eines Sachkontenbeleges
* NETTO  Nettowert der Buchungszeile d.h. ohne Steuer
*        Wird bei allen "Positionszeilen", d.h. ab Zeile 2 des Beleges benutzt
* Kontierungen
*        Im Beispiel habe ich Kontierungen auf Kostenstellen, Innenaufträge, SD-Belege
*        und Anlagen vorgesehen.
* SGTXT  Positionstext (braucht man manchmal)
* LANDL  Lieferland
*        Wird benötigt, wenn der Lieferant im Ausland ansässig ist - kann man aber auch
*        durch nachlesen des Landes aus der Adresse des Lieferanten holen. Hier der
*        Einfachheit halber in der Struktur
* Schmankerl 1
* LZBKZ  Landeszentralbankkennzeichen
*        Die betrifft Rechnungen von ausländischen Lieferanten die eine Sonstige Leistung
*        i.S. des Umsatzsteuergesetzes erbracht haben. Der §13b UStG regelt unter einzelnen
*        Punkten in welchen Fällen der Leistungsempfänger für die Leistungen die Umsatzsteuer schuldet.
*        Gleichzeitig darf der Leistungsempfänger sich diesen Betrag als Vorsteuer in Abzug bringen.
*        Steht in der BSEG als Feld zur Verfügung, ist aber nicht in der kreditorischen
*        Struktur BAPIACAP09 vorhanden!!! Muß über die Tabelle extension2 des BAPI's übergeben werden
*        Ausführungen dazu in der Unterroutine für die Kreditorenzeile
* Schmankerl 2
*        CO-PA Kontierung
*        Bei Kontierung auf CO-PA Objekte (Ergebnisobjekte) kommt es oft genug vor,
*        das vom Kunden nur der Vertriebsbeleg vorgegeben wird und alles andere soll
*        ermittelt werden. Wir befinden uns nicht in der FB01 oder FB60 und können auf
*        den Knopf "Ableitung" drücken.
*        Was also tun?
*        Siehe hierzu die Unterroutine "ADD_COPA_LINE'.

TYPES: BEGIN OF gtys_bseg,
         id     TYPE numc10,
         buzei  TYPE bseg-buzei,
         koart  TYPE bseg-koart,
         shkzg  TYPE bseg-shkzg,
         gkont  TYPE gkont,
         brutto TYPE bseg-wrbtr,
         netto  TYPE bseg-wrbtr,
         mwskz  TYPE zsc_soawf_bseg-mwskz,
         sgtxt  TYPE zsc_soawf_bseg-sgtxt,
         kostl  TYPE zsc_soawf_bseg-kostl,
         aufnr  TYPE zsc_soawf_bseg-aufnr,
         vbeln  TYPE zsc_soawf_bseg-vbeln,
         posnr  TYPE zsc_soawf_bseg-posnr,
         anln1  TYPE zsc_soawf_bseg-anln1,
         anln2  TYPE zsc_soawf_bseg-anln2,
         lzbkz  TYPE zsc_soawf_bseg-lzbkz,
         landl  TYPE zsc_soawf_bseg-landl,
       END OF gtys_bseg,
       gtyt_bseg TYPE STANDARD TABLE OF gtys_bseg.

* Struktur für den Aufbau der Steuerzeilen
TYPES: BEGIN OF gtys_tax,
         mwskz TYPE mwskz,
         wmwst TYPE wmwst,
         msatz TYPE msatz_f05l,
         ktosl TYPE ktosl,
         kawrt TYPE kawrt,
         hkont TYPE hkont,
         kschl TYPE kschl,
       END OF gtys_tax,
       gtyt_tax TYPE STANDARD TABLE OF gtys_tax.

* Org-Daten für CO-PA Ermittlung
TYPES: BEGIN OF gtys_org_copa,
         bukrs TYPE bukrs,
         kokrs TYPE kokrs,
         erkrs TYPE erkrs,
       END OF gtys_org_copa,
       gtyt_org_copa_hash TYPE HASHED TABLE OF gtys_org_copa
                       WITH UNIQUE KEY bukrs.
* Neue CO-PA Ableitung
TYPES: gtyt_copadata TYPE copadata_tab.

* Testparameter
PARAMETERS: p_xtest TYPE xfeld DEFAULT 'X'.

START-OF-SELECTION.
  PERFORM processing.
*&---------------------------------------------------------------------*
*&      Form  PROCESSING
*&---------------------------------------------------------------------*
FORM processing .

  DATA: lt_bkpf  TYPE gtyt_bkpf.
  DATA: ls_bkpf  TYPE gtys_bkpf.

  LOOP AT lt_bkpf INTO ls_bkpf.
    PERFORM post_acc_doc USING ls_bkpf.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_DATA_TO_BKPF
*&---------------------------------------------------------------------*
FORM add_data_to_bkpf CHANGING pcs_bkpf TYPE gtys_bkpf.

  TYPES: BEGIN OF ltys_t001,
           bukrs TYPE t001-bukrs,
           periv TYPE t001-periv,
         END OF ltys_t001,
         ltyt_t001 TYPE HASHED TABLE OF ltys_t001 WITH UNIQUE KEY bukrs.

  STATICS: lv_first_call TYPE xfeld.
  STATICS: lt_t001       TYPE ltyt_t001.
  DATA: ls_t001 TYPE ltys_t001.
  DATA: lv_buper TYPE poper.
  DATA: lv_gjahr TYPE gjahr.
  DATA: lv_budat TYPE bkpf-budat.

* Ermittlung der Geschäftsjahresvariante für alle im System vorhandenen
* Buchungskreise
  IF lv_first_call IS INITIAL.
    SELECT bukrs periv
           FROM t001
           INTO TABLE lt_t001.
    MOVE abap_true TO lv_first_call.
  ENDIF.

  READ TABLE lt_t001 INTO ls_t001
    WITH TABLE KEY bukrs = pcs_bkpf-bukrs.
  IF sy-subrc EQ 0.
    IF pcs_bkpf-budat IS INITIAL.
      MOVE sy-datum       TO lv_budat.
    ELSE.
      MOVE pcs_bkpf-budat TO lv_budat.
    ENDIF.

*   Ermittlung der Periode und des Geschäftsjahres
*   anhand des Buchungsdatum und der Geschäftsjahresvariante
*   (Stichwort: Verschobenes Geschäftsjahr)
    CALL FUNCTION 'DATE_TO_PERIOD_CONVERT'
      EXPORTING
        i_date         = lv_budat
        i_periv        = ls_t001-periv
      IMPORTING
        e_buper        = lv_buper
        e_gjahr        = lv_gjahr
      EXCEPTIONS
        input_false    = 1
        t009_notfound  = 2
        t009b_notfound = 3
        OTHERS         = 4.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
    MOVE: lv_buper TO pcs_bkpf-poper,
          lv_gjahr TO pcs_bkpf-gjahr.
  ELSE.
*   Fehlermeldung - darf nicht vorkommen !!!!
*   Buchungskreis &1 ist nicht vorhanden
    MESSAGE a215(fagl_emu) WITH pcs_bkpf-bukrs.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_CRED_LINE
*&---------------------------------------------------------------------*
FORM add_cred_line  USING    pis_bkpf TYPE gtys_bkpf
                             pis_bseg TYPE gtys_bseg
                    CHANGING pct_cred TYPE bapiacap09_tab
                             pct_ext2 TYPE tt_bapiparex.

  DATA: ls_struc_ext2 TYPE zsc_s_soawf_badi_acc_doc.
  DATA: ls_cred  LIKE LINE OF pct_cred.
  DATA: ls_ext2  LIKE LINE OF pct_ext2.

* Kreditorenzeile
  ls_cred-itemno_acc        = pis_bseg-buzei.       "Positionsnummer des Rechnungswesenbeleges
  ls_cred-vendor_no         = pis_bseg-gkont.       "Lieferantennummer
* Das Sachkonto auf welches gebucht wird, ist immer das im Lieferantenstamm
* eingetragene Abstimmkonto
* Gilt übrigens auch für Debitoren. Dort ist es AKONT in der KNB1
  SELECT SINGLE akont
                FROM lfb1
                INTO ls_cred-gl_account
                WHERE lifnr EQ pis_bseg-gkont
                AND   bukrs EQ pis_bkpf-bukrs.
  ls_cred-item_text         = pis_bseg-sgtxt.       "Positionstext
  ls_cred-supcountry        = pis_bseg-landl.       "Lieferland wenn nicht DE

* Schmankerl
* Übergabe eines nicht in der Kreditorenstruktur vorhandenen Feldes - in diesem
* Falle das Landeszentralbankkennzeichen
  IF NOT pis_bseg-lzbkz IS INITIAL.
*   Hierzu MUSS!! man sich im DDIC eine Struktur definieren, welche
*   all die Felder enthält, welche man zusätzlich übergeben will.
*   Diese wird im Feld STRUCTURE der Struktur BAPIPAREX übergeben.
*
*   Als Maximalmenge können die Felder der Struktur ACCIT übergeben werden.
*   Die Struktur MUSS!!! immer ein Feld vom Typen
*   POSNR TYPE POSNR_ACC
*   enthalten. Dieser stellt die Verbindung von der Übergabezeile (in diesem Falle
*   der Kreditorenzeile) zur Extension2-Zeile her.
*
*   Als weitere Felder werden dann die zu zusätzlich benötigten Felder übergeben.
*
*   Um nun die Felder auch ins BAPI zu bringen, muß man zum BADI ACC_DOCUMENT
*   mit der SE19 eine eigene Implementierung anlegen (oder, wenn Glück hat, ist
*   bereits eine vorhanden).
*   Hierzu MUSS!!! man den Filterwert auf BKPFF (nicht BKPF) stellen, da dieser
*   vom BAPI gefordert bzw. geschrieben wird.
*   Als Coding kann man das Coding der Beispielimplementierung der SAP nutzen, welche man
*   aus der Beispielimplementierung in die eigene Implementierung kopiert.
*   ACHTUNG!!!!!!
*   Nicht den Fehler machen und die ACCIT als Strukturnamen und Übergabestruktur
*   benutzen. Die Felder VALUEPART1 bis VALUEPART4 werden concateniert und sind
*   insgesamt nur 960 Zeichen lang !!! Da kann man mit der ACCIT und Ihren 496 Feldern!
*   auch schon mal ganz schnell ins Klo greifen, wenn die Felder erst hinter
*   den 960 Zeichen aufgerufen werden.
*   Wenn man mehr als 240 Zeichen Übergabe benötigt, ein Charakterfeld mit 960 Zeichen
*   definieren, die Struktur darauf moven, dann zerhaken und als VALUEPART1 bis 4 übergeben.
*   ACHTUNG !!!!
*   Bei Übergabe von Zahlfeldern diese vorher in Charakterwerte umwandeln und dann übergeben,
*   sonst geht es schief. Ggf. die Implentierung entsprechend anpassen.
*   ACHTUNG !!!
*   Da die Übergabefelder CHAR-Werte sind, kann Kleinschreibung nicht übergeben werden.
*   Danke SAP!!!
    MOVE 'Z_BADI_ACC_DOC' TO ls_ext2-structure.
    ls_struc_ext2-posnr = pis_bseg-buzei.
    ls_struc_ext2-lzbkz = pis_bseg-lzbkz.
    MOVE ls_struc_ext2 TO ls_ext2-valuepart1.
    APPEND ls_ext2 TO pct_ext2.
  ENDIF.

  APPEND ls_cred TO pct_cred.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_CURR_LINE
*&---------------------------------------------------------------------*
FORM add_curr_line  USING    pis_bkpf   TYPE gtys_bkpf
                             pis_bseg   TYPE gtys_bseg
                             piv_tabix  TYPE sy-tabix
                    CHANGING pet_curr   TYPE bapiaccr09_tab.

  DATA: ls_curr   LIKE LINE OF pet_curr.
  DATA: lv_amount TYPE bseg-wrbtr.

  CASE pis_bseg-koart.
*   Kreditorische/Debitorische Zeilen nur einmal im Beleg
*   als Kopfzeile - daher immer Brutto!!
    WHEN 'K' OR 'D'.
      MOVE pis_bseg-brutto TO lv_amount.
    WHEN 'S'.
*     Bei Sachkontenbuchungen Unterscheidung
*     nach Kopf- und Positionszeilen
      IF piv_tabix EQ 1.
        MOVE pis_bseg-brutto TO lv_amount.
      ELSE.
        MOVE pis_bseg-netto  TO lv_amount.
      ENDIF.
  ENDCASE.

* Habenwerte immer mit -1 multiplizieren (braucht das BAPI
* um zu erkennen, was es buchen soll)
  CASE pis_bseg-shkzg.
    WHEN 'H'.
      lv_amount = lv_amount * -1.
  ENDCASE.

  ls_curr-itemno_acc        = pis_bseg-buzei.
  ls_curr-currency          = pis_bkpf-waers.
* Wenn die Währung nicht stimmen sollte, hier umwandeln
  ls_curr-currency_iso      = pis_bkpf-waers.
  ls_curr-amt_doccur        = lv_amount.
* Währungstyp
* Hier steht die Belegwährung, was der Standardfall ist.
* Sollen zusätzlich andere Typen verwendet werden, müßen die Werte angepaßt
* werden. Aber das ist ein ganz eigenes Kapitel. Werde ich ggf. bei
* Zeiten ergänzen.
  ls_curr-curr_type         = '00'.
* Umrechnungskurs für Fremdwährung
* ACHTUNG!!!
* Entweder hier KURSF ODER!!!! im Kopf WWERT mitgeben
  ls_curr-exch_rate         = pis_bkpf-kursf.

  APPEND ls_curr TO pet_curr.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_SACH_LINE
*&---------------------------------------------------------------------*
FORM add_sach_line  USING    pis_bkpf  TYPE gtys_bkpf
                             pis_bseg  TYPE gtys_bseg
                    CHANGING pct_sach  TYPE bapiacgl09_tab
                             pct_crit  TYPE bapiackec9_tab
                             pct_value TYPE bapiackev9_tab
                             pev_subrc TYPE sy-subrc.

  DATA: ls_acc_gl LIKE LINE OF pct_sach.
  DATA: lv_subrc  TYPE sy-subrc.

  CLEAR pev_subrc.

  ls_acc_gl-itemno_acc        = pis_bseg-buzei.       "Positionsnummer des Rechnungswesenbeleges
  ls_acc_gl-gl_account        = pis_bseg-gkont.       "Sachkonto der Hauptbuchhaltung
  ls_acc_gl-item_text         = pis_bseg-sgtxt.       "Positionstext
  ls_acc_gl-acct_key          = space.                "Vorgangsschlüssel
  ls_acc_gl-acct_type         = pis_bseg-koart.       "Kontoart
  ls_acc_gl-tax_code          = pis_bseg-mwskz.       "Mehrwertsteuerkennzeichen
* Standardkontierungen, ggf. ergänzen.
  ls_acc_gl-costcenter        = pis_bseg-kostl.       "Kostenstelle
  ls_acc_gl-orderid           = pis_bseg-aufnr.       "Innenauftrag
  ls_acc_gl-asset_no          = pis_bseg-anln1.       "Anlagenhauptnummer
  ls_acc_gl-sub_number        = pis_bseg-anln2.       "Anlagenunternummer

  IF NOT pis_bseg-vbeln IS INITIAL.
    PERFORM add_copa_line USING    pis_bkpf
                                   pis_bseg
                          CHANGING pct_crit
                                   pct_value
                                   lv_subrc.
    IF sy-subrc NE 0.
      pev_subrc = 4.
      RETURN.
    ENDIF.
  ENDIF.

  APPEND ls_acc_gl TO pct_sach.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_HEAD_LINE
*&---------------------------------------------------------------------*
FORM add_head_line  CHANGING pcs_bkpf   TYPE gtys_bkpf
                             pes_header TYPE bapiache09.

  CLEAR pes_header.

  DATA: ls_header TYPE bapiache09.

  ls_header-bus_act           = 'RFBU'.               "Betriebswirtschaftlicher Vorgang
  ls_header-username          = sy-uname.             "Name des Benutzers
  ls_header-header_txt        = pcs_bkpf-bktxt.       "Belegkopftext
  ls_header-comp_code         = pcs_bkpf-bukrs.       "Buchungskreis
  ls_header-doc_date          = pcs_bkpf-bldat.       "Belegdatum

* Ermitteln von Geschäftsjahr und Periode aus dem Buchungsdatum
* In unserem Fall ist das Buchungsdatum leer, also nehmen wir das
* Tagesdatum. Es kann aber auch ein bestimmtes Datum übergeben werden
* Dann aber darauf achten, das die entsprechenden Perioden zum
* Buchen offen sind
  PERFORM add_data_to_bkpf CHANGING pcs_bkpf.
  IF pcs_bkpf-budat IS INITIAL.
    ls_header-pstng_date      = sy-datum.             "Buchungsdatum
  ELSE.
    ls_header-pstng_date      = pcs_bkpf-budat.     "Buchungsdatum
  ENDIF.

  ls_header-trans_date        = sy-datum.             "Umrechnungsdatum
  ls_header-fisc_year         = pcs_bkpf-gjahr.       "Geschäftsjahr
  ls_header-fis_period        = pcs_bkpf-poper.       "Geschäftsmonat
  ls_header-doc_type          = pcs_bkpf-blart.       "Belegart
  ls_header-ref_doc_no        = pcs_bkpf-xblnr.       "Referenznummer

* Achtung !!!!
* Entweder Umrechnungsdatum oder Kurs - nicht beides mitgeben !!!!!
  IF NOT pcs_bkpf-wwert IS INITIAL.
    ls_header-trans_date    = pcs_bkpf-wwert.
  ENDIF.

* Sollten zusätzliche Werte benötigt werden, hier übergeben
* oder die Kopftabelle entsprechend "aufbohren".

  pes_header = ls_header.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  POST_ACC_DOC
*&---------------------------------------------------------------------*
FORM post_acc_doc USING pis_bkpf  TYPE gtys_bkpf.

  DATA: ls_bkpf   TYPE gtys_bkpf.
  DATA: lt_bseg   TYPE gtyt_bseg.
  DATA: ls_bseg   TYPE gtys_bseg.
  DATA: lt_tax    TYPE gtyt_tax.

  DATA: BEGIN OF ls_awkey,
          belnr TYPE bkpf-belnr,
          bukrs TYPE bkpf-bukrs,
          gjahr TYPE bkpf-gjahr,
        END OF ls_awkey.

  DATA: lv_buzei TYPE bseg-buzei.
  DATA: lv_tabix TYPE sy-tabix.
  DATA: lv_subrc TYPE sy-subrc.
  DATA: lv_exit  TYPE xfeld.

* BAPI-Definitionen
* BKPF
  DATA ls_header TYPE bapiache09.
* BAPI-Protokoll
  DATA lt_return TYPE bapiret2_tab.
  DATA ls_return TYPE bapiret2.
* Sachkontenzeile
  DATA lt_acc_gl TYPE bapiacgl09_tab.
* Kreditorenzeile
  DATA lt_acc_py TYPE bapiacap09_tab.
* Debitorenzeile - Im Beispiel nicht ausgeführt
  DATA lt_acc_rv TYPE bapiacar09_tab               ##NEEDED.
* Wertzeile
  DATA lt_cur_am TYPE bapiaccr09_tab.
* Steuerzeile
  DATA lt_acc_tx TYPE bapiactx09_tab.
* Zusätzliche Parameter (siehe Routine add_cred_line)
  DATA lt_ext2   TYPE tt_bapiparex.
* CO-PA Merkmalstabelle
  DATA lt_acc_crit  TYPE bapiackec9_tab.
* CO-PA Wertetabelle
  DATA lt_acc_value TYPE bapiackev9_tab.

  ls_bkpf = pis_bkpf.

* Kopfdaten aufbereiten
  PERFORM add_head_line CHANGING ls_bkpf
                                 ls_header.

* Loop über alle Buchungszeilen des Beleges
* Hier kann auch ein Select stehen, wenn man sich aus einer
* DB-Tabelle bedient.
  LOOP AT lt_bseg INTO ls_bseg
    WHERE id EQ ls_bkpf-id.
    lv_tabix = sy-tabix.
*   Kopieren der aktuellen Buchungszeile
*   Brauchen wir später, wenn wir die Steuerzeilen erzeugen wollen
    lv_buzei = ls_bseg-buzei.

*   Unterscheidung nach Kontoart
    CASE ls_bseg-koart.
*     Debitorenzeile
      WHEN 'D'.
*       Behandeln wir hier nicht - ist aber analog zum Kreditoren

*     Kreditorenzeile
      WHEN 'K'.
*       Kreditorenzeile aufbauen
        PERFORM add_cred_line USING    pis_bkpf
                                       ls_bseg
                              CHANGING lt_acc_py
                                       lt_ext2.

*       Betragszeile
        PERFORM add_curr_line USING    pis_bkpf
                                       ls_bseg
                                       lv_tabix
                              CHANGING lt_cur_am.
      WHEN 'S'.
*       Sachkontenzeile
        PERFORM add_sach_line USING    ls_bkpf
                                       ls_bseg
                              CHANGING lt_acc_gl
                                       lt_acc_crit
                                       lt_acc_value
                                       lv_subrc.
        IF lv_subrc NE 0.
          lv_exit = abap_true.
          EXIT.
        ENDIF.

*       Betragszeile
        PERFORM add_curr_line USING    pis_bkpf
                                       ls_bseg
                                       lv_tabix
                              CHANGING lt_cur_am.

*       Steuer für Sachkontenpositionszeilen ermitteln
        PERFORM get_tax USING    pis_bkpf
                                 ls_bseg
                                 lv_tabix
                        CHANGING lt_tax.

    ENDCASE.
  ENDLOOP.

* Fehler bei der CO-PA Ermittlung - und raus
  IF lv_exit EQ abap_true.
    RETURN.
  ENDIF.

* Nachdem wir auf den Sachkontenzeilen alle Steuern
* gesammelt haben, bauen wir daraus jetzt die Steuerzeilen auf
  PERFORM add_tax_lines USING    lt_tax
                                 pis_bkpf
                                 lv_buzei
                        CHANGING lt_acc_tx
                                 lt_cur_am.

* Beleg prüfen
  CALL FUNCTION 'BAPI_ACC_DOCUMENT_CHECK'
    EXPORTING
      documentheader = ls_header
    TABLES
      accountgl      = lt_acc_gl
      accountpayable = lt_acc_py
      accounttax     = lt_acc_tx
      currencyamount = lt_cur_am
      extension2     = lt_ext2
      return         = lt_return.
* Protokoll auswerten
  READ TABLE lt_return INTO ls_return
    WITH KEY type   = 'S'
             id     = 'RW'
             number = '614'.
  IF sy-subrc EQ 0.
*   Testflag abfragen
*   Wenn gesetzt, raus
    IF NOT p_xtest IS INITIAL.
      FORMAT COLOR COL_POSITIVE.
      WRITE:/ 'ID', pis_bkpf-id,
            'erfolgreich gebucht'                       ##NO_TEXT.
      FORMAT COLOR OFF.
      RETURN.
    ENDIF.
*   Kein Testflag. Buchen
    FREE lt_return.
    CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
      EXPORTING
        documentheader = ls_header
      TABLES
        accountgl      = lt_acc_gl
        accountpayable = lt_acc_py
        accounttax     = lt_acc_tx
        currencyamount = lt_cur_am
        extension2     = lt_ext2
        return         = lt_return.
    READ TABLE lt_return INTO ls_return
      WITH KEY type   = 'S'
               id     = 'RW'
               number = '605'.
    IF sy-subrc EQ 0.
      MOVE ls_return-message_v2 TO ls_awkey.
*     Commit Work durchführen
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
        IMPORTING
          return = ls_return.
      IF NOT ls_return IS INITIAL.
      ELSE.
        FORMAT COLOR COL_POSITIVE.
        WRITE:/ 'ID', pis_bkpf-id,
                'erfolgreich gebucht'                  ##NO_TEXT.
        FORMAT COLOR OFF.
        WRITE:/ 'Beleg'                                ##NO_TEXT,
                pis_bkpf-id,
                ls_awkey-bukrs,
                ls_awkey-belnr,
                ls_awkey-gjahr,
                'erfolgreich gebucht'                  ##NO_TEXT.
      ENDIF.
    ELSE.
      FORMAT COLOR COL_NEGATIVE.
      WRITE: /'ID', pis_bkpf-id, 'fehlerhaft'          ##NO_TEXT.
      FORMAT COLOR OFF.
      LOOP AT lt_return INTO ls_return
      WHERE type NE 'S'
      AND   type NE 'I'.
        IF ls_return-id     EQ 'RW' AND
           ls_return-number EQ '609'.
          CONTINUE.
        ENDIF.
        WRITE: / pis_bkpf-id,
                 ls_return-row,
                 ls_return-type,
                 ls_return-id,
                 ls_return-number,
                 ls_return-message.
      ENDLOOP.
    ENDIF.
* Fehler bei der Belegprüfung
  ELSE.
    FORMAT COLOR COL_NEGATIVE.
    WRITE: /'ID', pis_bkpf-id, 'fehlerhaft'            ##NO_TEXT.
    FORMAT COLOR OFF.
    LOOP AT lt_return INTO ls_return
    WHERE type NE 'S'
    AND   type NE 'I'.
      IF ls_return-id EQ 'RW' AND
       ls_return-number EQ '609'.
        CONTINUE.
      ENDIF.
      WRITE:/ pis_bkpf-id,
              ls_return-row,
              ls_return-type,
              ls_return-id,
              ls_return-number,
              ls_return-message.
    ENDLOOP.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_TAX
*&---------------------------------------------------------------------*
FORM get_tax  USING    pis_bkpf  TYPE gtys_bkpf
                       pis_bseg  TYPE gtys_bseg
                       piv_tabix TYPE sy-tabix
              CHANGING pct_tax   TYPE gtyt_tax.

  DATA: lv_amount TYPE bseg-wrbtr.
  DATA: lt_mwdat  TYPE STANDARD TABLE OF rtax1u15.
  DATA: ls_mwdat  LIKE LINE OF lt_mwdat.
  DATA: ls_tax    TYPE gtys_tax.
  DATA: lt_tax    TYPE gtyt_tax.

* Nur Steuer auf Positions-, nicht auf Kopfzeilen
  IF piv_tabix EQ 1.
    RETURN.
  ENDIF.

* Steuerkennzeichen muß mitgegeben sein
  IF NOT pis_bseg-mwskz IS INITIAL.
*   ACHTUNG
*   Der Baustein ermittelt die Steuer abhängig vom
*   übergebenen Wert. Da wir mit positiven Werten arbeiten
*   müssen wir hier natürlich auch ggf. das Vorzeichen drehen
*   sonst geht es schief.
    lv_amount = pis_bseg-netto.
    IF pis_bseg-shkzg EQ 'H'.
      lv_amount = pis_bseg-netto * -1.
    ENDIF.

*   Baustein für Ermittlung der Steuer aus dem Nettowert
*   Anmerkung: Gibt es auch für Bruttowerte
*              CALCULATE_TAX_FROM_GROSSAMOUNT
    CALL FUNCTION 'CALCULATE_TAX_FROM_NET_AMOUNT'
      EXPORTING
        i_bukrs           = pis_bkpf-bukrs
        i_mwskz           = pis_bseg-mwskz
        i_waers           = pis_bkpf-waers
        i_wrbtr           = lv_amount
      TABLES
        t_mwdat           = lt_mwdat
      EXCEPTIONS
        bukrs_not_found   = 1
        country_not_found = 2
        mwskz_not_defined = 3
        mwskz_not_valid   = 4
        ktosl_not_found   = 5
        kalsm_not_found   = 6
        parameter_error   = 7
        knumh_not_found   = 8
        kschl_not_found   = 9
        unknown_error     = 10
        account_not_found = 11
        txjcd_not_valid   = 12
        OTHERS            = 13.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
    LOOP AT lt_mwdat INTO ls_mwdat.
      MOVE-CORRESPONDING ls_mwdat TO ls_tax                 ##ENH_OK.
*     Wir brauchen für die Steuerzeilen aber auch noch das Steuerkenn-
*     zeichen. Daher umkopieren auf eigene Struktur
      MOVE: pis_bseg-mwskz TO ls_tax-mwskz.
      APPEND ls_tax TO lt_tax.
    ENDLOOP.
    IF NOT lt_mwdat IS INITIAL.
      APPEND LINES OF lt_tax TO pct_tax.
    ENDIF.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_TAX_LINES
*&---------------------------------------------------------------------*
FORM add_tax_lines  USING    pit_tax    TYPE gtyt_tax
                             pis_bkpf   TYPE gtys_bkpf
                             piv_buzei  TYPE bseg-buzei
                    CHANGING pct_acc_tx TYPE bapiactx09_tab
                             pct_cur_am TYPE bapiaccr09_tab.

  DATA: ls_tax    LIKE LINE OF pit_tax.
  DATA: ls_acc_tx LIKE LINE OF pct_acc_tx.
  DATA: ls_cur_am LIKE LINE OF pct_cur_am.
  DATA: lv_buzei  TYPE bseg-buzei.

  DATA: BEGIN OF ls_collect,
          mwskz TYPE mwskz,
          kschl TYPE kschl,
          ktosl TYPE ktosl,
          hkont TYPE hkont,
          wmwst TYPE wmwst,
          kawrt TYPE kawrt,
        END OF ls_collect.
  DATA: lt_collect LIKE HASHED TABLE OF ls_collect
                   WITH UNIQUE KEY mwskz ktosl kschl hkont.

* Steuern müssen wir schon ermittelt haben
  IF NOT pit_tax IS INITIAL.

*   Über den Collect werden Steuer und Steuerbasis summiert
*   und ggf. verdichtet
    LOOP AT pit_tax INTO ls_tax.
      MOVE-CORRESPONDING ls_tax TO ls_collect.
      COLLECT ls_collect INTO lt_collect.
    ENDLOOP.

*   Wir kopieren die letzte Zeilennummer
    lv_buzei = piv_buzei.

*   Und los
    LOOP AT lt_collect INTO ls_collect.
*     Eins auf die Buchungszeile da wir eine neue
*     Zeile erzuegen
      ADD 1 TO lv_buzei.
      CLEAR ls_acc_tx.
*     Übertragung der Steuerdaten
      MOVE: lv_buzei         TO ls_acc_tx-itemno_acc,
            ls_collect-hkont TO ls_acc_tx-gl_account,
            ls_collect-kschl TO ls_acc_tx-cond_key,
            ls_collect-ktosl TO ls_acc_tx-acct_key,
            ls_collect-mwskz TO ls_acc_tx-tax_code.
*     Und anhängen
      APPEND ls_acc_tx TO pct_acc_tx.

*     Da dies nur die Parameter für die Steuerzeile sind,
*     müssen wir auch noch eine Wertezeile erzeugen
      CLEAR ls_cur_am.
*     Gleiche Zeile wie Steuerzeile (Bezug!!!)
      MOVE: lv_buzei         TO ls_cur_am-itemno_acc,
            pis_bkpf-waers   TO ls_cur_am-currency,
            pis_bkpf-waers   TO ls_cur_am-currency_iso,
*           Ermittelter, summierter Steuerwert für Steuerkennzeichen
            ls_collect-wmwst TO ls_cur_am-amt_doccur,
*           Ermittelter, summierter Basiswert für Steuerkennzeichen
            ls_collect-kawrt TO ls_cur_am-amt_base,
            '00'             TO ls_cur_am-curr_type,
*           Umrechnungskurs für Fremdwährung
*           ACHTUNG!!!
*           Entweder hier KURSF ODER!!!! im Kopf WWERT mitgeben!!!
            pis_bkpf-kursf   TO ls_cur_am-exch_rate.
      APPEND ls_cur_am TO pct_cur_am.
    ENDLOOP.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_COPA_LINE
*&---------------------------------------------------------------------*
*       Schmankerl CO-PA Kontierung
*       Dem BAPI ACC_DOCUMENT_POST müssen die Merkmals- sowie die
*       Wertedaten für die CO-PA Kontierung mitgegeben werden
*       Hierbei kommt es vor, das von Kundenseite oder der Schnittstellt
*       nur der Kundenauftrag zur Verfügung gestellt wird und die
*       CO-PA Kontierungen dem Programmierer "überlassen" werden.
*       Danke für die Info ;-)
*       Was tun?
*       Zum Glück für uns gibt es den Report RFBIBL00 bzw RFBBIBL01
*       der ebenfalls mit CO-PA Daten bestückt werden kann.
*       Hierfür gibt es den Baustein RKE_CONVERT_CRITERIA_PAOBJNR
*       der aus gegegbenen Daten eine neu CO-PA Ableitung fährt
*       aus der man dann die Merkmale nachlesen und dem BAPI unterschieben kann.
******  ACHTUNG !!!!!! ***********
*       Das neue Kontierungsobjekt wird nur dann weggeschrieben und
*       kann nachgelesen werden, wenn ein COMMIT WORK erfolgt!!!!
*       Das ist zwar unschön aber ich kenne keine andere Methode um an eine
*       komplette Ableitung zu gelangen. Wenn jemand eine kennt, wäre
*       ich dankbar, wenn diese öffentlich gemacht würde.
*       Man muß also aufpassen, das man vorher keine Daten auf der
*       Datenbank bereits geändert oder angelegt hat. Diese würde
*       hier unweigerlich commited!!!!!
*
*       Das ist aber leider nur die Hälfte der Wahrheit
*       Wir brauchen leider nicht nur die Merkmale, sondern wir müssen
*       ja auch noch die WErtfelder bestücken.
*       Hierzu siehe Routine ADD_VALUE_LINE
*
*       Und als ob das noch nicht reichen würde, müssen wir die erhaltene
*       Ableitung auch noch durch eine Routine schicken, welche die
*       alle relevanten Konvertierungsexits durchläuft, weil der
*       Ableitungsbaustein nur die externe Darstellung (RFBIBL -> BI-Programm)
*       zurückliefert aber nicht die interne, welche das BAPI fordert.
*       Hierzu siehe Routine 'CHANGE_DATA_CONV_EXIT
*       Diese Routine kann man in abgewandelter Form auch benutzen, um
*       z.B. Datenbankdaten für einen Batch-Input aufzubereiten (z.B.
*       Arbeitsplätze oder PSP-Elemente).
*----------------------------------------------------------------------*
FORM add_copa_line  USING    pis_bkpf  TYPE gtys_bkpf
                             pis_bseg  TYPE gtys_bseg
                    CHANGING pct_crit  TYPE bapiackec9_tab
                             pct_value TYPE bapiackev9_tab
                             pev_subrc TYPE sy-subrc.

  DATA: ls_copabbseg TYPE copabbseg.
  DATA: ls_crit      LIKE LINE OF pct_crit.
  DATA: lv_paobjnr   TYPE rkeobjnr.
  DATA: lv_subrc     TYPE sy-subrc.
  DATA: lt_copadata  TYPE gtyt_copadata.
  DATA: ls_copadata  LIKE LINE OF lt_copadata.
  DATA: ls_org_copa  TYPE gtys_org_copa.

  CLEAR pev_subrc.

  IF pis_bseg-vbeln IS INITIAL.
    RETURN.
  ENDIF.

* Zuordnung BURKS zu KOKRS/ERKRS ermitteln
  PERFORM get_orgdata_copa USING    pis_bkpf-bukrs
                           CHANGING ls_org_copa.

* Wertfeldtabelle füllen
  PERFORM add_value_line USING    pis_bkpf
                                  pis_bseg
                                  ls_org_copa-kokrs
                                  ls_org_copa-erkrs
                         CHANGING pct_value
                                  lv_subrc.
  IF lv_subrc NE 0.
    pev_subrc = 4.
    RETURN.
  ENDIF.

* Übergabe für Baustein füttern
* Buchungskreis MUSS zwingend gefüllt werden
  MOVE: pis_bkpf-bukrs TO ls_copabbseg-rke_bukrs.
  MOVE: pis_bseg-vbeln TO ls_copabbseg-rke_kaufn.
  MOVE: pis_bseg-posnr TO ls_copabbseg-rke_kdpos.

* Neue Ableitung
  CALL FUNCTION 'RKE_CONVERT_CRITERIA_PAOBJNR'
    EXPORTING
      is_copabbseg     = ls_copabbseg
*     i_date           =
    IMPORTING
      e_paobjnr        = lv_paobjnr
    EXCEPTIONS
      no_bukrs_found   = 1
      no_erkrs_found   = 2
      error_criterion  = 3
      error_derivation = 4
      OTHERS           = 5.
  IF sy-subrc <> 0.
*   Fehler bei Ableitung CO-PA Merkmale für ID & Buzei &.
    pev_subrc = 4.
    RETURN.
  ENDIF.

* Commit Work durchführen, damit die Ergebnisobjektnummer auf
* der Datenbank vorliegt
  COMMIT WORK  AND WAIT.
  IF sy-subrc NE 0.
*   Fehler bei der Fortschreibung PAOBJNR für ID & Buzei &.
    pev_subrc = 4.
    RETURN.
  ENDIF.

* Nachlesen der neuen Ableitung
  CALL FUNCTION 'RKE_CONVERT_PAOBJNR_COPADATA'
    EXPORTING
      bukrs          = pis_bkpf-bukrs
      kokrs          = ls_org_copa-kokrs
      paobjnr        = lv_paobjnr
    TABLES
      i_copadata     = lt_copadata
    EXCEPTIONS
      no_erkrs_found = 1
      paobjnr_wrong  = 2
      OTHERS         = 3.
  IF sy-subrc <> 0.
*   Fehler bei Ermittlung Wertfelder aus PAOBJNR für ID & Buzei &.
    pev_subrc = 4.
    RETURN.
  ENDIF.

* Umstellung der externen Darstellung der Merkmale auf
* interne Werte (durchlaufen der Konvertierungsexits)
  IF NOT lt_copadata IS INITIAL.
    PERFORM change_data_conv_exit USING    ls_org_copa-erkrs
                                  CHANGING lt_copadata.
  ENDIF.

* Anhängen der Merkmale an die Merkmalstabelle für das BAPI
  LOOP AT lt_copadata INTO ls_copadata.
    IF NOT ls_copadata-fval IS INITIAL.
      CLEAR ls_crit.

      MOVE: pis_bseg-buzei   TO ls_crit-itemno_acc,
            ls_copadata-fnam TO ls_crit-fieldname,
            ls_copadata-fval TO ls_crit-character.
      APPEND ls_crit TO pct_crit.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_ORGDATA_COPA
*&---------------------------------------------------------------------*
FORM get_orgdata_copa  USING    piv_bukrs    TYPE bukrs
                       CHANGING pes_org_copa TYPE gtys_org_copa.

  CLEAR pes_org_copa.

  DATA: ls_org_copa    LIKE pes_org_copa.
  DATA: lv_kokrs       TYPE kokrs.
  DATA: lv_erkrs       TYPE erkrs.
  STATICS: lt_org_copa TYPE gtyt_org_copa_hash.

  READ TABLE lt_org_copa INTO ls_org_copa
    WITH TABLE KEY bukrs = piv_bukrs.
  IF sy-subrc EQ 0.
    pes_org_copa = ls_org_copa.
    RETURN.
  ENDIF.

  CALL FUNCTION 'KOKRS_GET_FROM_BUKRS'
    EXPORTING
      i_bukrs        = piv_bukrs
    IMPORTING
      e_kokrs        = lv_kokrs
    EXCEPTIONS
      no_kokrs_found = 1
      OTHERS         = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  CALL FUNCTION 'COPA_ERKRS_FIND'
    EXPORTING
      bukrs              = piv_bukrs
    IMPORTING
      erkrs              = lv_erkrs
    EXCEPTIONS
      error_kokrs_find   = 1
      kokrs_wrong        = 2
      no_erkrs_defined   = 3
      no_erkrs_for_kokrs = 4
      OTHERS             = 5.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  MOVE: piv_bukrs TO ls_org_copa-bukrs,
        lv_kokrs  TO ls_org_copa-kokrs,
        lv_erkrs  TO ls_org_copa-erkrs.
  INSERT ls_org_copa INTO TABLE lt_org_copa.
  pes_org_copa = ls_org_copa.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CHANGE_DATA_CONV_EXIT
*&---------------------------------------------------------------------*
FORM change_data_conv_exit  USING    piv_erkrs TYPE erkrs
                            CHANGING pct_data  TYPE gtyt_copadata.

  DATA: BEGIN OF ls_ddic,
          tabname   TYPE dfies-tabname,
          fieldname TYPE dfies-fieldname,
          rollname  TYPE dfies-rollname,
          convexit  TYPE dfies-convexit,
          funcname  TYPE tfdir-funcname,
          reference TYPE REF TO data,
        END OF ls_ddic,
        lt_ddic LIKE HASHED TABLE OF ls_ddic
                WITH UNIQUE KEY tabname fieldname.
  DATA: lt_ddic_info TYPE ddfields.
  DATA: ls_ddic_info LIKE LINE OF lt_ddic_info.
  DATA: lv_tabname   TYPE tabname.
  DATA: lv_fieldname TYPE fieldname.
  DATA: lv_value     TYPE REF TO data.

  FIELD-SYMBOLS: <ls_data>  LIKE LINE OF pct_data,
                 <lv_value> TYPE any.


  CONCATENATE 'CE0' piv_erkrs INTO lv_tabname.

  LOOP AT pct_data ASSIGNING <ls_data>.
    CHECK NOT <ls_data>-fval IS INITIAL.
    CLEAR: lv_tabname, ls_ddic.

    CONCATENATE 'CE0' piv_erkrs INTO lv_tabname.
    CONDENSE lv_tabname.

    MOVE <ls_data>-fnam TO lv_fieldname.
    READ TABLE lt_ddic INTO ls_ddic
      WITH TABLE KEY tabname   = lv_tabname
                     fieldname = lv_fieldname.
    IF sy-subrc EQ 0.
      IF ls_ddic-funcname IS INITIAL.
        CONTINUE.
      ENDIF.
    ELSE.
      CALL FUNCTION 'DDIF_FIELDINFO_GET'
        EXPORTING
          tabname        = lv_tabname
          fieldname      = lv_fieldname
        TABLES
          dfies_tab      = lt_ddic_info
        EXCEPTIONS
          not_found      = 1
          internal_error = 2
          OTHERS         = 3.
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.
      CLEAR ls_ddic.
      READ TABLE lt_ddic_info INTO ls_ddic_info INDEX 1.
      MOVE-CORRESPONDING ls_ddic_info TO ls_ddic.
      IF NOT ls_ddic-convexit IS INITIAL.
        CONCATENATE 'CONVERSION_EXIT_' ls_ddic_info-convexit '_INPUT'
                    INTO ls_ddic-funcname.
        CONDENSE ls_ddic-funcname.
        CREATE DATA lv_value TYPE (ls_ddic-rollname).
        MOVE lv_value TO ls_ddic-reference.
      ENDIF.
      INSERT ls_ddic INTO TABLE lt_ddic.
    ENDIF.
    IF NOT ls_ddic-funcname IS INITIAL.
      ASSIGN ls_ddic-reference->* TO <lv_value>.
      MOVE <ls_data>-fval TO <lv_value>.
      CALL FUNCTION ls_ddic-funcname
        EXPORTING
          input  = <lv_value>
        IMPORTING
          output = <lv_value>
        EXCEPTIONS
          OTHERS = 0.
      CLEAR <ls_data>-fval.
      MOVE <lv_value> TO <ls_data>-fval.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  ADD_VALUE_LINE
*&---------------------------------------------------------------------*
*       Das BAPI fordert von uns nicht nur die Merkmale sondern wir
*       müssen auch die Wertfelder bestücken - und zwar die richtigen!!!
*
*       Dies erreichen wir, indem wir den Baustein
*       COPA_GET_SETTLEMENT_STRUCTURE benutzen. Dieser gibt uns
*       das Ergebnisschmema, die Zuordnung sowie den Inhalt der Tabelle
*       TKB9F zurück.
*       Hierzu muß man wissen, das für das Konto, auf welches gebucht
*       werden soll, im Customizing hinterlegt sein MUSS, auf welches
*       Wertfeld die Beträge laufen sollen.
*       Also lesen wir zunächst mit dem Baustein Schema und Zuordnung
*       und dann damit die Tabelle.
*       Nicht wundern, das hier bestimmte Werte hart verdrahtet sind.
*       Das ist so und muß auch so gecustomized sein.
*       Es MUSS ein Wertfeld sein (MWKZ = 1) und das Fix-/Variabel Kz.
*       MUSS auf Gesamtwert (FVKZ = 3) stehen. Ist das nicht der Fall,
*       ist dies ein Fehler!!!!
*       Hat man vor mehrere Belege für unterschiedliche Währungs-
*       sichten zu erzeugen, so muß man dies auch hier tun. Im diesem
*       Beispiel nehmen wir nur die Belegwährung
*----------------------------------------------------------------------*
FORM add_value_line USING    pis_bkpf  TYPE gtys_bkpf
                             pis_bseg  TYPE gtys_bseg
                             piv_kokrs TYPE kokrs
                             piv_erkrs TYPE erkrs
                    CHANGING pct_value TYPE bapiackev9_tab
                             pev_subrc TYPE sy-subrc.

  DATA: lt_9f TYPE STANDARD TABLE OF tkb9f.
  DATA: ls_9f LIKE LINE OF lt_9f.
  DATA: lv_ersch TYPE tkb9f-ersch.
  DATA: lv_erzuo TYPE tkb9f-erzuo.

  DATA: ls_value LIKE LINE OF pct_value.
  DATA: BEGIN OF ls_wertfeld,
          hkont  TYPE bseg-hkont,
          wrtfld TYPE fieldname,
        END OF ls_wertfeld.
  STATICS: lt_wertfeld LIKE HASHED TABLE OF ls_wertfeld
                       WITH UNIQUE KEY hkont.

  CLEAR pev_subrc.

* Statische Wertfeldtabelle lesen (damit es schneller geht)
  READ TABLE lt_wertfeld INTO ls_wertfeld
    WITH TABLE KEY hkont = pis_bseg-gkont.
  IF sy-subrc EQ 0.
    MOVE: pis_bseg-buzei     TO ls_value-itemno_acc,
          ls_wertfeld-wrtfld TO ls_value-fieldname,
          '00'               TO ls_value-curr_type,
          pis_bkpf-waers     TO ls_value-currency,
          pis_bkpf-waers     TO ls_value-currency_iso,
          pis_bseg-netto     TO ls_value-amt_valcom.
    APPEND ls_value TO pct_value.
    RETURN.
  ENDIF.

* Ansonsten Ergebnisschema und -zuordnung ermitteln
  CALL FUNCTION 'COPA_GET_SETTLEMENT_STRUCTURE'
    EXPORTING
      i_erkrs              = piv_erkrs
      i_vrgng              = 'RFBU'
      i_hkont              = pis_bseg-gkont
      i_kokrs              = piv_kokrs
    IMPORTING
      e_ersch              = lv_ersch
      e_erzuo              = lv_erzuo
    TABLES
      t_tkb9f              = lt_9f
    EXCEPTIONS
      incomplete_structure = 1
      error_structure      = 2
      OTHERS               = 3.
  IF sy-subrc <> 0.
*   Wertfeld für Bukrs & Konto & kann nicht ermittelt werden (&).
    pev_subrc = 4.
    RETURN.
  ENDIF.

* TKB9F mit den ermittelten Werten lesen
  READ TABLE lt_9f INTO ls_9f WITH KEY ersch = lv_ersch
                                       erzuo = lv_erzuo
                                       erkrs = piv_erkrs
                                       mwkz  = '1'
                                       fvkz  = '3'.
  IF sy-subrc NE 0.
*   Ist hier nichts zu finden, ist dies ein Fehler und der Beleg
*   würde sowieso aufbrummen - also Schluß
*   Wertfeld für Bukrs & Konto & kann nicht ermittelt werden (&)
    pev_subrc = 4.
    RETURN.
  ENDIF.

* Value Rückgabetabelle füllen
  MOVE: pis_bseg-buzei TO ls_value-itemno_acc,
        ls_9f-wrtfld   TO ls_value-fieldname,
        '00'           TO ls_value-curr_type,
        pis_bkpf-waers TO ls_value-currency,
        pis_bkpf-waers TO ls_value-currency_iso,
        pis_bseg-netto TO ls_value-amt_valcom.
  APPEND ls_value TO pct_value.

* Und zum Schluß noch die statische Wertfeldtabelle erweitern
  MOVE: pis_bseg-gkont TO ls_wertfeld-hkont,
        ls_9f-wrtfld   TO ls_wertfeld-wrtfld.
  INSERT ls_wertfeld INTO TABLE lt_wertfeld.

ENDFORM.
 

 

Der Beitrag Buchungsbelege erstellen erschien zuerst auf Tricktresor.

MD04 Start/Freigabedatum anzeigen

$
0
0

In der Bedarfs/Bestandsliste stehen alle Banfen und Planaufträge. Schön nach Datum sortiert mit dem Hinweis wann das Material im Werk sein soll.
Speziell bei plangesteuerter Disposition – mit Bedarfen in der Zukunft – stellt sich aber oftmals die Frage wann man denn die Banf in eine Bestellung umwandeln muss.

Hierzu kann man die im Standard ausgeblendete Spalte „Start-/Freigabedatum“ einblenden lassen.
Dort steht dann das Datum des Bedarfstermins minus der Wiederbeschaffungszeit, also der Tag an dem die Banf spätestens umgesetzt werden soll.

MD04

Zum Einblenden muss man mit dem Mauszeiger genau zwischen 2 Spalten bis sich der Mauszeiger von „verschieben/Größe ändern“ zu „einblenden“ ändert.
(2 parallele Balken mit Pfeilen nach links und rechts) (neben dem Feld „Dispoelement“). Dieses Vorgehen muss 2 mal wiederholt werden, bis die Spalte „Start-/Freigabedatum“ erscheint.

Danach kann das Layout gespeichert werden.

Layout speichern MD04

wie immer „aktivieren“ und schon wird die Spalte dauerhaft eingeblendet.

Layout aktivieren

Kleiner Trick – große Hilfe 🙂

AWI, 06/2015

Transaktionen

MD04

Der Beitrag MD04 Start/Freigabedatum anzeigen erschien zuerst auf Tricktresor.

Viewing all 32 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>