From 02b5769049ff81ecfc2c22ca3d28d12666cb798f Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Wed, 8 Apr 2026 18:52:16 +0200 Subject: [PATCH] Fix BWA Calc --- frontend/components/displayBWASummary.vue | 10 ++--- .../displayIncomeAndExpenditure.vue | 21 ++++------ frontend/composables/useDepreciation.ts | 3 ++ frontend/pages/accounting/bwa.vue | 19 +++++----- frontend/pages/accounting/depreciation.vue | 38 ++++++++++++++----- 5 files changed, 53 insertions(+), 38 deletions(-) diff --git a/frontend/components/displayBWASummary.vue b/frontend/components/displayBWASummary.vue index bd68b67..16f4ef4 100644 --- a/frontend/components/displayBWASummary.vue +++ b/frontend/components/displayBWASummary.vue @@ -7,7 +7,6 @@ import { import { getIncomingInvoiceDepreciationRows, getIncomingInvoiceImmediateExpenseNet, - getStatementAllocationDepreciationRow, getStatementAllocationImmediateExpenseAmount } from "~/composables/useDepreciation" @@ -79,9 +78,9 @@ const loadSummary = async () => { const statementDate = allocation?.bankstatement?.date || allocation?.bankstatement?.valueDate || allocation?.date || allocation?.created_at const date = dayjs(statementDate) - const amount = Number(allocation?.amount || 0) + const amount = getStatementAllocationImmediateExpenseAmount(allocation) - return amount < 0 && date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day") + return amount > 0 && date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day") }) const income = outputDocs.reduce((sum: number, doc: any) => { @@ -103,12 +102,11 @@ const loadSummary = async () => { }, 0) const directAccountExpenses = directExpenses.reduce((sum: number, allocation: any) => { - return sum + getStatementAllocationImmediateExpenseAmount(allocation) + return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0) }, 0) const depreciationRows = [ - ...inputDocs.flatMap((invoice: any) => getIncomingInvoiceDepreciationRows(invoice, bounds.start, bounds.end)), - ...(allocations || []).map((allocation: any) => getStatementAllocationDepreciationRow(allocation, bounds.start, bounds.end)).filter(Boolean) + ...inputDocs.flatMap((invoice: any) => getIncomingInvoiceDepreciationRows(invoice, bounds.start, bounds.end)) ] const depreciations = depreciationRows.reduce((sum: number, row: any) => sum + Number(row.amount || 0), 0) diff --git a/frontend/components/displayIncomeAndExpenditure.vue b/frontend/components/displayIncomeAndExpenditure.vue index 87ee6f4..c934f63 100644 --- a/frontend/components/displayIncomeAndExpenditure.vue +++ b/frontend/components/displayIncomeAndExpenditure.vue @@ -2,6 +2,10 @@ import customParseFormat from "dayjs/plugin/customParseFormat"; import dayjs from "dayjs"; import { Line } from "vue-chartjs"; +import { + getIncomingInvoiceImmediateExpenseGross, + getIncomingInvoiceImmediateExpenseNet +} from "~/composables/useDepreciation"; dayjs.extend(customParseFormat) @@ -84,7 +88,7 @@ const loadData = async () => { ]) incomeDocuments.value = (docs || []).filter((item) => item.state === "Gebucht" && ["invoices", "advanceInvoices", "cancellationInvoices"].includes(item.type)) - expenseInvoices.value = (incoming || []).filter((item) => item.date) + expenseInvoices.value = (incoming || []).filter((item) => item.state === "Gebucht" && item.date) } const yearsInData = computed(() => { @@ -128,18 +132,9 @@ const computeDocumentAmount = (doc) => { } const computeIncomingInvoiceAmount = (invoice) => { - let amount = 0 - - ;(invoice.accounts || []).forEach((account) => { - const net = Number(account.amountNet || 0) - const tax = Number(account.amountTax || 0) - const grossValue = Number(account.amountGross) - const gross = Number.isFinite(grossValue) ? grossValue : (net + tax) - - amount += amountMode.value === "gross" ? gross : net - }) - - return Number(amount.toFixed(2)) + return amountMode.value === "gross" + ? getIncomingInvoiceImmediateExpenseGross(invoice) + : getIncomingInvoiceImmediateExpenseNet(invoice) } const buckets = computed(() => { diff --git a/frontend/composables/useDepreciation.ts b/frontend/composables/useDepreciation.ts index d833449..bc870b2 100644 --- a/frontend/composables/useDepreciation.ts +++ b/frontend/composables/useDepreciation.ts @@ -291,6 +291,9 @@ export const getIncomingInvoiceDepreciationRows = (invoice: any, rangeStart: any } export const getStatementAllocationImmediateExpenseAmount = (allocation: any) => { + const hasLinkedDocument = allocation?.incominginvoice || allocation?.createddocument || allocation?.ii_id || allocation?.cd_id + if (hasLinkedDocument) return 0 + const mode = normalizeExpenseBookingMode(allocation?.bookingMode) const amount = Number(allocation?.amount || 0) if (mode !== "expense" || amount >= 0) return 0 diff --git a/frontend/pages/accounting/bwa.vue b/frontend/pages/accounting/bwa.vue index d4da15e..215010e 100644 --- a/frontend/pages/accounting/bwa.vue +++ b/frontend/pages/accounting/bwa.vue @@ -10,7 +10,6 @@ import { getIncomingInvoiceImmediateExpenseNet, isDepreciationBookingMode, normalizeIncomingInvoiceAccount, - getStatementAllocationDepreciationRow, getStatementAllocationImmediateExpenseAmount } from "~/composables/useDepreciation" @@ -156,7 +155,13 @@ const filteredStatementAllocations = computed(() => { }) const filteredAccountStatementAllocations = computed(() => { - return filteredStatementAllocations.value.filter((allocation) => allocation.account !== null && allocation.account !== undefined) + return filteredStatementAllocations.value.filter((allocation) => { + if (allocation.account === null || allocation.account === undefined) { + return false + } + + return getStatementAllocationImmediateExpenseAmount(allocation) > 0 + }) }) const selectedPeriodBounds = computed(() => { @@ -181,7 +186,7 @@ const expenseNetTotal = computed(() => { }, 0) const directAccountExpenses = filteredAccountStatementAllocations.value.reduce((sum, allocation) => { - return sum + getStatementAllocationImmediateExpenseAmount(allocation) + return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0) }, 0) const depreciations = depreciationTotal.value @@ -193,7 +198,7 @@ const expenseGrossTotal = computed(() => { const invoiceExpenses = filteredIncomingInvoices.value.reduce((sum, invoice) => sum + getIncomingInvoiceImmediateExpenseGross(invoice), 0) const directAccountExpenses = filteredAccountStatementAllocations.value.reduce((sum, allocation) => { - return sum + getStatementAllocationImmediateExpenseAmount(allocation) + return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0) }, 0) const depreciations = depreciationTotal.value @@ -249,13 +254,9 @@ const expenseDocumentCount = computed(() => { const depreciationRows = computed(() => { const invoiceRows = filteredIncomingInvoices.value.flatMap((invoice) => getIncomingInvoiceDepreciationRows(invoice, selectedPeriodBounds.value.start, selectedPeriodBounds.value.end)) - const allocationRows = filteredStatementAllocations.value - .map((allocation) => getStatementAllocationDepreciationRow(allocation, selectedPeriodBounds.value.start, selectedPeriodBounds.value.end)) - .filter(Boolean) - const grouped = new Map() - ;[...invoiceRows, ...allocationRows].forEach((row: any) => { + ;invoiceRows.forEach((row: any) => { const key = row.group || `${row.mode}:${row.label}` const current = grouped.get(key) || { id: key, diff --git a/frontend/pages/accounting/depreciation.vue b/frontend/pages/accounting/depreciation.vue index dddb7b5..378eb59 100644 --- a/frontend/pages/accounting/depreciation.vue +++ b/frontend/pages/accounting/depreciation.vue @@ -16,7 +16,8 @@ const loading = ref(true) const saving = ref(false) const incomingInvoices = ref([]) const statementAllocations = ref([]) -const asOfDate = ref(dayjs().format("YYYY-MM-DD")) +const periodStart = ref(dayjs().startOf("month").format("YYYY-MM-DD")) +const periodEnd = ref(dayjs().endOf("month").format("YYYY-MM-DD")) const selectedAsset = ref(null) const editState = ref(null) const editOpen = computed({ @@ -32,6 +33,22 @@ const formatCurrency = (value: number) => new Intl.NumberFormat("de-DE", { }).format(Number(value || 0)) const isRelevantInputInvoice = (invoice: any) => invoice?.state === "Gebucht" && !!invoice?.date +const normalizedPeriod = computed(() => { + const start = dayjs(periodStart.value) + const end = dayjs(periodEnd.value) + + if (start.isValid() && end.isValid() && start.isAfter(end, "day")) { + return { + start: end.startOf("day"), + end: start.endOf("day"), + } + } + + return { + start: start.isValid() ? start.startOf("day") : dayjs().startOf("month"), + end: end.isValid() ? end.endOf("day") : dayjs().endOf("month"), + } +}) const loadData = async () => { loading.value = true @@ -62,9 +79,9 @@ const depreciationAssets = computed(() => { depreciationStartDate: normalized.depreciationStartDate || invoice.date, depreciationMethod: normalized.depreciationMethod, residualValue: normalized.residualValue, - }, asOfDate.value) + }, normalizedPeriod.value.end) - const currentPeriodRow = getIncomingInvoiceDepreciationRows(invoice, dayjs(asOfDate.value).startOf("month"), dayjs(asOfDate.value).endOf("month")) + const currentPeriodRow = getIncomingInvoiceDepreciationRows(invoice, normalizedPeriod.value.start, normalizedPeriod.value.end) .find((row: any) => row.index === index) return { @@ -102,9 +119,9 @@ const depreciationAssets = computed(() => { depreciationStartDate: allocation.depreciationStartDate || allocation.created_at, depreciationMethod: allocation.depreciationMethod, residualValue: allocation.residualValue, - }, asOfDate.value) + }, normalizedPeriod.value.end) - const currentPeriodRow = getStatementAllocationDepreciationRow(allocation, dayjs(asOfDate.value).startOf("month"), dayjs(asOfDate.value).endOf("month")) + const currentPeriodRow = getStatementAllocationDepreciationRow(allocation, normalizedPeriod.value.start, normalizedPeriod.value.end) return { key: `allocation-${allocation.id}`, @@ -260,7 +277,8 @@ onMounted(loadData)