DI2 внедрение, таск 1: серверная интеграция Data-Insight2 (server/finance-di2)
- Копия 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
This commit is contained in:
154
server/finance-di2/table-config.ts
Normal file
154
server/finance-di2/table-config.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import type { TableConfig } from "./schema";
|
||||
|
||||
const TABLE_CONFIG_FILE = path.join(process.cwd(), "data", "table-config.json");
|
||||
|
||||
const SYSTEM_COLUMNS = ["id", "dataobnovleniyazapisi"];
|
||||
|
||||
const DEFAULT_COLUMN_LABELS: Record<string, string> = {
|
||||
data: "Дата",
|
||||
summa: "Сумма",
|
||||
summadokumenta: "Сумма документа",
|
||||
statya: "Статья",
|
||||
zakazchik: "Заказчик",
|
||||
dochka: "Дочка",
|
||||
vnuchka: "Внучка",
|
||||
kommentarii: "Комментарий",
|
||||
stavkands: "Ставка НДС",
|
||||
naznachenieplatezha: "Назначение платежа",
|
||||
otvetstvenniipokontraktu: "Ответственный",
|
||||
dogovorkontragenta: "Договор контрагента",
|
||||
dogovorzakazchika: "Договор заказчика",
|
||||
statyadop: "Статья (доп.)",
|
||||
schetnaoplatu: "Счет на оплату",
|
||||
nomervhodyaschegodokumenta: "Номер вх. документа",
|
||||
ssilkanomervhodyaschegodokumenta: "Номер вх. документа",
|
||||
kontragent: "Контрагент",
|
||||
dogovor: "Договор",
|
||||
summadolga: "Сумма долга",
|
||||
summaprosrocheno: "Сумма просрочено",
|
||||
period: "Период",
|
||||
klassprosrochki: "Класс просрочки",
|
||||
otvetstvennii: "Ответственный",
|
||||
organizaciya: "Организация",
|
||||
dokumentraschetov: "Документ расчётов",
|
||||
summaoplacheno: "Сумма оплачено",
|
||||
dneiprosrocheno: "Дней просрочено",
|
||||
dneidolga: "Дней долга",
|
||||
dataobrazovaniyadolga: "Дата образования долга",
|
||||
planovayadatapogasheniya: "Плановая дата погашения",
|
||||
otsrochkapodogovoru: "Отсрочка по договору",
|
||||
kontragentinn: "ИНН контрагента",
|
||||
valyuta: "Валюта",
|
||||
summadolgaval: "Сумма долга (вал.)",
|
||||
schet: "Счёт",
|
||||
klassdolga: "Класс долга",
|
||||
dataobnovleniyazapisi: "Дата обновления",
|
||||
};
|
||||
|
||||
export const DEFAULT_TABLE_CONFIG: TableConfig = {
|
||||
incomeTable: "opdohodi",
|
||||
expenseTable: "oprashodi",
|
||||
debtTable: "vw_debt_active",
|
||||
incomeSumColumn: "summa",
|
||||
expenseSumColumn: "summadokumenta",
|
||||
incomeColumns: ["id", "data", "summa", "statya", "zakazchik", "dochka", "vnuchka", "kommentarii", "stavkands", "naznachenieplatezha", "otvetstvenniipokontraktu", "dogovorkontragenta", "schetnaoplatu", "dogovorzakazchika", "statyadop", "nomervhodyaschegodokumenta", "dataobnovleniyazapisi"],
|
||||
expenseColumns: ["id", "data", "summadokumenta", "statya", "zakazchik", "dochka", "vnuchka", "kommentarii", "stavkands", "naznachenieplatezha", "otvetstvenniipokontraktu", "dogovorkontragenta", "dogovorzakazchika", "statyadop", "ssilkanomervhodyaschegodokumenta", "kontragent", "dataobnovleniyazapisi"],
|
||||
columnLabels: { ...DEFAULT_COLUMN_LABELS },
|
||||
};
|
||||
|
||||
let cachedConfig: TableConfig | null = null;
|
||||
|
||||
export function loadTableConfig(): TableConfig {
|
||||
if (cachedConfig) return cachedConfig;
|
||||
try {
|
||||
const raw = fs.readFileSync(TABLE_CONFIG_FILE, "utf-8");
|
||||
const parsed = JSON.parse(raw);
|
||||
cachedConfig = { ...DEFAULT_TABLE_CONFIG, ...parsed, columnLabels: { ...DEFAULT_COLUMN_LABELS, ...(parsed.columnLabels || {}) } };
|
||||
return cachedConfig!;
|
||||
} catch {
|
||||
cachedConfig = { ...DEFAULT_TABLE_CONFIG };
|
||||
return cachedConfig;
|
||||
}
|
||||
}
|
||||
|
||||
export function saveTableConfig(cfg: Partial<TableConfig>) {
|
||||
const current = loadTableConfig();
|
||||
const merged: TableConfig = {
|
||||
...current,
|
||||
...cfg,
|
||||
columnLabels: { ...current.columnLabels, ...(cfg.columnLabels || {}) },
|
||||
};
|
||||
if (!fs.existsSync("data")) fs.mkdirSync("data", { recursive: true });
|
||||
fs.writeFileSync(TABLE_CONFIG_FILE, JSON.stringify(merged, null, 2), "utf-8");
|
||||
cachedConfig = merged;
|
||||
}
|
||||
|
||||
export function getIncomeTable(): string {
|
||||
return "vw_income_effective";
|
||||
}
|
||||
|
||||
export function getExpenseTable(): string {
|
||||
return "vw_expense_effective";
|
||||
}
|
||||
|
||||
export function getIncomeBaseTable(): string {
|
||||
return loadTableConfig().incomeTable;
|
||||
}
|
||||
|
||||
export function getExpenseBaseTable(): string {
|
||||
return loadTableConfig().expenseTable;
|
||||
}
|
||||
|
||||
export function getIncomeEffectiveView(): string {
|
||||
return "vw_income_effective";
|
||||
}
|
||||
|
||||
export function getExpenseEffectiveView(): string {
|
||||
return "vw_expense_effective";
|
||||
}
|
||||
|
||||
export function getDebtTable(): string {
|
||||
return loadTableConfig().debtTable;
|
||||
}
|
||||
|
||||
export function getIncomeSumColumn(): string {
|
||||
return loadTableConfig().incomeSumColumn;
|
||||
}
|
||||
|
||||
export function getExpenseSumColumn(): string {
|
||||
return loadTableConfig().expenseSumColumn;
|
||||
}
|
||||
|
||||
export function getAllowedIncomeColumns(): string[] {
|
||||
const cfg = loadTableConfig();
|
||||
return cfg.incomeColumns.filter(c => !SYSTEM_COLUMNS.includes(c));
|
||||
}
|
||||
|
||||
export function getAllowedExpenseColumns(): string[] {
|
||||
const cfg = loadTableConfig();
|
||||
return cfg.expenseColumns.filter(c => !SYSTEM_COLUMNS.includes(c));
|
||||
}
|
||||
|
||||
export function getAutoDetectAllowedColumns(type: "income" | "expense"): string[] {
|
||||
const allowed = type === "income" ? getAllowedIncomeColumns() : getAllowedExpenseColumns();
|
||||
return allowed.filter(c => c !== "data" && c !== "id" && c !== "summa" && c !== "summadokumenta" && c !== "dataobnovleniyazapisi");
|
||||
}
|
||||
|
||||
export function getColumnLabel(col: string): string {
|
||||
const cfg = loadTableConfig();
|
||||
return cfg.columnLabels[col] || col;
|
||||
}
|
||||
|
||||
export function getAllIncomeColumns(): string[] {
|
||||
return loadTableConfig().incomeColumns;
|
||||
}
|
||||
|
||||
export function getAllExpenseColumns(): string[] {
|
||||
return loadTableConfig().expenseColumns;
|
||||
}
|
||||
|
||||
export function invalidateTableConfigCache() {
|
||||
cachedConfig = null;
|
||||
}
|
||||
Reference in New Issue
Block a user