disable expired desired booking slots
This commit is contained in:
@@ -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) {
|
async function sendTestNotification(profileId, channel) {
|
||||||
const title = 'Pickup Benachrichtigung (Test)';
|
const title = 'Pickup Benachrichtigung (Test)';
|
||||||
const message = 'Das ist eine Testnachricht. Bei Fragen wende dich bitte an den Admin.';
|
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 = {
|
module.exports = {
|
||||||
sendSlotNotification,
|
sendSlotNotification,
|
||||||
sendStoreWatchNotification,
|
sendStoreWatchNotification,
|
||||||
sendTestNotification
|
sendTestNotification,
|
||||||
|
sendDesiredWindowMissedNotification
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ function deactivateEntryInMemory(entry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function persistEntryDeactivation(profileId, entryId) {
|
function persistEntryDeactivation(profileId, entryId, options = {}) {
|
||||||
if (!profileId || !entryId) {
|
if (!profileId || !entryId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,9 +88,27 @@ function persistEntryDeactivation(profileId, entryId) {
|
|||||||
const config = readConfig(profileId);
|
const config = readConfig(profileId);
|
||||||
let changed = false;
|
let changed = false;
|
||||||
const updated = config.map((item) => {
|
const updated = config.map((item) => {
|
||||||
if (String(item?.id) === String(entryId) && 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;
|
changed = true;
|
||||||
return { ...item, active: false };
|
return updatedEntry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
@@ -150,6 +168,89 @@ function toDateValue(input) {
|
|||||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
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) {
|
function matchesDesiredDate(pickupDate, desiredDate, desiredDateRange) {
|
||||||
const pickupValue = toDateValue(pickupDate);
|
const pickupValue = toDateValue(pickupDate);
|
||||||
if (pickupValue === null) {
|
if (pickupValue === null) {
|
||||||
@@ -254,6 +355,11 @@ async function checkEntry(sessionId, entry, settings) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (desiredWindowExpired(entry)) {
|
||||||
|
await handleExpiredDesiredWindow(session, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ready = await ensureSession(session);
|
const ready = await ensureSession(session);
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user