Files
FEDEO/backend/tests/bankAllocationDetails.test.ts

70 lines
3.8 KiB
TypeScript

import assert from "node:assert/strict"
import test from "node:test"
import { PgDialect } from "drizzle-orm/pg-core"
import { normalizeBankAllocationDetails, validateBankAllocationCostCentre } from "../src/modules/bank-allocation-details"
import { prepareStatementAllocationInput } from "../src/mcp/statementAllocations"
import bankingRoutes from "../src/routes/banking"
import { statementallocations } from "../db/schema"
const costcentre = "57d31d62-11a2-47c5-b074-69f9c5ab8bba"
test("keeps cost centre and VAT key on the gross bank allocation through input preparation", () => {
const prepared = prepareStatementAllocationInput({ bankstatement: 42, account: 13, amount: -119, costcentre, datevTaxKey: " 9 " })
assert.equal(prepared.amount, -119)
assert.equal(prepared.costcentre, costcentre)
assert.equal(prepared.datevTaxKey, "9")
assert.deepEqual(normalizeBankAllocationDetails({ amount: -119, account: 13, bankstatement: 42 }), { costcentre: null, datevTaxKey: null })
})
test("rejects invalid cost centres, ambiguous document assignments and malformed tax keys", () => {
assert.throws(() => normalizeBankAllocationDetails({ costcentre: "invalid" }), /UUID/)
assert.throws(() => normalizeBankAllocationDetails({ costcentre, bankstatement: 1, account: 13, incominginvoice: 2 }), /direkte Bankbuchungen/)
assert.throws(() => normalizeBankAllocationDetails({ datevTaxKey: '9";evil' }), /Steuerschlüssel/)
})
test("cost centre lookup requires the active tenant and excludes archived centres", async () => {
let condition: any
const query = { from: () => query, where: (value: any) => { condition = value; return query }, limit: async () => [] }
await assert.rejects(validateBankAllocationCostCentre({ select: () => query }, 7, costcentre), /nicht gefunden oder ist archiviert/)
const sql = new PgDialect().sqlToQuery(condition)
assert.match(sql.sql, /"costcentres"\."tenant"/)
assert.match(sql.sql, /"costcentres"\."archived"/)
assert.deepEqual(sql.params, [costcentre, 7, false])
await validateBankAllocationCostCentre({ select: () => ({ ...query, from: () => ({ where: () => ({ limit: async () => [{ id: costcentre }] }) }) }) }, 7, costcentre)
await validateBankAllocationCostCentre({}, 7, null)
})
test("banking API persists the gross allocation with cost centre and VAT, and rejects unknown centres before writing", async () => {
const handlers = new Map<string, any>()
const saved: any[] = []
let centreExists = true
const lookup: any = { from: () => lookup, where: () => lookup, limit: async () => centreExists ? [{ id: costcentre }] : [] }
const server: any = {
get() {}, patch() {}, delete() {},
post: (url: string, handler: any) => handlers.set(url, handler),
db: {
select: () => lookup,
insert: (table: any) => ({ values: (value: any) => {
if (table === statementallocations) saved.push(value)
return { returning: async () => [{ id: "allocation", ...value }] }
} }),
},
}
await bankingRoutes(server)
const handler = handlers.get("/banking/statements")
const request = { user: { tenant_id: 7, user_id: "user" }, body: { data: { bankstatement: 42, account: 13, amount: -119, costcentre, datevTaxKey: "9" } } }
let status = 200
let response: any
const reply = { code: (code: number) => { status = code; return reply }, send: (body: any) => { response = body; return reply } }
await handler(request, reply)
assert.equal(status, 200)
assert.equal(response.amount, -119)
assert.equal(response.costcentre, costcentre)
assert.equal(response.datevTaxKey, "9")
assert.equal(saved[0].tenant, 7)
centreExists = false
await handler(request, reply)
assert.equal(status, 400)
assert.equal(saved.length, 1)
})