Files
Ильяс Султанов 66f4e5ef53 DI2: удаление старого модуля финансов — пул БД и аудит перенесены в finance-di2
- 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)
2026-09-06 21:53:47 +03:00

91 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# План: удаление старого модуля финансов + рестайл DI2 под дизайн iistwin
Репозиторий: `C:\1Ai\1iistwin\1Project` (main, автодеплой через push). Субапп DI2 уже в проде на `/di2` (server/finance-di2 + client-di2).
Решения пользователя (зафиксированы): /salary удалить и вести на /di2; рестайл = мост токенов + точечные правки (без замены 45 shadcn-компонентов); мобильная навигация = нижняя панель.
---
## Этап 1 — Удаление старого модуля финансов
### 1.1 Сервер
1. **Перенос пула БД**: содержимое `server/finance/db-client.ts` → новый `server/finance-di2/db-core.ts` (правка внутренних импортов: там только fs/path/pg). Обновить `server/finance-di2/db-client.ts`: реэкспорт из `./db-core` вместо `../finance/db-client`. Удалить папку `server/finance/` целиком (19 файлов).
2. **Шедулер аудита**: создать `server/finance-di2/audit-scheduler.ts` — порт `startAuditScheduler` (cron 03:00 МСК) из удаляемого `server/finance/audit.ts:524`, но вызывающий DI2-функцию `runIntegrityAudit` из `./audit-agent`. Запускать из `registerDi2Routes` (server/finance-di2/index.ts). Реализация — setInterval-проверка времени (как в оригинале) или порт через обычный таймер; node-cron НЕ добавлять.
3. **Персистентность истории аудита**: в `server/finance-di2/audit-agent.ts` добавить загрузку/запись `data/finance-audit-history.json` (порт логики из старого audit.ts): загрузка при старте модуля, append после каждого `runIntegrityAudit`. Сейчас история в памяти и теряется при рестарте.
4. **Регистрация**: `server/routes/index.ts` — убрать `import { registerFinanceRoutes }` (стр. 33) и вызов (стр. 116), оставить `registerDi2Routes`.
5. **Env сервера** (проверка, не код): DI2 Google-флоу использует `GOOGLE_CLIENT_ID`/`GOOGLE_CLIENT_SECRET` — проверить наличие в `.env` сервера; старый `FINANCE_GOOGLE_REDIRECT_URI` больше не нужен.
### 1.2 Клиент (основное приложение)
1. Удалить: `client/src/pages/finance/` (14 файлов), `client/src/components/finance/` (22 файла), `client/src/hooks/useFinance.ts`, `client/src/hooks/useColumnLabels.ts`, `client/src/lib/format.ts`, `client/src/pages/salary.tsx`.
- Перед удалением: `grep -rn "lib/format\|useFinance" client/src --include=*.tsx --include=*.ts` — все внешние импорты должны отсутствовать (по разведке используются только удаляемыми файлами — перепроверить!).
2. `client/src/index.css` — удалить блок `.hover-elevate`/`.hover-elevate-2` (строки ~343-374, использовался только finance DataTable).
3. `client/src/App.tsx`:
- Убрать lazy-импорты finance-страниц (строки 61-72) и роуты `/finance`, `/finance/debt`, `/finance/calculations`, `/finance/audit`, `/income*`, `/expenses*`, `/salary` (строки 117-120, 187-200).
- ROUTE_TITLES: убрать записи этих путей.
4. Навигация:
- `client/src/components/Sidebar.tsx` (строки 1084-1122, 1544, 1641-1645): `FinanceNavItem` и пункт «Финансы» в меню профиля → внешняя ссылка `<a href="/di2" target="_blank" rel="noopener">` (паттерн как в FinanceSidebar.tsx:88-99), гейт `moduleAccess.finance !== false && (isAdmin || hasPermission('finance.view'))` сохранить.
- `client/src/components/MobileBottomNav.tsx` (строки 383-389): пункт «Финансы» → `/di2`.
5. **Не трогать**: сиды прав `finance.view/manage` (`server/storage/roles.storage.ts:300-301` — gate DI2 ломается без них), `finance_access` (shared/schema.ts, module-access, Users.tsx матрица доступа).
### 1.3 Проверка этапа
`npm run check` + `npm run build` чисто; ключевые API DI2 авторизованно 200 (список из этапа 4).
---
## Этап 2 — Мост тем/скинов iistwin в DI2
Ключевая несовместимость: DI2 ждёт голые HSL-тройки (`hsl(var(--x) / <alpha>)`), скины iistwin генерируют полные значения (`hsl(...)`). Решение — перевод DI2 на формат основного клиента + общий generated-skins.css + свой провайдер.
### 2.1 Общий код тем
- Vite-алиас в `vite.config.di2.ts`: `"@skin": path.resolve(import.meta.dirname, "client/src/themes")` (через `../client` → фактически `1Project/client/src/themes`); пути в `client-di2/tsconfig.json`: `"@skin/*": ["../client/src/themes/*"]`.
- Импортируемые модули (чистый TS, без React): `tokens.ts` (`generateSkinCss`, `Skin` типы), `skins/index.ts` (`BUILT_IN_SKINS`, `DEFAULT_SKIN_ID`, `getBuiltInSkinById`), `styles/generated-skins.css` — через CSS-`@import` в index.css (путь `../../client/src/themes/styles/generated-skins.css` первой строкой).
### 2.2 Di2ThemeProvider — `client-di2/src/themes/Di2ThemeProvider.tsx`
Порт логики `client/src/themes/ThemeProvider.tsx` (строки 75-92, 151-209) минус useAuth/useQuery:
- Приоритет скина: `localStorage['skin']` (если id валиден среди BUILT_IN_SKINS + кастомных с сервера) → `GET /api/organization/current-skin` (`{skinId, skin}`) → `'iistwin'`.
- Кастомные скины: список через `GET /api/organization/skins`, токены через `GET /api/organization/skins/:id` (только для не-встроенного текущего).
- Тема: `localStorage['theme']` → `prefers-color-scheme` + слушатель.
- На `<html>`: `data-skin`, `data-theme`, класс `light|dark`; для кастомного скина — `<style id="skin-runtime">` с `generateSkinCss(skin, theme)`.
- Ключи localStorage `'skin'`/`'theme'` — **те же**, что в основном приложении: выбор пользователя синхронизируется между iistwin и /di2 автоматически.
- В `client-di2/src/main.tsx`: `<Router base="/di2"><Di2ThemeProvider><App/></Di2ThemeProvider></Router>`.
### 2.3 Перевод DI2 на полный формат токенов
1. `client-di2/tailwind.config.ts`: все цвета `hsl(var(--x) / <alpha-value>)` → `var(--x)` (как в корневом `tailwind.config.ts`); `borderRadius`: хардкод lg/md/sm → `var(--radius)` + каскад `calc(var(--radius) - 2px)`/`-4px` (скопировать блок из корневого конфига); добавить `warning/success/info` из var(--warning) и т.д. Если DI2 использует alpha-модификаторы семантических цветов (`bg-primary/50`) — заменить на `color-mix(in oklab, var(--primary) 50%, transparent)` (grep при исполнении).
2. `client-di2/src/index.css`:
- Заменить собственные `:root`/`.dark` HSL-тройки (строки 9-169) на fallback-блоки, скопированные из `client/src/index.css:13-80` (iistwin light/dark до гидратации).
- DI2-only переменные — переопределить от семантических токенов через `color-mix`: `--card-border`/`--popover-border` → `var(--border)`; `--primary-border`, `--secondary-border`, `--muted-border`, `--accent-border`, `--destructive-border`, `--sidebar-primary-border`, `--sidebar-accent-border` → `color-mix(in oklab, var(--X) 82%, black)`; `--button-outline` → `color-mix(in oklab, var(--primary) 35%, transparent)`; `--badge-outline` → `color-mix(in oklab, var(--muted-foreground) 35%, transparent)`; `--elevate-1/2` → `rgba(0,0,0,.05/.08)` (в `.dark` — светлые значения). Убрать `--opaque-button-border-intensity` и `hsl(from ...)` relative-color вычисления.
3. `client-di2/index.html`: `lang="ru"`; убрать оба preconnect и мега-link Google Fonts (23 семейства) → оставить только Inter (+DM Mono) как в `client/index.html:23`; viewport — убрать `maximum-scale=1`, добавить `interactive-widget=resizes-content` (паттерн фикса 2026-08-26).
4. Шрифты приходят из скина: `generateSkinCss` эмитит `--font-sans`/`--font-mono` — в index.css DI2 удалить жёсткие `--font-sans: Open Sans`.
### 2.4 Проверка этапа
`npm run check`, `npm run build`; визуально: `/di2` рендерится, светлая/тёмная тема переключается; смена скина в `/settings/appearance` основного приложения меняет вид `/di2` после обновления (проверить `data-skin` на `<html>`).
---
## Этап 3 — Визуальный рестайл (точечный)
1. **Графики recharts**: заменить hex-палитры (77 вхождений: `#2563eb` и т.п. в income/expenses-overview, debt, calculations, planning, dashboard, heatmap, salary) на `var(--chart-1..5)` для палитр и `var(--success)`/`var(--destructive)`/`var(--warning)` для семантики. Recharts принимает CSS-переменные в fill/stroke.
2. **Хардкод Tailwind-цветов** (133 вхождения `text-red-500`, `bg-amber-50`, `text-green-600` и т.п.): заменить на семантические классы (`text-destructive`, `text-success`, `bg-warning/10` + парные `dark:` где отсутствуют). Механическая замена по всем страницам client-di2.
3. **Таблицы по UI Style Guide**: `client-di2/src/components/ui/table.tsx` — шапка `bg-muted/50 text-[12px] font-medium text-muted-foreground`, строки `h-[var(--table-row-height,40px)]`, hover `bg-muted/40`, ячейки `px-3` (как в основном клиенте). Density из Темы 2.0 подхватится автоматически.
4. **Контролы**: скопировать `client/src/components/fields/field-styles.ts` в `client-di2/src/lib/field-styles.ts` (зависит только от `cn`), применить `fieldControlClass` в кастомных компонентах DI2 (column-filter, draggable-column-list, copyable-cell) — density/control-вид скина применится.
5. **app-sidebar**: активный пункт через `sidebar-accent` (уже так), убраить лишние отступы, привести брендинг-блок к нашему виду (оставить «ОмегаПром / Финансы»).
6. **Мобильная нижняя панель** — новый `client-di2/src/components/bottom-nav.tsx` по образцу `client/src/components/finance/FinanceBottomNav.tsx` (удаляемого — скопировать логику до удаления): три кнопки «Обзор» (дашборд), «Разделы» (dropdown: Доходы, Расходы, Дебиторка, Расчёты, Планирование, Зарплата, Аудит, Прибыльность, Тепловая карта), «Настройки»; видна только `<md`, контент получает `pb-20 md:pb-0`, сайдбар на мобильном скрывается (`hidden md:flex` на обёртке + отключить Sheet-триггер). Переходы — wouter Link (base-aware).
7. **Переключатель темы** в хедере DI2 (App.tsx): кнопка Sun/Moon, пишет `localStorage['theme']` и дергает перерендер Di2ThemeProvider (через кастомное событие/контекст — проще: Di2ThemeProvider экспортирует контекст с toggleTheme, как основной ThemeProvider).
8. Хедер/страницы: page-gutter через `var(--page-gutter, 1rem)` где уместно; крупные заголовки страниц — `text-lg font-semibold` (как основной клиент).
---
## Этап 4 — Проверка, деплой, документация
1. `npm run check` (оба tsc) + `npm run build` (main → di2 → server) — чисто.
2. Авторизованный smoke прод-API DI2: `/api/di2/dashboard`, `/api/income/tree-summary`, `/api/debt/analytics`, `/api/connection`, `/api/audit/history` — 200.
3. После деплоя: `/finance`, `/salary`, `/income` → 404/редирект (страниц нет); «Финансы» в Sidebar/MobileBottomNav открывает `/di2`; `/di2` светлая+тёмная, скин организации применяется; мобильная нижняя панель на телефоне.
4. Документация: AGENTS.md — удалить устаревшие разделы старого модуля (мобильная навигация финансов, деревья категорий, баг дебиторки, Google-флоу `/api/finance/google/*`) и дописать раздел про /di2 (мост тем, Di2ThemeProvider, нижняя панель); новая Obsidian-заметка `Features/2026-09-0X — Finance module replaced by Data-Insight2 subapp.md` + ссылка в Agent Guide Index; пометить устаревшей заметку `2026-09-05 — Finance debt calculations audit and Data-Insight2 migration`.
5. **Ручной шаг пользователя** (вне кода): Google Cloud Console — в OAuth-клиент добавить redirect URI `https://iistwin.ru/api/auth/google/callback` (нужен для синхронизации зарплаты из Google Sheets в DI2; старый `/api/finance/google/callback` удаляется вместе с модулем).
## Риски и ограничения
- Удаление `lib/format.ts`/`useFinance.ts` — только после grep-подтверждения отсутствия внешних импортов.
- `/api/finance-settings`, `/api/audit/status`, customer-sync/contract-sync, `/api/finance/google/*` умирают с модулем — потребителей кроме удаляемого UI нет (по разведке).
- Docker-compose не меняется → бэкап serverfix не нужен; миграций БД нет (iistwin-БД не трогаем; внешняя финансовая БД — только чтение + override-таблицы DI2, которые уже созданы).
- Если замена хардкод-цветов в графиках сломает читаемость в тёмной теме — вернуть семантические пары вручную (проверить глазами ключевые страницы).