Prevent duplicate invoice number reservations
This commit is contained in:
@@ -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") {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user