From 78692338f7687b6bca67db13a220152eb909739f Mon Sep 17 00:00:00 2001 From: jan Date: Wed, 27 May 2026 15:58:24 +0200 Subject: [PATCH] Monatsabos automatisch Stichtagen zuordnen --- src/components/dashboard/dashboard-shell.tsx | 36 ++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/dashboard/dashboard-shell.tsx b/src/components/dashboard/dashboard-shell.tsx index 0988073..eca90cd 100644 --- a/src/components/dashboard/dashboard-shell.tsx +++ b/src/components/dashboard/dashboard-shell.tsx @@ -2445,7 +2445,12 @@ export function DashboardShell({ }} required fullWidth - disabled={expenseCutoffOptions.length === 0} + disabled={expenseCutoffOptions.length === 0 || expenseForm.recurrence === "MONTHLY"} + helperText={ + expenseForm.recurrence === "MONTHLY" + ? "Monatliche Abos werden anhand ihrer Fälligkeit automatisch den Stichtagen zugeordnet." + : undefined + } > {expenseCutoffOptions.map((option) => ( @@ -3713,11 +3718,29 @@ export function DashboardShell({ const expenseById = new Map(allExpenses.map((expense) => [expense.id, expense])); const rows = expenseCutoffOptions.map((option) => { const expenses = allExpenses.filter( - (expense) => expense.cutoffId === option.cutoffId && expense.cutoffPhase === option.cutoffPhase + (expense) => + expense.recurrence !== "MONTHLY" && + expense.cutoffId === option.cutoffId && + expense.cutoffPhase === option.cutoffPhase + ); + const monthlyOccurrences = allExpenses.flatMap((expense) => + expense.recurrence === "MONTHLY" + ? expense.occurrences + .filter((occurrence) => getGeneralDonationCutoffSelectionValue(currentCutoffs, occurrence.dueAt) === option.value) + .map((occurrence) => ({ + amount: occurrence.amount, + approvalStatus: expense.approvalStatus, + paidAt: expense.paidAt + })) + : [] ); const donationsForSection = donations.filter((donation) => { if (donation.expenseId) { const expense = expenseById.get(donation.expenseId); + if (expense?.recurrence === "MONTHLY") { + return getGeneralDonationCutoffSelectionValue(currentCutoffs, donation.donatedAt) === option.value; + } + return ( expense?.cutoffId === option.cutoffId && expense.cutoffPhase === option.cutoffPhase @@ -3732,12 +3755,19 @@ export function DashboardShell({ planned: expenses.reduce( (sum, expense) => sum + (expense.approvalStatus === "PENDING" ? expense.netPeriodAmount : 0), 0 + ) + monthlyOccurrences.reduce( + (sum, occurrence) => sum + (occurrence.approvalStatus === "PENDING" ? occurrence.amount : 0), + 0 ), approved: expenses.reduce( (sum, expense) => sum + (expense.approvalStatus === "APPROVED" ? expense.netPeriodAmount : 0), 0 + ) + monthlyOccurrences.reduce( + (sum, occurrence) => sum + (occurrence.approvalStatus === "APPROVED" ? occurrence.amount : 0), + 0 ), - paid: expenses.reduce((sum, expense) => sum + (expense.paidAt ? expense.netPeriodAmount : 0), 0), + paid: expenses.reduce((sum, expense) => sum + (expense.paidAt ? expense.netPeriodAmount : 0), 0) + + monthlyOccurrences.reduce((sum, occurrence) => sum + (occurrence.paidAt ? occurrence.amount : 0), 0), donations: donationsForSection.reduce((sum, donation) => sum + donation.amount, 0) }; });