changes in backend

This commit is contained in:
Abhijit 2026-11-08 12:52:46 +05:30
parent a0b2020286
commit 5f3920891e
2 changed files with 30 additions and 9 deletions

View File

@ -165,25 +165,25 @@ async function collectSessionDates(from, cohort, count, weekdays, blocked) {
return dates.slice(0, count); return dates.slice(0, count);
} }
// Moves the existing Google event onto the new dates. The Meet link stays. // Updates the cohort's Google event to cover every held and upcoming session. The Meet link stays.
async function syncExistingMeetSeries(cohort, sessions) { async function syncExistingMeetSeries(cohort, sessions) {
const linked = sessions.find((session) => session.googleEventId); const linked = sessions.find((session) => session.googleEventId);
if (!linked) return; if (!linked) return;
const open = sessions const active = sessions
.filter((session) => session.status !== 'completed') .filter((session) => session.status !== 'cancelled')
.sort((a, b) => String(a.date).localeCompare(String(b.date))); .sort((a, b) => String(a.date).localeCompare(String(b.date)));
if (!open.length) return; if (!active.length) return;
const host = await sessionHost(linked, cohort); const host = await sessionHost(linked, cohort);
if (!host?.google?.refreshToken && !host?.google?.accessToken) return; if (!host?.google?.refreshToken && !host?.google?.accessToken) return;
const settings = await getAppSettings(); const settings = await getAppSettings();
const weekdays = await scheduleWeekdays(cohort.scheduleId); const weekdays = await scheduleWeekdays(cohort.scheduleId);
const first = open[0]; const first = active[0];
const last = open[open.length - 1]; const last = active[active.length - 1];
const times = slotDateTimes(first.date, first.slot || cohort.slot, cohort.durationMinutes || settings.defaultDurationMinutes || 60); const times = slotDateTimes(first.date, first.slot || cohort.slot, cohort.durationMinutes || settings.defaultDurationMinutes || 60);
try { try {
await updateCalendarEvent(host, linked.googleEventId, { await updateCalendarEvent(host, linked.googleEventId, {
title: `PR Session · ${cohort.name}`, title: `PR Session · ${cohort.name}`,
description: `Pulmonary rehab repeat meetings for ${cohort.name} (${open.length} upcoming sessions).`, description: `Pulmonary rehab repeat meetings for ${cohort.name} (${active.length} sessions).`,
start: times.start, start: times.start,
end: times.end, end: times.end,
timeZone: env.APP_TIMEZONE, timeZone: env.APP_TIMEZONE,
@ -193,7 +193,7 @@ async function syncExistingMeetSeries(cohort, sessions) {
interval: settings.repeatIntervalDays, interval: settings.repeatIntervalDays,
startTime: times.startTime, startTime: times.startTime,
timeZone: env.APP_TIMEZONE, timeZone: env.APP_TIMEZONE,
includeDates: open.map((session) => session.date), includeDates: active.map((session) => session.date),
weekdays, weekdays,
}), }),
}); });
@ -317,6 +317,17 @@ export async function nextAppendDate(cohort) {
return cursor; return cursor;
} }
// True when the cohort may meet on this date: its schedule weekdays if set, never Sunday, and not a holiday or PRT leave.
async function canMeetOn(cohort, date) {
if (weekdayOf(date) === 0) return false;
const weekdays = await scheduleWeekdays(cohort.scheduleId);
if (weekdays && !weekdays.map(Number).includes(weekdayOf(date))) return false;
const settings = await getAppSettings();
if (settings.skipHolidays !== false && (await holidayDatesBetween(date, date, cohort.language)).has(date)) return false;
if (settings.skipPrtLeave !== false && await leaveCoversDate(cohort.virtualPrt?._id || cohort.virtualPrt, date)) return false;
return true;
}
// Adds today's session to open cohorts with no future session left, when today is their next meeting day. // Adds today's session to open cohorts with no future session left, when today is their next meeting day.
export async function appendTodaySessions(date) { export async function appendTodaySessions(date) {
const cohorts = await Cohort.find(liveCohortFilter()); const cohorts = await Cohort.find(liveCohortFilter());
@ -324,7 +335,9 @@ export async function appendTodaySessions(date) {
for (const cohort of cohorts) { for (const cohort of cohorts) {
if (await CohortSession.exists({ cohort: cohort._id, date })) continue; if (await CohortSession.exists({ cohort: cohort._id, date })) continue;
if (await CohortSession.exists({ cohort: cohort._id, status: 'scheduled', date: { $gt: date } })) continue; if (await CohortSession.exists({ cohort: cohort._id, status: 'scheduled', date: { $gt: date } })) continue;
if (await nextAppendDate(cohort) !== date) continue; const next = await nextAppendDate(cohort);
if (next > date) continue;
if (next < date && !(await canMeetOn(cohort, date))) continue; // catching up after missed meeting days
const ids = patientIds(cohort).map(String); const ids = patientIds(cohort).map(String);
const length = await cohortProgramLength(cohort, await getAppSettings()); const length = await cohortProgramLength(cohort, await getAppSettings());
const finished = await finishedSessionCounts(ids); const finished = await finishedSessionCounts(ids);
@ -343,6 +356,7 @@ export async function appendTodaySessions(date) {
records: [], records: [],
}); });
await ensureSessionRecords(cohort); await ensureSessionRecords(cohort);
await syncExistingMeetSeries(cohort, await CohortSession.find({ cohort: cohort._id }));
added += 1; added += 1;
} }
return added; return added;
@ -386,6 +400,7 @@ export async function pushSession(session, reason, { notifyAdmins = false } = {}
records: recordsFor(patientIds(cohort)), records: recordsFor(patientIds(cohort)),
}); });
await ensureSessionRecords(cohort); await ensureSessionRecords(cohort);
await syncExistingMeetSeries(cohort, await CohortSession.find({ cohort: cohort._id }));
const admins = notifyAdmins ? await adminUsers() : []; const admins = notifyAdmins ? await adminUsers() : [];
await notifySessionPushed({ await notifySessionPushed({

View File

@ -203,6 +203,7 @@ export function sessionRecurrence({ firstDate, lastDate, interval, startTime, ti
let cursor = firstDate; let cursor = firstDate;
let count = 0; let count = 0;
const exdates = []; const exdates = [];
const reached = new Set();
let guard = 0; let guard = 0;
while (cursor <= lastDate && count < 120 && guard < 500) { while (cursor <= lastDate && count < 120 && guard < 500) {
guard += 1; guard += 1;
@ -213,6 +214,7 @@ export function sessionRecurrence({ firstDate, lastDate, interval, startTime, ti
exdates.push(cursor); exdates.push(cursor);
} else if (!weekdayBlocked && !sunday) { } else if (!weekdayBlocked && !sunday) {
count += 1; count += 1;
reached.add(cursor);
if (include.size && !include.has(cursor)) exdates.push(cursor); if (include.size && !include.has(cursor)) exdates.push(cursor);
} }
cursor = addDays(cursor, step); cursor = addDays(cursor, step);
@ -226,5 +228,9 @@ export function sessionRecurrence({ firstDate, lastDate, interval, startTime, ti
if (exdates.length) { if (exdates.length) {
lines.push(`EXDATE;TZID=${timeZone || 'Asia/Kolkata'}:${exdates.map(stamp).join(',')}`); lines.push(`EXDATE;TZID=${timeZone || 'Asia/Kolkata'}:${exdates.map(stamp).join(',')}`);
} }
const extra = [...include].filter((ymd) => !reached.has(ymd)).sort();
if (extra.length) {
lines.push(`RDATE;TZID=${timeZone || 'Asia/Kolkata'}:${extra.map(stamp).join(',')}`);
}
return lines; return lines;
} }