feat(accounting): Pflichtangaben der E-Rechnung vor dem Fertigstellen durchsetzen
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:
@@ -1131,8 +1131,54 @@ const checkAddressZip = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Pflichtangaben der E-Rechnung (ZUGFeRD) prüft das Backend, da Firmen- und Kundendaten dort vollständig vorliegen
|
||||
const eInvoiceDocumentTypes = ["invoices", "advanceInvoices", "cancellationInvoices", "serialInvoices"]
|
||||
const eInvoiceIssues = ref([])
|
||||
const eInvoiceCheckSource = computed(() => {
|
||||
if (!loaded.value || isTemplateMode.value || !eInvoiceDocumentTypes.includes(itemInfo.value.type)) return null
|
||||
const item = itemInfo.value
|
||||
return JSON.stringify({
|
||||
type: item.type,
|
||||
customer: item.customer,
|
||||
contact: item.contact,
|
||||
project: item.project,
|
||||
contract: item.contract,
|
||||
address: item.address,
|
||||
rows: item.rows,
|
||||
taxType: item.taxType,
|
||||
payment_type: item.payment_type,
|
||||
outgoingsepamandate: item.outgoingsepamandate,
|
||||
deliveryDateType: item.deliveryDateType,
|
||||
usedAdvanceInvoices: item.usedAdvanceInvoices,
|
||||
createddocument: item.createddocument,
|
||||
created_by: item.created_by,
|
||||
})
|
||||
})
|
||||
|
||||
const refreshEInvoiceIssues = async () => {
|
||||
const source = eInvoiceCheckSource.value
|
||||
if (!source) {
|
||||
eInvoiceIssues.value = []
|
||||
return eInvoiceIssues.value
|
||||
}
|
||||
try {
|
||||
const result = await useNuxtApp().$api("/api/functions/einvoice/check", {
|
||||
method: "POST",
|
||||
body: { document: JSON.parse(source) },
|
||||
})
|
||||
// Nur übernehmen, wenn sich der Beleg während der Anfrage nicht geändert hat
|
||||
if (source === eInvoiceCheckSource.value) eInvoiceIssues.value = result?.issues || []
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
eInvoiceIssues.value = [{ message: "E-Rechnung: Die Pflichtangaben konnten nicht geprüft werden", type: "breaking" }]
|
||||
}
|
||||
return eInvoiceIssues.value
|
||||
}
|
||||
|
||||
watchDebounced(eInvoiceCheckSource, refreshEInvoiceIssues, { debounce: 500, immediate: true })
|
||||
|
||||
const findDocumentErrors = computed(() => {
|
||||
let errors = []
|
||||
let errors = [...eInvoiceIssues.value]
|
||||
|
||||
if (itemInfo.value.customer === null) errors.push({message: "Es ist kein Kunde ausgewählt", type: "breaking"})
|
||||
if (itemInfo.value.contact === null) errors.push({message: "Es ist kein Kontakt ausgewählt", type: "info"})
|
||||
@@ -2025,6 +2071,18 @@ const saveFinalizedCostCentres = async () => {
|
||||
const selectedTab = ref("0")
|
||||
|
||||
const closeDocument = async () => {
|
||||
// Vor Vorschau und Fertigstellung mit dem aktuellen Stand prüfen, nicht mit dem letzten (entprellten) Ergebnis
|
||||
await refreshEInvoiceIssues()
|
||||
const breakingErrors = findDocumentErrors.value.filter(i => i.type === "breaking")
|
||||
if (breakingErrors.length > 0) {
|
||||
selectedTab.value = "0"
|
||||
toast.add({
|
||||
title: "Beleg kann nicht fertiggestellt werden",
|
||||
description: breakingErrors.map(i => i.message).join(" · "),
|
||||
color: "error",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if(selectedTab.value === "0") {
|
||||
await generateDocument()
|
||||
@@ -2034,7 +2092,16 @@ const closeDocument = async () => {
|
||||
|
||||
await saveDocument("Gebucht")
|
||||
|
||||
await uploadGeneratedDocument()
|
||||
try {
|
||||
await uploadGeneratedDocument()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
toast.add({
|
||||
title: "PDF bzw. E-Rechnung konnte nicht erstellt werden",
|
||||
description: error?.data?.error || error?.message,
|
||||
color: "error",
|
||||
})
|
||||
}
|
||||
|
||||
guard.value = false
|
||||
|
||||
@@ -2052,13 +2119,8 @@ const uploadGeneratedDocument = async () => {
|
||||
await generateDocument({
|
||||
createdDocumentId: itemInfo.value.id,
|
||||
onResult: (result) => {
|
||||
if (result?.einvoiceWarnings?.length) {
|
||||
toast.add({
|
||||
title: result.einvoice ? "E-Rechnung mit Hinweisen erstellt" : "E-Rechnung konnte nicht erstellt werden",
|
||||
description: result.einvoiceWarnings.join(" · "),
|
||||
color: "warning",
|
||||
})
|
||||
}
|
||||
const hints = (result?.einvoiceIssues || []).map(i => i.message)
|
||||
if (hints.length) toast.add({ title: "E-Rechnung mit Hinweisen erstellt", description: hints.join(" · "), color: "warning" })
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user