prevent re-auto-activation after manual station release
Introduce a manual-release reservation hold on station state so auto slot activation is suppressed for the current reserved user until the reservation window ends or is removed. Clear the hold on activation/reservation updates and backfill missing hold fields for existing station state files.
This commit is contained in:
@@ -2465,8 +2465,32 @@ async function autoActivateReservationSlotIfNeededUnlocked(options = {}) {
|
|||||||
await persistStationReservationsIfChanged(reservations, { lastAction: "reserve-sync" });
|
await persistStationReservationsIfChanged(reservations, { lastAction: "reserve-sync" });
|
||||||
const activeEntry = findActiveReservationEntry(reservations, nowMs);
|
const activeEntry = findActiveReservationEntry(reservations, nowMs);
|
||||||
if (!activeEntry) {
|
if (!activeEntry) {
|
||||||
|
if (runtime.station.manualReleaseReservationUserId || runtime.station.manualReleaseReservationUntil) {
|
||||||
|
runtime.station.manualReleaseReservationUserId = null;
|
||||||
|
runtime.station.manualReleaseReservationUntil = null;
|
||||||
|
runtime.station.updatedAt = new Date().toISOString();
|
||||||
|
await writeJson(files.station, runtime.station);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const holdUserId = String(runtime.station.manualReleaseReservationUserId || "");
|
||||||
|
const holdUntilMs = parseIsoMs(runtime.station.manualReleaseReservationUntil);
|
||||||
|
if (
|
||||||
|
holdUserId
|
||||||
|
&& Number.isFinite(holdUntilMs)
|
||||||
|
&& holdUntilMs > nowMs
|
||||||
|
&& String(activeEntry.userId || "") === holdUserId
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (holdUserId || runtime.station.manualReleaseReservationUntil) {
|
||||||
|
runtime.station.manualReleaseReservationUserId = null;
|
||||||
|
runtime.station.manualReleaseReservationUntil = null;
|
||||||
|
runtime.station.updatedAt = new Date().toISOString();
|
||||||
|
await writeJson(files.station, runtime.station);
|
||||||
|
}
|
||||||
|
|
||||||
if (excludeUserId && String(activeEntry.userId || "") === excludeUserId) {
|
if (excludeUserId && String(activeEntry.userId || "") === excludeUserId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2491,6 +2515,8 @@ async function autoActivateReservationSlotIfNeededUnlocked(options = {}) {
|
|||||||
startedAt: activeEntry.from,
|
startedAt: activeEntry.from,
|
||||||
endsAt: activeEntry.to,
|
endsAt: activeEntry.to,
|
||||||
reservations,
|
reservations,
|
||||||
|
manualReleaseReservationUserId: null,
|
||||||
|
manualReleaseReservationUntil: null,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
lastAction: "activate-auto-slot"
|
lastAction: "activate-auto-slot"
|
||||||
};
|
};
|
||||||
@@ -2520,6 +2546,14 @@ async function reconcileStationLeaseOnStartup() {
|
|||||||
runtime.station.endsAt = null;
|
runtime.station.endsAt = null;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(runtime.station, "manualReleaseReservationUserId")) {
|
||||||
|
runtime.station.manualReleaseReservationUserId = null;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(runtime.station, "manualReleaseReservationUntil")) {
|
||||||
|
runtime.station.manualReleaseReservationUntil = null;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
if (runtime.station.isInUse && runtime.station.startedAt && !runtime.station.endsAt) {
|
if (runtime.station.isInUse && runtime.station.startedAt && !runtime.station.endsAt) {
|
||||||
runtime.station.endsAt = computeLeaseEndIso(runtime.station.startedAt);
|
runtime.station.endsAt = computeLeaseEndIso(runtime.station.startedAt);
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -2766,6 +2800,8 @@ async function runActivationJob(job, user) {
|
|||||||
startedAt,
|
startedAt,
|
||||||
endsAt,
|
endsAt,
|
||||||
reservations: reservationsAfterActivate,
|
reservations: reservationsAfterActivate,
|
||||||
|
manualReleaseReservationUserId: null,
|
||||||
|
manualReleaseReservationUntil: null,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
lastAction: "activate"
|
lastAction: "activate"
|
||||||
};
|
};
|
||||||
@@ -2870,6 +2906,12 @@ async function handleStationRelease(res, user) {
|
|||||||
startedAt: null,
|
startedAt: null,
|
||||||
endsAt: null,
|
endsAt: null,
|
||||||
reservations: lockInfo.reservations,
|
reservations: lockInfo.reservations,
|
||||||
|
manualReleaseReservationUserId: lockInfo.activeEntry && String(lockInfo.activeEntry.userId || "") === String(user && user.id ? user.id : "")
|
||||||
|
? String(user.id || "")
|
||||||
|
: null,
|
||||||
|
manualReleaseReservationUntil: lockInfo.activeEntry && String(lockInfo.activeEntry.userId || "") === String(user && user.id ? user.id : "")
|
||||||
|
? String(lockInfo.activeEntry.to || "")
|
||||||
|
: null,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
lastAction: "deactivate"
|
lastAction: "deactivate"
|
||||||
};
|
};
|
||||||
@@ -2961,6 +3003,12 @@ async function handleDeleteOwnReservation(res, user) {
|
|||||||
startedAt: null,
|
startedAt: null,
|
||||||
endsAt: null,
|
endsAt: null,
|
||||||
reservations: removed.reservations,
|
reservations: removed.reservations,
|
||||||
|
manualReleaseReservationUserId: String(runtime.station.manualReleaseReservationUserId || "") === String(user && user.id ? user.id : "")
|
||||||
|
? null
|
||||||
|
: (runtime.station.manualReleaseReservationUserId || null),
|
||||||
|
manualReleaseReservationUntil: String(runtime.station.manualReleaseReservationUserId || "") === String(user && user.id ? user.id : "")
|
||||||
|
? null
|
||||||
|
: (runtime.station.manualReleaseReservationUntil || null),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
lastAction: "reserve-remove-current"
|
lastAction: "reserve-remove-current"
|
||||||
};
|
};
|
||||||
@@ -2978,6 +3026,12 @@ async function handleDeleteOwnReservation(res, user) {
|
|||||||
runtime.station = {
|
runtime.station = {
|
||||||
...runtime.station,
|
...runtime.station,
|
||||||
reservations: removed.reservations,
|
reservations: removed.reservations,
|
||||||
|
manualReleaseReservationUserId: String(runtime.station.manualReleaseReservationUserId || "") === String(user && user.id ? user.id : "")
|
||||||
|
? null
|
||||||
|
: (runtime.station.manualReleaseReservationUserId || null),
|
||||||
|
manualReleaseReservationUntil: String(runtime.station.manualReleaseReservationUserId || "") === String(user && user.id ? user.id : "")
|
||||||
|
? null
|
||||||
|
: (runtime.station.manualReleaseReservationUntil || null),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
lastAction: "reserve-remove"
|
lastAction: "reserve-remove"
|
||||||
};
|
};
|
||||||
@@ -6957,6 +7011,8 @@ function buildDefaultStationState() {
|
|||||||
startedAt: null,
|
startedAt: null,
|
||||||
endsAt: null,
|
endsAt: null,
|
||||||
reservations: [],
|
reservations: [],
|
||||||
|
manualReleaseReservationUserId: null,
|
||||||
|
manualReleaseReservationUntil: null,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
lastAction: "init"
|
lastAction: "init"
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user