Всем привет.

Хочу напомнить, что BAdI HRPAD00INFTY работает только в транзакциях PA30, PA51, но не работает в PTMW. Поэтому приходится дублировать логику проверки/обработки данных инфотипов в двух местах, если вы используете транзакции как PTMW, так и PA*. По работе с BAdI в PTMW крайне мало документации и всего три ноты:

Note 367249 — Customer enhancements for the BLP

Note 447097 — Questions and answers concerning the TMW implementation

Note 897623 — User exits and BADIs in the PT area

Промучившись несколько часов с поиском решения по расширению PTMW для своих нужд, решил поделиться опытом с общественностью. Опять же, напоминаю, что на красоту и изящество кода не претендую. Моя задача — оставить заметку, чтобы не забыть в каком направлении искать решение.

Итак, мы будем использовать BAdI PT_BLP_USER. В транзакции Se19 создаем новое внедрение. В TMW реализована система временных точек, когда один BAdI вызывается с разными значениями фильтра в разное время. Поэтому неплохо бы нам делать по одной реализации на один фильтр. Один бади для проверки данных, один для обработки после сохранения, один для заполнения инфотипа и так далее.

У меня была задача проверить данные на корректность. Например, чтобы нельзя было ввести праздничное присутствие больше 8 часов.

Это событие (значение фильтра в BAdI) SRP Individual Record Processing. За образец реализации класса берем пример из документации — BAdI PT_BLP_SAMPLE_SRP. Я прямо скопировал все решение один в один.

Остается дописать логику обработки данных в процедуре process_it2002. У меня она выглядит так:

method PROCESS_IT2002.
data:
dme type ref to if_pt_td_it2002,
cateye type boole_d,
ls_p2002 type p2002.

data l_message type bapiret2.
data is_holiday type c.

dme ?= i_record->data.
ls_p2002 = dme->p2002.

» Check holiday pay is on holiday date.
if ls_p2002-subty = ‘1540’.
CALL FUNCTION ‘HOLIDAY_CHECK_AND_GET_INFO’
EXPORTING
DATE                = ls_p2002-begda
HOLIDAY_CALENDAR_ID = ‘US’
IMPORTING
HOLIDAY_FOUND       = is_holiday.

if is_holiday ne ‘X’.
call function ‘BALW_BAPIRETURN_GET2’
exporting
type   = ‘E’
cl     = ‘Z001’
number = ‘023’
importing
return = l_message.

l_message-parameter = cl_pt_tmw_tdm_const=>rec_msg.
append l_message to e_messages.
EXIT.
endif.

if ls_p2002-stdaz > 8.
call function ‘BALW_BAPIRETURN_GET2’
exporting
type   = ‘E’
cl     = ‘Z001’
number = ‘022’
importing
return = l_message.

l_message-parameter = cl_pt_tmw_tdm_const=>rec_msg.
append l_message to e_messages.
EXIT.
endif.
endif.
endmethod.

 

Вроде бы ничего сложного, однако! Большое количество времени ушло на то, чтобы изучить внутренности работы механизма. Например, у меня PTMW вылетал в дамп с ошибкой:

Category ABAP Programming Error
Runtime Errors RAISE_EXCEPTION
ABAP Program CL_PT_APPLICATION_TMW_CORE====CP
Application Component PT-RC

Exception condition «MISSING_INT_DOC_NO» triggered

Оказалось, что для различных категорий сообщения (l_message-parameter = cl_pt_tmw_tdm_const=>rec_msg.) идет различная обработка и формирование ссылок на записи табличной части PTMW. И все это завязано на события (значение фильтра в BAdI). Говоря проще, я изначально поставил фильтр SAV Save (Activities Before Database Update), из перевода которого следует, что это как бы PAI логика, где можно проверить данные перед сохранением и вернуть ошибку. Ан нет. Вышеуказанный кусок кода в случае ошибки генерировал дамп. Только после смены фильтра на SRP механизм заработал.

Используемые категории сообщений об ошибке можно посмотреть в классе CL_PT_TMW_MESSAGE_HANDLER метод CHECK_MESSAGE_EXT. В нем-то все и ломалось 🙂