feat(Scheduler, MatchService, PredefinedActivity): enhance scheduling and match fetching features

- Added new scheduler routes to manage scheduling functionalities.
- Updated match fetching logic to include a scope parameter for more flexible data retrieval.
- Introduced a new field `excludeFromStats` in the PredefinedActivity model to manage activity visibility in statistics.
- Enhanced the diary date activity controller to handle predefined activities, improving activity management.
- Refactored various services to support new features and improve overall data handling.
This commit is contained in:
Torsten Schulz (local)
2026-03-17 14:10:35 +01:00
parent f1cfd1147d
commit afe51f399c
53 changed files with 2846 additions and 926 deletions

View File

@@ -7,10 +7,11 @@ export const createDiaryDateActivity = async (req, res) => {
try {
const { authcode: userToken } = req.headers;
const { clubId } = req.params;
const { diaryDateId, activity, duration, durationText, orderId, isTimeblock } = req.body;
const { diaryDateId, activity, predefinedActivityId, duration, durationText, orderId, isTimeblock } = req.body;
const activityItem = await diaryDateActivityService.createActivity(userToken, clubId, {
diaryDateId,
activity,
predefinedActivityId,
duration,
durationText,
orderId,
@@ -197,4 +198,4 @@ export const deleteGroupActivity = async(req, res) => {
devLog(error);
res.status(500).json({ error: 'Error deleting group activity' });
}
}
}

View File

@@ -51,7 +51,8 @@ export const getMatchesForLeague = async (req, res) => {
try {
const { authcode: userToken } = req.headers;
const { clubId, leagueId } = req.params;
const matches = await MatchService.getMatchesForLeague(userToken, clubId, leagueId);
const { scope = 'own' } = req.query;
const matches = await MatchService.getMatchesForLeague(userToken, clubId, leagueId, scope);
return res.status(200).json(matches);
} catch (error) {
console.error('Error retrieving matches:', error);

View File

@@ -7,6 +7,22 @@ import PredefinedActivity from '../models/PredefinedActivity.js';
import GroupActivity from '../models/GroupActivity.js';
import { Op } from 'sequelize';
const STANDARD_ACTIVITY_NAMES = new Set([
'Begrüßung',
'Aktivierung',
'Aufbauen',
'Turnier',
'Abbauen',
'Abschlussgespräch',
]);
const isTrackablePredefinedActivity = (predefinedActivity) => {
if (!predefinedActivity) {
return false;
}
return !predefinedActivity.excludeFromStats && !STANDARD_ACTIVITY_NAMES.has(predefinedActivity.name);
};
export const getMemberActivities = async (req, res) => {
try {
const { authcode: userToken } = req.headers;
@@ -213,12 +229,18 @@ export const getMemberActivities = async (req, res) => {
if (!ga.activity || !ga.activity.id || !ga.participant || !ga.participant.id) {
return false;
}
if (!isTrackablePredefinedActivity(ga.activity.predefinedActivity)) {
return false;
}
const key = `${ga.activity.id}-${ga.participant.id}`;
return !explicitActivityKeys.has(key);
});
// Kombiniere beide Listen
const allActivities = [...filteredMemberActivities, ...uniqueGroupActivities];
const allActivities = [...filteredMemberActivities, ...uniqueGroupActivities].filter((entry) => {
const predefinedActivity = entry?.activity?.predefinedActivity;
return isTrackablePredefinedActivity(predefinedActivity);
});
// Group activities by name and count occurrences
// Verwende einen Set pro Aktivität, um eindeutige Datum-Aktivität-Kombinationen zu tracken
@@ -228,6 +250,10 @@ export const getMemberActivities = async (req, res) => {
if (!ma.activity || !ma.activity.predefinedActivity || !ma.participant) {
continue;
}
if (!isTrackablePredefinedActivity(ma.activity.predefinedActivity)) {
continue;
}
const activity = ma.activity.predefinedActivity;
const activityName = activity.name;
@@ -454,12 +480,18 @@ export const getMemberLastParticipations = async (req, res) => {
if (!ga.activity || !ga.activity.id || !ga.participant || !ga.participant.id) {
return false;
}
if (!isTrackablePredefinedActivity(ga.activity.predefinedActivity)) {
return false;
}
const key = `${ga.activity.id}-${ga.participant.id}`;
return !explicitActivityKeys.has(key);
});
// Kombiniere beide Listen
const allActivities = [...filteredMemberActivities, ...uniqueGroupActivities];
const allActivities = [...filteredMemberActivities, ...uniqueGroupActivities].filter((entry) => {
const predefinedActivity = entry?.activity?.predefinedActivity;
return isTrackablePredefinedActivity(predefinedActivity);
});
// Gruppiere nach Datum
const participationsByDate = new Map();
@@ -469,7 +501,7 @@ export const getMemberLastParticipations = async (req, res) => {
if (!ma.activity || !ma.activity.predefinedActivity || !ma.activity.diaryDate || !ma.participant) {
return false;
}
return true;
return isTrackablePredefinedActivity(ma.activity.predefinedActivity);
})
.forEach(ma => {
const date = ma.activity.diaryDate.date;
@@ -528,4 +560,3 @@ export const getMemberLastParticipations = async (req, res) => {
return res.status(500).json({ error: 'Failed to fetch member last participations' });
}
};

View File

@@ -5,8 +5,8 @@ import fs from 'fs';
export const createPredefinedActivity = async (req, res) => {
try {
const { name, code, description, durationText, duration, imageLink, drawingData } = req.body;
const predefinedActivity = await predefinedActivityService.createPredefinedActivity({ name, code, description, durationText, duration, imageLink, drawingData });
const { name, code, description, durationText, duration, imageLink, drawingData, excludeFromStats } = req.body;
const predefinedActivity = await predefinedActivityService.createPredefinedActivity({ name, code, description, durationText, duration, imageLink, drawingData, excludeFromStats });
res.status(201).json(predefinedActivity);
} catch (error) {
console.error('[createPredefinedActivity] - Error:', error);
@@ -16,7 +16,8 @@ export const createPredefinedActivity = async (req, res) => {
export const getAllPredefinedActivities = async (req, res) => {
try {
const predefinedActivities = await predefinedActivityService.getAllPredefinedActivities();
const { scope = 'all' } = req.query;
const predefinedActivities = await predefinedActivityService.getAllPredefinedActivities(scope);
res.status(200).json(predefinedActivities);
} catch (error) {
console.error('[getAllPredefinedActivities] - Error:', error);
@@ -42,8 +43,8 @@ export const getPredefinedActivityById = async (req, res) => {
export const updatePredefinedActivity = async (req, res) => {
try {
const { id } = req.params;
const { name, code, description, durationText, duration, imageLink, drawingData } = req.body;
const updatedActivity = await predefinedActivityService.updatePredefinedActivity(id, { name, code, description, durationText, duration, imageLink, drawingData });
const { name, code, description, durationText, duration, imageLink, drawingData, excludeFromStats } = req.body;
const updatedActivity = await predefinedActivityService.updatePredefinedActivity(id, { name, code, description, durationText, duration, imageLink, drawingData, excludeFromStats });
res.status(200).json(updatedActivity);
} catch (error) {
console.error('[updatePredefinedActivity] - Error:', error);