import { and, eq } from "drizzle-orm" import { costcentres } from "../../db/schema" const invalidInput = (message: string) => Object.assign(new Error(message), { statusCode: 400 }) export function normalizeBankAllocationDetails(payload: Record) { const costcentre = payload.costcentre ? String(payload.costcentre).trim() : null const datevTaxKey = payload.datevTaxKey ? String(payload.datevTaxKey).trim() : null if (costcentre && !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(costcentre)) { throw invalidInput("Die Kostenstelle muss eine gültige UUID sein.") } if (datevTaxKey && !/^\d{1,4}$/.test(datevTaxKey)) { throw invalidInput("Der DATEV-Steuerschlüssel muss aus 1 bis 4 Ziffern bestehen.") } if (costcentre && (!payload.bankstatement || !(payload.account || payload.ownaccount) || payload.createddocument || payload.incominginvoice || payload.customer || payload.vendor)) { throw invalidInput("Kostenstellen sind hier nur für direkte Bankbuchungen auf Buchungskonten zulässig.") } return { costcentre, datevTaxKey } } export async function validateBankAllocationCostCentre(db: any, tenantId: number, costcentre: string | null) { if (!costcentre) return const [record] = await db.select({ id: costcentres.id }).from(costcentres).where(and( eq(costcentres.id, costcentre), eq(costcentres.tenant, tenantId), eq(costcentres.archived, false), )).limit(1) if (!record) throw invalidInput("Die Kostenstelle wurde nicht gefunden oder ist archiviert.") }