Automatische Maileingangsverarbeitung in SAP

Aus SAP-Wiki
Wechseln zu: Navigation, Suche

Bei interaktiven Adobe Forms-Formularen ist es ein häufiger Prozess, dass die PDF-Formulare ausgefüllt werden und dann an das SAP-System geschickt werden als Mailanhang. Hier besteht die Möglichkeit mit wenigen Konfigurationsschritten die Mail, bzw. das PDF/XML in der Mail direkt in SAP auszulesen.

Wenn nach der Konfiguration an eine im SAP-System bekannte Mailadresse eine Mail geschickt wird, dann können im Hintergrund die PDF, bzw. XML-Daten des Formulars automatisch im Hintergrund ausgelesen und weiterverarbeitet werden.

Exit-Regeln für die Eingangsverarbeitung (Transaktion SO50)

In der Transaktion SO50 muss ein Eintrag gepflegt sein mit

  • Kommunikationstyp = Internet-Mail
  • Emfängeradresse = Eingangsmailadresse (Die Eingangsmail-Adresse muss dem SAP bekannt sein und von außen erreichbar sein. Hier die Basis zur Konfiguration kontaktieren)
  • Dokumenttyp = *
  • Exit-Name = CL_FP_INBOUND_HANDLER

Eingangsverarbeitung01.jpg

Anlage Eingangshandler im Class Builder

  • In der Transaktion SE24 eine Z-Klasse anlegen

Eingangsverarbeitung02.jpg


  • Das Interface "IF_FP_OFFLINE" eintragen

Eingangsverarbeitung03.jpg


  • Durch das Interface erhält man zwei Methoden "GET_INSTANCE" und "HANDLE_PDF"

Eingangsverarbeitung04.jpg

Implementierung Methode "IF_FP_OFFLINE~GET_INSTANCE"

  • Erzeugen einer Instanz der Klasse

Eingangsverarbeitung05.jpg

Implementierung Methode "IF_FP_OFFLINE~HANDLE_PDF"

  • Als Eingangsparameter der Methode erhält man sowohl das PDF als auch die eingebettete XML. Diese beiden Parameter typisieren auf das Datenelement/Domäne FPCONTENT (RAWSTRING) typisiert. Aus dem XML lassen sich dann die im PDF-Formular sichtbaren Daten extrahieren (parsen).
  • In der Methode HANDLE_PDF lässt sich eine Ausnahme CX_FP_OFFLINE auslösen (s. a. Paket SAFPX)

Eingangsverarbeitung06.jpg

XML parsen

Hier ist ein Auszug aus einem Coding, wo ein (anderes) XML geparst wird. Letztlich werden die geparsten Daten in eine interne Tabelle LT_INVOICE gefüllt. Diese interne Tabelle kann dann hier für den weiteren Verarbeitungsprozess in SAP genutzt werden.

* In Variablen L_DATA ist XSTRING
* begin of XML parsen
  DATA: lo_ixml_factory        TYPE REF TO if_ixml,     
        lo_ixml_stream_factory TYPE REF TO if_ixml_stream_factory, 
        lo_ixml_istream        TYPE REF TO if_ixml_istream,  
        lo_ixml_document       TYPE REF TO if_ixml_document, 
        lo_ixml_parser         TYPE REF TO if_ixml_parser, 
        lv_str       TYPE string, 
        lv_node      TYPE REF TO if_ixml_node, 
        lv_iterator  TYPE REF TO if_ixml_node_iterator, 
        lv_node2     TYPE REF TO if_ixml_node, 
        lv_iterator2 TYPE REF TO if_ixml_node_iterator.

  Data: ls_invoice  type ZMCL_S_GB_INVOICE, 
        lt_invoice  type STANDARD TABLE OF ZMCL_S_GB_INVOICE, 
        lv_gb_belnr type /mcl/gbde_gbnr, 
        lr_gbdoc    TYPE REF TO /mcl/gbcl_doc.

  FIELD-SYMBOLS: <invoice> LIKE LINE OF lt_invoice,               "#EC NEEDED
                 <posi>    LIKE LINE OF lr_gbdoc->gbt_posi.       "#EC NEEDED

  " create new iXML factory
  lo_ixml_factory = cl_ixml=>create( ).

  " create new stream factory
  lo_ixml_stream_factory = lo_ixml_factory->create_stream_factory( ).

  "st_import-import_data
  "lo_ixml_istream = lo_ixml_stream_factory->create_istream_string( gv_xml_istream ).
  lo_ixml_istream = lo_ixml_stream_factory->create_istream_xstring( l_data ).


  " create new document
  lo_ixml_document = lo_ixml_factory->create_document( ).

  " connect all with a parser
  lo_ixml_parser = lo_ixml_factory->create_parser( stream_factory = lo_ixml_stream_factory
                                                   istream  = lo_ixml_istream
                                                   document = lo_ixml_document ).

  lo_ixml_parser->parse( ).
  lv_iterator  = lo_ixml_document->create_iterator( 1 ).


  IF lv_iterator IS INITIAL.
    "RAISE error_reply_format.
  ELSE.
    lv_node = lv_iterator->get_next( ).
    lv_str = lv_node->get_name( ).
    lv_node = lv_iterator->get_next( ).


    lv_str = lv_node->get_name( ).

    "Iterator auf den Zweig der uns eigentlich interessiert
    lv_iterator = lv_node->create_iterator( 1 ).
    lv_node = lv_iterator->get_next( ).


    WHILE NOT lv_node IS INITIAL.
      lv_str = lv_node->get_name( ).

      "BREAK-POINT.

      IF lv_str = 'GT_INVOICE'.

        lv_iterator2 = lv_node->create_iterator( 2 ).
        lv_node2 = lv_iterator2->get_next( ).
        WHILE NOT lv_node2 IS INITIAL.
          lv_str = lv_node2->get_name( ).
          CASE lv_str.
            WHEN 'GB_BELNR'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-gb_belnr = lv_str.
              shift ls_invoice-gb_belnr RIGHT DELETING TRAILING space.
              overlay ls_invoice-gb_belnr with '0000000000'.
              IF lv_gb_belnr IS INITIAL.
                lv_gb_belnr = ls_invoice-gb_belnr.
              ENDIF.
            WHEN 'GB_POSNR'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-gb_posnr = lv_str.
            WHEN 'VBELN_VF'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-vbeln_vf = lv_str.
              shift ls_invoice-vbeln_vf RIGHT DELETING TRAILING space.
              overlay ls_invoice-vbeln_vf with '0000000000'.
            WHEN 'VBELN_GS'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-vbeln_gs = lv_str.
              if ls_invoice-vbeln_gs is not initial.
                shift ls_invoice-vbeln_gs RIGHT DELETING TRAILING space.
                overlay ls_invoice-vbeln_gs with '0000000000'.
              endif.
            WHEN 'FKDAT'.
              lv_str = lv_node2->get_value( ).
              lv_datum_10 = lv_str.
              concatenate lv_datum_10(4)
                          lv_datum_10+5(2)
                          lv_datum_10+8(2)
                          into ls_invoice-fkdat.
            WHEN 'NETWR'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-netwr = lv_str.
            WHEN 'WAERK'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-waerk = lv_str.
            WHEN 'ORT'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-ort = lv_str.
            WHEN 'MONAT'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-monat = lv_str.
            WHEN 'NICHTOK'.
              lv_str = lv_node2->get_value( ).
              if lv_str = '1'.  "Checkbox füllt "1", umsetzen in "X"
                ls_invoice-nichtok = 'X'.
              endif.
            WHEN 'ANMERKUNG'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-anmerkung = lv_str.
            WHEN 'VBELN_VL'.
              lv_str = lv_node2->get_value( ).
              ls_invoice-vbeln_vl = lv_str.
              shift ls_invoice-vbeln_vl RIGHT DELETING TRAILING space.
              overlay ls_invoice-vbeln_vl with '0000000000'.
              append ls_invoice to lt_invoice.
              clear ls_invoice.
            WHEN OTHERS.
          ENDCASE.
          lv_node2 = lv_iterator2->get_next( ).
        ENDWHILE.

      ENDIF.

      lv_node = lv_iterator->get_next( ).
    ENDWHILE.
  endif.

Das Adobe Forms in Transaktion SFP pflegen

  • Im betreffenden Adobe Forms-Formular muss die Handlerklasse bekannt gemacht werden.

Eingangsverarbeitung07.jpg


  • Im Feld "Eingangsverarbeitung" die Handlerklasse eintragen

Eingangsverarbeitung08.jpg

Transaktion SOIN

  • Mit der Transaktion SOIN lässt sich eine Übersicht aller eingehenden Sendeaufträge über SAPconnect anzeigen
  • Es besteht die Möglichkeit der Nachverarbeitung, falls in der automatischen Eingangsverarbeitung (Offlinehandler) eine Ausnahme ausgelöst wurde

SOIN1.jpg

Web-Links

Literatur