Включение истории изменений в собственных документах

Есть два основных направления отслеживания истории изменения какого-либо объекта.

1. Историчность данных

В этом случае мы принимаем за основу, что нам интересно знать состояние объекта на любую заданную дату: год назад, месяц назад, вчера, сегодня. И знание такой информации важно для осуществления бизнес-операций.

Реализуется такое в БД посредством включения даты в ключ таблицы (BEGDA/ENDDA) и написания многих строк на ABAP, разруливания этого добра на экранах.

При этом предполагается, что пользователь может управлять диапазонами актуальности данных.

Модуль Управление кадрами HCM практически полностью использует этот подход, там всё зависит от даты (имя, должность, организационное присвоение, наименования, мероприятия, отсутствия, документы, счета).

2. Журналирование изменений

В этом случае мы принимаем за основу, что нас интересует только текущее состояние объекта, но мы хотим “на всякий случай” иметь историю изменения.

Эта история нужна в первую очередь для контроля за действиями пользователя пост-фактум. Как правило, её используют только в качестве улик, при разборе проблем. Информация о предыдущем состоянии объекта не может использоваться в бизнес-операциях, хотя я встречал в жизни и такие Z-кейсы.

При этом предполагается, что пользователь не может управлять журналированием – оно производится незаметно и всегда. При желании пользователь может посмотреть на историю, выбрав соответствующий пункт меню.

Самый базовый подход предполагает использование четырёх дополнительных полей: ERNAM (кто создал), ERDAT (когда создал), AENAM (кто изменил), AEDAT (когда изменил). Дело совсем нехитрое. Однако нас может и должен заинтересовать характер вносимых изменений, то есть список всех изменений, включая старые и новые значения полей:

Пользователь IVAN 13 декабря 2012 года в 14:15 GMT в объекте ANLA (ключ  001234567890) в таблице ANLA поменял поле TXT50 (Наименование основного средства) со значения «Мой компьютер» на «Просто компьютер».

Именно такой подход используется практически во всех основных данных ERP (ОС, Счёт, Дебитор, Кредитор), поэтому есть некоторый стандартный механизм в SAP, который используется везде, где это необходимо.

И именно о нём пойдёт речь под катом.

Основные таблицы с документами изменений

Есть две основных таблицы, в которых откладывается история изменений для всех объектов:

  • CDHDR – заголовок документа изменений
  • CDPOS – позиция документа изменений

Таблицы простые, структура и данные прозрачны. В реальной жизни эти таблицы практически не понадобятся в дельнейшем, но они есть. Впрочем некоторые консультанты могут иметь такую привычку.

Я в целом считаю, что потеря даных в этих таблицах не существена для бизнеса, хотя есть и прямо противоположное мнение. Кроме того, эти таблицы можно добавить в список исключений при копировании манданта, это положительно скажется на времени копирования.

 

Исходная таблица с основными данными

Предполагается, что основная таблица с основными данными у вас уже есть. К этой таблице у вас уже есть программа с экранами, которая позволяет создавать и изменять записи в этой таблице.

И всё что вы хотите – это быстро и просто прикрутить запись изменений.

В моём случае таблица называется ZPM_OPER – регистрация операций. Добавлять колонки нам дополнительно не надо, но надо убедиться в том, чтобы у нас элементы данных ко всем колонкам были правильными.

Документ изменений в домене

Для полей, которые мы хотим отслеживать, этот флаг должен быть включён, а для остальных – выключен.

Создание объекта документа изменений

Заходим в транзакцию SCDO, и создаём там объект. В качестве имени вполне подойдёт имя таблицы:

Объект документа изменений

Если включить флаг “Перенос как внутренней таблицы”, то в сгенерированном ФМ в качестве основного параметра будет таблица, а иначе – просто структура.

Особой разницы может быть и нет, но если вы сохраняете многопозиционный документ, то разумнее отразить сразу все позиции, чем дёргать этот ФМ в цикле. И наоборот, если у вас обрабатывается однострочная карточка какого-то объекта, то таблица вам не нужна и структуры вам достаточно.

Но вот галочку эту легко поставить и сгенерировать ФМ заново, а вот переписать его вызов – будет задачкой посложнее, так что будьте предусмотрительны.

К этому объекту надо сгенерировать программы:

Генерация программы

Если вы вдруг выберете флаг “Особая обработка текстов”, то в интерфейс ФМ будут добавлены дополнительные параметры по текстам, зависимым от языка. Но на практике основные данные не имеют текстов, зависимых от языка (а именно для них создаются документы изменений). Как правило, зависимостью от языка обладают только справочники/настройки (а для них изменения отслеживаются другими механизмами).

Чтоб не путаться, я предварительно создал отдельную группу функций по имени таблицы с префиксом ZCD (Change Document).

Самое главное что нам тут потом понадобится: сгенерированная функция ZPM_OPER_WRITE_DOCUMENT.

Включение записи изменений

Находим место в тексте программы, когда запись в БД наших данных уже гарантированно проходит и включаем туда вызов сгенерированной функции:

data: lv_objectid type cdhdr-objectid.
lv_objectid = ls_zpm_oper-eqopr.
call function ‘ZPM_OPER_WRITE_DOCUMENT’
exporting
objectid     = lv_objectid
tcode        = sy-tcode
utime        = sy-uzeit
udate        = sy-datum
username     = sy-uname
n_zpm_oper   = ls_zpm_oper      «New record
o_zpm_oper   = ls_zpm_oper_bak  «Old record
upd_zpm_oper = ‘U’.

 

ID объекта – это наш ключ к объекту (ключ таблицы). Если у вас в таблице несколько ключевых полей, то придётся их склеить в одно поле.

Во входных параметрах две строки-структуры: до изменений и после них. По-хорошему, у вас они и так должны быть, хотя бы в целях проверки необходимости сохранения. Значения и колонки анализируются внутри ФМ: сравниваются поля и проверяется признак в ЭД.

Пока это всё. Можно подёргать изменения и убедиться, что записи в таблице CDPOS появляются.

Написание программы для просмотра

Здесь можно пойти тремя разными путями:

  • полностью своя программа (просто: на базе ALV, таблицы известны)
  • стандартная программа (например: RSSCD100/RSSCD200)
  • своя программа на стандартном API (на базе ФМ)

А я расскажу о третьем пункте.

Набрасываем программку вокруг стандартных функциональных модулей. Вот первая версия такой программки (подсмотрено на основных средствах):

Пробуем и смотрим на результат:

Просмотр истории изменений

В целом, годная программа… Да вот как-то некрасиво показывается номер объекта, хочется перенести его из второй колонки в первую и обработать.

Сложилось ощущение, что в глубинах дёргаемых ФМ есть специальная обработка для некоторых объектов, в том числе и ANLA.

А вот как это действительно красиво подать?  Уж сильно не хочется делать параллельную реализацию со всеми красотульками…

Реализация API для красотулек

В нашей программе есть два основных недостатка:

  • Нет текста в первой колонке, который бы описывал объект
  • Некрасивый ключ во второй колонке

Есть несколько настроечных таблиц, в которых мы можем сделать тюнинг:

  • TBANK_CD_FCTM
  • TBANK_CD_FCOM

Технология условно примитивная: по определённому интерфейсу реализуете ФМ и прописываете его в эти таблицы. В нужный момент произойдёт CALL FUNCTION этих модулей. Образцы интерфейсов можно подсмотреть на тех же основных средствах (ANLA).

И после этого действа всё выглядит поглаже:

Просмотр истории изменения 2

Включение программы в основную транзакцию

Рисуем кнопку на экране (а можно и в меню):

Кнопка истории на экране

Обрабатываем нажатие:

case sy-ucomm.
when ‘ZCD’.
submit ZPM_EQT_POST_CD
with p_eqopr = zpm_oper_scr-eqopr
and return.
endcase.

Вот и всё.

Остаётся только протестировать работу кнопки и допилить напильником получившийся общий результат.

PS.

Не стоит забывать, что есть ешё транзакция SCU3. Но она ориентирована скорее на администраторов, чем на бизнес-пользователей. Базис может принять решение активировать или деактивировать эту штуку, не пососветовавшись со всем бизнесом. У них будут свои причины, например для продуктивной системы это может быть слишком большой нагрузкой.
С другой стороны в бизнес-транзакциях эти данные совершенно недоступны для просмотра, значит для бизнес-пользователей они не имеют значения.

2 комментария

  1. Здравствуйте! Это только для типа изменения update или возможно следить за типом изменения insert, delete?

  2. Как вы могли догадаться — всё приходится делать самому, то есть системный перехват команд UPDATE/DELETE/INSERT не производится.
    Если вы сгенерируете функциональный модуль и посмотрите на его интерфейс, то увидите там параметр OBJECT_CHANGE_INDICATOR, который можно установить в одно из значений (U, I, E, D).
    U — UPDATE (значение по умолчанию)
    I — вставка
    E, D — удаление поля или записи

Добавить комментарий

Ваш адрес email не будет опубликован.