Implementierung Datenbank pflege wegen doppelten einträgen

This commit is contained in:
2026-03-16 15:59:33 +01:00
parent 164cd78f3d
commit 5a8dcf2cb5
3 changed files with 249 additions and 0 deletions

View File

@@ -322,6 +322,96 @@ function registerAdminRoutes(app) {
});
}
});
// Timesheet-Duplikate (mehr als ein Eintrag pro Benutzer und Datum) als Übersicht
app.get('/admin/api/timesheet-duplicates', requireAdmin, (req, res) => {
const sql = `
SELECT
te.*,
dup.entry_count,
u.firstname,
u.lastname,
u.username
FROM timesheet_entries te
INNER JOIN (
SELECT user_id, date, COUNT(*) AS entry_count
FROM timesheet_entries
GROUP BY user_id, date
HAVING COUNT(*) > 1
) dup
ON dup.user_id = te.user_id
AND dup.date = te.date
INNER JOIN users u
ON u.id = te.user_id
ORDER BY te.user_id, te.date, te.id
`;
db.all(sql, [], (err, rows) => {
if (err) {
console.error('Fehler beim Laden der Timesheet-Duplikate:', err);
return res.status(500).json({ error: 'Fehler beim Laden der Timesheet-Duplikate' });
}
const groupsMap = new Map();
(rows || []).forEach(row => {
const key = `${row.user_id}|${row.date}`;
if (!groupsMap.has(key)) {
const userNameParts = [];
if (row.firstname) userNameParts.push(row.firstname);
if (row.lastname) userNameParts.push(row.lastname);
const user_name = userNameParts.join(' ') || row.username || `User #${row.user_id}`;
groupsMap.set(key, {
user_id: row.user_id,
user_name,
username: row.username,
date: row.date,
entry_count: row.entry_count,
entries: []
});
}
const group = groupsMap.get(key);
group.entries.push({
id: row.id,
start_time: row.start_time,
end_time: row.end_time,
break_minutes: row.break_minutes,
total_hours: row.total_hours,
status: row.status,
notes: row.notes,
created_at: row.created_at,
updated_at: row.updated_at
});
});
const groups = Array.from(groupsMap.values());
res.json({ groups });
});
});
// Einzelnen Timesheet-Eintrag löschen (zur manuellen Bereinigung von Duplikaten)
app.delete('/admin/api/timesheet-entry/:id', requireAdmin, (req, res) => {
const entryId = parseInt(req.params.id, 10);
if (!Number.isInteger(entryId) || entryId <= 0) {
return res.status(400).json({ error: 'Ungültige Eintrags-ID' });
}
db.run('DELETE FROM timesheet_entries WHERE id = ?', [entryId], function(err) {
if (err) {
console.error('Fehler beim Löschen des Timesheet-Eintrags:', err);
return res.status(500).json({ error: 'Fehler beim Löschen des Timesheet-Eintrags' });
}
if (this.changes === 0) {
return res.status(404).json({ error: 'Timesheet-Eintrag nicht gefunden' });
}
res.json({ success: true });
});
});
}
module.exports = registerAdminRoutes;