diff --git a/backend/src/utils/tenantFullExport.ts b/backend/src/utils/tenantFullExport.ts index 61ea64b..1fc4aeb 100644 --- a/backend/src/utils/tenantFullExport.ts +++ b/backend/src/utils/tenantFullExport.ts @@ -11,6 +11,7 @@ import { pool } from "../../db" import { s3 } from "./s3" import { secrets } from "./secrets" import { decrypt, encrypt } from "./crypt" +import { restoreImportedTenantNumberRanges } from "./tenantImportNumberRanges" type TableRows = Record[]> type TableMetadata = { @@ -991,6 +992,8 @@ export const importTenantFullExport = async ( progressDone += 1 await reportProgress("Kommunikationsräume bereinigt") + await restoreImportedTenantNumberRanges(client, exportData) + await refreshSequences(client, columnsByTable) progressDone = progressTotal await reportProgress("Import abgeschlossen") diff --git a/backend/src/utils/tenantImportNumberRanges.ts b/backend/src/utils/tenantImportNumberRanges.ts new file mode 100644 index 0000000..fe348b5 --- /dev/null +++ b/backend/src/utils/tenantImportNumberRanges.ts @@ -0,0 +1,28 @@ +type QueryClient = { + query: (query: string, values: unknown[]) => Promise<{ rowCount?: number | null }> +} + +type TenantImportData = { + tenantId: number + tables: Record[]> +} + +export const restoreImportedTenantNumberRanges = async ( + client: QueryClient, + exportData: TenantImportData +) => { + const tenantRow = (exportData.tables.tenants || []).find( + (row) => Number(row.id) === Number(exportData.tenantId) + ) + + if (!tenantRow || tenantRow.numberRanges === null || typeof tenantRow.numberRanges === "undefined") { + return 0 + } + + const result = await client.query( + `update "tenants" set "numberRanges" = $1::jsonb where "id" = $2`, + [JSON.stringify(tenantRow.numberRanges), exportData.tenantId] + ) + + return result.rowCount || 0 +} diff --git a/backend/tests/tenantImportNumberRanges.test.ts b/backend/tests/tenantImportNumberRanges.test.ts new file mode 100644 index 0000000..feeff0b --- /dev/null +++ b/backend/tests/tenantImportNumberRanges.test.ts @@ -0,0 +1,48 @@ +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) +})