Главное различие: событие, документ, проводка#
Экономическое событие - факт хозяйственной деятельности (например, поступление оплаты). Документ фиксирует событие в операционной или учётной системе. Проводка отражает его на бухгалтерских счетах по правилам соответствующего учётного контура.
Это не обязательно взаимно-однозначное соответствие: один документ может породить несколько проводок, а запись может быть сформирована пакетным процессом. Поэтому ключ операционной транзакции, номер документа и идентификатор строки проводки нельзя безусловно считать одним идентификатором.
В EDWH полезно хранить прослеживаемость:
source_system → source_event_id → document_id → journal_entry_id → journal_line_id
Связь зависит от исходной системы; отсутствующие идентификаторы следует фиксировать явно, а не синтезировать как будто они существовали в источнике.
Двойная запись как инвариант#
При определённой модели учёта и в пределах одной сбалансированной бухгалтерской записи:
Σ дебетовых сумм = Σ кредитовых сумм.
При машинном представлении можно выбрать соглашение: дебет положителен, кредит отрицателен. Тогда контроль по каждому документу и валюте:
sum(signed_amount_minor) = 0
Критически важно: равенство нужно проверять на корректном уровне детализации - обычно в рамках учётного документа / набора проводок, соответствующего валютного измерения и бухгалтерского контура. Общая нулевая сумма по всей базе может скрыть две компенсирующие ошибки.
Контракт минимального факта проводки#
| Поле | Смысл | Инвариант |
|---|---|---|
journal_line_id |
Уникальная строка проводки | Нет логических дублей |
document_id |
Бухгалтерский документ | Трассируемость к источнику |
account_code |
Код счета | Допустим в справочнике счетов |
side |
debit / credit |
Конечное множество значений |
amount_minor |
Сумма в минимальных единицах валюты | Целое неотрицательное значение |
currency |
Код валюты | Заполнен и согласован с суммой |
business_date |
Учётная дата | Отдельна от времени загрузки |
observed_at |
Когда изменение стало известно EDWH | Нужна для ретроспективных срезов |
В реальной финансовой системе могут понадобиться юридическое лицо, книга учёта, вид документа, аналитики, сумма в функциональной валюте и другие поля.
Валюты и точность#
Суммы в разных валютах нельзя складывать без установленной процедуры конвертации. В учебном стенде используется RUB и хранение целых копеек. Такой способ обеспечивает точность суммирования в выбранном диапазоне и при одной фиксированной размерности.
При промышленной реализации в PostgreSQL часто используют numeric(p,s) с явно определённой точностью, валютой, масштабом и правилами округления. Для Python следует предпочитать Decimal, а не двоичный float, когда нужны строгие десятичные расчёты.
Типичные архитектурные ошибки#
- Считать операционную транзакцию и бухгалтерскую проводку одним и тем же фактом.
- Агрегировать суммы без валюты, учётного контура и периода.
- Затирать старую проводку, когда пришла корректировка, без сохранения истории.
- Объявлять корректность доказанной только из-за нулевого общего баланса.
- Смешивать дату события, дату проводки, дату поступления в DWH и дату загрузки.
Следующий шаг - обороты и остатки и модель финансовых данных.