mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-05-18 20:08:19 +00:00
fix(slots): hide past slots today even on cache hit
Previous flow cached the unfiltered slot list AND applied the "hide past slots" filter — but only on the fresh-fetch path. A cache hit returned the stored list untouched, so by lunchtime agents saw morning slots that had already passed. Refactored into a post-cache filterPastSlotsForToday() helper applied on both cache-hit and fresh paths. Cache stores the full day's slots (keyed by doctorId + dayOfWeek), so same-weekday reuse across weeks stays correct. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -124,8 +124,12 @@ export class MasterdataService implements OnModuleInit {
|
|||||||
const dayOfWeek = new Date(date).toLocaleDateString('en-US', { weekday: 'long' }).toUpperCase();
|
const dayOfWeek = new Date(date).toLocaleDateString('en-US', { weekday: 'long' }).toUpperCase();
|
||||||
const cacheKey = `masterdata:slots:${doctorId}:${dayOfWeek}`;
|
const cacheKey = `masterdata:slots:${doctorId}:${dayOfWeek}`;
|
||||||
|
|
||||||
|
// Cache stores the UNFILTERED full-day slot list (keyed by dayOfWeek,
|
||||||
|
// so it's reusable across dates that fall on the same weekday). The
|
||||||
|
// "hide past slots on today" filter is applied AFTER cache read so it
|
||||||
|
// stays correct as real-time advances without cache churn.
|
||||||
const cached = await this.cache.getCache(cacheKey);
|
const cached = await this.cache.getCache(cacheKey);
|
||||||
if (cached) return JSON.parse(cached);
|
if (cached) return this.filterPastSlotsForToday(JSON.parse(cached), date);
|
||||||
|
|
||||||
const auth = `Bearer ${this.apiKey}`;
|
const auth = `Bearer ${this.apiKey}`;
|
||||||
const data = await this.platform.queryWithAuth<any>(
|
const data = await this.platform.queryWithAuth<any>(
|
||||||
@@ -169,21 +173,35 @@ export class MasterdataService implements OnModuleInit {
|
|||||||
// Sort by time
|
// Sort by time
|
||||||
slots.sort((a, b) => a.time.localeCompare(b.time));
|
slots.sort((a, b) => a.time.localeCompare(b.time));
|
||||||
|
|
||||||
|
// Cache the full UNFILTERED list so reuse across dates (same dayOfWeek)
|
||||||
|
// doesn't mis-serve filtered data from an earlier date.
|
||||||
await this.cache.setCache(cacheKey, JSON.stringify(slots), CACHE_TTL);
|
await this.cache.setCache(cacheKey, JSON.stringify(slots), CACHE_TTL);
|
||||||
this.logger.log(`Generated ${slots.length} slots for doctor ${doctorId} on ${dayOfWeek}`);
|
this.logger.log(`Generated ${slots.length} slots for doctor ${doctorId} on ${dayOfWeek}`);
|
||||||
|
|
||||||
// Filter out past time slots when the requested date is today (IST).
|
return this.filterPastSlotsForToday(slots, date);
|
||||||
// Cache stores the full day's slots — filtering happens post-cache
|
}
|
||||||
// so slots become available as the day progresses without cache churn.
|
|
||||||
const todayIST = new Date().toLocaleDateString('en-CA', { timeZone: 'Asia/Kolkata' });
|
|
||||||
if (date === todayIST) {
|
|
||||||
const nowHHMM = new Date().toLocaleTimeString('en-GB', { timeZone: 'Asia/Kolkata', hour: '2-digit', minute: '2-digit' });
|
|
||||||
const filtered = slots.filter(s => s.time >= nowHHMM);
|
|
||||||
this.logger.log(`[SLOTS] Today filter: ${slots.length} total → ${filtered.length} remaining (now=${nowHHMM} IST)`);
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
return slots;
|
// When the requested date is today (IST), hide slots whose time has
|
||||||
|
// already passed (30-min buffer so we don't offer the impossible-to-keep
|
||||||
|
// "in 5 minutes" slot). Applies to both cache-hit and fresh fetch paths.
|
||||||
|
private filterPastSlotsForToday(
|
||||||
|
slots: Array<{ time: string; label: string; clinicId: string; clinicName: string }>,
|
||||||
|
date: string,
|
||||||
|
): Array<{ time: string; label: string; clinicId: string; clinicName: string }> {
|
||||||
|
const todayIst = new Date().toLocaleDateString('en-CA', { timeZone: 'Asia/Kolkata' });
|
||||||
|
if (date !== todayIst) return slots;
|
||||||
|
|
||||||
|
const nowHHMM = new Date().toLocaleTimeString('en-GB', {
|
||||||
|
timeZone: 'Asia/Kolkata', hour: '2-digit', minute: '2-digit',
|
||||||
|
});
|
||||||
|
const [nowH, nowM] = nowHHMM.split(':').map(Number);
|
||||||
|
const cutoff = nowH * 60 + nowM + 30; // 30-min buffer
|
||||||
|
const filtered = slots.filter((s) => {
|
||||||
|
const [h, m] = s.time.split(':').map(Number);
|
||||||
|
return h * 60 + m >= cutoff;
|
||||||
|
});
|
||||||
|
this.logger.log(`[SLOTS] Today filter: ${slots.length} → ${filtered.length} (now=${nowHHMM} IST, cutoff=${Math.floor(cutoff / 60)}:${String(cutoff % 60).padStart(2, '0')})`);
|
||||||
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
async invalidateAll(): Promise<void> {
|
async invalidateAll(): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user