From 35fe771f592ed6f6640d01f31d5c39bdde0a512a Mon Sep 17 00:00:00 2001 From: jan Date: Wed, 27 May 2026 16:08:41 +0200 Subject: [PATCH] Monatsuebersicht nach Rechnungsdatum gruppieren --- src/components/dashboard/dashboard-shell.tsx | 36 ++++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/components/dashboard/dashboard-shell.tsx b/src/components/dashboard/dashboard-shell.tsx index eca90cd..7fd91ed 100644 --- a/src/components/dashboard/dashboard-shell.tsx +++ b/src/components/dashboard/dashboard-shell.tsx @@ -311,6 +311,22 @@ function getGeneralDonationCutoffSelectionValue(cutoffs: DashboardPeriodCutoff[] return createCutoffSelectionValue(cutoffs[cutoffs.length - 1].id, "POST"); } +function getExpenseFinanceDate(expense: { createdAt: string; documents: { invoiceDate: string }[] }) { + const invoiceDate = expense.documents + .map((document) => document.invoiceDate) + .sort((left, right) => new Date(left).getTime() - new Date(right).getTime())[0]; + + return new Date(invoiceDate ?? expense.createdAt); +} + +function getFinanceMonthKey(date: Date) { + return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`; +} + +function getFinanceMonthLabel(date: Date) { + return new Intl.DateTimeFormat("de-DE", { month: "long", year: "numeric" }).format(date); +} + function formatPeriodRange(startsAt: string, endsAt: string) { const formatter = new Intl.DateTimeFormat("de-DE", { dateStyle: "medium" }); return `${formatter.format(new Date(startsAt))} bis ${formatter.format(new Date(endsAt))}`; @@ -3681,10 +3697,10 @@ export function DashboardShell({ if (financeViewMode === "monthly") { const rows = new Map(); for (const expense of allExpenses) { - const date = new Date(expense.createdAt); - const key = `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`; + const date = getExpenseFinanceDate(expense); + const key = getFinanceMonthKey(date); const row = rows.get(key) ?? { - label: new Intl.DateTimeFormat("de-DE", { month: "long", year: "numeric" }).format(date), + label: getFinanceMonthLabel(date), planned: 0, approved: 0, paid: 0, @@ -3697,9 +3713,9 @@ export function DashboardShell({ } for (const donation of donations) { const date = new Date(donation.donatedAt); - const key = `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`; + const key = getFinanceMonthKey(date); const row = rows.get(key) ?? { - label: new Intl.DateTimeFormat("de-DE", { month: "long", year: "numeric" }).format(date), + label: getFinanceMonthLabel(date), planned: 0, approved: 0, paid: 0, @@ -3788,14 +3804,14 @@ export function DashboardShell({ const financeMonthOptions = (() => { const rows = new Map(); for (const expense of allExpenses) { - const date = new Date(expense.createdAt); - const key = `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`; - rows.set(key, new Intl.DateTimeFormat("de-DE", { month: "long", year: "numeric" }).format(date)); + const date = getExpenseFinanceDate(expense); + const key = getFinanceMonthKey(date); + rows.set(key, getFinanceMonthLabel(date)); } for (const donation of donations) { const date = new Date(donation.donatedAt); - const key = `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`; - rows.set(key, new Intl.DateTimeFormat("de-DE", { month: "long", year: "numeric" }).format(date)); + const key = getFinanceMonthKey(date); + rows.set(key, getFinanceMonthLabel(date)); } return [...rows.entries()].sort(([left], [right]) => left.localeCompare(right)); })();