From 3cbd627219631c89f3003307abe61726fa3b3a4c Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 28 Aug 2026 08:31:33 +0200 Subject: [PATCH] =?UTF-8?q?Optimiere=20die=20Berechnung=20der=20Gesamt?= =?UTF-8?q?=C3=BCberstunden,=20indem=20die=20korrigierte=20Ereignisfolge?= =?UTF-8?q?=20f=C3=BCr=20die=20Tages-=20und=20Wochenanzeige=20verwendet=20?= =?UTF-8?q?wird.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/services/TimeEntryService.js | 28 ++++++------------------ 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/backend/src/services/TimeEntryService.js b/backend/src/services/TimeEntryService.js index 890d7ea..95fe96d 100755 --- a/backend/src/services/TimeEntryService.js +++ b/backend/src/services/TimeEntryService.js @@ -1052,27 +1052,13 @@ class TimeEntryService { ORDER BY DATE(COALESCE(w1_fix.fix_date_time, w1.tstamp)) `; - // Die SQL-Abfrage oben kann nur originale `state`-/`relatedTo`-Paare - // erkennen. Bei Action-Korrekturen fehlen dadurch ganze Arbeitstage in - // der Gesamtstatistik. Verwende dieselbe effektive Ereignisfolge wie - // Timer und Wochenansicht. - const netMinutesByDate = new Map(); - this._buildEffectiveWorkBlocks(await this._getEffectiveEntries(userId)) - .filter(block => block.end) - .forEach(block => { - const start = new Date(block.start.effectiveTime); - const date = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')}`; - const day = start.getDay(); - if (date > endDateStr || day === 0 || day === 6) return; - const pauses = block.pauses.reduce((sum, pause) => sum + - new Date(pause.end.effectiveTime).getTime() - new Date(pause.start.effectiveTime).getTime(), 0); - const minutes = Math.round((new Date(block.end.effectiveTime).getTime() - start.getTime() - pauses) / 60000); - netMinutesByDate.set(date, (netMinutesByDate.get(date) || 0) + minutes); - }); - const workDays = [...netMinutesByDate.entries()].map(([work_date, minutes]) => ({ - work_date, - net_hours: minutes / 60 - })); + // Die Gesamtüberstunden enthalten einen historischen Übertrag. Ihre + // etablierte SQL-Basis bleibt deshalb unverändert; die korrigierte + // Ereignisfolge wird für die laufende Tages- und Wochenanzeige genutzt. + const workDays = await sequelize.query(query, { + replacements: [userId, endDateStr], + type: sequelize.QueryTypes.SELECT + }); // Hole User-Bundesland const { State: StateModel } = database.getModels();