168 lines
4.6 KiB
JavaScript
168 lines
4.6 KiB
JavaScript
const database = require('../config/database');
|
|
const { Op } = require('sequelize');
|
|
|
|
/**
|
|
* Service-Klasse für Zeitwünsche (Timewish)
|
|
* Verwaltet gewünschte Arbeitszeiten pro Wochentag und Zeitraum
|
|
*/
|
|
class TimewishService {
|
|
/**
|
|
* Holt alle Zeitwünsche eines Users
|
|
* @param {number} userId - Benutzer-ID
|
|
* @returns {Promise<Array>} Array von Zeitwünschen
|
|
*/
|
|
async getAllTimewishes(userId) {
|
|
const { Timewish } = database.getModels();
|
|
|
|
const timewishes = await Timewish.findAll({
|
|
where: {
|
|
user_id: userId
|
|
},
|
|
order: [['day', 'ASC'], ['start_date', 'DESC']],
|
|
raw: true
|
|
});
|
|
|
|
// Konvertiere DB-Format zu Frontend-Format
|
|
const dayNames = {
|
|
1: 'Montag',
|
|
2: 'Dienstag',
|
|
3: 'Mittwoch',
|
|
4: 'Donnerstag',
|
|
5: 'Freitag',
|
|
6: 'Samstag',
|
|
7: 'Sonntag'
|
|
};
|
|
|
|
const wishtypeNames = {
|
|
0: 'Kein Wunsch',
|
|
1: 'Frei',
|
|
2: 'Arbeit'
|
|
};
|
|
|
|
return timewishes.map(tw => ({
|
|
id: tw.id,
|
|
day: tw.day,
|
|
dayName: dayNames[tw.day] || `Tag ${tw.day}`,
|
|
wishtype: tw.wishtype,
|
|
wishtypeName: wishtypeNames[tw.wishtype] || 'Unbekannt',
|
|
hours: tw.hours,
|
|
startDate: tw.start_date,
|
|
endDate: tw.end_date
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Erstellt einen neuen Zeitwunsch
|
|
* @param {number} userId - Benutzer-ID
|
|
* @param {number} day - Wochentag (1=Mo, 7=So)
|
|
* @param {number} wishtype - Typ (0=Kein Wunsch, 1=Frei, 2=Arbeit)
|
|
* @param {number} hours - Stunden (nur bei wishtype=2)
|
|
* @param {string} startDate - Startdatum (YYYY-MM-DD)
|
|
* @param {string} endDate - Enddatum (YYYY-MM-DD, optional)
|
|
* @returns {Promise<Object>} Erstellter Zeitwunsch
|
|
*/
|
|
async createTimewish(userId, day, wishtype, hours, startDate, endDate) {
|
|
const { Timewish } = database.getModels();
|
|
|
|
// Validierung
|
|
if (day < 1 || day > 7) {
|
|
throw new Error('Wochentag muss zwischen 1 (Montag) und 7 (Sonntag) liegen');
|
|
}
|
|
|
|
if (wishtype < 0 || wishtype > 2) {
|
|
throw new Error('Ungültiger Wunschtyp');
|
|
}
|
|
|
|
if (wishtype === 2 && (!hours || hours < 0 || hours > 24)) {
|
|
throw new Error('Arbeitsstunden müssen zwischen 0 und 24 liegen');
|
|
}
|
|
|
|
if (!startDate) {
|
|
throw new Error('Startdatum ist erforderlich');
|
|
}
|
|
|
|
// Prüfe auf Überschneidungen
|
|
const overlapping = await Timewish.findOne({
|
|
where: {
|
|
user_id: userId,
|
|
day: day,
|
|
[Op.or]: [
|
|
// Fall 1: Neuer Eintrag hat kein Enddatum (gilt ab start_date)
|
|
endDate ? {} : {
|
|
[Op.or]: [
|
|
// Bestehender Eintrag hat kein Enddatum UND start_date <= neuer start_date
|
|
{
|
|
end_date: null,
|
|
start_date: { [Op.lte]: startDate }
|
|
},
|
|
// Bestehender Eintrag hat Enddatum UND überlappt
|
|
{
|
|
end_date: { [Op.gte]: startDate }
|
|
}
|
|
]
|
|
},
|
|
// Fall 2: Neuer Eintrag hat Enddatum
|
|
endDate ? {
|
|
[Op.or]: [
|
|
// Bestehender Eintrag hat kein Enddatum UND start_date <= neues end_date
|
|
{
|
|
end_date: null,
|
|
start_date: { [Op.lte]: endDate }
|
|
},
|
|
// Bestehender Eintrag hat Enddatum UND überlappt
|
|
{
|
|
start_date: { [Op.lte]: endDate },
|
|
end_date: { [Op.gte]: startDate }
|
|
}
|
|
]
|
|
} : {}
|
|
]
|
|
}
|
|
});
|
|
|
|
if (overlapping) {
|
|
throw new Error(`Überschneidung mit bestehendem Zeitwunsch: ${overlapping.start_date} - ${overlapping.end_date || 'unbegrenzt'}`);
|
|
}
|
|
|
|
const timewish = await Timewish.create({
|
|
user_id: userId,
|
|
day,
|
|
wishtype,
|
|
hours: wishtype === 2 ? hours : null,
|
|
start_date: startDate,
|
|
end_date: endDate || null,
|
|
version: 0
|
|
});
|
|
|
|
// Formatiere für Response
|
|
const allTimewishes = await this.getAllTimewishes(userId);
|
|
return allTimewishes.find(tw => tw.id === timewish.id);
|
|
}
|
|
|
|
/**
|
|
* Löscht einen Zeitwunsch
|
|
* @param {number} userId - Benutzer-ID
|
|
* @param {number} timewishId - Timewish-ID
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async deleteTimewish(userId, timewishId) {
|
|
const { Timewish } = database.getModels();
|
|
|
|
const timewish = await Timewish.findByPk(timewishId);
|
|
|
|
if (!timewish) {
|
|
throw new Error('Zeitwunsch nicht gefunden');
|
|
}
|
|
|
|
// Prüfe Berechtigung
|
|
if (timewish.user_id !== userId) {
|
|
throw new Error('Keine Berechtigung für diesen Eintrag');
|
|
}
|
|
|
|
await timewish.destroy();
|
|
}
|
|
}
|
|
|
|
module.exports = new TimewishService();
|
|
|