Плейбук: управленческий расчёт и бухгалтерский контроль УСН 6% по магазинам
Актуализировано: 16.08.2026.
Важно: реализованный в системе режим
buyer_cash— управленческий резерв владельца, а не автоматически готовая налоговая база для декларации. По позиции ФНС компенсация собственной скидки маркетплейса может образовывать отдельный доход на дату её получения. Финальный состав доходов, даты признания и сумму к уплате подтверждает бухгалтер по отчётам площадок и расчётным документам. Плейбук не заменяет налоговую консультацию.
Три горизонта, одна методика:
| Горизонт | Где живёт | Чем считается | Зачем |
|---|---|---|---|
| День | tax_accrual (period_kind='day') |
scripts/refresh_taxes.py |
оперативный управленческий резерв, виден в прибыли на сайте |
| Закрытая неделя Пн–Вс (только WB) | tax_accrual (period_kind='week') |
scripts/refresh_taxes.py |
закрытый управленческий резерв по отчётности WB |
| Закрытый месяц | отчёт + JSON | scripts/monthly_usn_tax.py |
сверка покупательской части и компенсаций для бухгалтера |
Ежедневный и недельный показатели ведутся одновременно и независимо — см. раздел «Ведение налога в БД». Месячный регламент ниже — канон сбора и сверки данных, но не подмена бухгалтерского определения налоговой базы.
Зафиксированное правило управленческого расчёта
Плейбук применяется для управленческого расчёта УСН «Доходы» по
Siluetta WB (shop_id=3), Siluetta Ozon (shop_id=4) и Tote WB (shop_id=5).
Текущая методика владельца от 27.07.2026 (USN_BASIS=buyer_cash):
- база управленческого резерва магазина — сумма, фактически уплаченная покупателями;
- продажи уменьшаются на покупательскую стоимость возвратов текущего месяца;
- комиссия, логистика, реклама, хранение и прочие удержания площадки базу не уменьшают;
- компенсации скидок и бонусы Ozon не смешиваются с покупательской частью и показываются отдельной контрольной суммой;
- ставка УСН — 6%;
- расчёт по каждому магазину хранится отдельно. Итог нескольких магазинов складывается только тогда, когда они принадлежат одному налогоплательщику.
Это расчётный резерв до уменьшения на страховые взносы. Он не становится
заявляемым налогом только потому, что сохранён в tax_accrual. Официальный авансовый
платёж УСН считается нарастающим итогом за I квартал, полугодие и 9 месяцев; перед
его определением бухгалтер отдельно учитывает компенсации скидок и даты их признания.
⚠ Контрольная разница: что именно площадка компенсирует (проверено 30.07.2026)
Управленческое правило «база = кэш покупателя» подтверждено владельцем 30.07.2026 повторно, уже с цифрами на руках. Что именно стоит за разницей:
- WB.
retail_price— цена продавца,retail_amount— что заплатил покупатель, СПП — скидка за счёт WB. На реальной строке июня:retail_price1970 →retail_amount1527 (СПП 22.5%) →for_pay1219.42, то есть 61.9% от 1970. Доля держится ~62% на всех строках независимо отretail_amount→ WB платит от цены продавца и СПП компенсирует сам. - Ozon. По всем 241 строке отчёта за июнь без исключений выполняется
amount + bonus + bank_coinvestment = seller_price × quantity(строка ELS04-black-S: 2264.76 + 3002.59 + 22.65 = 5290). В транзакциях по тому же постингуaccruals_for_sale= 5290,payout= 2803.70 = 5290 − 47% комиссии → Ozon начисляет продавцу полную цену продавца.
Масштаб разницы за июнь 2026:
| Магазин | Кэш покупателя | Начислено площадкой | Разница |
|---|---|---|---|
| Siluetta WB | 288 976.57 | 376 825.60 | 87 849.03 (СПП) |
| Tote WB | 238 364.29 | 333 567.45 | 95 203.16 (СПП) |
| Siluetta Ozon | 439 866.62 | 1 060 794.00 | 620 927.38 (баллы+банк) |
| Резерв 6% по двум сценариям | 58 032 | 106 331 | +48 299 |
Поэтому tax_accrual всегда хранит обе величины: buyer_net (база
управленческого сценария) и accrued_net / platform_comp_net (контрольная
разница). Переключить сценарий резерва можно без правки кода —
USN_BASIS=accrued_income в .env. Ни один из двух переключателей сам по себе
не определяет законную базу: platform_comp_net построен как разница начислений,
а не как реестр реально признанных компенсаций по датам. Для декларации бухгалтер
сверяет её с отчётами и расчётными документами площадки.
Контрольный ориентир по позиции ФНС:
доход УСН к проверке бухгалтером =
поступления покупателей нетто возвратов
+ компенсации собственных скидок маркетплейса,
признанные доходом на соответствующие даты
Комиссию и услуги маркетплейса при объекте УСН «Доходы» из дохода не вычитать.
Обязательные источники
Wildberries
Источник — закрытый отчёт реализации fin_report_detail.
| Что | Поле |
|---|---|
| Дата включения в месяц | rr_date |
| Тип строки | seller_oper_name |
| Покупательская сумма | retail_amount — «Вайлдберриз реализовал Товар (Пр)» |
| Продажи | seller_oper_name='Продажа' |
| Возвраты | seller_oper_name='Возврат' |
В WB retail_amount у возврата хранится положительным числом. Формула поэтому
обязательно явная:
WB покупательская часть `buyer_cash` =
SUM(retail_amount для Продажа)
− SUM(retail_amount для Возврат)
Не использовать for_pay: это сумма после части удержаний, а не оплата покупателя.
Ozon
Источник точного расчёта покупательской части сценария buyer_cash — закрытый
месячный отчёт о реализации:
POST /v1/finance/realization/posting
{"month": <1..12>, "year": <YYYY>}
| Что | Поле отчёта |
|---|---|
| Покупатели оплатили | delivery_commission.amount |
| Возвраты покупателям | return_commission.amount |
| Количество продаж | delivery_commission.quantity |
| Количество возвратов | return_commission.quantity |
| Цена продавца, только контроль | seller_price_per_instance |
Ozon покупательская часть `buyer_cash` =
SUM(delivery_commission.amount)
− SUM(return_commission.amount)
Для точного расчёта покупательской части нельзя брать:
ozon_posting_items.price;ozon_finance_operations.accruals_for_sale;ozon_finance_operations.amount;- текущую цену карточки;
ozon_buyer_price_daily.
Первые три значения описывают цену продавца, начисления или выплату после удержаний. Ежедневный снимок цены описывает витрину в один момент и не видит персональные скидки, баллы и купоны конкретного заказа.
Ozon формирует месячный отчёт после закрытия месяца, обычно не позднее 5-го числа следующего месяца. До его появления разрешён только отчёт «ПРЕДВАРИТЕЛЬНАЯ ОЦЕНКА»; он не заменяет закрытую сверку.
Доступность реализации
На 16.08.2026 таблица tax_accrual, app/reports/taxes.py,
scripts/refresh_taxes.py и scripts/monthly_usn_tax.py есть в рабочей копии на
Hetzner, но ещё не входят в origin/main и локальную кодовую базу. Ниже описано
фактическое серверное поведение; локально команды запускать только после отдельной
синхронизации налогового кода. Документация синхронизируется сейчас, код — нет.
Ведение налога в БД (tax_accrual)
Движок — app/reports/taxes.py, запуск — scripts/refresh_taxes.py. Одна строка
= один магазин × один период. UNIQUE (shop_id, period_kind, period_start,
period_end): пересчёт идёт upsert'ом, повторный прогон строк не плодит.
.venv/bin/python scripts/refresh_taxes.py # 35 дней + 8 недель
.venv/bin/python scripts/refresh_taxes.py --days 90 --weeks 13 # бэкфилл
.venv/bin/python scripts/refresh_taxes.py --show 14 # что лежит в БД
Локальный пересчёт не ходит в API — гонять можно сколько угодно. Единственный
шаг с обращением к Ozon Seller API — --ozon-month YYYY-MM.
Два показателя
День (period_kind='day', WB + Ozon) — оперативный, пересчитывается каждым
прогоном. is_closed=1 у WB-дня значит, что финреп его уже покрыл; до полудня
вчерашний день висит незакрытым, это норма (WB отдаёт дневную реализацию к
12:00 МСК, см. таймер mp-finreport@).
Закрытая неделя (period_kind='week', только WB) — по отчётности WB.
Строка пишется только если финреп покрывает воскресенье недели; неполную
неделю в недельный показатель не пускаем вообще (не «половина недели», а пропуск).
Контроль сходимости: сумма дневных строк недели = недельная строка, до копейки.
Закрытый месяц Ozon (period_kind='month') — точный отчёт о реализации.
Нужен не только бухгалтеру: из него берётся доля кэша покупателя в начислении,
которой оцениваются дневные Ozon-строки. Запускать раз в месяц, после 5-го числа:
.venv/bin/python scripts/refresh_taxes.py --ozon-month 2026-06
Почему Ozon по дням — оценка, а не факт
Покупательскую часть Ozon отдаёт только в месячном отчёте о реализации. В
дневных транзакциях (ozon_finance_operations) есть лишь accruals_for_sale =
цена продавца. Поэтому дневная строка Ozon считается как
начисление × доля кэша из последнего закрытого месяца, is_closed всегда 0,
а способ расчёта пишется в note. Точность на июне 2026: оценка 442 188.72 против
факта 439 866.62 — +0.53% (расхождение из-за того, что operation_date
относит часть операций к другому месяцу, чем отчёт о реализации). Пока закрытого
месяца нет, работает константа OZON_CASH_RATIO_FALLBACK.
Возвраты учитываются: у возвратных операций
(ClientReturnAgentOperation, OperationAgentStornoDeliveredToCustomer)
accruals_for_sale отрицательный и суммируется как есть.
Автообновление
scripts/run_collect.py гоняет шаг taxes последним в каждом сборе (ночной
WB, ночной Ozon и полуденный --only-finreport). Шаг локальный и идемпотентный,
~4 с. Отдельного таймера намеренно нет: налог обязан пересчитаться сразу после
полуденного finreport, иначе вчерашний WB-день останется недосчитанным.
Управленческий резерв в прибыли на wb-ozon-ai.ru
С 30.07.2026 на сервере метрика tax есть в app/reports/aggregate.py
(METRIC_FIELDS), и profit считается после выбранного налогового резерва —
одинаково в вебе и в Telegram-кэше. Это управленческая прибыль, а не подтверждение
суммы налога в декларации.
Где видно:
/— KPI-карточка «Налог УСН», колонка «Налог ₽» в таблице по магазинам, своя статья в «Структуре расходов», упоминание в AI-сводке;/finance— KPI-карточка + колонка «Налог ₽» на уровне магазина и SKU;- Telegram: колонка «Налог» во второй таблице отчёта «Прибыль» и в rich-своде.
Разноска по SKU. Налог пропорционален покупательской базе, поэтому по SKU
разносится множителем tax_factor():
- WB —
revenueв отчёте это ужеretail_amountнетто, то есть сама покупательская часть сценарияbuyer_cash→ множитель прямой; - Ozon —
revenueэто начисление (цена продавца) и оно брутто возвратов (возвраты режут толькоorders). Поэтому база управленческого резерва считается отдельным накопителем поaccruals_for_saleнетто возвратов и домножается на долю кэша. Не менятьrevenueпод налог: сдвинутся выручка и ДРР на всех страницах.
Контроль: сумма tax по SKU за окно = сумма tax_accrued дневных строк
tax_accrual за то же окно (сверено до копейки на окнах 1/7/30 дн по трём
магазинам). Расхождение = разъехались методики, надо смотреть.
В «Структуре расходов» налог обязан быть своей статьёй: остаток «Комиссия и
прочее» считается как выручка − себес − логистика − реклама − налог − прибыль,
и без вычета налога он бы целиком осел в комиссии.
Ежемесячный регламент
Оптимальный день запуска — 5–7 число следующего месяца.
1. Зафиксировать параметры
- закрытый месяц
YYYY-MM; - магазины и принадлежность к ИП/ООО;
- ставка УСН;
- освобождение от НДС или действующая ставка НДС;
- страховые взносы для последующего уменьшения налога.
Если продавец платит НДС и он включён в покупательскую цену:
Управленческая база `buyer_cash` без НДС =
покупательская часть / (1 + ставка НДС / 100)
2. Проверить и при необходимости обновить WB
У WB отчёт должен покрывать последний календарный день месяца. Сначала
проверить MAX(period_end); API без необходимости не вызывать из-за квоты.
SELECT shop_id, MAX(period_end), MAX(fetched_at)
FROM fin_report_detail
WHERE shop_id IN (3, 5)
GROUP BY shop_id;
Если покрытия нет, по одному разу обновить каждый магазин:
.venv/bin/python scripts/ingest_wb.py --shop-id 3 finreport \
--from 2026-07-01 --to 2026-07-31 --period daily
.venv/bin/python scripts/ingest_wb.py --shop-id 5 finreport \
--from 2026-07-01 --to 2026-07-31 --period daily
WB finance API имеет жёсткую квоту. Не повторять запрос, если нужный закрытый
отчёт уже есть в корневом mp.db.
3. Запустить закрытый управленческий расчёт
При освобождении от НДС:
.venv/bin/python scripts/monthly_usn_tax.py \
--month 2026-07 --usn-rate 6 --vat-rate 0
Если в цене есть НДС 5%:
.venv/bin/python scripts/monthly_usn_tax.py \
--month 2026-07 --usn-rate 6 --vat-rate 5
Сохранить машиночитаемый контрольный отчёт:
.venv/bin/python scripts/monthly_usn_tax.py \
--month 2026-07 --usn-rate 6 --vat-rate 0 \
--json-out data/exports/taxes/2026-07-usn.json
По одному налогоплательщику или магазину:
# Только Siluetta: WB + Ozon
.venv/bin/python scripts/monthly_usn_tax.py \
--month 2026-07 --wb-shop 3 --ozon-shop 4
# Только Tote WB
.venv/bin/python scripts/monthly_usn_tax.py \
--month 2026-07 --wb-shop 5 --no-ozon
Скрипт намеренно отклоняет текущий незакрытый месяц и Ozon-отчёт с неверными границами периода.
4. Проверить результат
Для каждого магазина должны быть видны:
- продажи и возвраты в штуках;
- сколько заплатили покупатели;
- покупательская сумма возвратов;
- чистая покупательская база сценария
buyer_cash; - резерв УСН 6% по выбранному сценарию;
- источник и закрытая граница периода.
Для Ozon дополнительно выводятся:
- цена продавца net;
- разница между ценой продавца и покупательской частью.
Эта разница — контроль, защищающий от повторения ошибки, когда за покупательскую
цену принимается seller_price_per_instance или accruals_for_sale. Одновременно
это сигнал бухгалтеру проверить компенсацию скидки; автоматически прибавлять всю
разницу к базе нельзя без сверки её природы и даты признания.
5. Сохранить и передать бухгалтеру
Хранить один JSON на месяц:
data/exports/taxes/YYYY-MM-usn.json
Передавать бухгалтеру:
- расчёт по каждому магазину;
- объединение по конкретному ИП/ООО;
- отдельные
buyer_net,accrued_netиplatform_comp_net, а также документы площадки для сверки фактически признанных компенсаций; - ставку и статус НДС;
- страховые взносы, которыми уменьшается начисленный УСН.
Контрольные формулы
Покупательская часть = продажи покупателям − возвраты покупателям
Управленческая база buyer_cash без НДС =
покупательская часть / (1 + НДС / 100)
Управленческий резерв buyer_cash =
управленческая база buyer_cash без НДС × 6%
Контроль дохода для бухгалтера =
покупательская часть
+ подтверждённые компенсации собственных скидок маркетплейса
Денежные суммы внутри расчёта хранятся с копейками. Итог управленческого резерва округляется до полного рубля только после суммирования магазинов одного налогоплательщика. Итог к уплате рассчитывает бухгалтер нарастающим итогом.
Юридическая контрольная точка
По письму ФНС от 08.05.2024 № СД-4-3/5416@ вся сумма поступлений покупателя учитывается в доходах, а комиссия маркетплейса не уменьшает доход при объекте УСН «Доходы». В разъяснении ФНС от 01.12.2025 отдельно указано: компенсация собственной скидки маркетплейса включается в доход на дату её получения, а возврат уменьшает доход в периоде возврата.
Следствие для этой системы: buyer_cash допустим как прозрачный нижний
управленческий сценарий, но не как готовая цифра декларации. Перед подачей
отчётности бухгалтер обязан определить, какая часть platform_comp_net
действительно является компенсацией, и разнести её по датам. Сценарий
accrued_income тоже не объявляется автоматически законным: начисление цены
продавца и признанный налоговый доход могут расходиться по составу и моменту.
Официальные ориентиры:
- письмо ФНС от 08.05.2024 № СД-4-3/5416@: https://www.nalog.gov.ru/rn77/taxation/taxes/usn/14923199/;
- разъяснение ФНС по скидкам маркетплейса и возвратам: https://www.nalog.gov.ru/rn31/news/seminar/16585481/.
Чек-лист ежедневного/недельного ведения
- [ ] Шаг
taxesпрошёл в последнем сборе (виден в Telegram-алертеrun_collect). - [ ] У вчерашнего WB-дня
is_closed=1(если нет — финреп ещё не пришёл, ждать полдня). - [ ] Сумма дневных строк недели = недельная строка.
- [ ] Сумма
taxпо SKU на/finance= суммаtax_accruedза то же окно. - [ ] Доля кэша Ozon взята из закрытого месяца, а не из фолбэк-константы
(
--showпечатает источник). - [ ] После 5-го числа прогнан
--ozon-monthза прошлый месяц.
Чек-лист закрытия месяца
- [ ] Месяц полностью закрыт.
- [ ] WB
period_endпокрывает последний день месяца. - [ ] Ozon вернул месячный отчёт с точными
start_dateиstop_date. - [ ] Покупательская часть рассчитана отдельно от цены продавца.
- [ ] Возвраты вычтены.
- [ ] Статус НДС подтверждён.
- [ ] Магазины сгруппированы по правильному ИП/ООО.
- [ ] Компенсации/разница площадок показаны бухгалтеру отдельно и сверены по датам.
- [ ]
buyer_cashне выдан за финальную базу декларации без решения бухгалтера. - [ ] Страховые взносы применены только после расчёта начисленного УСН.
- [ ] JSON сохранён в
data/exports/taxes/.