feat(accounting): Pflichtangaben der E-Rechnung vor dem Fertigstellen durchsetzen
All checks were successful
Build and Release FEDEO / verify (push) Successful in 59s
Build and Release FEDEO / build-and-release (push) Successful in 6m27s

Fehlende Pflichtangaben (Firmendaten, Steuer-ID, Kundenanschrift, IBAN,
§ 13b-USt-Id, Lastschriftmandat) erscheinen im Editor als blockierende
Fehler und verhindern Vorschau und Fertigstellung. Serienrechnungslauf,
MCP-Finalisierung und PDF-Erzeugung prüfen serverseitig vor der
Nummernvergabe bzw. Ablage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-04 11:24:28 +01:00
parent 549b469a41
commit e9697ef197
7 changed files with 224 additions and 55 deletions

View File

@@ -19,7 +19,7 @@ import duration from "dayjs/plugin/duration.js";
import timezone from "dayjs/plugin/timezone.js";
import {generateTimesEvaluation} from "../modules/time/evaluation.service";
import {citys, createddocuments, files} from "../../db/schema";
import { attachZugferdToPdf } from "../modules/einvoice/outgoingZugferd.service";
import { attachZugferdToPdf, checkOutgoingEInvoice, EInvoiceRequirementsError } from "../modules/einvoice/outgoingZugferd.service";
import {and, eq, isNull, not} from "drizzle-orm";
import {cancelManualGeneration, executeManualGeneration, finishManualGeneration} from "../modules/serialexecution.service";
import { updateOutgoingDocumentCostCentres } from "../modules/outgoing-document-cost-centres.service";
@@ -137,7 +137,7 @@ export default async function functionRoutes(server: FastifyInstance) {
.limit(1)
if (!document) return reply.code(404).send({ error: "Beleg nicht gefunden" })
const result = await attachZugferdToPdf(server, tenantId, document, Buffer.from(pdf.base64, "base64"))
pdf = { ...pdf, base64: result.pdf.toString("base64"), einvoice: result.einvoice, einvoiceWarnings: result.warnings }
pdf = { ...pdf, base64: result.pdf.toString("base64"), einvoice: result.einvoice, einvoiceIssues: result.issues }
}
} else if(type === "timesheet") {
pdf = await createTimeSheetPDF(
@@ -150,6 +150,9 @@ export default async function functionRoutes(server: FastifyInstance) {
return pdf // Fastify wandelt automatisch in JSON
} catch (err) {
if (err instanceof EInvoiceRequirementsError) {
return reply.code(422).send({ error: err.message, code: err.code, issues: err.issues })
}
console.log(err)
const unsupportedCharacterMessage = getUnsupportedPdfCharacterMessage(err, body.data)
if (unsupportedCharacterMessage) {
@@ -163,6 +166,14 @@ export default async function functionRoutes(server: FastifyInstance) {
}
})
// Prüft die Pflichtangaben der E-Rechnung für den aktuellen (ggf. ungespeicherten) Stand aus dem Editor
server.post("/functions/einvoice/check", async (req, reply) => {
const { document } = (req.body || {}) as { document?: any }
if (!document || typeof document !== "object") return reply.code(400).send({ error: "document fehlt" })
const issues = await checkOutgoingEInvoice(server, (req as any).user.tenant_id, document)
return { issues }
})
server.get("/functions/usenextnumber/:numberrange", async (req, reply) => {
const { numberrange } = req.params as { numberrange: string };
const tenant = (req as any).user.tenant_id