- Динамика НДС (месяц): поверх столбцов «к уплате за месяц»/«накоплено за квартал»
добавлены линии «Начислено» и «Вычет»
- Трекер авансовых УПД: без лимита 15 (все ждущие), настоящая table с фиксированными
колонками (table-fixed, truncate+title), видимы первые ~5 строк, дальше скролл
внутри блока, шапка прилипает (sticky)
- Контроль квартала: главная таблица и «Показать все» — то же оформление table + скролл
- Новый GET /api/di2/nds/advance-vat-tracker (nds_advance_vat_tracker): KPI «сколько можем
сбавить НДС» (оценка сверху 22/122) + топ-15 поставщиков без авансовой УПД; карточка
сразу после «Динамики НДС» с обязательными оговорками из спеки
- Новый GET /api/di2/nds/quarter-control: redHanging / redNoAdvance («проверить зачёт») /
totals / byMarker / ?all=1 — по правкам виджета из спеки
- График «Динамика НДС» (месяц): два столбца «К уплате за месяц» и «Накоплено за квартал»,
кварталы выделены фоновыми полосами (ReferenceArea)
- Виджет «Контроль квартала»: легенда с подписями маркеров, итог «N договоров, сумма
авансов X», кнопка «Показать все» (полный список с маркерами), отдельный список
«Оплачено, аванс не висячий», полный год в датах договоров, overflow-x для таблиц
- summary: без фильтров дат период = весь доступный диапазон nds_monthly (с 2025-01)
- «К уплате» теперь всегда квартальный: квартал выбранного периода, если он внутри одного
квартала, иначе квартал последнего месяца в данных (НДС не копится между кварталами)
- карточки KPI: «Начислено»/«Вычет» за период с подписью, «К уплате» с меткой квартала
Шаг 2.1 плана production-готовности:
- единый 401 при любом отказе логина + constant-time bcrypt
- forgot-password: идентичный ответ независимо от существования email
- sanitizeReturnTo (open redirect fix в /api/documents/generate-link)
- 10 неудачных попыток → блок 15 мин (in-memory, аудит)
- DATABASE_SSL_REJECT_UNAUTHORIZED env (дефолт true)
- доделка 0.7: статичные тексты в llm-providers/rag/finance-di2
- 8 новых тестов (104/104)
Шаг 0.7 плана production-готовности:
- глобальный error handler: нейтральный текст + код инцидента, детали в лог
- route-уровень: зачистка err.message/String(err) в 5xx по 12 файлам,
оригинальные ошибки логируются с контекстом
- server/finance/ (19 файлов) удалён: пул финансовой БД перенесён в server/finance-di2/db-core.ts, db-client.ts теперь реэкспортирует из ./db-core
- Шедулер аудита перенесён в server/finance-di2/audit-scheduler.ts (03:00 МСК, setInterval, без node-cron), запуск из registerDi2Routes с защитой от повторного старта
- История аудита DI2 теперь персистентна: загрузка/запись data/finance-audit-history.json в audit-agent.ts (порт из удалённого server/finance/audit.ts)
- registerFinanceRoutes убран из server/routes/index.ts, registerDi2Routes остался на его месте
- Клиент: удалены pages/finance/, components/finance/, hooks/useFinance.ts, hooks/useColumnLabels.ts, lib/format.ts, pages/salary.tsx; роуты /finance*, /income*, /expenses*, /salary и lazy-импорты убраны из App.tsx
- Навигация: «Финансы» в Sidebar и MobileBottomNav ведёт на субапп /di2 (внешняя ссылка), гейт moduleAccess.finance + finance.view сохранён
- index.css: удалён блок .hover-elevate/.hover-elevate-2/.active-elevate (использовался только старым модульным DataTable)
- FinanceBottomNav.tsx сохранён как референс для этапа 3 (.superpowers/sdd/di2-restyle/FinanceBottomNav.reference.tsx)
- Не тронуто: client-di2/, сиды прав finance.view/manage, finance_access (module-access)
DI2-роутер регистрируется перед основным dashboard.routes.ts и перехватывал
GET /api/dashboard (403 без finance.manage и неверный JSON — live-регрессия
главного дашборда CRM). Роут переименован, в DI2_PREFIXES /api/dashboard
заменён на /api/di2, клиент client-di2 ходит на новый путь (fetch + queryKey
+ prefetch в app-sidebar). Форматы старого модуля финансов не тронуты.
- Копия DI2-сервера в server/finance-di2/ с правками: schema/db-client/cache/table-config/override-tables/google-auth/audit-agent/routes
- db-client — обёртка над существующим пулом server/finance/db-client (второй пул не создаётся, добавлен экспорт isConnectionError)
- ai-config.ts — чистое IO конфигов из ai-agent.ts без Telegram-поллинга; роуты /api/ai/toggle и /api/ai/status удалены, без compression/startAuditScheduler/autoStartIfEnabled
- Обёртка registerDi2Routes с auth-gate (authenticateToken + finance.manage), регистрация строго перед registerFinanceRoutes
- Статика /di2 из dist/public-di2 перед веткой vite/static (dev и prod)
- Фикс предсуществующего бага DI2: buildGlobalExclusionConditions без cats в /api/profitability