КОНТРОЛЬ КАЧЕСТВАP0L4

Финансовые сверки и доказательство корректности данных

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

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

Три разных вопроса о достоверности#

Когда итоговые суммы источника и EDWH совпали, проверка ещё не завершена. Нужно разделять:

  1. Полноту: всё ли, что должно было прийти, действительно загружено?
  2. Точность: совпадают ли значения и атрибуты каждой сопоставленной записи?
  3. Согласованность: не нарушены ли финансовые ограничения и связи между сущностями?

Эти свойства логически независимы. Можно получить правильный общий итог при двух компенсирующих ошибках либо загрузить все записи с неверными атрибутами.

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

Уровни сверки#

Уровень Проверка Что выявляет
L1 - транспортный Число сообщений, контрольные суммы файлов, batch ID Пропуск при доставке
L2 - ключи Множества уникальных ID источника и приёмника Отсутствующие и лишние записи
L3 - содержимое Хеши канонизированных полезных нагрузок по ID Неверные атрибуты
L4 - финансы Баланс строк по документу/валюте, обороты, остатки Нарушение предметных инвариантов
L5 - история Срезы по времени известности и учётному времени Некорректные задние исправления

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

Почему общий ноль недостаточен#

Пусть в источнике два документа: +100 и −100. Оба исчезли на этапе загрузки. Сумма источника равна нулю, сумма приёмника тоже ноль, но загрузка неполная.

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

source_ids = {id | id должен войти в этот срез}
target_ids = {id | id действительно представлен}

missing = source_ids - target_ids
extra   = target_ids - source_ids

Следом сравниваем канонические содержимое и версии по каждому id.

Финансовые инварианты#

В первой версии стенда включены:

  • Для каждого загруженного события ровно две строки журнала: одна дебетовая, одна кредитовая (частное правило учебного стенда).
  • Обе строки относятся к одной валюте и равной денежной величине.
  • Подписанная сумма по событию равна нулю.
  • Повторный импорт идентичного пакета не увеличивает число событий или строк.
  • Событие с тем же ID, но иной полезной нагрузкой отклоняется, а не молча перезаписывается.
  • Срез на историческую дату отличается от пересчитанного после поздней коррекции.

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

Расследование расхождений#

Корректный результат проверки - не просто PASS/FAIL. Полезно сохранять: ID контрольного набора, входной batch, бизнес-срез, системный срез, правило, число нарушений, идентификаторы проблемных записей и версию кода преобразований.

Для массовых загрузок стоит разделять ошибки источника и ошибки обработки. Если входной документ уже несбалансирован, задача EDWH - явно обнаружить и корректно зарегистрировать проблему, а не создать баланс путём скрытого исправления.

Практика#

Financial EDWH Lab содержит небольшой исполняемый пример. Тесты проверяют повторные загрузки, конфликты ID, баланс, полноту и позднюю финансовую корректировку. Исходники и тесты доступны архивом.

Источники и документация

  1. SAP S/4HANA - Journal Entry ↗
  2. PostgreSQL - Numeric Types ↗
  3. Python - decimal ↗

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