# План: удаление старого модуля финансов + рестайл 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` и пункт «Финансы» в меню профиля → внешняя ссылка `` (паттерн как в 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) / )`), скины 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` + слушатель. - На ``: `data-skin`, `data-theme`, класс `light|dark`; для кастомного скина — `