Prevent duplicate invoice number reservations

This commit is contained in:
2026-08-17 17:47:07 +02:00
parent 060fde7bda
commit 391375b3a7
2 changed files with 40 additions and 34 deletions

View File

@@ -5,7 +5,7 @@ import bwipjs from "bwip-js"
import Sharp from "sharp" import Sharp from "sharp"
import { tenants } from "../../db/schema" import { tenants } from "../../db/schema"
import { eq } from "drizzle-orm" import { eq, sql } from "drizzle-orm"
export const useNextNumberRangeNumber = async ( export const useNextNumberRangeNumber = async (
server: FastifyInstance, server: FastifyInstance,
@@ -19,47 +19,53 @@ export const useNextNumberRangeNumber = async (
cancellationInvoices: "invoices", cancellationInvoices: "invoices",
} }
const [tenant] = await server.db return server.db.transaction(async (tx) => {
.select() // Serialisiert Nummernvergaben dieses Mandanten auch ueber mehrere
.from(tenants) // Backend-Prozesse hinweg, bis die Transaktion abgeschlossen ist.
.where(eq(tenants.id, tenantId)) await tx.execute(sql`select pg_advisory_xact_lock(${tenantId})`)
if (!tenant) { const [tenant] = await tx
throw new Error(`Tenant ${tenantId} not found`) .select()
} .from(tenants)
.where(eq(tenants.id, tenantId))
const numberRanges = tenant.numberRanges || {} if (!tenant) {
throw new Error(`Tenant ${tenantId} not found`)
}
const resolvedNumberRange = numberRanges[numberRange] const numberRanges = tenant.numberRanges || {}
? numberRange
: numberRangeFallbacks[numberRange]
if (!resolvedNumberRange || !numberRanges[resolvedNumberRange]) { const resolvedNumberRange = numberRanges[numberRange]
throw new Error(`Number range '${numberRange}' not found`) ? numberRange
} : numberRangeFallbacks[numberRange]
const current = numberRanges[resolvedNumberRange] if (!resolvedNumberRange || !numberRanges[resolvedNumberRange]) {
throw new Error(`Number range '${numberRange}' not found`)
}
const usedNumber = const current = numberRanges[resolvedNumberRange]
(current.prefix || "") +
current.nextNumber +
(current.suffix || "")
const updatedRanges = { const usedNumber =
// @ts-ignore (current.prefix || "") +
...numberRanges, current.nextNumber +
[resolvedNumberRange]: { (current.suffix || "")
...current,
nextNumber: current.nextNumber + 1,
},
}
await server.db const updatedRanges = {
.update(tenants) // @ts-ignore
.set({ numberRanges: updatedRanges }) ...numberRanges,
.where(eq(tenants.id, tenantId)) [resolvedNumberRange]: {
...current,
nextNumber: current.nextNumber + 1,
},
}
return { usedNumber } await tx
.update(tenants)
.set({ numberRanges: updatedRanges })
.where(eq(tenants.id, tenantId))
return { usedNumber }
})
} }
export async function encodeBase64ToNiimbot(base64Png: string, printDirection: "top" | "left" = "top") { export async function encodeBase64ToNiimbot(base64Png: string, printDirection: "top" | "left" = "top") {

View File

@@ -1761,7 +1761,7 @@ const saveDocument = async (state, resetup = false) => {
itemInfo.value.state = state itemInfo.value.state = state
normalizeCustomSurchargePercentage() normalizeCustomSurchargePercentage()
if (state !== "Entwurf") { if (state !== "Entwurf" && !itemInfo.value.documentNumber) {
console.log("???") console.log("???")
const type = itemInfo.value.type const type = itemInfo.value.type