Как обычно или лыжи не едут или что-то поменялось в S/4HANA, но возникла проблема позиционирования ошибки в стандартном заказе для журнала сообщений. Проблема возникла в том, что в ходе проверки позиций, находим например позицию которая заполнена не правильно, формируем согласно документации сообщение об ошибке и на выходе получаем, что в журнале и по статусам данное сообщение почему-то относится всегда к последней позиции заказа, т.е. все ошибки отражаются в журнале так, как будто они возникли на последней позиции заказа. В документации, да и в мировом разуме написано все довольно прозрачно.
1. В реализации метода включаем стандартную группу макросов по работе с журналом ошибок документа
* ---------------------------------------------------------------------*
INCLUDE mm_messages_mac. "useful macros for message handling
* ---------------------------------------------------------------------*
2. Далее в месте где возникла ошибка связываем класс ошибки с пользовательским кодом расширения, для этого вызываем макрос, с кодом сообщения пользовательская ошибка mmmfd_cust_01 (таких констант, там определено с 01 по 09)
mmpur_metafield mmmfd_cust_01.
3. Далее по вкусу или вызываем ошибку сами, для быстрого поиска места возникновения сообщения, а потом вызываем макрос записи в журнал или сразу вызываем макрос записи ошибки/сообщения в журнал, я вставляю обычно вызов сообщения с ключем INTO l_dummy, где l_dummy определено как строка 132 символа. После чего вызываю макрос записи в журнал.
MESSAGE e001(zmm_013) WITH ls_position-matnr INTO l_dummy.
mmpur_message_forced sy-msgty sy-msgid sy-msgno
sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
4. Если нужно дальше отметить позицию как ошибочную то после записи ошибки в журнал, для выбранной позиции вызываем метод invalidate( ).
CALL METHOD is_item-item->invalidate( ).
На этом вроде как все должно работать, однако в 1710 не работает, точнее работает, но выдает всегда позиционирование ошибки в последней строке заказа. Как оказалось в группе макросов появились еще дополнительные определения, которые там написаны не просто, так. В общем перед вызовом всего этого барахла, нужно через макрос mmpur_business_obj_id позиционировать для журнала место возникновения ошибки. При этом позиционирование выполняем или для заголовка, если хотим чтобы сообщение выдавалось для всего заказа или для конкретной позиции. Вызов простой, для этого в структуре полей заголовка и каждой позиции есть поле ID, которое и нужно передать в макрос. Таким образом структура вызова сообщения об ошибке в методе CHECK должна выглядеть следующим образом:
DATA: l_dummy TYPE c LENGTH 128.
DATA(ls_header) = im_header->get_data( ).
IF <ошибка в заголовке>.
mmpur_business_obj_id ls_header-id.
mmpur_metafield mmmfd_cust_01.
MESSAGE e014(zmm_013) INTO l_dummy.
mmpur_message_forced sy-msgty sy-msgid sy-msgno
sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
im_header->invalidate( ).
ch_failed = abap_true.
ENDIF.
LOOP AT im_header->get_items( ) INTO DATA(ls_item).
DATA(ls_position) = ls_item-item->get_data( ).
IF <ошибка в позиции>.
mmpur_business_obj_id ls_position-id.
mmpur_metafield mmmfd_cust_01.
MESSAGE e012(zmm_013) WITH ls_position-matnr INTO l_dummy.
mmpur_message_forced sy-msgty sy-msgid sy-msgno
sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
CALL METHOD ls_item-item->invalidate( ).
ch_failed = abap_true.
ENDIF.
ENDLOOP.
Таким образом получаем правильное позиционирование сообщения об ошибке в позиции или заголовке заказа, в зависимости от необходимости. Само собой, если возникло критическое сообщение в позиции то в заголовок будет всегда выдано автоматически сообщение, что заказ в позициях все еще содержит ошибки, поэтому сохранение не возможно. Как на рисунке mmpur_business_obj_id.png ниже.