Перейти к содержимому

7. Бухгалтерия

Что это

Модуль бухгалтерии ведёт финансовый учёт по принципу двойной записи: план счетов, проводки, платежи за документы, ПКО, акты услуг.


План счетов

Счёт — это «ячейка» для учёта денег. Все финансовые операции записываются как движения между счетами.

Типы счетов

ТипЧто учитываетПример
АктивЧто у нас есть (имущество, деньги)Касса, Банковский счёт, Склад
ПассивЧто мы должны (обязательства)Задолженность перед поставщиками
ДоходыЧто мы заработалиВыручка от продаж
РасходыЧто мы потратилиЗакупки, зарплата, аренда

Иерархия счетов

План счетов «Бергамот»
├── 10. АКТИВЫ
│ ├── 10.01 Касса (наличные)
│ ├── 10.02 Банковский счёт
│ └── 10.03 Товарные запасы
├── 20. ПАССИВЫ
│ ├── 20.01 Расчёты с поставщиками
│ └── 20.02 Расчёты с сотрудниками
├── 30. ДОХОДЫ
│ ├── 30.01 Выручка от продаж
│ └── 30.02 Прочие доходы
└── 40. РАСХОДЫ
├── 40.01 Себестоимость продаж
├── 40.02 Аренда
├── 40.03 Зарплата
└── 40.04 Списания (порча)

Некоторые счета — системные (неудаляемые). Они создаются автоматически для стандартных операций.


Двойная запись (проводки)

Каждая финансовая операция — это проводка: деньги уходят с одного счёта и приходят на другой. Сумма дебета всегда равна сумме кредита.

ПРОВОДКА = Дебет (куда) + Кредит (откуда) + Сумма
┌─────────────────┐ 5 000 ₽ ┌─────────────────┐
│ │ ◄────────────── │ │
│ Дебет │ │ Кредит │
│ (получает) │ │ (отдаёт) │
│ │ │ │
│ Счёт: Касса │ │ Счёт: Расчёты │
│ 10.01 │ │ с поставщиками │
│ │ │ 20.01 │
└─────────────────┘ └─────────────────┘

Типы проводок

ТипКто создаётКогда
MANUALБухгалтер вручнуюНестандартные операции
AUTOMATICСистемаПри оплате документов, инкассации и т.д.

Примеры проводок

Оплата поставщику:

Дебет: 20.01 Расчёты с поставщиками (+5 000 ₽)
Кредит: 10.02 Банковский счёт (−5 000 ₽)
Комментарий: «Оплата накладной #042 — ООО МясоПром»

Выручка за день:

Дебет: 10.01 Касса (+98 000 ₽)
Кредит: 30.01 Выручка от продаж (−98 000 ₽)
Комментарий: «Выручка за 16.04.2026, смена #001»

Списание испорченного товара:

Дебет: 40.04 Списания (+955 ₽)
Кредит: 10.03 Товарные запасы (−955 ₽)
Комментарий: «Акт списания — просроченная курица и молоко»

Инкассация (изъятие из кассы):

Дебет: 10.02 Банковский счёт (+15 000 ₽)
Кредит: 10.01 Касса (−15 000 ₽)
Комментарий: «Инкассация 16.04.2026»

Платежи

Платёж — оплата за документ (накладную или акт услуг). При создании платежа автоматически создаётся проводка.

Как работает

ДОКУМЕНТ ПЛАТЁЖ ПРОВОДКА
(накладная) (оплата) (двойная запись)
│ │ │
│ 1. Бухгалтер │ │
│ создаёт платёж │ │
│───────────────────────►│ │
│ │ 2. Система │
│ │ автоматически │
│ │ создаёт проводку │
│ │─────────────────────────►│
│ │ │
│ 3. Обновляется │ │
│ статус оплаты │ │
│◄───────────────────────│ │

Статусы оплаты документа

0 ₽ оплачено Частично Полностью
┌──────────────────┐ ┌──────────────────────┐ ┌──────────────────┐
│ НЕ ОПЛАЧЕНА │───►│ ЧАСТИЧНО ОПЛАЧЕНА │───►│ ОПЛАЧЕНА │
│ (UNPAID) │ │ (PARTIALLY_PAID) │ │ (PAID) │
└──────────────────┘ └──────────────────────┘ └──────────────────┘

Пример

Накладная #042: сумма 39 500 ₽
Платёж 1: 20 000 ₽ (16.04) → статус: ЧАСТИЧНО ОПЛАЧЕНА
Платёж 2: 19 500 ₽ (23.04) → статус: ОПЛАЧЕНА
Каждый платёж создаёт проводку:
Дебет: 20.01 Расчёты с поставщиками
Кредит: 10.02 Банковский счёт (или 10.01 Касса)

Отмена платежа

При отмене система создаёт сторнирующую проводку — обратную запись с той же суммой. Это обнуляет эффект исходной проводки.

Исходная проводка: Дебет 20.01 (+20 000) Кредит 10.02 (−20 000)
Сторнирующая: Дебет 10.02 (+20 000) Кредит 20.01 (−20 000)
─────────────────────────────────────────────────────────────────────
Результат: 0 ₽ (как будто платежа не было)

Акты услуг

Документ для учёта услуг (аренда, клининг, бухгалтерское обслуживание) — то, что нельзя оформить накладной.

┌──────────┐ проведение ┌──────────┐
│ ЧЕРНОВИК │─────────────────►│ ПРОВЕДЁН │
│ (DRAFT) │ │ (POSTED) │
└────┬─────┘ └──────────┘
│ отмена
┌──────────┐
│ ОТМЕНЁН │
└──────────┘

Пример

┌─────────────────────────────────────────────────────┐
│ АКТ УСЛУГ #SA-2026-042 │
│ Контрагент: ООО «Клининг-Про» │
│ Юрлицо: ООО «Бергамот» │
│ Дата: 30.04.2026 │
├─────────────────────────────────────────────────────┤
│ Услуга: Уборка помещений (апрель) │
│ Сумма: 45 000 ₽ │
│ Счёт расходов: 40.02 Аренда и услуги │
│ Статус: ПРОВЕДЁН → можно создавать платёж │
└─────────────────────────────────────────────────────┘

ПКО (Приходный кассовый ордер)

Объединяет несколько платежей в один кассовый документ для бумажной отчётности.

┌─────────────────────────────────────────────────────┐
│ ПКО #PKO-2026-016 │
│ Дата: 16.04.2026 │
│ Тип: сводный │
├─────────────────────────────────────────────────────┤
│ Включённые платежи: │
│ ├── Платёж #P-101: 20 000 ₽ (за накладную #042) │
│ ├── Платёж #P-102: 15 000 ₽ (за накладную #038) │
│ └── Платёж #P-103: 10 000 ₽ (за акт услуг #042) │
│ │
│ Итого: 45 000 ₽ │
└─────────────────────────────────────────────────────┘

Типы внесений и изъятий

Для кассовых операций (внесения/изъятия в POS) настраиваются типы с привязкой к бухгалтерским счетам.

Тип: «Инкассация»
├── Основной счёт: 10.01 Касса
├── Корреспондентский счёт: 10.02 Банковский счёт
└── ДДС-счёт: (движение денежных средств)
Тип: «Размен»
├── Основной счёт: 10.01 Касса
├── Корреспондентский счёт: 10.01 Касса (тот же)
└── ДДС-счёт: —

Когда кассир делает изъятие типа «Инкассация» — система знает, какие счета дебетовать/кредитовать.


Внесение и изъятие наличных (DWT-операции)

Назначение

Операция внесения/изъятия (DWT-операция) — это конкретный факт движения наличных по выбранному типу, проведённый кассиром на POS-терминале. Тип определяет «как считать» (счета и аналитика), сама операция — это «когда и сколько» (факт + ссылка на тип). Журнал DWT-операций в офисе используется для бухгалтерского аудита кассы (например, при сверке инкассации) и для контроля лимита наличных расчётов ЦБ.

Источники

DWT-операции в офис попадают только с кассы — ручного создания/редактирования из офиса нет. Источник маркируется в самой операции:

  • POS_MANUAL — кассир выбрал тип на POS и провёл внесение или изъятие. Это основной поток: инкассации, выплаты подотчётникам, размены, выдачи поставщикам.
  • POS_AUTO_DISCREPANCY — операция создаётся кассой автоматически при закрытии смены, если зафиксировано расхождение «Излишек» или «Недостача» сверх порога корпорации. Используются системные DWT-типы (systemKey = CASH_DISCREPANCY_SURPLUS / CASH_DISCREPANCY_SHORTAGE), которые офис заводит сидером и которые нельзя удалить из UI.

Касса публикует факт операции узким CloudEvent core.company.kassa.deposit_withdrawal_operation.performed. Узкое событие нужно, чтобы офис мог селективно реагировать на денежные движения, не разбирая шумный поток документов кассовой смены (X-отчёт, «Внесение/изъятие в журнал», смена кассира и т.п.).

Формирование проводок

Офис получает событие через KassaInboundProcessor и в одной транзакции:

  1. Проверяет идемпотентность по sourceEventId (= id CloudEvent). Повтор доставки → возвращается уже созданная запись, дубль не пишется.
  2. Сверяет cross-tenant: PosTerminal.corporationId должен совпадать с payload.corporationId. Подразделение из payload должно совпадать с posTerminal.subdivisionId.
  3. Загружает DWT-тип, корпорацию, подразделение, счета (chefAccount, correspondentAccount). chefAccount берётся из типа; если он null — fallback на Corporation.defaultPaymentDebitAccountId («Касса/банк по умолчанию»).
  4. Считает учётную дату через calculateAccountingDate(occurredAt, corporation.accountingDayStartTime, corporation.timezone).
  5. Создаёт двойную проводку + аналитику.
  6. Создаёт DepositWithdrawalOperation со ссылкой на проводку.
  7. Пишет журнал DepositWithdrawalOperationAuditLog с действием PERFORMED и снимком payload-а.

Направление проводки:

DEPOSIT (внесение, деньги приходят в кассу):
Дт: chefAccount (например, 50.01 Касса)
Кт: correspondentAccount (например, 71.01 Подотчётный сотрудник)
WITHDRAWAL (изъятие, деньги уходят из кассы):
Дт: correspondentAccount (например, 60.01 Поставщик)
Кт: chefAccount (например, 50.01 Касса)

Проводка маркируется type = AUTOMATIC, sourceEventType = "DWT_OPERATION_PERFORMED", sourceTerminalId = payload.posTerminalId. Документу присваивается офисный номер КАС-NNNNNN через DocumentNumberGenerator.

Активация PostingAnalytics.employeeId (Подход 1)

Поле PostingAnalytics.employeeId существовало в схеме раньше, но нигде не заполнялось. DWT-операции — первое место, где оно действительно пишется (Подход 1: использовать поле при первой реальной потребности, без миграции данных назад). Заполняется так:

DWT-операцияanalytics.employeeIdanalytics.counterpartyId
Выплата подотчётнику (counterpartyType = EMPLOYEE)payload.recipientEmployeeIdnull
Расчёт с внешним контрагентом (counterpartyType = COUNTERPARTY)nullpayload.recipientCounterpartyId

subdivisionId, legalEntityId (из Subdivision), ddsAccountId (из DWT-типа) заполняются всегда — это базовая аналитика проводки.

Лимит наличных расчётов ЦБ (R-10)

Указание Банка России от 09.12.2019 № 5348-У ограничивает наличные расчёты между юрлицами 100 000 ₽ по одному договору. В офисе лимит хранится в Corporation.cashSettlementLimit; если поле не задано — используется fallback DEFAULT_CASH_SETTLEMENT_LIMIT_RUB = 100 000 ₽.

При проведении WITHDRAWAL с counterpartyType = COUNTERPARTY handler сравнивает amount с лимитом. Если amount > limit — в журнал аудита пишется changes.cashLimitExceeded = true и в лог приложения уходит warning. Операция всё равно проводится: это не ошибка, а предупреждение для дальнейшего анализа аудитором — кассир мог сознательно превысить лимит (например, по нескольким договорам).

Лимит не проверяется для выплат сотрудникам (EMPLOYEE) и для внесений (DEPOSIT) — это требование ЦБ касается только расчётов между юрлицами.

Системные типы излишек/недостача

Сидер 004-system-deposit-withdrawal-types.seeder.ts создаёт в каждой корпорации два системных DWT-типа с isSystem = true:

  • CASH_DISCREPANCY_SURPLUSDEPOSIT, контрагент-юрлицо корпорации. Применяется кассой при закрытии смены, если фактическая выручка больше плановой выше порога Corporation.cashShiftDiscrepancyThreshold.
  • CASH_DISCREPANCY_SHORTAGEWITHDRAWAL, контрагент-юрлицо корпорации. Применяется при недоборе кассы.

Системные типы нельзя удалить или переименовать через UI: касса находит их в локальной реплике по systemKey, и сломанная привязка остановит авто-проводку. Поле systemDescription объясняет назначение типа администратору. Идемпотентность сидера — partial unique index (corporation_id, system_key) WHERE system_key IS NOT NULL.

Что вне scope

  • Сторно и ручное редактирование DWT-операций из офиса — backlog (R-15). Сейчас единственный способ «отменить» операцию — провести обратную (например, на тот же тип в обратную сторону).
  • PIN-авторизация: проверка прав менеджера живёт на кассе. Офис принимает authorizedById как факт и не пересчитывает.
  • UI журнала операций в офисном фронте — отдельная задача.

Категории учёта

Группировка номенклатуры для бухгалтерских целей. Каждая категория привязана к счетам доходов/расходов.

Категория: «Основное меню»
├── Счёт доходов: 30.01 Выручка от продаж
└── Счёт расходов: 40.01 Себестоимость продаж
Категория: «Алкоголь»
├── Счёт доходов: 30.01 Выручка от продаж
└── Счёт расходов: 40.01 Себестоимость продаж (алкоголь)
Привязка: Стейк Рибай → «Основное меню»
Вино Кьянти → «Алкоголь»

Связь бухгалтерии с другими модулями

┌──────────┐ ┌──────────────┐
│ СКЛАД │ ─накладная─► │ │
│ │ │ │
│ │ ─списание──► │ БУХГАЛТЕРИЯ │ ──► проводки
│ │ │ │
│ │ ─инвентар.─► │ │
└──────────┘ │ │
│ │
┌──────────┐ │ │
│ POS │ ─выручка───► │ │
│ │ │ │
│ │ ─инкассац.─► │ │
└──────────┘ │ │
│ │
┌──────────┐ │ │
│ ЗАКУПКИ │ ─методы────► │ │
│ │ оплаты │ │
└──────────┘ └──────────────┘

Бизнес-правила

ПравилоОписание
Дебет ≠ КредитОдин и тот же счёт не может быть и дебетом, и кредитом
Сумма > 0Отрицательные проводки запрещены
Точность 2 знакаВсе суммы с точностью до копеек
Блокировка периодовНельзя создать проводку в заблокированном периоде
Системные счетаНельзя удалить системные счета
СторнированиеОтмена платежа создаёт обратную проводку, а не удаляет исходную
ПереплатаСистема не позволит оплатить больше, чем сумма документа

Задолженность по документам

Система отслеживает остаток к оплате по каждому документу (накладной, акту услуг).

Формула:
Остаток к оплате = Сумма документа − Оплаченная сумма
Пример:
Накладная #042: сумма 39 500 ₽
Платёж 1: 20 000 ₽
→ Остаток: 39 500 − 20 000 = 19 500 ₽
→ Статус: ЧАСТИЧНО ОПЛАЧЕНА
Платёж 2: 19 500 ₽
→ Остаток: 39 500 − 39 500 = 0 ₽
→ Статус: ОПЛАЧЕНА

Статусы оплаты

┌──────────────────┬─────────────────┬───────────────────────────┐
│ Оплачено │ Статус │ Когда │
├──────────────────┼─────────────────┼───────────────────────────┤
│ 0 ₽ │ НЕ ОПЛАЧЕНА │ Нет ни одного платежа │
│ 1 ₽ – 39 499 ₽ │ ЧАСТИЧНО ОПЛАЧ. │ Есть платежи, но не всё │
│ 39 500 ₽ │ ОПЛАЧЕНА │ Сумма платежей = сумме │
└──────────────────┴─────────────────┴───────────────────────────┘

Система не позволит создать платёж на сумму больше остатка.