feat(payments): send no fiscal receipt; keep the code switchable
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 21s
CI / ui (pull_request) Successful in 1m28s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m45s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 21s
CI / ui (pull_request) Successful in 1m28s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m45s
The merchant accepts payments as a sole proprietor on НПД, which is outside 54-ФЗ: there is no online cash register, YooKassa does not serve receipts for that regime at all (checked with their support), and each operation is reported by the merchant to «Мой налог», which issues the чек. So no `receipt` is sent with a payment or a refund. This also removes a failure class rather than just code: a malformed receipt was an API error at payment creation, which broke the purchase outright. The fiscal code is kept dormant rather than deleted. All of it now sits behind one switch, `BACKEND_YOOKASSA_VAT_CODE`: unset — the default — builds and sends nothing; a 54-ФЗ rate code turns «Чеки от ЮKassa» back on unchanged. The return is foreseeable, which is why the switch exists: НПД carries an annual income ceiling, and losing the regime puts 54-ФЗ back in force, at which point this is a deploy-variable edit instead of writing the integration again. The D36 email anchor still gates a direct purchase. It had two justifications — a recovery anchor and the receipt address — and only the second is gone; without an email a paying customer who loses the account loses the chips with it. What was missing is that the rule was enforced but never communicated: the wallet showed the packs to a player signed in through VK or Telegram in a browser, and tapping Buy produced a bare "something went wrong". It now says "add an email in your profile" in the buy tab instead, linking to the profile; spending already-earned chips is untouched. The predicate is a pure function so it is covered by the node-env unit tests rather than needing a browser. Tests: the receipt-off default is pinned by an integration test asserting a purchase carries no receipt, and the dormant path by one that switches a VAT code on and checks the receipt reappears with the right fiscal attributes; plus unit coverage for the enable predicate and the wallet's email rule. A note for whoever runs the numbers next: the shared (svelte + i18n) chunk is now 40 bytes under its 31 KB gzip budget. Decision D51 revised.
This commit is contained in:
@@ -323,16 +323,20 @@ web+PWA / native Android+iOS через Capacitor). Владелец (самоз
|
||||
**Частичный возврат не записываем вовсе** — движок по устройству работает только с полной суммой
|
||||
заказа, а непроизвольного способа решить, скольких Фишек стоит часть возврата, нет; вместо записи —
|
||||
громкий лог для оператора.
|
||||
- **D51. Фискализация — «Чеки от ЮKassa», чек отправляем из кода.** Ревизия D41: у ЮKassa нет
|
||||
кабинетного «обобщённого чека», как у Robokassa, — чек регистрируется **только если запрос его
|
||||
несёт**, поэтому itemized-код, от которого отказались в D41, возвращается в объём. Каждый платёж и
|
||||
возврат шлют `receipt`: одна позиция (название пакета, количество 1, сумма), код ставки НДС
|
||||
(тег 1199), признак предмета расчёта `service` (тег 1212), признак способа расчёта `full_payment`
|
||||
(тег 1214); доставка только на email — на подтверждённый якорь D36. Код ставки НДС — **переменная
|
||||
деплоя** (дефолт `1` = «Без НДС» для УСН/ПСН): это единственный реквизит, который реально меняется
|
||||
(с 1 января 2026 ставки выросли, появились коды 11/12), и менять его без релиза нужно; признаки
|
||||
предмета и способа расчёта — константы в коде. `tax_system_code` не шлём: для «Чеков от ЮKassa»
|
||||
провайдер его игнорирует.
|
||||
- **D51 (ревизия). Чеки не передаём: владелец на НПД, это вне 54-ФЗ.** Уточнено у поддержки ЮKassa:
|
||||
при НПД провайдер с чеками не работает. Онлайн-кассы нет, `receipt` в запросах не отправляется, о
|
||||
каждой операции владелец сообщает в **«Мой налог»**, он и формирует чек. Побочный выигрыш: исчезает
|
||||
целый класс отказов — некорректный `receipt` был ошибкой API прямо при создании платежа, то есть
|
||||
ломал покупку.
|
||||
**Код чеков при этом консервируем, а не удаляем** (решение владельца): вся сборка `receipt` живёт за
|
||||
одним переключателем `BACKEND_YOOKASSA_VAT_CODE` — пусто (дефолт) значит «не отправлять», код ставки
|
||||
по 54-ФЗ (тег 1199) возвращает прежнее поведение: одна позиция, признак предмета расчёта `service`
|
||||
(тег 1212), способ расчёта `full_payment` (тег 1214), доставка на email-якорь D36,
|
||||
`tax_system_code` не шлём. Возврат к чекам предсказуем: у НПД годовой потолок дохода 2,4 млн ₽, и
|
||||
его превышение возвращает 54-ФЗ — тогда это правка переменной, а не кода.
|
||||
Связка с «Мой налог» — **отдельная задача**. Всё нужное для неё уже хранится (идентификатор заказа
|
||||
и платежа провайдера, сумма, валюта, время зачисления, снимок пакета, возвраты); не хватает только
|
||||
отметки «операция уже отправлена» для идемпотентности выгрузки — её заводит та задача.
|
||||
|
||||
## Заметки к оформлению документов
|
||||
|
||||
@@ -371,6 +375,11 @@ D47-D51 — консервация Robokassa с откатом по кредам
|
||||
добавлена D52 — обработка `refund.succeeded`, потому что кабинет ЮKassa позволяет вернуть деньги
|
||||
мимо нашего API. Обе правки вошли в тот же PR, что и переход на рельс.
|
||||
|
||||
**Уточнение по фискализации (владелец, 2026-07-28).** D51 ревизована: владелец принимает платежи как
|
||||
ИП на **НПД**, при котором ЮKassa с чеками не работает (подтверждено поддержкой), поэтому `receipt`
|
||||
не передаётся вовсе, а отчётность идёт через «Мой налог». Код чеков законсервирован за переменной
|
||||
`BACKEND_YOOKASSA_VAT_CODE` на случай потери режима. Правка вошла в тот же PR.
|
||||
|
||||
## План внедрения (черновик PLAN.md — «слоями»)
|
||||
|
||||
Владелец выбрал слоёную стратегию: сначала вся механика без реальных денег (обкатка
|
||||
|
||||
Reference in New Issue
Block a user