Added Kostenschätzung und Packschein
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 22s
Build and Push Docker Images / build-frontend (push) Successful in 59s

This commit is contained in:
2026-03-25 15:38:28 +01:00
parent 01b4d0f973
commit eb718021fd
11 changed files with 176 additions and 68 deletions

View File

@@ -128,8 +128,11 @@ export const tenants = pgTable(
customers: { prefix: "", suffix: "", nextNumber: 10000 },
products: { prefix: "AT-", suffix: "", nextNumber: 1000 },
quotes: { prefix: "AN-", suffix: "", nextNumber: 1000 },
costEstimates: { prefix: "KS-", suffix: "", nextNumber: 1000 },
confirmationOrders: { prefix: "AB-", suffix: "", nextNumber: 1000 },
invoices: { prefix: "RE-", suffix: "", nextNumber: 1000 },
deliveryNotes: { prefix: "LS-", suffix: "", nextNumber: 1000 },
packingSlips: { prefix: "PS-", suffix: "", nextNumber: 1000 },
spaces: { prefix: "LP-", suffix: "", nextNumber: 1000 },
customerspaces: { prefix: "KLP-", suffix: "", nextNumber: 1000 },
inventoryitems: { prefix: "IA-", suffix: "", nextNumber: 1000 },

View File

@@ -12,6 +12,13 @@ export const useNextNumberRangeNumber = async (
tenantId: number,
numberRange: string
) => {
const numberRangeFallbacks: Record<string, string> = {
costEstimates: "quotes",
packingSlips: "deliveryNotes",
advanceInvoices: "invoices",
cancellationInvoices: "invoices",
}
const [tenant] = await server.db
.select()
.from(tenants)
@@ -23,11 +30,15 @@ export const useNextNumberRangeNumber = async (
const numberRanges = tenant.numberRanges || {}
if (!numberRanges[numberRange]) {
const resolvedNumberRange = numberRanges[numberRange]
? numberRange
: numberRangeFallbacks[numberRange]
if (!resolvedNumberRange || !numberRanges[resolvedNumberRange]) {
throw new Error(`Number range '${numberRange}' not found`)
}
const current = numberRanges[numberRange]
const current = numberRanges[resolvedNumberRange]
const usedNumber =
(current.prefix || "") +
@@ -37,7 +48,7 @@ export const useNextNumberRangeNumber = async (
const updatedRanges = {
// @ts-ignore
...numberRanges,
[numberRange]: {
[resolvedNumberRange]: {
...current,
nextNumber: current.nextNumber + 1,
},

View File

@@ -58,6 +58,8 @@ const getDuration = (time) => {
export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoiceData, backgroundPath:string) => {
const deliveryNoteLikeDocumentTypes = ["deliveryNotes", "packingSlips"]
const isPackingSlip = invoiceData?.type === "packingSlips"
const genPDF = async (invoiceData, backgroundSourceBuffer) => {
const pdfDoc = await PDFDocument.create()
@@ -347,7 +349,19 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
font: fontBold
})
if (invoiceData.type !== "deliveryNotes") {
if (isPackingSlip) {
pages[pageCounter - 1].drawText("Check", {
...getCoordinatesForPDFLib(180, 137, page1),
size: 12,
color: rgb(0, 0, 0),
lineHeight: 12,
opacity: 1,
maxWidth: 240,
font: fontBold
})
}
if (!deliveryNoteLikeDocumentTypes.includes(invoiceData.type)) {
pages[pageCounter - 1].drawText("Steuer", {
...getCoordinatesForPDFLib(135, 137, page1),
size: 12,
@@ -414,9 +428,21 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
maxWidth: 240
})
if (isPackingSlip) {
pages[pageCounter - 1].drawRectangle({
...getCoordinatesForPDFLib(182, rowHeight + 1, page1),
width: 12,
height: 12,
borderColor: rgb(0, 0, 0),
borderWidth: 0.8,
opacity: 1,
borderOpacity: 1,
})
}
let rowTextLines = 0
if (invoiceData.type !== "deliveryNotes") {
if (!deliveryNoteLikeDocumentTypes.includes(invoiceData.type)) {
pages[pageCounter - 1].drawText(splitStringBySpace(row.text, 35).join("\n"), {
...getCoordinatesForPDFLib(52, rowHeight, page1),
size: 10,
@@ -428,7 +454,7 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
rowTextLines = splitStringBySpace(row.text, 35).length
} else {
pages[pageCounter - 1].drawText(splitStringBySpace(row.text, 80).join("\n"), {
pages[pageCounter - 1].drawText(splitStringBySpace(row.text, isPackingSlip ? 68 : 80).join("\n"), {
...getCoordinatesForPDFLib(52, rowHeight, page1),
size: 10,
color: rgb(0, 0, 0),
@@ -437,13 +463,13 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
font: fontBold
})
rowTextLines = splitStringBySpace(row.text, 80).length
rowTextLines = splitStringBySpace(row.text, isPackingSlip ? 68 : 80).length
}
let rowDescriptionLines = 0
if (row.descriptionText) {
if (invoiceData.type !== "deliveryNotes") {
if (!deliveryNoteLikeDocumentTypes.includes(invoiceData.type)) {
rowDescriptionLines = splitStringBySpace(row.descriptionText, 60).length
pages[pageCounter - 1].drawText(splitStringBySpace(row.descriptionText, 60).join("\n"), {
...getCoordinatesForPDFLib(52, rowHeight + (rowTextLines * 5), page1),
@@ -454,8 +480,8 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
})
} else {
rowDescriptionLines = splitStringBySpace(row.descriptionText, 80).length
pages[pageCounter - 1].drawText(splitStringBySpace(row.descriptionText, 80).join("\n"), {
rowDescriptionLines = splitStringBySpace(row.descriptionText, isPackingSlip ? 68 : 80).length
pages[pageCounter - 1].drawText(splitStringBySpace(row.descriptionText, isPackingSlip ? 68 : 80).join("\n"), {
...getCoordinatesForPDFLib(52, rowHeight + (rowTextLines * 5), page1),
size: 10,
color: rgb(0, 0, 0),
@@ -466,7 +492,7 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
}
if (invoiceData.type !== "deliveryNotes") {
if (!deliveryNoteLikeDocumentTypes.includes(invoiceData.type)) {
pages[pageCounter - 1].drawText(`${row.taxPercent} %`, {
...getCoordinatesForPDFLib(135, rowHeight, page1),
size: 10,
@@ -632,7 +658,19 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
font: fontBold
})
if (invoiceData.type !== "deliveryNotes") {
if (isPackingSlip) {
page.drawText("Check", {
...getCoordinatesForPDFLib(180, 22, page1),
size: 12,
color: rgb(0, 0, 0),
lineHeight: 12,
opacity: 1,
maxWidth: 240,
font: fontBold
})
}
if (!deliveryNoteLikeDocumentTypes.includes(invoiceData.type)) {
page.drawText("Steuer", {
...getCoordinatesForPDFLib(135, 22, page1),
size: 12,
@@ -742,7 +780,7 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
let endTextDiff = 35
if (invoiceData.type !== "deliveryNotes") {
if (!deliveryNoteLikeDocumentTypes.includes(invoiceData.type)) {
pages[pageCounter - 1].drawLine({
start: getCoordinatesForPDFLib(20, rowHeight, page1),
end: getCoordinatesForPDFLib(198, rowHeight, page1),
@@ -864,10 +902,10 @@ export const createInvoicePDF = async (server:FastifyInstance, returnMode, invoi
opacity: 1,
maxWidth: 500
})
return await pdfDoc.saveAsBase64()
}
return await pdfDoc.saveAsBase64()
}
const pdfBytes = await genPDF(invoiceData, await getBackgroundSourceBuffer(server,backgroundPath))
@@ -1138,4 +1176,4 @@ export const createTimeSheetPDF = async (server: FastifyInstance, returnMode, da
console.log(error)
throw error; // Fehler weiterwerfen, damit er oben ankommt
}
}
}