From 4edd0c69de7ff1b499e154f0f4bc774ab937339b Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 12 Aug 2025 11:12:08 +0530 Subject: [PATCH 01/35] Changes Updated --- .../membershipStatusNotifications.ts | 116 +++++++++++------- 1 file changed, 74 insertions(+), 42 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 3b0b61b..1c01fff 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -63,10 +63,18 @@ export const checkExpiredMemberships = onSchedule( expiringMemberships.map((m) => processExpiringMembership(m.id, m.data)) ); - const expiredSuccessful = expiredResults.filter((r) => r.status === "fulfilled").length; - const expiredFailed = expiredResults.filter((r) => r.status === "rejected").length; - const expiringSuccessful = expiringResults.filter((r) => r.status === "fulfilled").length; - const expiringFailed = expiringResults.filter((r) => r.status === "rejected").length; + const expiredSuccessful = expiredResults.filter( + (r) => r.status === "fulfilled" + ).length; + const expiredFailed = expiredResults.filter( + (r) => r.status === "rejected" + ).length; + const expiringSuccessful = expiringResults.filter( + (r) => r.status === "fulfilled" + ).length; + const expiringFailed = expiringResults.filter( + (r) => r.status === "rejected" + ).length; logger.info( `Completed processing. Expired - Success: ${expiredSuccessful}, Failed: ${expiredFailed}. Expiring - Success: ${expiringSuccessful}, Failed: ${expiringFailed}` @@ -139,7 +147,10 @@ async function findMembershipsExpiringIn10Days(): Promise< const batchResults = await Promise.allSettled( batch.map(async (doc) => { const data = doc.data() as MembershipData; - const isExpiringIn10Days = await checkIfMembershipExpiringIn10Days(doc.id, data); + const isExpiringIn10Days = await checkIfMembershipExpiringIn10Days( + doc.id, + data + ); if (isExpiringIn10Days) { return { id: doc.id, data }; } @@ -241,11 +252,11 @@ async function checkIfMembershipExpiringIn10Days( startDate, data.subscription.frequency ); - + const now = new Date(); const tenDaysFromNow = new Date(); tenDaysFromNow.setDate(now.getDate() + 10); - + const isExpiringIn10Days = expiryDate > now && expiryDate <= tenDaysFromNow; if (isExpiringIn10Days) { @@ -381,7 +392,10 @@ async function processExpiringMembership( logger.info(`Processing expiring membership ${membershipId}`); await sendPlanExpiringNotification(membershipId, membershipData); } catch (error) { - logger.error(`Error processing expiring membership ${membershipId}:`, error); + logger.error( + `Error processing expiring membership ${membershipId}:`, + error + ); } } @@ -394,19 +408,6 @@ async function sendPlanExpiredNotification( const gymOwnerId = await getGymOwnerId(membershipData.gymId); const gymName = await getGymName(membershipData.gymId); - const existing = await app - .firestore() - .collection("notifications") - .where("type", "==", "plan_expired") - .where("data.membershipId", "==", membershipId) - .limit(1) - .get(); - - if (!existing.empty) { - logger.info(`Notification already sent for ${membershipId}, skipping...`); - return; - } - let expiryDate: Date | undefined; let formattedDate = "Unknown Date"; @@ -422,7 +423,26 @@ async function sendPlanExpiredNotification( month: "long", day: "numeric", }); - + } + + const existing = await app + .firestore() + .collection("notifications") + .where("type", "==", "plan_expired") + .where("data.membershipId", "==", membershipId) + .where( + "data.expiryDate", + "==", + expiryDate + ? admin.firestore.Timestamp.fromDate(expiryDate) + : admin.firestore.Timestamp.fromDate(new Date()) + ) + .limit(1) + .get(); + + if (!existing.empty) { + logger.info(`Notification already sent for ${membershipId}, skipping...`); + return; } await app @@ -435,13 +455,13 @@ async function sendPlanExpiredNotification( notificationSent: false, timestamp: admin.firestore.FieldValue.serverTimestamp(), read: false, - readBy: [], + readBy: [], data: { planName: membershipData.subscription?.name || "Unknown Plan", clientName, membershipId, gymName, - ownerId: gymOwnerId, + ownerId: gymOwnerId, formattedExpiryDate: formattedDate, expiryDate: expiryDate ? admin.firestore.Timestamp.fromDate(expiryDate) @@ -466,19 +486,6 @@ async function sendPlanExpiringNotification( const gymOwnerId = await getGymOwnerId(membershipData.gymId); const gymName = await getGymName(membershipData.gymId); - const existing = await app - .firestore() - .collection("notifications") - .where("type", "==", "plan_expiring_soon") - .where("data.membershipId", "==", membershipId) - .limit(1) - .get(); - - if (!existing.empty) { - logger.info(`Expiring notification already sent for ${membershipId}, skipping...`); - return; - } - let expiryDate: Date | undefined; let formattedDate = "Unknown Date"; let daysUntilExpiry = 10; @@ -495,12 +502,34 @@ async function sendPlanExpiringNotification( month: "long", day: "numeric", }); - + const now = new Date(); const timeDiff = expiryDate.getTime() - now.getTime(); daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); } + const existing = await app + .firestore() + .collection("notifications") + .where("type", "==", "plan_expiring_soon") + .where("data.membershipId", "==", membershipId) + .where( + "data.expiryDate", + "==", + expiryDate + ? admin.firestore.Timestamp.fromDate(expiryDate) + : admin.firestore.Timestamp.fromDate(new Date()) + ) + .limit(1) + .get(); + + if (!existing.empty) { + logger.info( + `Expiring notification already sent for ${membershipId}, skipping...` + ); + return; + } + await app .firestore() .collection("notifications") @@ -511,13 +540,13 @@ async function sendPlanExpiringNotification( notificationSent: false, timestamp: admin.firestore.FieldValue.serverTimestamp(), read: false, - readBy: [], + readBy: [], data: { planName: membershipData.subscription?.name || "Unknown Plan", clientName, membershipId, gymName, - ownerId: gymOwnerId, + ownerId: gymOwnerId, formattedExpiryDate: formattedDate, expiryDate: expiryDate ? admin.firestore.Timestamp.fromDate(expiryDate) @@ -530,7 +559,10 @@ async function sendPlanExpiringNotification( `Expiring notification sent for membership ${membershipId} (expires on ${formattedDate}, ${daysUntilExpiry} days remaining)` ); } catch (error) { - logger.error(`Error sending expiring notification for ${membershipId}:`, error); + logger.error( + `Error sending expiring notification for ${membershipId}:`, + error + ); } } @@ -577,4 +609,4 @@ async function getGymName(gymId: string): Promise { logger.error(`Error getting gym name for gym ${gymId}:`, error); return "Unknown Gym"; } -} \ No newline at end of file +} -- 2.43.0 From b59e0033db675ace5bbf18fe4f0abf8f848fa9f1 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 13 Aug 2025 12:08:05 +0530 Subject: [PATCH 02/35] Changes Updated --- functions/src/notifications/processNotification.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/src/notifications/processNotification.ts b/functions/src/notifications/processNotification.ts index 3cc4811..2efed4c 100644 --- a/functions/src/notifications/processNotification.ts +++ b/functions/src/notifications/processNotification.ts @@ -180,7 +180,7 @@ function prepareNotificationMessage( case "trainer_response": title = notification.data?.title || - (notification.data?.status === "accepted" + (notification.data?.status === "Accepted" ? "Trainer Request Accepted" : "Trainer Request Update"); body = -- 2.43.0 From 57a4fab6c8b2b0d6cbc9883f284f84be2ef20b96 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 13 Aug 2025 13:31:42 +0530 Subject: [PATCH 03/35] Changes Updated --- firestore.indexes.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index 4e84252..2016f51 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -166,6 +166,20 @@ } ] }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, { "collectionGroup": "workout_logs", "queryScope": "COLLECTION", -- 2.43.0 From d7bf910baa60a84c7da8bc65bcbb95fb32ed3250 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 13 Aug 2025 18:44:51 +0530 Subject: [PATCH 04/35] Changes Updated --- .../membershipStatusNotifications.ts | 192 +++++++++++++++++- .../src/notifications/processNotification.ts | 20 +- 2 files changed, 208 insertions(+), 4 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 1c01fff..7dd0541 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -33,6 +33,15 @@ interface PaymentData { discount?: number; } +interface PersonalTrainerAssign { + id: string; + ownerId: string; + trainerId?: string; + clientId: string; + membershipId: string; + gymId: string; +} + export const checkExpiredMemberships = onSchedule( { schedule: "*/5 * * * *", @@ -367,6 +376,66 @@ function calculateRenewalDateFromPayment( return renewalDate; } +async function getTrainerAssignmentsForMembership( + membershipId: string +): Promise { + try { + const querySnapshot = await app + .firestore() + .collection("personal_trainer_assignments") + .where("membershipId", "==", membershipId) + .get(); + + return querySnapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as PersonalTrainerAssign[]; + } catch (error) { + logger.error( + `Error getting trainer assignments for membership ${membershipId}:`, + error + ); + return []; + } +} + +async function getTrainerName(trainerId: string): Promise { + try { + const doc = await app + .firestore() + .collection("trainer_profiles") + .doc(trainerId) + .get(); + + if (!doc.exists) { + const userDoc = await app + .firestore() + .collection("users") + .doc(trainerId) + .get(); + + if (userDoc.exists) { + const userData = userDoc.data(); + return userData?.name || userData?.displayName || "Unknown Trainer"; + } + return "Unknown Trainer"; + } + + const data = doc.data(); + const fields = data?.fields; + if (fields) { + const firstName = fields["first-name"] || ""; + const lastName = fields["last-name"] || ""; + return `${firstName} ${lastName}`.trim() || "Unknown Trainer"; + } + + return data?.name || data?.displayName || "Unknown Trainer"; + } catch (error) { + logger.error(`Error getting trainer name for ${trainerId}:`, error); + return "Unknown Trainer"; + } +} + async function processExpiredMembership( membershipId: string, membershipData: MembershipData @@ -378,7 +447,10 @@ async function processExpiredMembership( }); logger.info(`Marked membership ${membershipId} as EXPIRED`); + await sendPlanExpiredNotification(membershipId, membershipData); + + await sendTrainerNotifications(membershipId, membershipData, "expired"); } catch (error) { logger.error(`Error processing membership ${membershipId}:`, error); } @@ -390,7 +462,10 @@ async function processExpiringMembership( ): Promise { try { logger.info(`Processing expiring membership ${membershipId}`); + await sendPlanExpiringNotification(membershipId, membershipData); + + await sendTrainerNotifications(membershipId, membershipData, "expiring"); } catch (error) { logger.error( `Error processing expiring membership ${membershipId}:`, @@ -399,6 +474,121 @@ async function processExpiringMembership( } } +async function sendTrainerNotifications( + membershipId: string, + membershipData: MembershipData, + notificationType: "expired" | "expiring" +): Promise { + try { + const trainerAssignments = await getTrainerAssignmentsForMembership(membershipId); + + if (trainerAssignments.length === 0) { + logger.info(`No trainer assignments found for membership ${membershipId}`); + return; + } + + const clientName = await getClientName(membershipId, membershipData.userId); + const gymName = await getGymName(membershipData.gymId); + + let expiryDate: Date | undefined; + let formattedDate = "Unknown Date"; + let daysUntilExpiry = 0; + + const payments = await getPaymentsForMembership(membershipId); + if (payments.length > 0) { + const latestPayment = payments[0]; + expiryDate = calculateRenewalDateFromPayment( + membershipData.subscription, + latestPayment.dateTimestamp + ); + formattedDate = expiryDate.toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + }); + + if (notificationType === "expiring") { + const now = new Date(); + const timeDiff = expiryDate.getTime() - now.getTime(); + daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); + } + } + + for (const assignment of trainerAssignments) { + if (!assignment.trainerId) continue; + + try { + const trainerName = await getTrainerName(assignment.trainerId); + + const notifType = notificationType === "expired" ? "trainer_client_plan_expired" : "trainer_client_plan_expiring"; + const existing = await app + .firestore() + .collection("notifications") + .where("type", "==", notifType) + .where("recipientId", "==", assignment.trainerId) + .where("data.membershipId", "==", membershipId) + .where( + "data.expiryDate", + "==", + expiryDate + ? admin.firestore.Timestamp.fromDate(expiryDate) + : admin.firestore.Timestamp.fromDate(new Date()) + ) + .limit(1) + .get(); + + if (!existing.empty) { + logger.info( + `${notificationType} notification already sent to trainer ${assignment.trainerId} for membership ${membershipId}, skipping...` + ); + continue; + } + + const notificationData: any = { + senderId: "system", + recipientId: assignment.trainerId, + type: notifType, + notificationSent: false, + timestamp: admin.firestore.FieldValue.serverTimestamp(), + read: false, + readBy: [], + data: { + planName: membershipData.subscription?.name || "Unknown Plan", + clientName, + membershipId, + gymName, + assignmentId: assignment.id, + formattedExpiryDate: formattedDate, + expiryDate: expiryDate + ? admin.firestore.Timestamp.fromDate(expiryDate) + : admin.firestore.Timestamp.fromDate(new Date()), + }, + }; + + if (notificationType === "expiring") { + notificationData.data.daysUntilExpiry = daysUntilExpiry; + } + + await app.firestore().collection("notifications").add(notificationData); + + logger.info( + `${notificationType} notification sent to trainer ${assignment.trainerId} (${trainerName}) for client ${clientName}'s membership ${membershipId}` + ); + } catch (trainerError) { + logger.error( + `Error sending notification to trainer ${assignment.trainerId} for membership ${membershipId}:`, + trainerError + ); + } + } + } catch (error) { + logger.error( + `Error sending trainer notifications for membership ${membershipId}:`, + error + ); + } +} + async function sendPlanExpiredNotification( membershipId: string, membershipData: MembershipData @@ -609,4 +799,4 @@ async function getGymName(gymId: string): Promise { logger.error(`Error getting gym name for gym ${gymId}:`, error); return "Unknown Gym"; } -} +} \ No newline at end of file diff --git a/functions/src/notifications/processNotification.ts b/functions/src/notifications/processNotification.ts index 2efed4c..d8edce7 100644 --- a/functions/src/notifications/processNotification.ts +++ b/functions/src/notifications/processNotification.ts @@ -180,7 +180,7 @@ function prepareNotificationMessage( case "trainer_response": title = notification.data?.title || - (notification.data?.status === "Accepted" + (notification.data?.status === "accepted" ? "Trainer Request Accepted" : "Trainer Request Update"); body = @@ -240,14 +240,28 @@ function prepareNotificationMessage( title = notification.data?.title || "Plan Expired"; body = notification.data?.message || - `${notification.data?.clientName}'s membership subscription for ${notification.data?.planName} has expired.`; + `${notification.data?.clientName}'s membership for ${notification.data?.planName} has expired.`; break; case "plan_expiring_soon": title = notification.data?.title || "Plan Expiring Soon"; body = notification.data?.message || - `${notification.data?.clientName}'s membership subscription for ${notification.data?.planName} will expire on ${notification.data?.formattedExpiryDate}.`; + `${notification.data?.clientName}'s membership for ${notification.data?.planName} will expire on ${notification.data?.formattedExpiryDate}.`; + break; + + case "trainer_client_plan_expired": + title = notification.data?.title || "Client Plan Expired"; + body = + notification.data?.message || + `${notification.data?.clientName}'s membership for ${notification.data?.planName} has expired.`; + break; + + case "trainer_client_plan_expiring": + title = notification.data?.title || "Client Plan Expiring Soon"; + body = + notification.data?.message || + `${notification.data?.clientName}'s membership for ${notification.data?.planName} will expire on ${notification.data?.formattedExpiryDate}.`; break; case "schedule_update": -- 2.43.0 From ded8e1591854006a82bb87e81e7a5d596a259d9b Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Thu, 14 Aug 2025 12:07:04 +0530 Subject: [PATCH 05/35] Changed TrainerId to TraineruserId --- .../membershipStatusNotifications.ts | 62 ++++++++++++++----- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 7dd0541..9067c77 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -406,14 +406,14 @@ async function getTrainerName(trainerId: string): Promise { .collection("trainer_profiles") .doc(trainerId) .get(); - + if (!doc.exists) { const userDoc = await app .firestore() .collection("users") .doc(trainerId) .get(); - + if (userDoc.exists) { const userData = userDoc.data(); return userData?.name || userData?.displayName || "Unknown Trainer"; @@ -428,7 +428,7 @@ async function getTrainerName(trainerId: string): Promise { const lastName = fields["last-name"] || ""; return `${firstName} ${lastName}`.trim() || "Unknown Trainer"; } - + return data?.name || data?.displayName || "Unknown Trainer"; } catch (error) { logger.error(`Error getting trainer name for ${trainerId}:`, error); @@ -447,9 +447,9 @@ async function processExpiredMembership( }); logger.info(`Marked membership ${membershipId} as EXPIRED`); - + await sendPlanExpiredNotification(membershipId, membershipData); - + await sendTrainerNotifications(membershipId, membershipData, "expired"); } catch (error) { logger.error(`Error processing membership ${membershipId}:`, error); @@ -462,9 +462,9 @@ async function processExpiringMembership( ): Promise { try { logger.info(`Processing expiring membership ${membershipId}`); - + await sendPlanExpiringNotification(membershipId, membershipData); - + await sendTrainerNotifications(membershipId, membershipData, "expiring"); } catch (error) { logger.error( @@ -474,16 +474,44 @@ async function processExpiringMembership( } } +async function getTrainerUserId(trainerId: string): Promise { + try { + const trainerDoc = await app + .firestore() + .collection("trainer_profiles") + .doc(trainerId) + .get(); + + if (!trainerDoc.exists) { + throw new Error(`Trainer profile not found for ID: ${trainerId}`); + } + + const trainerData = trainerDoc.data(); + if (!trainerData?.userId) { + throw new Error(`userId not found in trainer profile: ${trainerId}`); + } + + return trainerData.userId; + } catch (error) { + logger.error(`Error getting userId for trainer ${trainerId}:`, error); + return trainerId; + } +} + async function sendTrainerNotifications( membershipId: string, membershipData: MembershipData, notificationType: "expired" | "expiring" ): Promise { try { - const trainerAssignments = await getTrainerAssignmentsForMembership(membershipId); - + const trainerAssignments = await getTrainerAssignmentsForMembership( + membershipId + ); + if (trainerAssignments.length === 0) { - logger.info(`No trainer assignments found for membership ${membershipId}`); + logger.info( + `No trainer assignments found for membership ${membershipId}` + ); return; } @@ -519,13 +547,17 @@ async function sendTrainerNotifications( try { const trainerName = await getTrainerName(assignment.trainerId); - - const notifType = notificationType === "expired" ? "trainer_client_plan_expired" : "trainer_client_plan_expiring"; + const trainerUserId = await getTrainerUserId(assignment.trainerId); + + const notifType = + notificationType === "expired" + ? "trainer_client_plan_expired" + : "trainer_client_plan_expiring"; const existing = await app .firestore() .collection("notifications") .where("type", "==", notifType) - .where("recipientId", "==", assignment.trainerId) + .where("recipientId", "==", trainerUserId) .where("data.membershipId", "==", membershipId) .where( "data.expiryDate", @@ -546,7 +578,7 @@ async function sendTrainerNotifications( const notificationData: any = { senderId: "system", - recipientId: assignment.trainerId, + recipientId: trainerUserId, type: notifType, notificationSent: false, timestamp: admin.firestore.FieldValue.serverTimestamp(), @@ -799,4 +831,4 @@ async function getGymName(gymId: string): Promise { logger.error(`Error getting gym name for gym ${gymId}:`, error); return "Unknown Gym"; } -} \ No newline at end of file +} -- 2.43.0 From e1822f925797cb179d38df1d92e64defd79c637c Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Thu, 14 Aug 2025 12:47:03 +0530 Subject: [PATCH 06/35] Added role to navigate to notification screen --- functions/src/notifications/membershipStatusNotifications.ts | 1 + functions/src/notifications/processNotification.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 8d25206..4a99688 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -588,6 +588,7 @@ async function sendTrainerNotifications( gymName, assignmentId: assignment.id, formattedExpiryDate: formattedDate, + role: 'Trainer', expiryDate: expiryDate ? admin.firestore.Timestamp.fromDate(expiryDate) : admin.firestore.Timestamp.fromDate(new Date()), diff --git a/functions/src/notifications/processNotification.ts b/functions/src/notifications/processNotification.ts index d8edce7..fe7ce6a 100644 --- a/functions/src/notifications/processNotification.ts +++ b/functions/src/notifications/processNotification.ts @@ -181,8 +181,8 @@ function prepareNotificationMessage( title = notification.data?.title || (notification.data?.status === "accepted" - ? "Trainer Request Accepted" - : "Trainer Request Update"); + ? "Trainer Invitation Accepted" + : "Trainer Invitation Update"); body = notification.data?.message || `${ -- 2.43.0 From bdd94264a69fa028021a1ebaf3a6563e5a1fd7c7 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Thu, 14 Aug 2025 14:01:53 +0530 Subject: [PATCH 07/35] Added role --- functions/src/notifications/membershipStatusNotifications.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 4a99688..218ff95 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -545,6 +545,7 @@ async function sendTrainerNotifications( try { const trainerName = await getTrainerName(assignment.trainerId); const trainerUserId = await getTrainerUserId(assignment.trainerId); + const kTrainerRole = 'Trainer'; const notifType = notificationType === "expired" @@ -588,7 +589,7 @@ async function sendTrainerNotifications( gymName, assignmentId: assignment.id, formattedExpiryDate: formattedDate, - role: 'Trainer', + role: kTrainerRole, expiryDate: expiryDate ? admin.firestore.Timestamp.fromDate(expiryDate) : admin.firestore.Timestamp.fromDate(new Date()), -- 2.43.0 From 59d8df180eb8351e180bc67f447fcc2ff5dece23 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Thu, 14 Aug 2025 14:03:35 +0530 Subject: [PATCH 08/35] updated --- functions/src/notifications/membershipStatusNotifications.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 218ff95..2ed768f 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -4,6 +4,7 @@ import * as admin from "firebase-admin"; const app = getAdmin(); const logger = getLogger(); +const kTrainerRole = 'Trainer'; interface MembershipData { id?: string; @@ -545,7 +546,7 @@ async function sendTrainerNotifications( try { const trainerName = await getTrainerName(assignment.trainerId); const trainerUserId = await getTrainerUserId(assignment.trainerId); - const kTrainerRole = 'Trainer'; + const notifType = notificationType === "expired" -- 2.43.0 From 3e989493b08011c6315181e3cbc20bed004032b9 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Thu, 14 Aug 2025 18:40:41 +0530 Subject: [PATCH 09/35] Gym index added --- firestore.indexes.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2016f51..0530c8b 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -28,6 +28,34 @@ } ] }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "isApproved", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "gyms", "queryScope": "COLLECTION_GROUP", -- 2.43.0 From d15c04fc910f145cee58e1e736a2f9bc4ea8f380 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Mon, 18 Aug 2025 19:07:45 +0530 Subject: [PATCH 10/35] Changes Updated --- .../membershipStatusNotifications.ts | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 2ed768f..a26f9eb 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -4,7 +4,7 @@ import * as admin from "firebase-admin"; const app = getAdmin(); const logger = getLogger(); -const kTrainerRole = 'Trainer'; +const kTrainerRole = "Trainer"; interface MembershipData { id?: string; @@ -439,15 +439,33 @@ async function processExpiredMembership( membershipData: MembershipData ): Promise { try { - await app.firestore().collection("memberships").doc(membershipId).update({ - status: "EXPIRED", - updatedAt: admin.firestore.FieldValue.serverTimestamp(), - }); + const payments = await getPaymentsForMembership(membershipId); + if (payments.length > 0) { + const latestPayment = payments[0]; + const expiryDate = calculateExpiryDate( + latestPayment.dateTimestamp, + membershipData.subscription?.frequency || "monthly" + ); + + await app + .firestore() + .collection("memberships") + .doc(membershipId) + .update({ + expirationDate: admin.firestore.Timestamp.fromDate(expiryDate), + status: "EXPIRED", + updatedAt: admin.firestore.FieldValue.serverTimestamp(), + }); + } else { + await app.firestore().collection("memberships").doc(membershipId).update({ + status: "EXPIRED", + updatedAt: admin.firestore.FieldValue.serverTimestamp(), + }); + } logger.info(`Marked membership ${membershipId} as EXPIRED`); await sendPlanExpiredNotification(membershipId, membershipData); - await sendTrainerNotifications(membershipId, membershipData, "expired"); } catch (error) { logger.error(`Error processing membership ${membershipId}:`, error); @@ -461,8 +479,25 @@ async function processExpiringMembership( try { logger.info(`Processing expiring membership ${membershipId}`); - await sendPlanExpiringNotification(membershipId, membershipData); + const payments = await getPaymentsForMembership(membershipId); + if (payments.length > 0) { + const latestPayment = payments[0]; + const expiryDate = calculateExpiryDate( + latestPayment.dateTimestamp, + membershipData.subscription?.frequency || "monthly" + ); + await app + .firestore() + .collection("memberships") + .doc(membershipId) + .update({ + expirationDate: admin.firestore.Timestamp.fromDate(expiryDate), + updatedAt: admin.firestore.FieldValue.serverTimestamp(), + }); + } + + await sendPlanExpiringNotification(membershipId, membershipData); await sendTrainerNotifications(membershipId, membershipData, "expiring"); } catch (error) { logger.error( @@ -546,7 +581,6 @@ async function sendTrainerNotifications( try { const trainerName = await getTrainerName(assignment.trainerId); const trainerUserId = await getTrainerUserId(assignment.trainerId); - const notifType = notificationType === "expired" -- 2.43.0 From 25f77d2fec2fa4be31be68860ebed7971de2e451 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Mon, 18 Aug 2025 23:21:09 +0530 Subject: [PATCH 11/35] Changes updated --- firestore.indexes.json | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 0530c8b..c1c2245 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -56,20 +56,7 @@ } ] }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, + { "collectionGroup": "gyms", "queryScope": "COLLECTION", -- 2.43.0 From 559997a16e9bd26cbc7972992f767e027ec3f40a Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 09:53:01 +0530 Subject: [PATCH 12/35] Changes Updated --- firestore.indexes.json | 14 --- .../membershipStatusNotifications.ts | 96 +++++++++++++++++++ 2 files changed, 96 insertions(+), 14 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index c1c2245..2d8dc7b 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -57,20 +57,6 @@ ] }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, { "collectionGroup": "memberships", "queryScope": "COLLECTION", diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index a26f9eb..ba73340 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -53,6 +53,8 @@ export const checkExpiredMemberships = onSchedule( logger.info("Starting scheduled membership expiry check..."); try { + + await updateDaysUntilExpiryForAllMemberships(); const expiredMemberships = await findExpiredMemberships(); const expiringMemberships = await findMembershipsExpiringIn10Days(); @@ -377,6 +379,100 @@ function calculateRenewalDateFromPayment( return renewalDate; } +async function updateDaysUntilExpiryForAllMemberships(): Promise { + try { + logger.info("Starting to update daysUntilExpiry for all active memberships..."); + + const snapshot = await app + .firestore() + .collection("memberships") + .where("status", "==", "ACTIVE") + .get(); + + const batchSize = 10; + const docs = snapshot.docs; + let updatedCount = 0; + + for (let i = 0; i < docs.length; i += batchSize) { + const batch = docs.slice(i, i + batchSize); + const batchResults = await Promise.allSettled( + batch.map(async (doc) => { + const data = doc.data() as MembershipData; + const daysUntilExpiry = await calculateDaysUntilExpiry(doc.id, data); + + if (daysUntilExpiry !== null) { + await app + .firestore() + .collection("memberships") + .doc(doc.id) + .update({ + daysUntilExpiry: daysUntilExpiry, + updatedAt: admin.firestore.FieldValue.serverTimestamp(), + }); + return doc.id; + } + return null; + }) + ); + + batchResults.forEach((result) => { + if (result.status === "fulfilled" && result.value) { + updatedCount++; + } + }); + } + + logger.info(`Updated daysUntilExpiry for ${updatedCount} memberships`); + } catch (error) { + logger.error("Error updating daysUntilExpiry for memberships:", error); + throw error; + } +} + + +async function calculateDaysUntilExpiry( + membershipId: string, + data: MembershipData +): Promise { + try { + if (!data.subscription || !data.subscription.frequency) { + logger.warn( + `Skipping expiry calculation for membership ${membershipId} with missing subscription data.` + ); + return null; + } + + const payments = await getPaymentsForMembership(membershipId); + if (payments.length === 0) { + logger.warn( + `No payments found for membership ${membershipId}, cannot determine expiry` + ); + return null; + } + + const latestPayment = payments[0]; + const startDate = latestPayment.dateTimestamp; + + const expiryDate = calculateExpiryDate( + startDate, + data.subscription.frequency + ); + + const now = new Date(); + const timeDiff = expiryDate.getTime() - now.getTime(); + const daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); + + return daysUntilExpiry; + } catch (error) { + logger.error( + `Error calculating daysUntilExpiry for membership ${membershipId}:`, + error + ); + return null; + } +} + + async function getTrainerAssignmentsForMembership( membershipId: string ): Promise { -- 2.43.0 From 2987a8c15999d6bb1dd60407cc0602d0bfaa858a Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 10:16:27 +0530 Subject: [PATCH 13/35] Index Updated --- firestore.indexes.json | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2d8dc7b..0bae7a0 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,19 +1,5 @@ { "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, { "collectionGroup": "day_pass_entries", "queryScope": "COLLECTION", @@ -56,7 +42,6 @@ } ] }, - { "collectionGroup": "memberships", "queryScope": "COLLECTION", -- 2.43.0 From 0f3c2909f84ad51fb3ab5bbb4f8c360befdc2f26 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 10:24:23 +0530 Subject: [PATCH 14/35] index changed --- firestore.indexes.json | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 0bae7a0..2016f51 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,5 +1,19 @@ { "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, { "collectionGroup": "day_pass_entries", "queryScope": "COLLECTION", @@ -24,20 +38,20 @@ }, { "fieldPath": "createdAt", - "order": "DESCENDING" + "order": "ASCENDING" } ] }, { "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", + "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "isApproved", + "fieldPath": "userId", "order": "ASCENDING" }, { - "fieldPath": "createdAt", + "fieldPath": "name", "order": "ASCENDING" } ] -- 2.43.0 From 9f01685278b1126a8e111c9043795a1904a36eda Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 10:42:12 +0530 Subject: [PATCH 15/35] Added New Index --- firestore.indexes.json | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index ef951a9..da30ef2 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,5 +1,19 @@ { "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, { "collectionGroup": "day_pass_entries", "queryScope": "COLLECTION", @@ -42,6 +56,34 @@ } ] }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "isApproved", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, { "collectionGroup": "memberships", "queryScope": "COLLECTION", -- 2.43.0 From beffe778e6cd2761c408f724c35e53f0f541f36f Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 10:57:30 +0530 Subject: [PATCH 16/35] Updated Index file --- firestore.indexes.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 4aa6594..c305011 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -56,20 +56,6 @@ } ] }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, { "collectionGroup": "gyms", "queryScope": "COLLECTION_GROUP", @@ -84,6 +70,20 @@ } ] }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "isApproved", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "memberships", "queryScope": "COLLECTION", -- 2.43.0 From 1abf6b3d58a35dbbcd04e296017aae49956ad619 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 11:06:23 +0530 Subject: [PATCH 17/35] Changes done for index --- firestore.indexes.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index c305011..887fe07 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -28,20 +28,6 @@ } ] }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, { "collectionGroup": "gyms", "queryScope": "COLLECTION", -- 2.43.0 From 2467e71ec0ce4aa97fb30fae549617f16c30655a Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 11:08:39 +0530 Subject: [PATCH 18/35] Updated --- firestore.indexes.json | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 887fe07..c4bf41d 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,33 +1,5 @@ { "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "day_pass_entries", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "bookingId", - "order": "ASCENDING" - }, - { - "fieldPath": "entryDate", - "order": "ASCENDING" - } - ] - }, { "collectionGroup": "gyms", "queryScope": "COLLECTION", -- 2.43.0 From 1e80333bc5103316157de524767b179e1a9b5c1b Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 11:51:03 +0530 Subject: [PATCH 19/35] Index file rremoved --- firestore.indexes.json | 231 ----------------------------------------- 1 file changed, 231 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index c4bf41d..e69de29 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,231 +0,0 @@ -{ - "indexes": [ - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "isApproved", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "memberships", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "gymId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "data.clientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "data.clientId", - "order": "ASCENDING" - }, - { - "fieldPath": "type", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "type", - "order": "ASCENDING" - }, - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "data.ownerId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "data.ownerId", - "order": "ASCENDING" - }, - { - "fieldPath": "type", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "data.trainerId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "start_time", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "terms_and_conditions", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "normalizedName", - "order": "ASCENDING" - }, - { - "fieldPath": "userUid", - "order": "ASCENDING" - } - ] - } - ], - "fieldOverrides": [] -} \ No newline at end of file -- 2.43.0 From 83cb1d83fae85585a2c93d63ecd7cb1417a80df2 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 12:07:32 +0530 Subject: [PATCH 20/35] Changes done for index --- firestore.indexes.json | 259 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index e69de29..887fe07 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -0,0 +1,259 @@ +{ + "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "day_pass_entries", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "bookingId", + "order": "ASCENDING" + }, + { + "fieldPath": "entryDate", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "isApproved", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "memberships", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "gymId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "data.clientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "data.clientId", + "order": "ASCENDING" + }, + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "data.ownerId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "data.ownerId", + "order": "ASCENDING" + }, + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "data.trainerId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "start_time", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "terms_and_conditions", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "normalizedName", + "order": "ASCENDING" + }, + { + "fieldPath": "userUid", + "order": "ASCENDING" + } + ] + } + ], + "fieldOverrides": [] +} \ No newline at end of file -- 2.43.0 From d27d41318b44865183701b0cab12acfcdf3fabc5 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 12:19:52 +0530 Subject: [PATCH 21/35] updated --- firestore.indexes.json | 88 ------------------------------------------ 1 file changed, 88 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 9e692cc..53cc445 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -165,94 +165,6 @@ "order": "DESCENDING" } ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "data.trainerId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "start_time", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "terms_and_conditions", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "normalizedName", - "order": "ASCENDING" - }, - { - "fieldPath": "userUid", - "order": "ASCENDING" - } - ] } ], "fieldOverrides": [] -- 2.43.0 From 5e2aacab581b90b90e7209cba66f9d69e331a635 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 12:23:28 +0530 Subject: [PATCH 22/35] updated --- firestore.indexes.json | 136 +++++++++-------------------------------- 1 file changed, 29 insertions(+), 107 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 53cc445..980f655 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,95 +1,11 @@ { "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "day_pass_entries", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "bookingId", - "order": "ASCENDING" - }, - { - "fieldPath": "entryDate", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "isApproved", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "memberships", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "gymId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { +{ "collectionGroup": "notifications", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "data.clientId", + "fieldPath": "data.trainerId", "order": "ASCENDING" }, { @@ -103,11 +19,7 @@ "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "data.clientId", - "order": "ASCENDING" - }, - { - "fieldPath": "type", + "fieldPath": "recipientId", "order": "ASCENDING" }, { @@ -117,52 +29,62 @@ ] }, { - "collectionGroup": "notifications", + "collectionGroup": "workout_logs", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "type", + "fieldPath": "user_id", "order": "ASCENDING" }, { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", + "fieldPath": "date", "order": "DESCENDING" } ] }, { - "collectionGroup": "notifications", + "collectionGroup": "workout_logs", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "data.ownerId", + "fieldPath": "user_id", "order": "ASCENDING" }, { - "fieldPath": "timestamp", - "order": "DESCENDING" + "fieldPath": "date", + "order": "ASCENDING" } ] }, { - "collectionGroup": "notifications", + "collectionGroup": "workout_logs", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "data.ownerId", + "fieldPath": "user_id", "order": "ASCENDING" }, { - "fieldPath": "type", + "fieldPath": "start_time", "order": "ASCENDING" }, { - "fieldPath": "timestamp", - "order": "DESCENDING" + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "terms_and_conditions", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "normalizedName", + "order": "ASCENDING" + }, + { + "fieldPath": "userUid", + "order": "ASCENDING" } ] } -- 2.43.0 From fb6141f0b35047fc7fa56d2e867685f338b5d36c Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 12:35:02 +0530 Subject: [PATCH 23/35] Changes Updated --- firestore.indexes.json | 110 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 980f655..ae7170d 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,11 +1,114 @@ { "indexes": [ -{ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "day_pass_entries", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "bookingId", + "order": "ASCENDING" + }, + { + "fieldPath": "entryDate", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "isApproved", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "memberships", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "gymId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + + { "collectionGroup": "notifications", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "data.trainerId", + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "userId", "order": "ASCENDING" }, { @@ -14,6 +117,7 @@ } ] }, + { "collectionGroup": "notifications", "queryScope": "COLLECTION", @@ -90,4 +194,4 @@ } ], "fieldOverrides": [] -} +} \ No newline at end of file -- 2.43.0 From b51f4d81f0bdc8d41664541746fbd923ed78dcb8 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 12:40:32 +0530 Subject: [PATCH 24/35] Changed --- firestore.indexes.json | 1 + 1 file changed, 1 insertion(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index 6f214a4..2ffd217 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -189,5 +189,6 @@ ] } ], + "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From 99fed340aa559f5f789059748682a021676c81e0 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 12:49:47 +0530 Subject: [PATCH 25/35] updated --- firestore.indexes.json | 143 ++++------------------------------------- 1 file changed, 14 insertions(+), 129 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ffd217..f39047e 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,133 +1,5 @@ { "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "day_pass_entries", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "bookingId", - "order": "ASCENDING" - }, - { - "fieldPath": "entryDate", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "isApproved", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "memberships", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "gymId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "DESCENDING" - } - ] - }, - - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, { "collectionGroup": "workout_logs", "queryScope": "COLLECTION", @@ -187,8 +59,21 @@ "order": "ASCENDING" } ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] } ], - "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From 9f8ea011c192230a828a673df6107bdbb47fc384 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 15:11:59 +0530 Subject: [PATCH 26/35] Updated --- firestore.indexes.json | 121 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 14 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index f39047e..d2b6856 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,5 +1,112 @@ { "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "day_pass_entries", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "bookingId", + "order": "ASCENDING" + }, + { + "fieldPath": "entryDate", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "memberships", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "gymId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + + + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + + + + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, { "collectionGroup": "workout_logs", "queryScope": "COLLECTION", @@ -59,20 +166,6 @@ "order": "ASCENDING" } ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] } ], "fieldOverrides": [] -- 2.43.0 From 1bd8d24df6af35637a6cab2bd4336b14c8938a77 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 15:21:12 +0530 Subject: [PATCH 27/35] Updated --- firestore.indexes.json | 185 +---------------------------------------- 1 file changed, 1 insertion(+), 184 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 077a143..2ddb5ce 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,187 +1,4 @@ { - "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "day_pass_entries", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "bookingId", - "order": "ASCENDING" - }, - { - "fieldPath": "entryDate", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "memberships", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "gymId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - - - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "type", - "order": "ASCENDING" - }, - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - - - - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "start_time", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "terms_and_conditions", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "normalizedName", - "order": "ASCENDING" - }, - { - "fieldPath": "userUid", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - } - ], - + "indexes": [], "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From 86b2073e8e562cf69294384e5dd1e407616b07a2 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 15:49:09 +0530 Subject: [PATCH 28/35] Done --- firestore.indexes.json | 165 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ddb5ce..054170d 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,4 +1,167 @@ { - "indexes": [], + "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "day_pass_entries", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "bookingId", + "order": "ASCENDING" + }, + { + "fieldPath": "entryDate", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "memberships", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "gymId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "start_time", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "terms_and_conditions", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "normalizedName", + "order": "ASCENDING" + }, + { + "fieldPath": "userUid", + "order": "ASCENDING" + } + ] + } + ], "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From a62db929aa5df4cbfac576f85f30093782082be8 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 16:25:16 +0530 Subject: [PATCH 29/35] Changes Updated --- .../membershipStatusNotifications.ts | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index ba73340..7e1b88e 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -53,7 +53,6 @@ export const checkExpiredMemberships = onSchedule( logger.info("Starting scheduled membership expiry check..."); try { - await updateDaysUntilExpiryForAllMemberships(); const expiredMemberships = await findExpiredMemberships(); const expiringMemberships = await findMembershipsExpiringIn10Days(); @@ -381,8 +380,10 @@ function calculateRenewalDateFromPayment( async function updateDaysUntilExpiryForAllMemberships(): Promise { try { - logger.info("Starting to update daysUntilExpiry for all active memberships..."); - + logger.info( + "Starting to update daysUntilExpiry for all active memberships..." + ); + const snapshot = await app .firestore() .collection("memberships") @@ -399,16 +400,22 @@ async function updateDaysUntilExpiryForAllMemberships(): Promise { batch.map(async (doc) => { const data = doc.data() as MembershipData; const daysUntilExpiry = await calculateDaysUntilExpiry(doc.id, data); - + if (daysUntilExpiry !== null) { + const updateData: any = { + daysUntilExpiry: daysUntilExpiry, + updatedAt: admin.firestore.FieldValue.serverTimestamp(), + }; + await app .firestore() .collection("memberships") .doc(doc.id) - .update({ - daysUntilExpiry: daysUntilExpiry, - updatedAt: admin.firestore.FieldValue.serverTimestamp(), - }); + .update(updateData); + + logger.info( + `Updated membership ${doc.id} with daysUntilExpiry: ${daysUntilExpiry}` + ); return doc.id; } return null; @@ -429,7 +436,6 @@ async function updateDaysUntilExpiryForAllMemberships(): Promise { } } - async function calculateDaysUntilExpiry( membershipId: string, data: MembershipData @@ -459,7 +465,14 @@ async function calculateDaysUntilExpiry( ); const now = new Date(); - const timeDiff = expiryDate.getTime() - now.getTime(); + const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + const expiryDateOnly = new Date( + expiryDate.getFullYear(), + expiryDate.getMonth(), + expiryDate.getDate() + ); + + const timeDiff = expiryDateOnly.getTime() - today.getTime(); const daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); return daysUntilExpiry; @@ -472,7 +485,6 @@ async function calculateDaysUntilExpiry( } } - async function getTrainerAssignmentsForMembership( membershipId: string ): Promise { -- 2.43.0 From 33ada04122a27503c27ea89c1a0b01278cfe27b8 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 17:10:55 +0530 Subject: [PATCH 30/35] Removed --- firestore.indexes.json | 165 +---------------------------------------- 1 file changed, 1 insertion(+), 164 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 054170d..2ddb5ce 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,167 +1,4 @@ { - "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "day_pass_entries", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "bookingId", - "order": "ASCENDING" - }, - { - "fieldPath": "entryDate", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "memberships", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "gymId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "type", - "order": "ASCENDING" - }, - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "start_time", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "terms_and_conditions", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "normalizedName", - "order": "ASCENDING" - }, - { - "fieldPath": "userUid", - "order": "ASCENDING" - } - ] - } - ], + "indexes": [], "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From a0cd3fa4873788b85416fef64086e2bf62fb9deb Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 17:12:12 +0530 Subject: [PATCH 31/35] Removed indexes --- firestore.indexes.json | 165 +---------------------------------------- 1 file changed, 1 insertion(+), 164 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 054170d..2ddb5ce 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,167 +1,4 @@ { - "indexes": [ - { - "collectionGroup": "day_pass_bookings", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "day_pass_entries", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "bookingId", - "order": "ASCENDING" - }, - { - "fieldPath": "entryDate", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION_GROUP", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "gyms", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "name", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "memberships", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "gymId", - "order": "ASCENDING" - }, - { - "fieldPath": "createdAt", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "type", - "order": "ASCENDING" - }, - { - "fieldPath": "userId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "notifications", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "recipientId", - "order": "ASCENDING" - }, - { - "fieldPath": "timestamp", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "DESCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "workout_logs", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "user_id", - "order": "ASCENDING" - }, - { - "fieldPath": "start_time", - "order": "ASCENDING" - }, - { - "fieldPath": "date", - "order": "ASCENDING" - } - ] - }, - { - "collectionGroup": "terms_and_conditions", - "queryScope": "COLLECTION", - "fields": [ - { - "fieldPath": "normalizedName", - "order": "ASCENDING" - }, - { - "fieldPath": "userUid", - "order": "ASCENDING" - } - ] - } - ], + "indexes": [], "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From b3ea601a0f8c978cf1fb7f1b146103bc44fca1b7 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 17:19:25 +0530 Subject: [PATCH 32/35] Added Index --- firestore.indexes.json | 165 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ddb5ce..054170d 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,4 +1,167 @@ { - "indexes": [], + "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "day_pass_entries", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "bookingId", + "order": "ASCENDING" + }, + { + "fieldPath": "entryDate", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "memberships", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "gymId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "start_time", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "terms_and_conditions", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "normalizedName", + "order": "ASCENDING" + }, + { + "fieldPath": "userUid", + "order": "ASCENDING" + } + ] + } + ], "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From 4385d4579d06627280d03affc435f5be8888f55d Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 17:20:27 +0530 Subject: [PATCH 33/35] Added Index --- firestore.indexes.json | 165 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ddb5ce..054170d 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,4 +1,167 @@ { - "indexes": [], + "indexes": [ + { + "collectionGroup": "day_pass_bookings", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "day_pass_entries", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "bookingId", + "order": "ASCENDING" + }, + { + "fieldPath": "entryDate", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "memberships", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "gymId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "type", + "order": "ASCENDING" + }, + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "workout_logs", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "user_id", + "order": "ASCENDING" + }, + { + "fieldPath": "start_time", + "order": "ASCENDING" + }, + { + "fieldPath": "date", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "terms_and_conditions", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "normalizedName", + "order": "ASCENDING" + }, + { + "fieldPath": "userUid", + "order": "ASCENDING" + } + ] + } + ], "fieldOverrides": [] } \ No newline at end of file -- 2.43.0 From f1976f12b687035caff02b83ee8ed3e4c62851f8 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 20 Aug 2025 13:37:22 +0530 Subject: [PATCH 34/35] Changes Updated for days until expiry --- .../membershipStatusNotifications.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 7e1b88e..85799cf 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -465,17 +465,11 @@ async function calculateDaysUntilExpiry( ); const now = new Date(); - const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); - const expiryDateOnly = new Date( - expiryDate.getFullYear(), - expiryDate.getMonth(), - expiryDate.getDate() - ); - const timeDiff = expiryDateOnly.getTime() - today.getTime(); - const daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); + const timeDiff = expiryDate.getTime() - now.getTime(); + const daysUntilExpiry = Math.floor(timeDiff / (1000 * 3600 * 24)); - return daysUntilExpiry; + return Math.max(0, daysUntilExpiry); } catch (error) { logger.error( `Error calculating daysUntilExpiry for membership ${membershipId}:`, @@ -679,7 +673,7 @@ async function sendTrainerNotifications( if (notificationType === "expiring") { const now = new Date(); const timeDiff = expiryDate.getTime() - now.getTime(); - daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); + daysUntilExpiry = Math.floor(timeDiff / (1000 * 3600 * 24)); } } @@ -869,7 +863,7 @@ async function sendPlanExpiringNotification( const now = new Date(); const timeDiff = expiryDate.getTime() - now.getTime(); - daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24)); + daysUntilExpiry = Math.floor(timeDiff / (1000 * 3600 * 24)); } const existing = await app @@ -929,7 +923,6 @@ async function sendPlanExpiringNotification( ); } } - async function getClientName( membershipId: string, clientId: string -- 2.43.0 From 687d9716b38bf8376ca34b02de304a6f8949087c Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 20 Aug 2025 13:58:09 +0530 Subject: [PATCH 35/35] new Index added --- firestore.indexes.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index 054170d..54f5709 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -56,6 +56,34 @@ } ] }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "userId", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "DESCENDING" + } + ] + }, + { + "collectionGroup": "gyms", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "isApproved", + "order": "ASCENDING" + }, + { + "fieldPath": "createdAt", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "memberships", "queryScope": "COLLECTION", -- 2.43.0