245 lines
7.5 KiB
JavaScript
245 lines
7.5 KiB
JavaScript
const express = require("express");
|
||
const pool = require("../db"); // PostgreSQL-Datenbankverbindung
|
||
const { requireAuth, requireRole } = require("../middleware/auth"); // Auth-Middleware
|
||
|
||
const router = express.Router();
|
||
|
||
// **Trainings abrufen (mit Geräten & Leitern)**
|
||
router.get("/:year?/:kw?", requireAuth, async (req, res) => {
|
||
const { year, kw } = req.params;
|
||
const abteilung = req.abteilung; // Abteilung aus Middleware
|
||
|
||
if (!abteilung) {
|
||
return res.status(400).json({ error: "Abteilung ist erforderlich" });
|
||
}
|
||
|
||
try {
|
||
let query;
|
||
let values = [abteilung];
|
||
|
||
if (year && kw) {
|
||
// **Trainings einer bestimmten Woche abrufen**
|
||
query = `
|
||
SELECT * FROM trainings
|
||
WHERE abteilung = $1 AND year = $2 AND kw = $3
|
||
ORDER BY year DESC, kw DESC
|
||
`;
|
||
values.push(year, kw);
|
||
} else if (year) {
|
||
// **Alle Trainings eines yeares abrufen**
|
||
query = `
|
||
SELECT * FROM trainings
|
||
WHERE abteilung = $1 AND year = $2
|
||
ORDER BY kw ASC
|
||
`;
|
||
values.push(year);
|
||
} else {
|
||
// **Alle Trainings der Abteilung abrufen**
|
||
query = `
|
||
SELECT * FROM trainings
|
||
WHERE abteilung = $1
|
||
ORDER BY year DESC, kw DESC
|
||
`;
|
||
}
|
||
|
||
const result = await pool.query(query, values);
|
||
|
||
if (result.rows.length === 0) {
|
||
return res.status(404).json({ error: "Keine Trainings gefunden" });
|
||
}
|
||
|
||
return res.json(result.rows);
|
||
} catch (err) {
|
||
console.error(err);
|
||
res.status(500).json({ error: "Interner Serverfehler" });
|
||
}
|
||
});
|
||
|
||
router.post("/leiten/:id", requireAuth, requireRole(3), async (req, res) => {
|
||
const { id } = req.params; // Trainings-ID
|
||
const abteilung = req.abteilung; // Abteilung aus Middleware
|
||
const { fid_helfer, fid_spiel, typ, action } = req.body; // Daten aus POST-Body
|
||
|
||
if (!action || !["new", "update"].includes(action)) {
|
||
return res.status(400).json({
|
||
error: 'Es muss "new" oder "update" als action angegeben werden',
|
||
});
|
||
}
|
||
if (!fid_helfer || !typ) {
|
||
return res
|
||
.status(400)
|
||
.json({ error: "fid_helfer und typ sind erforderlich" });
|
||
}
|
||
if (typ !== "a" && typ !== "s") {
|
||
return res
|
||
.status(400)
|
||
.json({ error: 'Typ muss "a" (Aufwärmen) oder "s" (Spiel) sein' });
|
||
}
|
||
|
||
try {
|
||
if (action === "new") {
|
||
// **Neuen Eintrag erstellen**
|
||
const result = await pool.query(
|
||
`INSERT INTO leiten (fid_training, fid_helfer, fid_spiel, typ)
|
||
VALUES ($1, $2, $3, $4)
|
||
RETURNING *`,
|
||
[id, fid_helfer, fid_spiel || null, typ]
|
||
);
|
||
|
||
return res.status(201).json({
|
||
message: "Leiten erfolgreich hinzugefügt",
|
||
leiten: result.rows[0],
|
||
});
|
||
} else {
|
||
// **Vorhandenen Eintrag aktualisieren**
|
||
const checkLeiten = await pool.query(
|
||
`SELECT * FROM leiten WHERE fid_training = $1 AND fid_helfer = $2 AND typ = $3`,
|
||
[id, fid_helfer, typ]
|
||
);
|
||
|
||
if (checkLeiten.rows.length === 0) {
|
||
return res
|
||
.status(404)
|
||
.json({ error: "Kein passender Leiten-Eintrag gefunden" });
|
||
}
|
||
|
||
const updateResult = await pool.query(
|
||
`UPDATE leiten
|
||
SET fid_spiel = $1
|
||
WHERE fid_training = $2 AND fid_helfer = $3 AND typ = $4
|
||
RETURNING *`,
|
||
[fid_spiel || null, id, fid_helfer, typ]
|
||
);
|
||
|
||
return res.json({
|
||
message: "Leiten erfolgreich aktualisiert",
|
||
leiten: updateResult.rows[0],
|
||
});
|
||
}
|
||
} catch (err) {
|
||
console.error(err);
|
||
res.status(500).json({ error: "Interner Serverfehler" });
|
||
}
|
||
});
|
||
|
||
router.post("/new/:jahr/:kw", requireAuth, requireRole(2), async (req, res) => {
|
||
const { jahr, kw } = req.params;
|
||
const abteilung = req.abteilung; // Abteilung aus Middleware
|
||
|
||
if (!abteilung) {
|
||
return res.status(400).json({ error: "Abteilung ist erforderlich" });
|
||
}
|
||
|
||
try {
|
||
await pool.query("BEGIN"); // Transaktion starten
|
||
|
||
// **1. Prüfen, ob bereits ein Training in dieser Woche existiert**
|
||
const existingTraining = await pool.query(
|
||
`SELECT id FROM trainings WHERE year = $1 AND kw = $2 AND abteilung = $3`,
|
||
[jahr, kw, abteilung]
|
||
);
|
||
|
||
if (existingTraining.rows.length > 0) {
|
||
await pool.query("ROLLBACK");
|
||
return res
|
||
.status(400)
|
||
.json({ error: "Training für diese Woche existiert bereits" });
|
||
}
|
||
|
||
// **2. Prüfen, ob die Abteilung Riegen hat**
|
||
const abteilungResult = await pool.query(
|
||
`SELECT riegen, geraete FROM abteilungen WHERE id = $1`,
|
||
[abteilung]
|
||
);
|
||
|
||
if (abteilungResult.rows.length === 0) {
|
||
return res.status(404).json({ error: "Abteilung nicht gefunden" });
|
||
}
|
||
|
||
const { riegen, geraete } = abteilungResult.rows[0]; // `riegen = true/false`, `geraete` = int[]
|
||
|
||
// **3. Neues Training anlegen**
|
||
const trainingResult = await pool.query(
|
||
`INSERT INTO trainings (year, kw, abteilung) VALUES ($1, $2, $3) RETURNING id`,
|
||
[jahr, kw, abteilung]
|
||
);
|
||
|
||
const trainingId = trainingResult.rows[0].id;
|
||
|
||
let geraeteplan = [];
|
||
|
||
if (riegen) {
|
||
// **4. Die letzten zwei Trainings abrufen**
|
||
const lastTrainings = await pool.query(
|
||
`SELECT g.geraete
|
||
FROM trainings t
|
||
JOIN geraeteplan g ON t.id = g.fid_training
|
||
WHERE t.abteilung = $1
|
||
ORDER BY t.year DESC, t.kw DESC
|
||
LIMIT 2`,
|
||
[abteilung]
|
||
);
|
||
|
||
let lastUsed1 =
|
||
lastTrainings.rows.length > 0 ? lastTrainings.rows[0].geraete : [];
|
||
let lastUsed2 =
|
||
lastTrainings.rows.length > 1 ? lastTrainings.rows[1].geraete : [];
|
||
|
||
// **5. Falls eines der letzten beiden Trainings Geräte 11–13 enthielt → Letztes gültiges Training nehmen**
|
||
if (lastUsed1.some((g) => g >= 11 && g <= 13)) {
|
||
lastUsed1 = [];
|
||
}
|
||
if (lastUsed2.some((g) => g >= 11 && g <= 13)) {
|
||
lastUsed2 = [];
|
||
}
|
||
|
||
// **6. Bestimmen, ob hochgezählt werden soll**
|
||
let nextGeraete = [];
|
||
|
||
if (
|
||
lastUsed1.length > 0 &&
|
||
JSON.stringify(lastUsed1) === JSON.stringify(lastUsed2)
|
||
) {
|
||
// Hochzählen, weil die letzten beiden Trainings identisch waren
|
||
let lastDeviceIndex = geraete.findIndex((g) => g === lastUsed1[0]);
|
||
|
||
// Falls letztes Gerät 10 war, dann zurück auf 1
|
||
let nextDevice = geraete[(lastDeviceIndex + 1) % geraete.length];
|
||
if (lastUsed1[0] === 10) {
|
||
nextDevice = 1;
|
||
}
|
||
|
||
nextGeraete = [nextDevice, ...lastUsed1.slice(0, 4)];
|
||
} else if (lastUsed1.length > 0) {
|
||
// Letztes Training wiederholen
|
||
nextGeraete = lastUsed1;
|
||
} else {
|
||
// Erstes Training → Starte mit den ersten fünf Geräten
|
||
nextGeraete = geraete.slice(0, 5);
|
||
}
|
||
|
||
// **7. Geräteplan speichern als int[]**
|
||
await pool.query(
|
||
`INSERT INTO geraeteplan (fid_training, geraete) VALUES ($1, $2)`,
|
||
[trainingId, nextGeraete]
|
||
);
|
||
|
||
geraeteplan = nextGeraete;
|
||
}
|
||
|
||
await pool.query("COMMIT"); // Transaktion abschließen
|
||
|
||
res.status(201).json({
|
||
message: "Training erfolgreich erstellt",
|
||
training: { id: trainingId, year: jahr, kw, abteilung },
|
||
geraeteplan,
|
||
});
|
||
} catch (err) {
|
||
await pool.query("ROLLBACK"); // Falls Fehler, Transaktion rückgängig machen
|
||
console.error(err);
|
||
res.status(500).json({ error: "Interner Serverfehler" });
|
||
}
|
||
});
|
||
|
||
module.exports = router;
|