John Doe's blog


Использование Exits программирования в шагах ПО

Thu Jan 24, 2008 12:37 am

Задача: При использовании собственной Z-таблицы для хранения информации о состоянии процесса и этапов согласования (маршрутная таблица) необходимо было реализовать функциональность изменения статусов обработки (отличных от стандартной статусной схемы обработки ЭПО) конкретных маршрутов и присвоение им идентификаторов ЭПО.
На основании данной таблицы, в диалоге пользователь получал полную и уже "разжованную" информацию о состоянии бизнес-процесса без запуска и расшифровки журнала ПО.

Первоначальная организация: Заполнение и сохранение данной информации осуществлялось в PBO-модулях экрана пользовательского расширения объекта.
Минус реализации: Первоначально формируется маршрутная таблица, где определены задачи и исполнители. На основании ее в ходе выполнения ПО формируются ЭПО. Идентификатор ЭПО попадает в маршрутную таблицу только в случае, если пользователь "взял" задачу из inbox. Если же он прохалявил (или забил) - то определение ЭПО, которое нужно подпихнуть, превращается в сложный процесс (особенно если исполнитель задействован в нескольких последовательных маршрутах).

Реализация через Exits программирования:
1. В шаге ПО переходим на нужную закладку (тр. SWDD).

Внимательно читаем описание, как работают eixts Smile В принципе стало все понятно. Если нет - идем дальше.

2. Запускаем Построитель классов (тр. SE24) и создаем свой класс ZMYCLASSEXIT, к примеру. Класс может быть каким угодно, у мну он обычный и конечный.
Переходим на закладку интерфейсы и прописываем нужный нам интерфейс IF_SWF_IFS_WORKITEM_EXIT - Workflow Interfaces: Runtime Exit. Созданный класс автоматически наследует от интерфейса метод EVENT_RAISED, который нам и нужен.

Также автоматом определяются атрибуты


3. Приступаем к написанию метода.
Code:
METHOD IF_SWF_IFS_WORKITEM_EXIT~EVENT_RAISED.
  DATA: LV_WIID         TYPE SWW_WIID,     " Current workitem
        LV_CONTAINER    TYPE REF TO IF_SWF_IFS_PARAMETER_CONTAINER.
  DATA: L_OBJECT        TYPE SIBFLPORB.    " BO instance
  DATA: LS_APPRDATA     TYPE ZDF_APPRDATA, " My approval table
        L_ACTOR         TYPE SWHACTOR,     " Current executor
        L_PROJECT       TYPE PS_PSPID.     " BO key

* Get workitem ID
  LV_WIID = IM_WORKITEM_CONTEXT->GET_WORKITEM_ID( ).

* Get task container
  LV_CONTAINER = IM_WORKITEM_CONTEXT->GET_WF_CONTAINER( ).

* You can work with container elements too
  TRY.
      CALL METHOD LV_CONTAINER->GET
        EXPORTING
          NAME  = 'BUS2001'
        IMPORTING
          VALUE = L_OBJECT.
    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_CONTAINER .
  ENDTRY.
  MOVE L_OBJECT-INSTID TO L_PROJECT.

* Get current event
  CASE IM_EVENT_NAME. " Look at this! This is "our" interface attributes

    WHEN IF_SWF_IFS_WORKITEM_EXIT~C_EVTTYP_AFTER_CREATE.      " After workitem creation
      TRY.
          CALL METHOD LV_CONTAINER->GET
            EXPORTING
              NAME  = 'AGENT'
            IMPORTING
              VALUE = L_ACTOR.
        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_CONTAINER .
      ENDTRY.

      " Get approval table entry
      SELECT SINGLE * FROM ZDF_APPRDATA CLIENT SPECIFIED INTO LS_APPRDATA
        WHERE MANDT = SY-MANDT
        AND   PSPID = L_PROJECT.
      LS_APPRDATA-WIID  = LV_WIID.
      LS_APPRDATA-APRST = '1'. " Own status - NEW TASK
      MODIFY ZDF_APPRDATA FROM LS_APPRDATA.
      COMMIT WORK.

    WHEN IF_SWF_IFS_WORKITEM_EXIT~C_EVTTYP_BEFORE_EXECUTION.  " Before workitem execute
      " Get approval table entry
      SELECT SINGLE * FROM ZDF_APPRDATA CLIENT SPECIFIED INTO LS_APPRDATA
        WHERE MANDT = SY-MANDT
        AND   WIID = LV_WIID.
      IF LS_APPRDATA-APRST = '1'.
        LS_APPRDATA-APRST = '2'. " Own status - IN WORK
        MODIFY ZDF_APPRDATA FROM LS_APPRDATA.
        COMMIT WORK.
      ENDIF.

    WHEN IF_SWF_IFS_WORKITEM_EXIT~C_EVTTYP_AFTER_EXECUTION.   " After workitem execute

    WHEN IF_SWF_IFS_WORKITEM_EXIT~C_EVTTYP_BEFORE_REMOVE.     " Before workitem delete

      " You can use all other event from interface attributes

  ENDCASE.

* Commit
  CALL METHOD IM_WORKITEM_CONTEXT->DO_COMMIT_WORK.

ENDMETHOD.


Проверяем и активируем.

Тут следует отметить следующее:
а) можно "ловить" любое из событий, которое определено в атрибутах класса;
б) не все события можно поймать в отладке. К примеру, при написании процедуры в событии AFTER_CREATE (т.е. непосредственно выполняемом в фоне после формирования ЭПО) приходится писать "вслепую";
в) в ходе выполнения метода можно работать с элементами контейнера текущей задачи, выполняемой в нашем шаге;
г) иногда, в ходе выполнения метода происходят ошибки типа "Разрушена скобка транзакции" (к сожалению не знаю как с ними бороться). После этого ЭПО переводится в ЕГГОГ-статус и его приходится перезапускать. Случаи единичные и, возможно, связаны с чем то другим в системе Workflow, но у меня имеют место быть - поэтому и предупреждаю.

4. Возвращаемся в наш редактор ПО, к первой картинке. После создания нашего класса, он должен автоматически появится в средстве поиска на поле "Класс". Находим и выбираем его.
Сохраняем шаг и активируем наш ПО. Вроде все!

Плюсы реализации: Разгружено пользовательское расширение объекта, апдейты технической информации вынесены за пределы функциональной сферы разработки. Информация заполняется в различные этапы жизни ЭПО, так как и требовалась.

The Trackback URL for this entry is:

http://www.sapnet.ru/trackback.php?e=2

Author Message
There are no replies for this entry.
Display posts from previous:   
Powered by The Blog Mod version 0.2.4 by Hyperion & TheBlogMod.com
Powered by phpBB © 2001, 2002 phpBB Group
Weblog style by Hyperion