Files
iistwin/server/finance-di2/audit-scheduler.ts
Ильяс Султанов 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

54 lines
2.1 KiB
TypeScript
Raw 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: ежедневно в 03:00 (МСК) + первый запуск через 10 сек после старта.
// Порт из удалённого server/finance/audit.ts (без node-cron, setInterval-проверка).
import { runIntegrityAudit, getAuditHistory } from "./audit-agent";
const TICK_MS = 60_000;
const MSK_OFFSET_MS = 3 * 60 * 60 * 1000; // МСК = UTC+3
const AUDIT_HOUR_MSK = 3;
let lastRunDay: string | null = getAuditHistory()[0]?.timestamp
? new Date(new Date(getAuditHistory()[0].timestamp).getTime() + MSK_OFFSET_MS).toISOString().slice(0, 10)
: null;
let schedulerStarted = false;
function mskToday(): string {
return new Date(Date.now() + MSK_OFFSET_MS).toISOString().slice(0, 10);
}
function mskHourNow(): number {
return new Date(Date.now() + MSK_OFFSET_MS).getUTCHours();
}
async function tick(): Promise<void> {
const today = mskToday();
if (lastRunDay === today) return; // сегодня уже запускался
if (mskHourNow() < AUDIT_HOUR_MSK) return; // ещё не наступило 03:00 по МСК
lastRunDay = today;
try {
await runIntegrityAudit();
} catch (err) {
console.error("[AUDIT-AGENT] Ошибка при выполнении аудита:", err);
}
}
export function startAuditScheduler(): void {
if (schedulerStarted) return; // защита от повторной регистрации роутов (тесты и т.п.)
schedulerStarted = true;
setInterval(() => {
tick().catch((err) => console.error("[AUDIT-AGENT] Tick error:", err));
}, TICK_MS);
console.log("[AUDIT-AGENT] Планировщик запущен (ежедневно в 03:00 по МСК)");
// Первый запуск через 10 секунд после старта сервера
setTimeout(async () => {
try {
const result = await runIntegrityAudit();
lastRunDay = new Date(new Date(result.timestamp).getTime() + MSK_OFFSET_MS).toISOString().slice(0, 10);
} catch (err) {
console.error("[AUDIT-AGENT] Ошибка при начальном аудите:", err);
}
}, 10000);
}