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 и в одной транзакции:
- Проверяет идемпотентность по
sourceEventId(= idCloudEvent). Повтор доставки → возвращается уже созданная запись, дубль не пишется. - Сверяет cross-tenant:
PosTerminal.corporationIdдолжен совпадать сpayload.corporationId. Подразделение из payload должно совпадать сposTerminal.subdivisionId. - Загружает DWT-тип, корпорацию, подразделение, счета (
chefAccount,correspondentAccount).chefAccountберётся из типа; если онnull— fallback наCorporation.defaultPaymentDebitAccountId(«Касса/банк по умолчанию»). - Считает учётную дату через
calculateAccountingDate(occurredAt, corporation.accountingDayStartTime, corporation.timezone). - Создаёт двойную проводку + аналитику.
- Создаёт
DepositWithdrawalOperationсо ссылкой на проводку. - Пишет журнал
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.employeeId | analytics.counterpartyId |
|---|---|---|
Выплата подотчётнику (counterpartyType = EMPLOYEE) | payload.recipientEmployeeId | null |
Расчёт с внешним контрагентом (counterpartyType = COUNTERPARTY) | null | payload.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_SURPLUS—DEPOSIT, контрагент-юрлицо корпорации. Применяется кассой при закрытии смены, если фактическая выручка больше плановой выше порогаCorporation.cashShiftDiscrepancyThreshold.CASH_DISCREPANCY_SHORTAGE—WITHDRAWAL, контрагент-юрлицо корпорации. Применяется при недоборе кассы.
Системные типы нельзя удалить или переименовать через 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 ₽ │ ОПЛАЧЕНА │ Сумма платежей = сумме │└──────────────────┴─────────────────┴───────────────────────────┘Система не позволит создать платёж на сумму больше остатка.