Всем привет.
Хочу напомнить, что 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. В нем-то все и ломалось 🙂