From dfd169c78da531f452397f4e675cd43f1eae1f1b Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 20 Oct 2025 11:49:33 +0200 Subject: [PATCH] Enhance TimeEntryService to incorporate timefix corrections for start and end times of work and pauses. Update logic to ensure accurate time calculations by integrating timefix data, improving the reliability of time entries. Add debug logging for better traceability of time calculations. --- backend/src/services/TimeEntryService.js | 44 +++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/backend/src/services/TimeEntryService.js b/backend/src/services/TimeEntryService.js index b3c9be1..b1cb3e1 100644 --- a/backend/src/services/TimeEntryService.js +++ b/backend/src/services/TimeEntryService.js @@ -232,6 +232,10 @@ class TimeEntryService { // Hole alle Einträge von heute (wird auch für Pausen verwendet) allEntries = await worklogRepository.findByDateRange(uid, todayStart, todayEnd); + // Hole Timefixes für alle Einträge von heute + const allEntryIds = allEntries.map(e => e.id); + const timefixMap = await worklogRepository.getTimefixesByWorklogIds(allEntryIds); + // Finde alle Start-Work-Paare von heute const workBlocks = []; const startWorks = {}; @@ -249,14 +253,22 @@ class TimeEntryService { const action = state?.action || state; if (action === 'start work') { + // Prüfe auf Timefix-Korrektur + const startFix = timefixMap.get(entry.id)?.find(f => f.fix_type === 'start work'); + const startTime = startFix?.fix_date_time || entry.tstamp; + startWorks[entry.id] = { id: entry.id, - startTime: entry.tstamp, + startTime: startTime, endTime: null, pauses: [] }; } else if (action === 'stop work' && entry.relatedTo_id && startWorks[entry.relatedTo_id]) { - startWorks[entry.relatedTo_id].endTime = entry.tstamp; + // Prüfe auf Timefix-Korrektur + const endFix = timefixMap.get(entry.id)?.find(f => f.fix_type === 'stop work'); + const endTime = endFix?.fix_date_time || entry.tstamp; + + startWorks[entry.relatedTo_id].endTime = endTime; } }); @@ -274,9 +286,13 @@ class TimeEntryService { const action = state?.action || state; if (action === 'start pause' && entry.relatedTo_id && startWorks[entry.relatedTo_id]) { + // Prüfe auf Timefix-Korrektur + const pauseStartFix = timefixMap.get(entry.id)?.find(f => f.fix_type === 'start pause'); + const pauseStartTime = pauseStartFix?.fix_date_time || entry.tstamp; + startWorks[entry.relatedTo_id].pauses.push({ id: entry.id, - startTime: entry.tstamp, + startTime: pauseStartTime, endTime: null }); } else if (action === 'stop pause' && entry.relatedTo_id) { @@ -284,7 +300,9 @@ class TimeEntryService { Object.values(startWorks).forEach(block => { const pause = block.pauses.find(p => p.id === entry.relatedTo_id); if (pause) { - pause.endTime = entry.tstamp; + // Prüfe auf Timefix-Korrektur + const pauseEndFix = timefixMap.get(entry.id)?.find(f => f.fix_type === 'stop pause'); + pause.endTime = pauseEndFix?.fix_date_time || entry.tstamp; } }); } @@ -461,6 +479,8 @@ class TimeEntryService { const missingBreakMinutes = Math.max(0, requiredBreakMinutes - alreadyTakenBreakMinutes); // Addiere fehlende Pausen zur "Offen" Zeit + console.log(`🔍 Offen Berechnung: currentlyWorked=${currentlyWorked}, open (vor Pause)=${open}, missingBreakMinutes=${missingBreakMinutes}`); + if (open && open !== '—' && open !== 'Arbeitsende erreicht') { const openParts = open.split(':'); const openH = parseInt(openParts[0]); @@ -472,6 +492,8 @@ class TimeEntryService { const newOpenM = openMinutes % 60; const newOpenS = openS; + console.log(`🔍 Offen Berechnung: open (nach Pause)=${newOpenH}:${newOpenM.toString().padStart(2, '0')}:${newOpenS.toString().padStart(2, '0')}`); + open = `${newOpenH.toString().padStart(2, '0')}:${newOpenM.toString().padStart(2, '0')}:${newOpenS.toString().padStart(2, '0')}`; } @@ -716,9 +738,12 @@ class TimeEntryService { const currentTime = new Date(); // ===== GENERELL ===== - // Verbleibende Zeit = Offen - Gesamt-Überstunden + fehlende Pausen + // Verbleibende Zeit = Offen - Gesamt-Überstunden + // WICHTIG: "open" enthält bereits die fehlenden Pausen! const generalOvertimeMinutes = totalOvertimeResult.minutes || 0; - const generalRemainingMinutes = openMinutes - generalOvertimeMinutes + missingBreakMinutes; + const generalRemainingMinutes = openMinutes - generalOvertimeMinutes; + + console.log(`🔍 Bereinigtes Arbeitsende - Generell: openMinutes=${openMinutes}, overtimeMinutes=${generalOvertimeMinutes}, remaining=${generalRemainingMinutes}`); if (generalRemainingMinutes <= 0) { adjustedEndTodayGeneral = 'Arbeitsende erreicht'; @@ -731,9 +756,12 @@ class TimeEntryService { } // ===== WOCHE ===== - // Verbleibende Zeit = Offen - Wochen-Über/Unterstunden + fehlende Pausen + // Verbleibende Zeit = Offen - Wochen-Über/Unterstunden + // WICHTIG: "open" enthält bereits die fehlenden Pausen! const weekOvertimeMinutes = overtimeMinutes; // Bereits berechnet - const weekRemainingMinutes = openMinutes - weekOvertimeMinutes + missingBreakMinutes; + const weekRemainingMinutes = openMinutes - weekOvertimeMinutes; + + console.log(`🔍 Bereinigtes Arbeitsende - Woche: openMinutes=${openMinutes}, overtimeMinutes=${weekOvertimeMinutes}, remaining=${weekRemainingMinutes}`); if (weekRemainingMinutes <= 0) { adjustedEndTodayWeek = 'Arbeitsende erreicht';