feat(accounting): fehlende PDF von Ausgangsbelegen nacherzeugen

Auf der Belegansicht erscheint "PDF nacherzeugen", wenn ein
fertiggestellter Beleg kein angehängtes Dokument hat. Die PDF wird mit
derselben Logik wie beim Fertigstellen erzeugt und angehängt, ohne den
Datensatz zu speichern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 20:40:25 +01:00
parent f814689ddd
commit 76e82eae4f
2 changed files with 93 additions and 33 deletions

View File

@@ -730,6 +730,12 @@ const setupPage = async () => {
await router.replace('/createDocument')
return
}
if (route.query.regeneratePdf && route.params.id) {
await regenerateMissingPdf()
return
}
loaded.value = true
}
@@ -1980,8 +1986,24 @@ const closeDocument = async () => {
await saveDocument("Gebucht")
await uploadGeneratedDocument()
guard.value = false
await router.push(`/createDocument/show/${itemInfo.value.id}`)
}
}
// Erzeugt die PDF aus dem aktuellen Stand und hängt sie an den Beleg an, ohne den Datensatz zu speichern
const uploadGeneratedDocument = async () => {
await generateDocument()
if (!uri.value) throw new Error("PDF konnte nicht erzeugt werden")
let fileData = {}
fileData.project = itemInfo.value.project
@@ -2012,15 +2034,39 @@ const closeDocument = async () => {
let file = dataURLtoFile(uri.value, `${itemInfo.value.documentNumber}.pdf`)
await useFiles().uploadFiles(fileData, [file])
guard.value = false
await router.push(`/createDocument/show/${itemInfo.value.id}`)
}
const regenerateMissingPdf = async () => {
guard.value = false
const showPath = `/createDocument/show/${route.params.id}`
try {
const document = await useEntities("createddocuments").selectSingle(route.params.id, "*,files(*)")
if (document?.state === "Entwurf" || document?.type === "serialInvoices") {
toast.add({ title: "PDF kann nur für fertiggestellte Belege nacherzeugt werden", color: "error" })
} else if ((document?.files || []).length > 0) {
toast.add({ title: "Am Beleg ist bereits ein Dokument angehängt", color: "warning" })
} else {
// Vertrags- und Mandats-Watcher überschreiben beim Laden die Zahlungsdaten, für die PDF gilt der gespeicherte Stand
const restoreStoredPaymentData = () => {
itemInfo.value.payment_type = document.payment_type
itemInfo.value.outgoingsepamandate = normalizeEntityId(document.outgoingsepamandate)
}
await nextTick()
restoreStoredPaymentData()
await nextTick()
restoreStoredPaymentData()
await uploadGeneratedDocument()
toast.add({ title: "PDF nacherzeugt", color: "success" })
}
} catch (error) {
console.error(error)
toast.add({ title: "PDF konnte nicht nacherzeugt werden", description: error?.data?.error || error?.message, color: "error" })
}
await router.replace(showPath)
}
const getTextTemplateByType = (type, pos) => {

View File

@@ -110,9 +110,17 @@ const setupPage = async () => {
links.value = createddocuments.filter(i => i.createddocument?.id === itemInfo.value.id)
}
if (itemInfo.value.files?.length > 0) {
linkedDocument.value = await useFiles().selectDocument(itemInfo.value.files[0].id)
}
}
}
const canRegeneratePdf = computed(() => itemInfo.value.id
&& itemInfo.value.state !== 'Entwurf'
&& itemInfo.value.type !== 'serialInvoices'
&& Array.isArray(itemInfo.value.files)
&& itemInfo.value.files.length === 0)
setupPage()
@@ -282,6 +290,12 @@ const togglePortalRelease = async () => {
:loading="costCentresLoading"
@click="openCostCentres"
>Kostenstellen bearbeiten</UButton>
<UButton
v-if="canRegeneratePdf"
icon="i-heroicons-document-arrow-down"
variant="outline"
@click="router.push(`/createDocument/edit/${itemInfo.id}?regeneratePdf=1`)"
>PDF nacherzeugen</UButton>
<!-- <UButton
:to="dataStore.documents.find(i => i.createdDocument === itemInfo.id) ? dataStore.documents.find(i => i.createdDocument === itemInfo.id).url : ''"
target="_blank"