Tauschanfragen gegen offene Plätze erlauben und Lücken nachbesetzen
Ein Wunschtag ohne Tauschpartner bedeutet jetzt: die Person übernimmt dort einen offenen Platz; ihr alter Platz wird beim Ausführen sofort fair nachbesetzt, ohne sie selbst. Rollen werden bei allen Tauschformen geprüft. Bearbeiter können Person und Wunschtag einer Anfrage nachtragen, etwa aus der Notiz. Der Anfragedialog zeigt, was am Wunschtag los ist. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
e8ab95159e
commit
42d495c54e
7 files changed
+196
-30
No files matched your search
+49
-7
@@ -11,6 +11,21 @@ export function roleOn(assignment, personId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Darf die Person diese Rolle übernehmen? */
|
||||
export function canTake(person, role) {
|
||||
if (!person || person.active === false) return false;
|
||||
return role === 'main' ? person.canMain !== false : person.canCo !== false;
|
||||
}
|
||||
|
||||
/** Offener Platz an einem Tag, den die Person übernehmen könnte: 'main', 'co' oder null. */
|
||||
export function openSlotFor(assignment, person) {
|
||||
if (!assignment || assignment.off || !person) return null;
|
||||
if (assignment.main === person.id || assignment.co === person.id) return null;
|
||||
if (!assignment.main && canTake(person, 'main')) return 'main';
|
||||
if (!assignment.co && canTake(person, 'co')) 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).
|
||||
@@ -29,37 +44,64 @@ export function validateRequest(body, persons, assignments) {
|
||||
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.' };
|
||||
if (partnerDate && !partnerId) {
|
||||
// Ohne Tauschpartner heißt der Wunsch: einen noch offenen Platz am Wunschtag übernehmen
|
||||
const me = active(personId);
|
||||
const a = assignments[partnerDate];
|
||||
if (!a || a.off) return { error: 'Am Wunschtag ist kein Meeting geplant.' };
|
||||
if (a.main === personId || a.co === personId) return { error: 'Am Wunschtag bist du schon eingeteilt.' };
|
||||
if (!openSlotFor(a, me)) return { error: 'Am Wunschtag ist kein Platz frei, den du übernehmen könntest. Nenne eine Person zum Tauschen.' };
|
||||
}
|
||||
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.
|
||||
* Tausch ausführen. Liefert { changes: [{date, role, from, to}], vacated } 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.
|
||||
* - Nur Wunschtag: die Person übernimmt dort einen offenen Platz; ihr alter Platz wird frei (vacated) und
|
||||
* sollte vom Aufrufer nachbesetzt werden.
|
||||
* - Weder noch: nicht automatisch ausführbar.
|
||||
* persons: [{ id, canMain, canCo, active }] für die Rollenprüfung.
|
||||
*/
|
||||
export function applySwap(assignments, req) {
|
||||
export function applySwap(assignments, req, persons = []) {
|
||||
const find = (id) => persons.find((p) => p.id === id) || null;
|
||||
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 me = find(req.personId);
|
||||
const changes = [];
|
||||
|
||||
if (!req.partnerId) {
|
||||
if (!req.partnerDate) throw new Error('Ohne Wunschpartner oder Wunschtag bitte den Tag öffnen und selbst jemanden auswählen.');
|
||||
const b = assignments[req.partnerDate];
|
||||
const slot = openSlotFor(b, me || { id: req.personId, canMain: true, canCo: true });
|
||||
if (!slot) throw new Error('Am Wunschtag ist kein passender Platz mehr frei. Bitte den Tag von Hand anpassen.');
|
||||
b[slot] = req.personId;
|
||||
changes.push({ date: req.partnerDate, role: slot, from: null, to: req.personId });
|
||||
a[role] = null;
|
||||
changes.push({ date: req.date, role, from: req.personId, to: null });
|
||||
return { changes, vacated: { date: req.date, role } };
|
||||
}
|
||||
|
||||
const partner = find(req.partnerId);
|
||||
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 (partner && !canTake(partner, role)) throw new Error(`Der Wunschpartner darf keine ${role === 'main' ? 'Haupt' : 'Neben'}moderation übernehmen. Bitte den Tag von Hand anpassen.`);
|
||||
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.');
|
||||
if (me && !canTake(me, partnerRole)) throw new Error(`Die anfragende Person darf keine ${partnerRole === 'main' ? 'Haupt' : 'Neben'}moderation übernehmen. 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 };
|
||||
return { changes, vacated: null };
|
||||
}
|
||||
Reference in new issue
Block a user