Verbessere die Verarbeitung von Zeiteinträgen und integriere Zeitkorrekturen in die Logik zur Erstellung von Arbeitsblöcken
All checks were successful
Deploy production / deploy (push) Successful in 52s

This commit is contained in:
Torsten Schulz (local)
2026-08-27 08:31:12 +02:00
parent c239ef19d1
commit 9274500443
2 changed files with 68 additions and 7 deletions

View File

@@ -1283,18 +1283,74 @@ class TimeEntryService {
const weekEnd = new Date(year, month, day + daysToMonday + (weekOffset * 7) + 6); const weekEnd = new Date(year, month, day + daysToMonday + (weekOffset * 7) + 6);
weekEnd.setHours(23, 59, 59, 999); weekEnd.setHours(23, 59, 59, 999);
// Hole alle Worklog-Einträge für diese Woche
const pairs = await worklogRepository.findPairsByUserInDateRange(uid, weekStart, weekEnd);
// Hole auch alle einzelnen Einträge für Pausen // Hole auch alle einzelnen Einträge für Pausen
const allEntries = await worklogRepository.findByDateRange(uid, weekStart, weekEnd); const allEntries = await worklogRepository.findByDateRange(uid, weekStart, weekEnd);
// Hole Timefix-Einträge für alle Worklog-IDs // Hole Timefix-Einträge für alle Worklog-IDs
const allWorklogIds = [...new Set([ const allWorklogIds = [...new Set(allEntries.map(e => e.id))];
...pairs.map(p => p.id),
...allEntries.map(e => e.id)
])];
const timefixMap = await worklogRepository.getTimefixesByWorklogIds(allWorklogIds); const timefixMap = await worklogRepository.getTimefixesByWorklogIds(allWorklogIds);
// Arbeitsblöcke aus den effektiven Aktionen bilden. Eine Zeitkorrektur
// kann nicht nur den Zeitpunkt, sondern auch den Aktionstyp ändern (z. B.
// „Pause beginnen“ zu „Arbeit beenden“). Die Repository-Paarbildung kennt
// nur die Original-Aktion und würde einen solchen Block als laufend lassen.
const getAction = (entry) => {
const fixes = timefixMap.get(entry.id);
if (fixes?.length) return fixes[fixes.length - 1].fix_type;
let state = entry.state;
if (typeof state === 'string') {
try {
state = JSON.parse(state);
} catch (_) {
// Der String ist bereits die Aktion.
}
}
return state?.action || state;
};
const getEffectiveTime = (entry) => {
const fixes = timefixMap.get(entry.id);
const fix = fixes?.[fixes.length - 1];
if (!fix) return entry.tstamp;
return typeof fix.fix_date_time === 'string'
? fix.fix_date_time.replace(' ', 'T') + 'Z'
: fix.fix_date_time;
};
const pairs = [];
const openWorkEntries = new Map();
[...allEntries]
.sort((a, b) => new Date(getEffectiveTime(a)) - new Date(getEffectiveTime(b)))
.forEach(entry => {
const action = getAction(entry);
if (action === 'start work') {
openWorkEntries.set(String(entry.id), entry);
} else if (action === 'stop work' && entry.relatedTo_id) {
const startEntry = openWorkEntries.get(String(entry.relatedTo_id));
if (startEntry) {
pairs.push({
id: startEntry.id,
end_id: entry.id,
start_time: startEntry.tstamp,
end_time: entry.tstamp,
start_state: startEntry.state,
end_state: entry.state
});
openWorkEntries.delete(String(entry.relatedTo_id));
}
}
});
openWorkEntries.forEach(startEntry => {
pairs.push({
id: startEntry.id,
start_time: startEntry.tstamp,
end_time: null,
start_state: startEntry.state,
end_state: null
});
});
// Hole Vacation-Einträge für diese Woche // Hole Vacation-Einträge für diese Woche
const vacations = await worklogRepository.getVacationsByUserInDateRange(uid, weekStart, weekEnd); const vacations = await worklogRepository.getVacationsByUserInDateRange(uid, weekStart, weekEnd);

View File

@@ -481,6 +481,11 @@ do_update() {
print_info "Kopiere Frontend..." print_info "Kopiere Frontend..."
rsync -av --exclude 'node_modules' --exclude 'dist' --exclude '.env*' --delete "$CURRENT_DIR/frontend/" "$FRONTEND_DIR/" rsync -av --exclude 'node_modules' --exclude 'dist' --exclude '.env*' --delete "$CURRENT_DIR/frontend/" "$FRONTEND_DIR/"
# Der Workspace-Lock gilt für Backend und Frontend gemeinsam und muss bei
# jedem Update mit dem Quell-Checkout synchronisiert werden.
print_info "Kopiere Workspace-Metadaten..."
rsync -av "$CURRENT_DIR/package.json" "$CURRENT_DIR/package-lock.json" "$PROJECT_DIR/"
print_info "Kopiere Konfigurations-Dateien..." print_info "Kopiere Konfigurations-Dateien..."
rsync -av "$CURRENT_DIR"/*.{sh,conf,md,service} "$PROJECT_DIR/" 2>/dev/null || true rsync -av "$CURRENT_DIR"/*.{sh,conf,md,service} "$PROJECT_DIR/" 2>/dev/null || true