Есть один занятный BAPI по работе с услугами и работами, а именно BAPI_SERVICE_CHANGE. Тараканов в его реализации хватает с головой (использование данного BAPI, как нибудь опишу отдельно), но меня позабавил такой момент как заполнение структур расширений пользовательских полей, это касается таблицы параметров: EXTENSION_IN STRUCTURE BAPIPAREX. Принципы заполнения стандартные, но вот то как написана обработка передаваемых данных это та вещь, которую не надо так писать, если вы пишете, что-то универсальное.
В общем суть заполнения это передать значения пользовательских полей, которые мы добавляем в таблицу ASMD - Основная запись работы/услуги: основные данные, и вторая структура которую мы заполняем это скажем так стандартная для BAPI техника структура типа <Имя структуры>X, где для каждого поля мы записываем флаг = "Х", если нужно выполнить обновление поля. В данном случае SAP предлагает следующее, вы должны добавить в структуру BAPISRV_ASMD расширение CI_ASMDDB, а в структуру BAPISRV_ASMDX соответственно расширение CI_ASMDDBX. При этом, в первом расширении вы перечисляете поля которые добавили в таблицу ASMD, а во вторую структуру добавляете такие по имени поля, но с типом BAPIUPDATE, соответственно если вам нужно вызвать обновление данных в этом расширении, напротив нужного поля, будет стоять флажок "X" и, как обычно, мы думаем, что SAP, корректно перенесет пользовательские данные из BAPISRV_ASMD в таблицу ASMD при изменении основной записи работы/услуги в данном BAPI.
А теперь, как не надо писать. Ну тут как бы частично кривые руки локального абапера, выполнившего расширение объекта пользовательскими полями, процентов на 20, остальное 80, на совести писавшего реализацию BAPI. В общем в классе CL_SERVICE_MASTER_MMSRV метод MERGE_DATA написан чудный обработчик определения того, какие поля нужно перенести из переданной структуры и в конечном итоге обновить в базе данных:
* Merge the service data: Overwrite the interface values (my_) by
* the data base values (ls_) if the corresponding change parameter
* is set to 'X'.
WHILE sy-subrc EQ 0.
ASSIGN COMPONENT sy-index OF STRUCTURE my_service_data TO <comp_my>.
ASSIGN COMPONENT sy-index OF STRUCTURE ls_service_data TO <comp_ls>.
ASSIGN COMPONENT sy-index OF STRUCTURE my_service_datax TO <comp_x>.
*-- Check if update flag in my_service_datax is set for this field
IF <comp_x> NE 'X'.
*---- No update, use DB data instead of interface data
<comp_my> = <comp_ls>.
ENDIF.
ENDWHILE.
Как видим писавшему глубоко фиолетово какие там поля, кто, куда и как добавил, боец просто обращается к полям структур по индексу и как следствие, если порядок полей в структурах несколько нарушен (ну переставили два поля местами в с дополнении CI_ASMDDBX), то на выходе вы получите странные обновления данных, для полей которые не заказывали и не обновления данных для полей, которые вы передавали. Вопрос почему не воспользоваться универсальным обращением по именам полей, остается за кадром.