feat(banking): add cost centres and VAT to account allocations

This commit is contained in:
2026-09-23 18:08:09 +02:00
parent 847a616285
commit cbec5b058d
21 changed files with 517 additions and 42 deletions

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import dayjs from "dayjs"
import { getBankAllocationTaxBreakdown, isDirectBankAllocation } from "~/utils/bankAllocationTax"
import customParseFormat from "dayjs/plugin/customParseFormat"
import {
formatTaxEvaluationPeriodLabel,
@@ -20,6 +21,7 @@ const loading = ref(true)
const createdDocuments = ref<any[]>([])
const incomingInvoices = ref<any[]>([])
const manualBookings = ref<any[]>([])
const bankAllocations = ref<any[]>([])
const periodType = computed(() => normalizeTaxEvaluationPeriod(auth.activeTenantData?.taxEvaluationPeriod))
@@ -42,15 +44,17 @@ const loadData = async () => {
loading.value = true
try {
const [docs, incoming, manual] = await Promise.all([
const [docs, incoming, manual, allocations] = await Promise.all([
useEntities("createddocuments").select(),
useEntities("incominginvoices").select(),
useNuxtApp().$api("/api/banking/manual-bookings")
useNuxtApp().$api("/api/banking/manual-bookings"),
useEntities("statementallocations").select("*, bankstatement(*)")
])
createdDocuments.value = (docs || []).filter(isRelevantOutputDocument)
incomingInvoices.value = (incoming || []).filter(isRelevantInputInvoice)
manualBookings.value = (manual as any[]) || []
bankAllocations.value = (allocations || []).filter(isDirectBankAllocation)
} finally {
loading.value = false
}
@@ -108,6 +112,18 @@ const periods = computed(() => {
}
}, { net19: 0, tax19: 0, net7: 0, tax7: 0, net0: 0 })
const directBookings = bankAllocations.value.filter((allocation) => {
const date = dayjs(allocation.bankstatement?.date || allocation.bankstatement?.valueDate)
return date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day")
})
directBookings.forEach((allocation) => {
const breakdown = getBankAllocationTaxBreakdown(allocation)
for (const key of ["net19", "tax19", "net7", "tax7", "net0"] as const) {
output[key] += breakdown.output[key]
input[key] += breakdown.input[key]
}
})
output.tax19 = Number((output.tax19 + manualTax.outputTax19).toFixed(2))
input.tax19 = Number((input.tax19 + manualTax.inputTax19).toFixed(2))
@@ -127,6 +143,7 @@ const periods = computed(() => {
input,
outputCount: outputDocs.length,
inputCount: inputDocs.length,
bankCount: directBookings.length,
}
})
})
@@ -136,7 +153,7 @@ const currentPeriod = computed(() => periods.value[0] || null)
const columns = [
{ key: "label", label: "Zeitraum" },
{ key: "range", label: "Datumsbereich" },
{ key: "outputTax", label: "USt Rechnungen" },
{ key: "outputTax", label: "Umsatzsteuer" },
{ key: "inputTax", label: "Vorsteuer" },
{ key: "balance", label: "Ergebnis" },
{ key: "documents", label: "Belege" },
@@ -166,7 +183,8 @@ onMounted(loadData)
</h2>
<p class="text-sm text-gray-500 dark:text-gray-400">
Intervall: {{ periodType === "monthly" ? "monatlich" : periodType === "quarterly" ? "quartalsweise" : "jährlich" }}.
Berücksichtigt werden gebuchte Ausgangsrechnungen, Abschlags- und Stornorechnungen, gebuchte Eingangsbelege sowie manuelle Buchungen auf SKR03 1576 und 1776.
Berücksichtigt werden gebuchte Ausgangsrechnungen, Abschlags- und Stornorechnungen, gebuchte Eingangsbelege,
direkte Bankbuchungen mit Umsatzsteuer oder Vorsteuer sowie manuelle Buchungen auf SKR03 1576 und 1776.
</p>
<p v-if="currentPeriod" class="text-sm text-gray-500 dark:text-gray-400">
{{ currentPeriod.range }}
@@ -203,7 +221,7 @@ onMounted(loadData)
{{ formatCurrency(currentPeriod.balance) }}
</div>
<div class="mt-3 text-sm text-gray-500 dark:text-gray-400">
{{ currentPeriod.outputCount }} Ausgangsbelege | {{ currentPeriod.inputCount }} Eingangsbelege
{{ currentPeriod.outputCount }} Ausgangsbelege | {{ currentPeriod.inputCount }} Eingangsbelege | {{ currentPeriod.bankCount }} direkte Bankbuchungen
</div>
</UCard>
</div>
@@ -211,7 +229,7 @@ onMounted(loadData)
<div v-if="currentPeriod" class="mt-6 grid gap-4 xl:grid-cols-2">
<UCard>
<template #header>
<div class="font-semibold">Ausgangsrechnungen</div>
<div class="font-semibold">Umsatzsteuer aus Belegen und Bankbuchungen</div>
</template>
<div class="space-y-3 text-sm">
<div class="flex items-center justify-between">
@@ -239,7 +257,7 @@ onMounted(loadData)
<UCard>
<template #header>
<div class="font-semibold">Eingangsbelege</div>
<div class="font-semibold">Vorsteuer aus Belegen und Bankbuchungen</div>
</template>
<div class="space-y-3 text-sm">
<div class="flex items-center justify-between">
@@ -298,7 +316,7 @@ onMounted(loadData)
</template>
<template #documents-cell="{ row }">
{{ row.original.outputCount }} / {{ row.original.inputCount }}
{{ row.original.outputCount }} / {{ row.original.inputCount }} · {{ row.original.bankCount }} Bankbuchungen
</template>
<template #empty>
<TableEmptyState label="Keine Daten für die USt-Auswertung vorhanden" icon="i-heroicons-calculator" />