Restrict tenant imports to new tenants
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
import assert from "node:assert/strict"
|
||||
import test from "node:test"
|
||||
|
||||
import { addTenantExportGlobalResources } from "../src/utils/tenantExportGlobalResources"
|
||||
|
||||
test("adds global resources and the tenant account chart to a tenant export", async () => {
|
||||
const tables: Record<string, Record<string, any>[]> = {}
|
||||
const calls: { table: string, whereSql: string, params?: any[] }[] = []
|
||||
const rowsByTable: Record<string, Record<string, any>[]> = {
|
||||
units: [{ id: 1, name: "Monat" }],
|
||||
citys: [{ id: 1, zip: 26316 }],
|
||||
countrys: [{ id: 1, name: "Deutschland" }],
|
||||
accounts: [{ id: 1, accountChart: "skr04", number: "4400" }],
|
||||
}
|
||||
|
||||
await addTenantExportGlobalResources(
|
||||
tables,
|
||||
new Set(Object.keys(rowsByTable)),
|
||||
{ id: 42, accountChart: "skr04" },
|
||||
async (table, whereSql, params) => {
|
||||
calls.push({ table, whereSql, params })
|
||||
return rowsByTable[table]
|
||||
},
|
||||
(target, table, rows) => {
|
||||
target[table] = rows
|
||||
}
|
||||
)
|
||||
|
||||
assert.deepEqual(tables, rowsByTable)
|
||||
assert.deepEqual(calls, [
|
||||
{ table: "units", whereSql: "true", params: undefined },
|
||||
{ table: "citys", whereSql: "true", params: undefined },
|
||||
{ table: "countrys", whereSql: "true", params: undefined },
|
||||
{ table: "accounts", whereSql: `"accountChart" = $1`, params: ["skr04"] },
|
||||
])
|
||||
})
|
||||
|
||||
test("skips global tables that do not exist in an older database schema", async () => {
|
||||
const tables: Record<string, Record<string, any>[]> = {}
|
||||
|
||||
await addTenantExportGlobalResources(
|
||||
tables,
|
||||
new Set(["units"]),
|
||||
{ id: 42 },
|
||||
async () => [{ id: 1, name: "Stück" }],
|
||||
(target, table, rows) => {
|
||||
target[table] = rows
|
||||
}
|
||||
)
|
||||
|
||||
assert.deepEqual(tables, { units: [{ id: 1, name: "Stück" }] })
|
||||
})
|
||||
@@ -1,48 +0,0 @@
|
||||
import assert from "node:assert/strict"
|
||||
import test from "node:test"
|
||||
|
||||
import { restoreImportedTenantNumberRanges } from "../src/utils/tenantImportNumberRanges"
|
||||
|
||||
test("restores number ranges when importing into an existing target tenant", async () => {
|
||||
const queries: { query: string, values: unknown[] }[] = []
|
||||
const numberRanges = {
|
||||
invoices: { prefix: "RE-", suffix: "", nextNumber: 4712 },
|
||||
}
|
||||
const client = {
|
||||
async query(query: string, values: unknown[]) {
|
||||
queries.push({ query, values })
|
||||
return { rowCount: 1 }
|
||||
},
|
||||
}
|
||||
|
||||
const updated = await restoreImportedTenantNumberRanges(client, {
|
||||
tenantId: 42,
|
||||
tables: {
|
||||
tenants: [{ id: 42, name: "Zieltenant", numberRanges }],
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(updated, 1)
|
||||
assert.deepEqual(queries, [{
|
||||
query: `update "tenants" set "numberRanges" = $1::jsonb where "id" = $2`,
|
||||
values: [JSON.stringify(numberRanges), 42],
|
||||
}])
|
||||
})
|
||||
|
||||
test("does not overwrite number ranges when the export contains none", async () => {
|
||||
let queryCalled = false
|
||||
const client = {
|
||||
async query() {
|
||||
queryCalled = true
|
||||
return { rowCount: 1 }
|
||||
},
|
||||
}
|
||||
|
||||
const updated = await restoreImportedTenantNumberRanges(client, {
|
||||
tenantId: 42,
|
||||
tables: { tenants: [{ id: 42, name: "Zieltenant" }] },
|
||||
})
|
||||
|
||||
assert.equal(updated, 0)
|
||||
assert.equal(queryCalled, false)
|
||||
})
|
||||
@@ -1,68 +0,0 @@
|
||||
import assert from "node:assert/strict"
|
||||
import test from "node:test"
|
||||
|
||||
import { buildTenantMergePlan } from "../src/utils/tenantMergePlan"
|
||||
|
||||
test("classifies imports, existing rows, conflicts and global id collisions", () => {
|
||||
const plan = buildTenantMergePlan({
|
||||
units: [
|
||||
{ id: 1, name: "Stück", short: "Stk." },
|
||||
{ id: 2, name: "Monat", short: "Mon." },
|
||||
{ id: 3, name: "Stunde", short: "Std." },
|
||||
],
|
||||
customers: [
|
||||
{ id: 10, tenant: 42, name: "Neu" },
|
||||
{ id: 11, tenant: 42, name: "Geändert" },
|
||||
],
|
||||
}, {
|
||||
units: [
|
||||
{ id: 1, name: "Stück", short: "Stk.", updated_at: "later" },
|
||||
{ id: 2, name: "Kilometer", short: "km" },
|
||||
{ id: 9, name: "Stunde", short: "h" },
|
||||
],
|
||||
customers: [
|
||||
{ id: 11, tenant: 42, name: "Zieländerung" },
|
||||
],
|
||||
}, {
|
||||
units: { primaryKey: ["id"] },
|
||||
customers: { primaryKey: ["id"] },
|
||||
})
|
||||
|
||||
assert.deepEqual(plan.summary, {
|
||||
import: 1,
|
||||
existing: 1,
|
||||
conflict: 2,
|
||||
id_collision: 1,
|
||||
})
|
||||
|
||||
assert.equal(plan.items.find((item) => item.label === "Monat")?.kind, "id_collision")
|
||||
assert.equal(plan.items.find((item) => item.label === "Stunde")?.kind, "conflict")
|
||||
assert.equal(plan.items.find((item) => item.label === "Geändert")?.defaultDecision, "target")
|
||||
})
|
||||
|
||||
test("uses target as the safe default for two-way conflicts", () => {
|
||||
const plan = buildTenantMergePlan({
|
||||
accounts: [{ id: 5, accountChart: "skr03", number: "8400", label: "Quelle" }],
|
||||
}, {
|
||||
accounts: [{ id: 99, accountChart: "skr03", number: "8400", label: "Ziel" }],
|
||||
}, {
|
||||
accounts: { primaryKey: ["id"] },
|
||||
})
|
||||
|
||||
assert.equal(plan.items[0].kind, "conflict")
|
||||
assert.equal(plan.items[0].targetKey, "id=99")
|
||||
assert.equal(plan.items[0].defaultDecision, "target")
|
||||
assert.deepEqual(plan.items[0].differences.sort(), ["id", "label"])
|
||||
})
|
||||
|
||||
test("ignores maintenance locks and audit timestamps during comparison", () => {
|
||||
const plan = buildTenantMergePlan({
|
||||
tenants: [{ id: 42, name: "Tenant", locked: null, updatedAt: "before" }],
|
||||
}, {
|
||||
tenants: [{ id: 42, name: "Tenant", locked: "maintenance_tenant", updatedAt: "after" }],
|
||||
}, {
|
||||
tenants: { primaryKey: ["id"] },
|
||||
})
|
||||
|
||||
assert.equal(plan.items[0].kind, "existing")
|
||||
})
|
||||
Reference in New Issue
Block a user