Belegansichten um Bankbuchungsdatum erweitern #110
Zeigt Bankbuchungsdaten in Ausgangsbelegen direkt an und ergänzt Bankdetails im Modal. Überarbeitet die Eingangsbeleg-Showansicht zu einer echten Lesedarstellung mit Bankbuchungsdaten und Positionsübersicht.
This commit is contained in:
@@ -56,7 +56,7 @@ const setup = async () => {
|
||||
vendors.value = await useEntities("vendors").select()
|
||||
accounts.value = await useEntities("accounts").selectSpecial()
|
||||
|
||||
const invoiceData = await useEntities("incominginvoices").selectSingle(route.params.id, "*, files(*)")
|
||||
const invoiceData = await useEntities("incominginvoices").selectSingle(route.params.id, "*, files(*), statementallocations(*, bs_id(*))")
|
||||
|
||||
// 2. Mapping
|
||||
itemInfo.value = {
|
||||
@@ -129,6 +129,34 @@ const setDateFieldToToday = (field) => {
|
||||
}
|
||||
|
||||
const getDateButtonLabel = (value, emptyLabel = "Kein Datum") => value ? dayjs(value).format('DD.MM.YYYY') : emptyLabel
|
||||
const formatDate = (value) => value ? dayjs(value).format("DD.MM.YYYY") : "-"
|
||||
const formatMoney = (value) => `${Number(value || 0).toFixed(2).replace(".", ",")} €`
|
||||
const getStatementLike = (allocation) => allocation?.bankstatement || (typeof allocation?.bs_id === "object" ? allocation.bs_id : null)
|
||||
const getBankBookingDate = (allocation) => {
|
||||
const statement = getStatementLike(allocation)
|
||||
|
||||
return statement?.date || statement?.valueDate || allocation?.manualBookingDate || null
|
||||
}
|
||||
const bankBookingDates = computed(() => [...new Set(
|
||||
(itemInfo.value.statementallocations || [])
|
||||
.map(getBankBookingDate)
|
||||
.filter(Boolean)
|
||||
)].sort())
|
||||
const bankBookingDateLabel = computed(() => {
|
||||
if (bankBookingDates.value.length === 0) return "Nicht zugewiesen"
|
||||
if (bankBookingDates.value.length === 1) return formatDate(bankBookingDates.value[0])
|
||||
|
||||
return bankBookingDates.value.map(formatDate).join(", ")
|
||||
})
|
||||
const vendorName = computed(() => vendors.value.find((vendor) => vendor.id === itemInfo.value.vendor)?.name || "-")
|
||||
const getAccountLabel = (item) => {
|
||||
const account = accounts.value.find((entry) => entry.id === item.account)
|
||||
|
||||
return account ? `${account.number || ""} ${account.label || ""}`.trim() : "-"
|
||||
}
|
||||
const getCostCentreLabel = (item) => costcentres.value.find((costcentre) => costcentre.id === item.costCentre)?.name || "-"
|
||||
const getBookingModeLabel = (item) => EXPENSE_BOOKING_MODE_ITEMS.find((mode) => mode.value === item.bookingMode)?.label || "-"
|
||||
const getTaxLabel = (item) => taxOptions.value.find((tax) => tax.key === item.taxType)?.label || "-"
|
||||
|
||||
const totalCalculated = computed(() => {
|
||||
let totalNet = 0
|
||||
@@ -329,7 +357,7 @@ const hasBlockingIncomingInvoiceErrors = computed(() => blockingIncomingInvoiceE
|
||||
</UButton>
|
||||
|
||||
<UAlert
|
||||
v-if="findIncomingInvoiceErrors.length > 0"
|
||||
v-if="mode !== 'show' && findIncomingInvoiceErrors.length > 0"
|
||||
title="Prüfung erforderlich"
|
||||
:color="hasBlockingIncomingInvoiceErrors ? 'error' : 'orange'"
|
||||
variant="soft"
|
||||
@@ -363,7 +391,79 @@ const hasBlockingIncomingInvoiceErrors = computed(() => blockingIncomingInvoiceE
|
||||
</template>
|
||||
</UAlert>
|
||||
|
||||
<UCard>
|
||||
<div v-if="mode === 'show'" class="space-y-6">
|
||||
<div class="rounded-md border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-gray-900">
|
||||
<div class="mb-4 flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500">Eingangsbeleg</p>
|
||||
<h2 class="text-xl font-semibold">{{ itemInfo.reference || "-" }}</h2>
|
||||
</div>
|
||||
<UBadge :color="itemInfo.state === 'Gebucht' ? 'primary' : 'neutral'" variant="soft">
|
||||
{{ itemInfo.state || "Entwurf" }}
|
||||
</UBadge>
|
||||
</div>
|
||||
|
||||
<dl class="grid grid-cols-1 gap-4 text-sm md:grid-cols-2">
|
||||
<div>
|
||||
<dt class="text-gray-500">Lieferant / Partner</dt>
|
||||
<dd class="font-medium">{{ vendorName }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Zahlart</dt>
|
||||
<dd class="font-medium">{{ itemInfo.paymentType || "-" }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Rechnungsdatum</dt>
|
||||
<dd class="font-medium">{{ formatDate(itemInfo.date) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Fälligkeitsdatum</dt>
|
||||
<dd class="font-medium">{{ formatDate(itemInfo.dueDate) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Bankbuchungsdatum</dt>
|
||||
<dd class="font-medium">{{ bankBookingDateLabel }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Art</dt>
|
||||
<dd class="font-medium">{{ itemInfo.expense ? "Ausgabe" : "Einnahme" }}</dd>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<dt class="text-gray-500">Beschreibung / Notiz</dt>
|
||||
<dd class="font-medium whitespace-pre-wrap">{{ itemInfo.description || "-" }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="itemInfo.statementallocations?.length > 0"
|
||||
class="rounded-md border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-gray-900"
|
||||
>
|
||||
<h3 class="mb-4 font-semibold">Bankbuchungen</h3>
|
||||
<div class="space-y-3">
|
||||
<div
|
||||
v-for="allocation in itemInfo.statementallocations"
|
||||
:key="allocation.id"
|
||||
class="grid grid-cols-1 gap-2 rounded-md border border-gray-200 p-3 text-sm dark:border-gray-800 md:grid-cols-3"
|
||||
>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Bankbuchungsdatum</p>
|
||||
<p class="font-medium">{{ formatDate(getBankBookingDate(allocation)) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Betrag</p>
|
||||
<p class="font-medium">{{ formatMoney(allocation.amount) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Text</p>
|
||||
<p class="font-medium">{{ getStatementLike(allocation)?.text || allocation.description || "-" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UCard v-if="mode !== 'show'">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="font-semibold">Stammdaten</h3>
|
||||
@@ -492,7 +592,54 @@ const hasBlockingIncomingInvoiceErrors = computed(() => blockingIncomingInvoiceE
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div v-if="mode === 'show'" class="space-y-4">
|
||||
<div class="flex justify-between items-end border-b pb-2 dark:border-gray-700">
|
||||
<h3 class="font-semibold text-lg">Positionen</h3>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="(item, index) in itemInfo.accounts"
|
||||
:key="`show-${index}`"
|
||||
class="rounded-md border border-gray-200 bg-white p-4 text-sm dark:border-gray-800 dark:bg-gray-900"
|
||||
>
|
||||
<div class="mb-3 flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Position {{ index + 1 }}</p>
|
||||
<p class="font-medium">{{ item.description || "Ohne Positionstext" }}</p>
|
||||
</div>
|
||||
<UBadge variant="soft" color="neutral">{{ getBookingModeLabel(item) }}</UBadge>
|
||||
</div>
|
||||
|
||||
<dl class="grid grid-cols-1 gap-3 md:grid-cols-3">
|
||||
<div>
|
||||
<dt class="text-gray-500">Konto / Kategorie</dt>
|
||||
<dd class="font-medium">{{ getAccountLabel(item) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Kostenstelle</dt>
|
||||
<dd class="font-medium">{{ getCostCentreLabel(item) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Steuerschlüssel</dt>
|
||||
<dd class="font-medium">{{ getTaxLabel(item) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Netto</dt>
|
||||
<dd class="font-medium">{{ formatMoney(item.amountNet) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Steuerbetrag</dt>
|
||||
<dd class="font-medium">{{ formatMoney(item.amountTax) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-500">Brutto</dt>
|
||||
<dd class="font-medium">{{ formatMoney(item.amountGross) }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="mode !== 'show'" class="space-y-4">
|
||||
<div class="flex justify-between items-end border-b pb-2 dark:border-gray-700">
|
||||
<h3 class="font-semibold text-lg">Positionen</h3>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
|
||||
Reference in New Issue
Block a user