Refactor member activity retrieval to include group activities and eliminate duplicates
This commit enhances the `getMemberActivities` and `getMemberLastParticipations` functions by introducing logic to gather group activities for members based on their group associations. It ensures that both explicitly assigned member activities and group activities are combined while filtering out duplicates. The overall structure of the activity retrieval process is improved for better clarity and efficiency, enhancing the accuracy of the data returned to the frontend.
This commit is contained in:
@@ -49,13 +49,19 @@ export const getMemberActivities = async (req, res) => {
|
||||
|
||||
const participantIds = participants.map(p => p.id);
|
||||
|
||||
// Get all diary member activities for this member
|
||||
const whereClause = {
|
||||
participantId: participantIds
|
||||
};
|
||||
// Sammle alle Gruppen-IDs, zu denen der Member gehört
|
||||
const memberGroupIds = new Set();
|
||||
participants.forEach(p => {
|
||||
if (p.groupId !== null && p.groupId !== undefined) {
|
||||
memberGroupIds.add(p.groupId);
|
||||
}
|
||||
});
|
||||
|
||||
// 1. Get all diary member activities explicitly assigned to this member
|
||||
const memberActivities = await DiaryMemberActivity.findAll({
|
||||
where: whereClause,
|
||||
where: {
|
||||
participantId: participantIds
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Participant,
|
||||
@@ -90,28 +96,90 @@ export const getMemberActivities = async (req, res) => {
|
||||
order: [[{ model: DiaryDateActivity, as: 'activity' }, { model: DiaryDates, as: 'diaryDate' }, 'date', 'DESC']]
|
||||
});
|
||||
|
||||
// Group activities by name and count occurrences, considering group assignment
|
||||
// 2. Get all group activities for groups the member belongs to
|
||||
const groupActivities = [];
|
||||
if (memberGroupIds.size > 0) {
|
||||
const groupActivitiesData = await DiaryDateActivity.findAll({
|
||||
include: [
|
||||
{
|
||||
model: DiaryDates,
|
||||
as: 'diaryDate',
|
||||
where: startDate ? {
|
||||
date: {
|
||||
[Op.gte]: startDate
|
||||
}
|
||||
} : {}
|
||||
},
|
||||
{
|
||||
model: PredefinedActivity,
|
||||
as: 'predefinedActivity',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
model: GroupActivity,
|
||||
as: 'groupActivities',
|
||||
where: {
|
||||
groupId: {
|
||||
[Op.in]: Array.from(memberGroupIds)
|
||||
}
|
||||
},
|
||||
required: true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Erstelle virtuelle DiaryMemberActivity-Objekte für Gruppen-Aktivitäten
|
||||
for (const activity of groupActivitiesData) {
|
||||
// Finde den entsprechenden Participant für diese Aktivität
|
||||
const diaryDateId = activity.diaryDateId;
|
||||
const relevantParticipants = participants.filter(p => p.diaryDateId === diaryDateId);
|
||||
|
||||
for (const participant of relevantParticipants) {
|
||||
// Prüfe, ob die Aktivität für die Gruppe des Participants ist
|
||||
const activityGroupIds = activity.groupActivities?.map(ga => ga.groupId) || [];
|
||||
if (participant.groupId !== null && activityGroupIds.includes(participant.groupId)) {
|
||||
// Erstelle ein virtuelles DiaryMemberActivity-Objekt
|
||||
groupActivities.push({
|
||||
activity: activity,
|
||||
participant: participant,
|
||||
id: null // Virtuell, nicht in DB
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Kombiniere beide Listen und entferne Duplikate
|
||||
// Ein Duplikat liegt vor, wenn dieselbe Aktivität für denselben Participant bereits explizit zugeordnet ist
|
||||
const explicitActivityKeys = new Set();
|
||||
memberActivities.forEach(ma => {
|
||||
if (ma.activity && ma.activity.id && ma.participant && ma.participant.id) {
|
||||
// Erstelle einen eindeutigen Schlüssel: activityId-participantId
|
||||
const key = `${ma.activity.id}-${ma.participant.id}`;
|
||||
explicitActivityKeys.add(key);
|
||||
}
|
||||
});
|
||||
|
||||
// Filtere Gruppen-Aktivitäten, die bereits explizit zugeordnet sind
|
||||
const uniqueGroupActivities = groupActivities.filter(ga => {
|
||||
if (!ga.activity || !ga.activity.id || !ga.participant || !ga.participant.id) {
|
||||
return false;
|
||||
}
|
||||
const key = `${ga.activity.id}-${ga.participant.id}`;
|
||||
return !explicitActivityKeys.has(key);
|
||||
});
|
||||
|
||||
// Kombiniere beide Listen
|
||||
const allActivities = [...memberActivities, ...uniqueGroupActivities];
|
||||
|
||||
// Group activities by name and count occurrences
|
||||
const activityMap = new Map();
|
||||
|
||||
for (const ma of memberActivities) {
|
||||
for (const ma of allActivities) {
|
||||
if (!ma.activity || !ma.activity.predefinedActivity || !ma.participant) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check group assignment
|
||||
const participantGroupId = ma.participant.groupId;
|
||||
const activityGroupIds = ma.activity.groupActivities?.map(ga => ga.groupId) || [];
|
||||
|
||||
// Filter: Only count if:
|
||||
// 1. Activity has no group assignment (empty activityGroupIds) - activity is for all groups OR
|
||||
// 2. Participant's group matches one of the activity's groups
|
||||
const shouldCount = activityGroupIds.length === 0 ||
|
||||
(participantGroupId !== null && activityGroupIds.includes(participantGroupId));
|
||||
|
||||
if (!shouldCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const activity = ma.activity.predefinedActivity;
|
||||
const activityName = activity.name;
|
||||
const date = ma.activity.diaryDate?.date;
|
||||
@@ -162,7 +230,15 @@ export const getMemberLastParticipations = async (req, res) => {
|
||||
|
||||
const participantIds = participants.map(p => p.id);
|
||||
|
||||
// Get last participations for this member
|
||||
// Sammle alle Gruppen-IDs, zu denen der Member gehört
|
||||
const memberGroupIds = new Set();
|
||||
participants.forEach(p => {
|
||||
if (p.groupId !== null && p.groupId !== undefined) {
|
||||
memberGroupIds.add(p.groupId);
|
||||
}
|
||||
});
|
||||
|
||||
// 1. Get last participations explicitly assigned to this member
|
||||
const memberActivities = await DiaryMemberActivity.findAll({
|
||||
where: {
|
||||
participantId: participantIds
|
||||
@@ -197,22 +273,92 @@ export const getMemberLastParticipations = async (req, res) => {
|
||||
limit: parseInt(limit) * 10 // Get more to filter by group
|
||||
});
|
||||
|
||||
// Format the results, considering group assignment
|
||||
const participations = memberActivities
|
||||
// 2. Get all group activities for groups the member belongs to
|
||||
const groupActivities = [];
|
||||
if (memberGroupIds.size > 0) {
|
||||
const groupActivitiesData = await DiaryDateActivity.findAll({
|
||||
include: [
|
||||
{
|
||||
model: DiaryDates,
|
||||
as: 'diaryDate'
|
||||
},
|
||||
{
|
||||
model: PredefinedActivity,
|
||||
as: 'predefinedActivity',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
model: GroupActivity,
|
||||
as: 'groupActivities',
|
||||
where: {
|
||||
groupId: {
|
||||
[Op.in]: Array.from(memberGroupIds)
|
||||
}
|
||||
},
|
||||
required: true
|
||||
}
|
||||
],
|
||||
order: [[{ model: DiaryDates, as: 'diaryDate' }, 'date', 'DESC']],
|
||||
limit: parseInt(limit) * 10 // Get more to filter
|
||||
});
|
||||
|
||||
// Erstelle virtuelle DiaryMemberActivity-Objekte für Gruppen-Aktivitäten
|
||||
for (const activity of groupActivitiesData) {
|
||||
// Finde den entsprechenden Participant für diese Aktivität
|
||||
const diaryDateId = activity.diaryDateId;
|
||||
const relevantParticipants = participants.filter(p => p.diaryDateId === diaryDateId);
|
||||
|
||||
for (const participant of relevantParticipants) {
|
||||
// Prüfe, ob die Aktivität für die Gruppe des Participants ist
|
||||
const activityGroupIds = activity.groupActivities?.map(ga => ga.groupId) || [];
|
||||
if (participant.groupId !== null && activityGroupIds.includes(participant.groupId)) {
|
||||
// Erstelle ein virtuelles DiaryMemberActivity-Objekt
|
||||
groupActivities.push({
|
||||
activity: activity,
|
||||
participant: participant,
|
||||
id: null // Virtuell, nicht in DB
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Kombiniere beide Listen und entferne Duplikate
|
||||
// Ein Duplikat liegt vor, wenn dieselbe Aktivität für denselben Participant bereits explizit zugeordnet ist
|
||||
const explicitActivityKeys = new Set();
|
||||
memberActivities.forEach(ma => {
|
||||
if (ma.activity && ma.activity.id && ma.participant && ma.participant.id) {
|
||||
// Erstelle einen eindeutigen Schlüssel: activityId-participantId
|
||||
const key = `${ma.activity.id}-${ma.participant.id}`;
|
||||
explicitActivityKeys.add(key);
|
||||
}
|
||||
});
|
||||
|
||||
// Filtere Gruppen-Aktivitäten, die bereits explizit zugeordnet sind
|
||||
const uniqueGroupActivities = groupActivities.filter(ga => {
|
||||
if (!ga.activity || !ga.activity.id || !ga.participant || !ga.participant.id) {
|
||||
return false;
|
||||
}
|
||||
const key = `${ga.activity.id}-${ga.participant.id}`;
|
||||
return !explicitActivityKeys.has(key);
|
||||
});
|
||||
|
||||
// Kombiniere beide Listen
|
||||
const allActivities = [...memberActivities, ...uniqueGroupActivities];
|
||||
|
||||
// Format the results
|
||||
const participations = allActivities
|
||||
.filter(ma => {
|
||||
if (!ma.activity || !ma.activity.predefinedActivity || !ma.activity.diaryDate || !ma.participant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check group assignment
|
||||
const participantGroupId = ma.participant.groupId;
|
||||
const activityGroupIds = ma.activity.groupActivities?.map(ga => ga.groupId) || [];
|
||||
|
||||
// Filter: Only count if:
|
||||
// 1. Activity has no group assignment (empty activityGroupIds) - activity is for all groups OR
|
||||
// 2. Participant's group matches one of the activity's groups
|
||||
return activityGroupIds.length === 0 ||
|
||||
(participantGroupId !== null && activityGroupIds.includes(participantGroupId));
|
||||
return true;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
// Sortiere nach Datum (neueste zuerst)
|
||||
const dateA = new Date(a.activity.diaryDate.date);
|
||||
const dateB = new Date(b.activity.diaryDate.date);
|
||||
return dateB - dateA;
|
||||
})
|
||||
.slice(0, parseInt(limit)) // Limit after filtering
|
||||
.map(ma => ({
|
||||
|
||||
Reference in New Issue
Block a user