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
All checks were successful
Deploy production / deploy (push) Successful in 52s
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user