Справочник, версионность и update

В статье показан пример, раскрывающий некоторые тонкости, полезные при проектировании справочников.

Амбула

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

Явление бухгалтера первое.

К вам приходит бухгалтер и говорит, что сотрудница Иванова поменяла фамилию на Петрова. Вы заходите в справочник и меняете фамилию сотрудницы.

Явление бухгалтера второе.

Приходит бухгалтер и говорит, что в отчете за прошлый квартал Петрова отображается неправильно, поскольку тогда она была еще Иванова.

Осознание.

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

Явление бухгалтера третье.

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

Явление бухгалтера четвертое.

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

Просветление.

Тут приходит понимание, что в справочнике нужно сделать кнопку "Сохранить" немного сложнее. При нажатии кнопки необходимо спросить у пользователя, что, собственно, он хочет сделать, исправить ошибку или актуализировать значение?

  • Исправить ошибку
    В этом случае версия записи порождаться не будет, но исправление должно быть сделано в актуальной и исторических версиях.
  • Актуализировать значение
    В этом случае нужно потребовать дату ввода в учет нового значения. Будет порождена новая версия записи.

Прочие подсказки

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

Следует понимать, что учетное версионирование не заменяет механизм логирования действий пользователей.

Версионность можно организовать, добавив в таблицу насколько технических полей:

  • id
    Идентификатор строки. Обязательное.
  • actual_id
    Идентификатор последней (актуальной) версии. Обязательное. Для актуальной версии id = actual_id.
  • actual_from
    Дата старта срока актуальности. Обязательное. Значение для первой версии = 2001.01.01.
  • actual_to
    Дата, до которой версия была актуальна. Обязательное. Значение для последней (актуальной) версии = 3001.01.01

Кортежи actual_id + actual_from должны быть уникальными.

Если в отчетах нужно вывести актуальные значения, то JOIN делается к id, если нужно вывести исторические значения, то JOIN делается к actual_id с добавлением условия на срок актуальности. Примерно так …

fact JOIN staff ON fact.staff_id = staff.actual_id and fact.datetime >= staff.actual_from and fact.datetime < staff.actual_to
Начать дискуссию