// Tauschanfragen: Betrachter melden, dass sie an einem Tag nicht können; Bearbeiter führen den Tausch aus. import { isValidDate } from './scheduler.js'; export const REQUEST_STATUS = ['offen', 'erledigt', 'abgelehnt']; /** Rolle einer Person an einem Tag: 'main', 'co' oder null. */ export function roleOn(assignment, personId) { if (!assignment || assignment.off || !personId) return null; if (assignment.main === personId) return 'main'; if (assignment.co === personId) return 'co'; return null; } /** * Eingabe einer Anfrage prüfen. persons: [{id, active}], assignments: { date: {main, co, off} }. * Liefert { error } oder { request } (ohne id/status/createdAt). */ export function validateRequest(body, persons, assignments) { const b = body || {}; const active = (id) => persons.find((p) => p.id === id && p.active !== false); const personId = String(b.personId || ''); if (!active(personId)) return { error: 'Bitte wähle deinen Namen.' }; const date = String(b.date || ''); if (!isValidDate(date)) return { error: 'Ungültiger Tag.' }; const role = roleOn(assignments[date], personId); if (!role) return { error: 'An diesem Tag bist du laut Plan nicht eingeteilt.' }; const partnerId = b.partnerId ? String(b.partnerId) : null; if (partnerId && !active(partnerId)) return { error: 'Tauschpartner nicht gefunden.' }; if (partnerId === personId) return { error: 'Mit dir selbst kannst du nicht tauschen.' }; const partnerDate = b.partnerDate ? String(b.partnerDate) : null; if (partnerDate && !isValidDate(partnerDate)) return { error: 'Ungültiger Wunschtag.' }; if (partnerDate && !partnerId) return { error: 'Zum Wunschtag bitte auch die Person angeben, mit der du tauschen möchtest.' }; if (partnerDate === date) return { error: 'Der Wunschtag ist derselbe Tag.' }; const note = String(b.note || '').trim().slice(0, 300); return { request: { personId, date, role, partnerId, partnerDate, note } }; } /** * Tausch ausführen. Liefert { changes: [{date, role, from, to}] } und verändert assignments direkt. * Fälle: * - Partner + Wunschtag: über Kreuz – Partner übernimmt den Tag des Anfragenden, dieser den Slot des Partners am Wunschtag. * - Nur Partner: Partner übernimmt den Slot des Anfragenden. * - Ohne Partner: nicht automatisch ausführbar. */ export function applySwap(assignments, req) { const a = assignments[req.date]; const role = roleOn(a, req.personId); if (!role) throw new Error('Die Person ist an diesem Tag nicht mehr eingeteilt. Bitte den Tag von Hand anpassen.'); if (!req.partnerId) throw new Error('Ohne Wunschpartner bitte den Tag öffnen und selbst jemanden auswählen.'); const otherRole = role === 'main' ? 'co' : 'main'; if (a[otherRole] === req.partnerId) throw new Error('Der Wunschpartner ist an diesem Tag schon die andere Moderation. Bitte den Tag von Hand anpassen.'); const changes = []; if (req.partnerDate) { const b = assignments[req.partnerDate]; const partnerRole = roleOn(b, req.partnerId); if (!partnerRole) throw new Error('Der Wunschpartner ist am Wunschtag nicht eingeteilt. Bitte den Tag von Hand anpassen.'); const otherB = partnerRole === 'main' ? 'co' : 'main'; if (b[otherB] === req.personId) throw new Error('Die anfragende Person ist am Wunschtag schon die andere Moderation. Bitte den Tag von Hand anpassen.'); b[partnerRole] = req.personId; changes.push({ date: req.partnerDate, role: partnerRole, from: req.partnerId, to: req.personId }); } a[role] = req.partnerId; changes.push({ date: req.date, role, from: req.personId, to: req.partnerId }); return { changes }; }