Update worshipController.js to enhance worship data parsing and conflict resolution. Introduce unparsedText for better tracking of source data. Modify date handling functions for improved accuracy in event filtering. Update .gitignore to exclude generated frontend artifacts, including index.html and assets directory, to streamline deployment.
All checks were successful
Deploy miriamgemeinde / deploy (push) Successful in 6s

This commit is contained in:
Torsten Schulz (local)
2026-04-29 18:47:15 +02:00
parent 05a8229b83
commit 7d5e2526d3
600 changed files with 183 additions and 4253 deletions

View File

@@ -490,9 +490,16 @@ function parseNbrSegment(segment, baseDateUtc, leaderNormalizedMap) {
break;
}
}
const title = tokens.join(' ').trim() || 'Gottesdienst';
const unparsedText = tokens.join(' ').trim();
return { dateUtc, time, title, officiant };
return {
dateUtc,
time,
title: 'Gottesdienst',
officiant,
sourceText: raw,
unparsedText,
};
}
// Hilfsfunktion zum Parsen eines Gottesdienstes aus der zweiten Spalte
@@ -1511,20 +1518,32 @@ async function parseNbrPlanningRecords(records) {
const imported = [];
const errors = [];
const getDateKey = (dateValue) => {
const date = dateValue instanceof Date ? dateValue : new Date(dateValue);
const y = date.getUTCFullYear();
const m = String(date.getUTCMonth() + 1).padStart(2, '0');
const d = String(date.getUTCDate()).padStart(2, '0');
return `${y}-${m}-${d}`;
};
const findExisting = (dateUtc, time, eventPlaceId) => {
const dateKey = getDateKey(dateUtc);
const timeKey = time ? String(time).substring(0, 5) : '';
return existingWorships.find((w) => {
const wKey = getDateKey(w.date);
const wTime = w.time ? String(w.time).substring(0, 5) : '';
return wKey === dateKey && wTime === timeKey && String(w.eventPlaceId || '') === String(eventPlaceId || '');
});
};
const findDayPlaceConflicts = (dateUtc, eventPlaceId) => {
const y = dateUtc.getUTCFullYear();
const m = String(dateUtc.getUTCMonth() + 1).padStart(2, '0');
const d = String(dateUtc.getUTCDate()).padStart(2, '0');
const dateKey = `${y}-${m}-${d}`;
const timeKey = time ? String(time).substring(0, 5) : '';
return existingWorships.find((w) => {
const wDate = w.date instanceof Date ? w.date : new Date(w.date);
const wy = wDate.getUTCFullYear();
const wm = String(wDate.getUTCMonth() + 1).padStart(2, '0');
const wd = String(wDate.getUTCDate()).padStart(2, '0');
const wKey = `${wy}-${wm}-${wd}`;
const wTime = w.time ? String(w.time).substring(0, 5) : '';
return wKey === dateKey && wTime === timeKey && String(w.eventPlaceId || '') === String(eventPlaceId || '');
return existingWorships.filter((w) => {
const wKey = getDateKey(w.date);
return wKey === dateKey && String(w.eventPlaceId || '') === String(eventPlaceId || '');
});
};
@@ -1578,10 +1597,13 @@ async function parseNbrPlanningRecords(records) {
sacristanService: normalizeText(service),
organPlaying: normalizeText(music),
eventPlaceId,
_sourceText: parsed.sourceText,
_unparsedText: parsed.unparsedText,
};
const existing = findExisting(worshipData.date, worshipData.time, worshipData.eventPlaceId);
if (!hasChanges(worshipData, existing)) {
const dayPlaceConflicts = findDayPlaceConflicts(worshipData.date, worshipData.eventPlaceId);
if (!hasChanges(worshipData, existing) && dayPlaceConflicts.length === 0) {
continue;
}
@@ -1601,6 +1623,20 @@ async function parseNbrPlanningRecords(records) {
worshipData._isNew = true;
}
if (dayPlaceConflicts.length > 0) {
worshipData._hasDayPlaceConflict = true;
worshipData._importChoice = 'keepExisting';
worshipData._replaceExistingIds = dayPlaceConflicts.map((w) => w.id);
worshipData._conflictingWorships = dayPlaceConflicts.map((w) => ({
id: w.id,
date: getDateKey(w.date),
time: w.time ? String(w.time).substring(0, 5) : '',
title: w.title || '',
organizer: w.organizer || '',
eventPlaceId: w.eventPlaceId,
}));
}
imported.push(worshipData);
}
}
@@ -1670,6 +1706,10 @@ exports.saveImportedWorships = async (req, res) => {
for (const worshipData of worships) {
try {
if (worshipData._importChoice === 'keepExisting') {
continue;
}
// Prüfen ob Datum in der Vergangenheit liegt
const worshipDate = new Date(worshipData.date);
worshipDate.setHours(0, 0, 0, 0);
@@ -1677,21 +1717,51 @@ exports.saveImportedWorships = async (req, res) => {
continue; // Überspringe vergangene Daten
}
if (!worshipData.date || !worshipData.time || !worshipData.eventPlaceId) {
errors.push(`Pflichtfelder fehlen: ${worshipData.date || 'kein Datum'} ${worshipData.time || 'keine Uhrzeit'} - kein Ort`);
continue;
}
// Freigabe-Status aus Import-Dialog übernehmen (Checkbox in der UI).
// Fallback: wenn kein Wert gesetzt ist, bleibt es false.
worshipData.approved = !!worshipData.approved;
worshipData.title = normalizeText(worshipData.title) || 'Gottesdienst';
const replaceExistingIds = Array.isArray(worshipData._replaceExistingIds)
? worshipData._replaceExistingIds.filter(Boolean)
: [];
const cleanWorshipData = {
date: worshipData.date,
dayName: worshipData.dayName || '',
time: worshipData.time,
title: worshipData.title,
organizer: worshipData.organizer || '',
collection: worshipData.collection || '',
sacristanService: worshipData.sacristanService || '',
organPlaying: worshipData.organPlaying || '',
approved: worshipData.approved,
eventPlaceId: worshipData.eventPlaceId,
};
if (replaceExistingIds.length > 0) {
await Worship.destroy({
where: {
id: { [Op.in]: replaceExistingIds },
},
});
}
// Prüfen ob bereits ein Eintrag für dieses Datum und diese Uhrzeit existiert
const whereClause = {
date: {
[Op.eq]: sequelize.fn('DATE', worshipData.date)
[Op.eq]: sequelize.fn('DATE', cleanWorshipData.date)
},
time: worshipData.time
time: cleanWorshipData.time
};
// Wenn eventPlaceId gesetzt ist, auch danach suchen
if (worshipData.eventPlaceId) {
whereClause.eventPlaceId = worshipData.eventPlaceId;
if (cleanWorshipData.eventPlaceId) {
whereClause.eventPlaceId = cleanWorshipData.eventPlaceId;
} else {
// Wenn kein eventPlaceId, suche nach Einträgen ohne eventPlaceId
whereClause.eventPlaceId = { [Op.is]: null };
@@ -1701,11 +1771,11 @@ exports.saveImportedWorships = async (req, res) => {
if (existingWorship) {
// Update bestehenden Eintrag
await existingWorship.update(worshipData);
await existingWorship.update(cleanWorshipData);
updatedCount++;
} else {
// Neuen Eintrag erstellen
await Worship.create(worshipData);
await Worship.create(cleanWorshipData);
savedCount++;
}
} catch (error) {