From 46b08b29b9c0818967d896b1fd445f7531a85e69 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Thu, 23 Apr 2026 21:18:11 +0200 Subject: [PATCH] =?UTF-8?q?Regelm=C3=A4=C3=9Fige=20Bewegungen=20auf=20Ausg?= =?UTF-8?q?aben=20begrenzen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Berücksichtigt in der Liquiditätsprognose nur noch negative, also ausgehende, wiederkehrende Bankbewegungen aus Heuristik und KI-Erkennung. --- backend/src/utils/liquidityForecast.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/utils/liquidityForecast.ts b/backend/src/utils/liquidityForecast.ts index 986d40f..e9d8b3d 100644 --- a/backend/src/utils/liquidityForecast.ts +++ b/backend/src/utils/liquidityForecast.ts @@ -157,7 +157,7 @@ const detectRecurringHeuristically = (statements: any[]): RecurringCandidate[] = statements.forEach((statement) => { const parsedDate = dayjs(statement.valueDate || statement.date); - if (!parsedDate.isValid()) return; + if (!parsedDate.isValid() || Number(statement.amount || 0) >= 0) return; const partner = normalizeText(getStatementPartner(statement)); const purpose = normalizeText(statement.text).split(" ").slice(0, 5).join(" "); @@ -236,6 +236,7 @@ const detectRecurringWithAi = async (server: FastifyInstance, statements: any[]) return (completion.choices[0].message.parsed?.candidates || []) .filter((candidate) => dayjs(candidate.nextDate).isValid()) + .filter((candidate) => Number(candidate.amount || 0) < 0) .map((candidate) => ({ ...candidate, amount: roundMoney(candidate.amount), @@ -270,6 +271,7 @@ const mergeRecurringCandidates = (heuristic: RecurringCandidate[], ai: Recurring ...candidate, key: getRecurringKey(candidate), })) + .filter((candidate) => Number(candidate.amount || 0) < 0) .filter((candidate) => Math.abs(candidate.amount) >= 1) .sort((a, b) => a.nextDate.localeCompare(b.nextDate)); };