fix(generative/financial): VAT only on parking, residential ДДУ exempt (ст. 149 НК) #1898

Merged
bot-backend merged 1 commit from fix/vat-residential-exempt into main 2026-06-25 07:22:59 +00:00
Collaborator

Проблема

compute_financial начисляла НДС на всю валовую маржу:

vat = max(0, gross_margin) * 0.20/1.20   # ← таксует и жильё

Для РФ-девелопмента это неверно: реализация жилых помещений + услуги застройщика по ДДУ освобождены от НДС (пп.22 / пп.23.1 п.3 ст. 149 НК РФ). Выходной НДС на жильё = 0. Невозмещаемый входной НДС по СМР (п.2 ст.170) уже встроен в gross-ставки себестоимости (Excel-эталон СМР «с НДС»). Итог: модель завышала налоговую нагрузку и занижала прибыль почти каждого проекта.

Фикс

НДС начисляется только на нежилую часть — паркинг (машиноместа нежилые, реализация облагается):

parking_value_added = revenue_parking - construction_parking
vat = max(0.0, parking_value_added) * _VAT_RATE / (1.0 + _VAT_RATE)

Если паркинг тоже окажется по ДДУ-льготе — оценка консервативна (чуть занижает прибыль), что соответствует honest/conservative-политике модуля.

Эффект (репрезентативный comfort: жильё 10000 м², GFA 11000, паркинг 50)

было стало
vat_rub 8.49М 2.50М
net_profit_rub 31.8М 36.3М

Прирост = освобождённый НДС минус 25% налог на прибыль на возросшую базу.

Корректность

  • Инвариант Σ cashflow == net_profit сохранёнvat по-прежнему прокидывается в _build_monthly_cashflow (прорейтится на признание выручки). Проверено численно (diff 0.0).
  • Residential-only (parking=0) → vat == 0 (тест).
  • Ни один класс паркинга не продаётся ниже себестоимости (econom +450k / comfort +300k / business +100k), max(0, …) guard корректен.
  • Deep-review — налоговый режим независимо подтверждён (output жильё=0 + input в себестоимости реконсилится; паркинг-VATable = осознанный консервативный выбор), edge-cases, инвариант, backend↔UI consistency.

Изменения

  • financial.py — VAT-база + module docstring (ст. 149 трактовка).
  • exporters/pdf.py — label «НДС (паркинг)» + caveat.
  • ConceptVariantsResult.tsx — caveat + label синхронизированы с новой трактовкой.
  • test_financial_dcf.py — +3 теста (residential-only vat==0; parking vat == точная база; инвариант с паркинг-НДС). 44 passed.

Без schema-change (vat_rub уже существует) → codegen не нужен.

Known follow-up (отдельно)

Dev-фикстура frontend/src/lib/mocks/parcel-analyze.json устарела (vat по старой формуле + parking-цена до #1893) — нужен полный регенерейт фикстуры, не патч одного поля. Вынесено в отдельную задачу.

Refs #1881

## Проблема `compute_financial` начисляла НДС на **всю** валовую маржу: ```python vat = max(0, gross_margin) * 0.20/1.20 # ← таксует и жильё ``` Для РФ-девелопмента это неверно: **реализация жилых помещений + услуги застройщика по ДДУ освобождены от НДС** (пп.22 / пп.23.1 п.3 ст. 149 НК РФ). Выходной НДС на жильё = 0. Невозмещаемый входной НДС по СМР (п.2 ст.170) уже встроен в gross-ставки себестоимости (Excel-эталон СМР «с НДС»). Итог: модель завышала налоговую нагрузку и занижала прибыль почти каждого проекта. ## Фикс НДС начисляется только на **нежилую** часть — паркинг (машиноместа нежилые, реализация облагается): ```python parking_value_added = revenue_parking - construction_parking vat = max(0.0, parking_value_added) * _VAT_RATE / (1.0 + _VAT_RATE) ``` Если паркинг тоже окажется по ДДУ-льготе — оценка консервативна (чуть занижает прибыль), что соответствует honest/conservative-политике модуля. ## Эффект (репрезентативный comfort: жильё 10000 м², GFA 11000, паркинг 50) | | было | стало | |---|---|---| | `vat_rub` | 8.49М | 2.50М | | `net_profit_rub` | 31.8М | 36.3М | Прирост = освобождённый НДС минус 25% налог на прибыль на возросшую базу. ## Корректность - **Инвариант `Σ cashflow == net_profit` сохранён** — `vat` по-прежнему прокидывается в `_build_monthly_cashflow` (прорейтится на признание выручки). Проверено численно (diff 0.0). - Residential-only (`parking=0`) → `vat == 0` (тест). - Ни один класс паркинга не продаётся ниже себестоимости (econom +450k / comfort +300k / business +100k), `max(0, …)` guard корректен. - **Deep-review ✅** — налоговый режим независимо подтверждён (output жильё=0 + input в себестоимости реконсилится; паркинг-VATable = осознанный консервативный выбор), edge-cases, инвариант, backend↔UI consistency. ## Изменения - `financial.py` — VAT-база + module docstring (ст. 149 трактовка). - `exporters/pdf.py` — label «НДС (паркинг)» + caveat. - `ConceptVariantsResult.tsx` — caveat + label синхронизированы с новой трактовкой. - `test_financial_dcf.py` — +3 теста (residential-only vat==0; parking vat == точная база; инвариант с паркинг-НДС). 44 passed. **Без schema-change** (`vat_rub` уже существует) → codegen не нужен. ## Known follow-up (отдельно) Dev-фикстура `frontend/src/lib/mocks/parcel-analyze.json` устарела (vat по старой формуле + parking-цена до #1893) — нужен полный регенерейт фикстуры, не патч одного поля. Вынесено в отдельную задачу. Refs #1881
bot-backend added 1 commit 2026-06-25 07:10:35 +00:00
fix(generative/financial): VAT only on parking, residential ДДУ exempt (ст. 149 НК)
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Successful in 59s
CI / openapi-codegen-check (pull_request) Successful in 1m55s
CI / backend-tests (pull_request) Successful in 11m48s
2c9629a64c
compute_financial начисляла НДС на ВСЮ валовую маржу — неверно для РФ жилья:
реализация жилых помещений и услуги застройщика по ДДУ освобождены (пп.22/пп.23.1
п.3 ст. 149 НК РФ), а невозмещаемый входной НДС по СМР уже встроен в gross-ставки
себестоимости. НДС теперь только на нежилой value-added паркинга:
max(0, revenue_parking − construction_parking) × 0.20/1.20.

Инвариант Σ cashflow == net_profit сохранён (vat прокидывается в построитель
cashflow). Обновлены docstring модуля + caveat/label в PDF-экспортёре и
concept-UI (ConceptVariantsResult). Repr. comfort: VAT 8.5М → 2.5М, net 31.8М → 36.3М.

Deep-review  (налоговый режим независимо подтверждён, edge-cases, инвариант).

Refs #1881
bot-backend merged commit 3073651812 into main 2026-06-25 07:22:59 +00:00
bot-backend deleted branch fix/vat-residential-exempt 2026-06-25 07:22:59 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1898
No description provided.