disable expired desired booking slots

This commit is contained in:
2025-11-11 09:51:42 +01:00
parent c49e270315
commit bbde08f89a
2 changed files with 129 additions and 5 deletions

View File

@@ -112,6 +112,23 @@ async function sendStoreWatchNotification({ profileId, storeName, storeId, regio
});
}
async function sendDesiredWindowMissedNotification({ profileId, storeName, desiredWindowLabel }) {
if (!profileId) {
return;
}
const title = `Keine Slots gefunden: ${storeName}`;
const messageBase = desiredWindowLabel
? `Für den gewünschten Zeitraum ${desiredWindowLabel} konnte kein Slot gefunden werden.`
: 'Für den gewünschten Zeitraum konnte kein Slot gefunden werden.';
const message = `${messageBase} Der Eintrag wurde deaktiviert.`;
await notifyChannels(profileId, {
title,
message,
link: null,
priority: 'default'
});
}
async function sendTestNotification(profileId, channel) {
const title = 'Pickup Benachrichtigung (Test)';
const message = 'Das ist eine Testnachricht. Bei Fragen wende dich bitte an den Admin.';
@@ -148,5 +165,6 @@ async function sendTestNotification(profileId, channel) {
module.exports = {
sendSlotNotification,
sendStoreWatchNotification,
sendTestNotification
sendTestNotification,
sendDesiredWindowMissedNotification
};

View File

@@ -80,7 +80,7 @@ function deactivateEntryInMemory(entry) {
}
}
function persistEntryDeactivation(profileId, entryId) {
function persistEntryDeactivation(profileId, entryId, options = {}) {
if (!profileId || !entryId) {
return;
}
@@ -88,9 +88,27 @@ function persistEntryDeactivation(profileId, entryId) {
const config = readConfig(profileId);
let changed = false;
const updated = config.map((item) => {
if (String(item?.id) === String(entryId) && item?.active !== false) {
changed = true;
return { ...item, active: false };
if (String(item?.id) === String(entryId)) {
let mutated = false;
const updatedEntry = { ...item };
if (item?.active !== false) {
updatedEntry.active = false;
mutated = true;
}
if (options.resetDesiredWindow) {
if (updatedEntry.desiredDate !== undefined) {
delete updatedEntry.desiredDate;
mutated = true;
}
if (updatedEntry.desiredDateRange !== undefined) {
delete updatedEntry.desiredDateRange;
mutated = true;
}
}
if (mutated) {
changed = true;
return updatedEntry;
}
}
return item;
});
@@ -150,6 +168,89 @@ function toDateValue(input) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
}
function formatDesiredWindowLabel(entry) {
if (!entry) {
return null;
}
const formatValue = (value) => {
if (!value) {
return null;
}
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return null;
}
return date.toLocaleDateString('de-DE', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
};
if (entry.desiredDateRange) {
const startLabel = formatValue(entry.desiredDateRange.start);
const endLabel = formatValue(entry.desiredDateRange.end);
if (startLabel && endLabel) {
return startLabel === endLabel ? startLabel : `${startLabel} ${endLabel}`;
}
return startLabel || endLabel;
}
return formatValue(entry.desiredDate);
}
function desiredWindowExpired(entry) {
if (!entry?.active) {
return false;
}
const todayValue = toDateValue(new Date());
if (todayValue === null) {
return false;
}
if (entry.desiredDateRange?.start || entry.desiredDateRange?.end) {
const endValue = toDateValue(entry.desiredDateRange.end) ?? toDateValue(entry.desiredDateRange.start);
return endValue !== null && endValue < todayValue;
}
const desiredValue = toDateValue(entry.desiredDate);
return desiredValue !== null && desiredValue < todayValue;
}
function resetDesiredWindow(entry) {
if (!entry) {
return;
}
if (entry.desiredDate !== undefined) {
delete entry.desiredDate;
}
if (entry.desiredDateRange !== undefined) {
delete entry.desiredDateRange;
}
}
async function handleExpiredDesiredWindow(session, entry) {
const profileId = session?.profile?.id;
const storeName = entry.label || entry.id;
const desiredLabel = formatDesiredWindowLabel(entry);
console.log(
`[INFO] Wunschzeitraum abgelaufen für ${storeName}${desiredLabel ? ` (${desiredLabel})` : ''}. Eintrag wird deaktiviert.`
);
deactivateEntryInMemory(entry);
resetDesiredWindow(entry);
persistEntryDeactivation(profileId, entry.id, { resetDesiredWindow: true });
if (profileId) {
try {
await notificationService.sendDesiredWindowMissedNotification({
profileId,
storeName,
desiredWindowLabel: desiredLabel
});
} catch (error) {
console.error(
`[NOTIFY] Benachrichtigung zum verpassten Zeitraum für ${storeName} fehlgeschlagen:`,
error.message
);
}
}
}
function matchesDesiredDate(pickupDate, desiredDate, desiredDateRange) {
const pickupValue = toDateValue(pickupDate);
if (pickupValue === null) {
@@ -254,6 +355,11 @@ async function checkEntry(sessionId, entry, settings) {
return;
}
if (desiredWindowExpired(entry)) {
await handleExpiredDesiredWindow(session, entry);
return;
}
const ready = await ensureSession(session);
if (!ready) {
return;