feat: Add excludeFromBilling option for diary dates and update related functionality
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s

This commit is contained in:
Torsten Schulz (local)
2026-05-30 16:10:34 +02:00
parent 25f3802d66
commit 9d9481ac76
12 changed files with 208 additions and 25 deletions

View File

@@ -18,14 +18,14 @@ const createDateForClub = async (req, res) => {
try {
const { clubId } = req.params;
const { authcode: userToken } = req.headers;
const { date, trainingStart, trainingEnd } = req.body;
const { date, trainingStart, trainingEnd, excludeFromBilling } = req.body;
if (!date) {
throw new HttpError('The date field is required', 400);
}
if (isNaN(new Date(date).getTime())) {
throw new HttpError('Invalid date format', 400);
}
const newDate = await diaryService.createDateForClub(userToken, clubId, date, trainingStart, trainingEnd);
const newDate = await diaryService.createDateForClub(userToken, clubId, date, trainingStart, trainingEnd, excludeFromBilling);
res.status(201).json(newDate);
} catch (error) {
console.error('[createDateForClub] - Error:', error);
@@ -37,15 +37,22 @@ const updateTrainingTimes = async (req, res) => {
try {
const { clubId } = req.params;
const { authcode: userToken } = req.headers;
const { dateId, trainingStart, trainingEnd } = req.body;
if (!dateId || !trainingStart) {
devLog(dateId, trainingStart, trainingEnd);
const { dateId, trainingStart, trainingEnd, excludeFromBilling } = req.body;
if (!dateId) {
devLog(dateId, trainingStart, trainingEnd, excludeFromBilling);
throw new HttpError('notallfieldsfilled', 400);
}
const updatedDate = await diaryService.updateTrainingTimes(userToken, clubId, dateId, trainingStart, trainingEnd);
const updatedDate = await diaryService.updateTrainingTimes(
userToken,
clubId,
dateId,
trainingStart,
trainingEnd,
excludeFromBilling,
);
// Emit Socket-Event
emitDiaryDateUpdated(clubId, dateId, { trainingStart, trainingEnd });
emitDiaryDateUpdated(clubId, dateId, { trainingStart, trainingEnd, excludeFromBilling });
res.status(200).json(updatedDate);
} catch (error) {

View File

@@ -23,6 +23,12 @@ const DiaryDate = sequelize.define('DiaryDate', {
trainingEnd: {
type: DataTypes.TIME,
allowNull: true,
},
excludeFromBilling: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'exclude_from_billing',
}
}, {
tableName: 'diary_dates',

View File

@@ -321,7 +321,8 @@ class BillingService {
clubId,
date: { [Op.between]: [periodStart, periodEnd] },
trainingStart: { [Op.ne]: null },
trainingEnd: { [Op.ne]: null }
trainingEnd: { [Op.ne]: null },
excludeFromBilling: false,
},
attributes: ['date', 'trainingStart', 'trainingEnd'],
order: [['date', 'ASC'], ['trainingStart', 'ASC']]

View File

@@ -26,7 +26,7 @@ class DiaryService {
return dates;
}
async createDateForClub(userToken, clubId, date, trainingStart, trainingEnd) {
async createDateForClub(userToken, clubId, date, trainingStart, trainingEnd, excludeFromBilling = false) {
await checkAccess(userToken, clubId);
const club = await Club.findByPk(clubId);
if (!club) {
@@ -44,12 +44,13 @@ class DiaryService {
clubId,
trainingStart: trainingStart || null,
trainingEnd: trainingEnd || null,
excludeFromBilling: Boolean(excludeFromBilling),
});
return newDate;
}
async updateTrainingTimes(userToken, clubId, dateId, trainingStart, trainingEnd) {
async updateTrainingTimes(userToken, clubId, dateId, trainingStart, trainingEnd, excludeFromBilling) {
await checkAccess(userToken, clubId);
const diaryDate = await DiaryDate.findOne({ where: { clubId, id: dateId } });
if (!diaryDate) {
@@ -60,6 +61,9 @@ class DiaryService {
}
diaryDate.trainingStart = trainingStart || null;
diaryDate.trainingEnd = trainingEnd || null;
if (excludeFromBilling !== undefined) {
diaryDate.excludeFromBilling = Boolean(excludeFromBilling);
}
await diaryDate.save();
return diaryDate;
}