Здесь я хотел написать много букв про креативные ИТ подходы во многих компаниях мира, где на каждый бизнес-чих бегут покупать новую ИТ систему вместо того, чтобы доработать существующую ERP, и создать интегрированную платформу вместо свалки из систем, интеграционных потоков и так далее. Но не буду. Буду позже, когда совсем накипит. Сегодня мы делаем мини-контактный центр для HR. У SAP есть стандартное решение SAP Employee Iteraction Center и SAP Shared Service Framework. Второе лучше первого. Но оба стоят денег.

В стандарте SAP нет такой простой штуки, как принять входящее электронное сообщение и отправить его в поток операций, где консультант сможет проанализировать сообщение и выстроить правильную маршрутизацию. Есть кусочные решения для отдельных блоков ALM, SRM, EIC, SOLMAN, еще чего-то.

Попробуем сделать свое решение за пять минут, чтобы мы могли получить электронное письмо, и запустить поток операций на выполнение, приложив к нему это самое письмо. Своего рода входящая почта в SAP HR для HR. Дальше коллеги из HR включат свою фантазию и придумают ей применение.

Настройка приема почты в самой системе осуществляется элементарно за 5 минут. Для этого читаем ноту  455140 . Там пара параметров в профиле, перезагрузка системы, настройка в SCOT и все. После этого вы сможете получать почту снаружи для ваших логинов. То есть, можно отправить почту с vasya@pupkin.com на *@potceluev.com.

Да, не забываем, что для этого ваш САП сервер должен быть прописан в DNS корпоративной сети. Это уже вне САП.

Существует три способа реализовать нашу задачу.

  • Создать расширение для обработки писем для транзакции SO50 через наследование интерфейса IF_INBOUND_EXIT_BCS BCS: Exit for Inbound Processing
  • Создать BOR объект (SWO1) через наследование интерфейса IFRECEIVE Receive Office objects. Указать его получателем в транзакции SO28
  • Создать программку, которая в фоне будет опрашивать почтовый ящик и обрабатывать письма

Давайте начнем с первого способа. В se24 создаем класс с реализацией интерфейса IF_INBOUND_EXIT_BCS и интерфейса IF_WORKFLOW. Второй нужен для того, чтобы мы могли инициировать с его помощью запуск потока операций с нужным нам событием. Также создаем событие с параметрами SENDER_ADDRESS и BODY_TEXT. Мы будем брать эти два параметра из входящего письма и передавать их в поток операций.

Исходник класса внизу. Там всего ничего, поэтому быстро разберетесь.

Создаем простой поток операций в транзакции SWDD.

В транзакции SWETYPV прописывам связку события с классом:

Теперь осталось прописать наш класс в SO50, чтобы он вызывался, когда приходит входящая почта.

Проверяем:

А в транзакции SWIA смотрим вызов потока:

15.09.2017                        Display Class                                1
--------------------------------------------------------------------------------
class-pool .



INCLUDE <cntn02>.

class ZCL_SMTP_WORKFLOW definition
  public
  final
  create public .
public section.
  type-pools SX .
  interfaces IF_INBOUND_EXIT_BCS .
  interfaces BI_OBJECT .
  interfaces BI_PERSISTENT .
  interfaces IF_WORKFLOW .
  events MAIL_RECEIVED
    exporting
      value(SENDER_ADDRESS) type STRING
      value(BODY_TEXT) type STRING .

protected section.

private section.
endclass. "ZCL_SMTP_WORKFLOW definition

class ZCL_SMTP_WORKFLOW implementation.

  method IF_INBOUND_EXIT_BCS~CREATE_INSTANCE.
    DATA:   lcl_OBJECT type ref to ZCL_SMTP_WORKFLOW.
    CREATE OBJECT lcl_OBJECT.
    RO_REF = lcl_OBJECT.
  endmethod.

  method IF_INBOUND_EXIT_BCS~PROCESS_INBOUND.
    DATA:
      l_sender_addr       TYPE string,
      l_body_text         TYPE string,
      lo_sender           TYPE REF TO IF_SENDER_BCS,
      l_uuid              TYPE SYSUUID_C32,
      lv_objtype          TYPE sibftypeid,
      lv_event            TYPE sibfevent,
      lv_objkey           TYPE sibfinstid,
      lr_event_parameters TYPE REF TO if_swf_ifs_parameter_container.
    lo_sender           = io_sreq->get_sender( ).
    l_sender_addr = lo_sender->address_string( ).
    TRY.
        CALL METHOD CL_SYSTEM_UUID=>IF_SYSTEM_UUID_STATIC~CREATE_UUID_C32
          RECEIVING
            UUID = l_uuid.
      CATCH CX_UUID_ERROR .
    ENDTRY.
    lv_objtype = 'ZCL_SMTP_WORKFLOW'.
    lv_event = 'MAIL_RECEIVED'.
    MOVE l_uuid TO lv_objkey.
    CALL METHOD cl_swf_evt_event=>get_event_container
      EXPORTING
        im_objcateg  = cl_swf_evt_event=>mc_objcateg_cl
        im_objtype   = lv_objtype
        im_event     = lv_event
      RECEIVING
        re_reference = lr_event_parameters.
    TRY.

        CALL METHOD lr_event_parameters->set
          EXPORTING
            name  = 'SENDER_ADDRESS'
            value = l_sender_addr.
        CALL METHOD lr_event_parameters->set
          EXPORTING
            name  = 'BODY_TEXT'
            value = l_body_text.
      CATCH cx_swf_cnt_cont_access_denied.
      CATCH cx_swf_cnt_elem_access_denied .
      CATCH cx_swf_cnt_elem_not_found .
      CATCH cx_swf_cnt_elem_type_conflict .
      CATCH cx_swf_cnt_unit_type_conflict .
      CATCH cx_swf_cnt_elem_def_invalid .
      CATCH cx_swf_cnt_container .
    ENDTRY.
    TRY.
        CALL METHOD cl_swf_evt_event=>raise
          EXPORTING
            im_objcateg        = cl_swf_evt_event=>mc_objcateg_cl
            im_objtype         = lv_objtype
            im_event           = lv_event
            im_objkey          = lv_objkey
            im_event_container = lr_event_parameters.
      CATCH cx_swf_evt_invalid_objtype .
      CATCH cx_swf_evt_invalid_event .
    ENDTRY.
    COMMIT WORK.
    e_retcode = if_inbound_exit_bcs=>gc_terminate.
  endmethod.

  method BI_PERSISTENT~FIND_BY_LPOR.
    create object result TYPE ZCL_SMTP_WORKFLOW.
  endmethod.

  method BI_PERSISTENT~LPOR.
    DATA: lpor TYPE sibflpor.
  lpor-catid   = 'CL'.
  lpor-typeid  = 'ZCL_SMTP_WORKFLOW'.
  lpor-instid  = '1'.
  result = lpor.
  endmethod.

  method BI_PERSISTENT~REFRESH.
  endmethod.

  method BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE.
  endmethod.

  method BI_OBJECT~EXECUTE_DEFAULT_METHOD.
  endmethod.

  method BI_OBJECT~RELEASE.
  endmethod.
endclass. "ZCL_SMTP_WORKFLOW implementation