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 = { 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) { 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; }