From 39ea6dcafbf1f1769014eec719f985c92ad6ab5f Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Mon, 18 Aug 2025 13:42:26 +0000 Subject: [PATCH 01/24] notification-bug-fix (#87) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/87 Reviewed-by: Allen T J Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 28 +++++++++++ .../membershipStatusNotifications.ts | 50 ++++++++++++++++--- 2 files changed, 70 insertions(+), 8 deletions(-) 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", 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" From 209354ec6b33b5b43ad9115fb982dd383cff270d Mon Sep 17 00:00:00 2001 From: Benoy Bose Date: Mon, 18 Aug 2025 19:16:18 +0530 Subject: [PATCH 02/24] UPDATED firebase-functions package --- functions/package-lock.json | 9 +- functions/package.json | 2 +- package-lock.json | 242 ------------------------------------ package.json | 7 -- 4 files changed, 6 insertions(+), 254 deletions(-) delete mode 100644 package-lock.json delete mode 100644 package.json diff --git a/functions/package-lock.json b/functions/package-lock.json index 1d81e0c..1ef4a3f 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -15,7 +15,7 @@ "cors": "^2.8.5", "date-fns": "^4.1.0", "firebase-admin": "^12.6.0", - "firebase-functions": "^6.0.1", + "firebase-functions": "^6.4.0", "form-data": "^4.0.1", "functions": "file:", "html-to-text": "^9.0.5", @@ -4897,9 +4897,10 @@ } }, "node_modules/firebase-functions": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.3.2.tgz", - "integrity": "sha512-FC3A1/nhqt1ZzxRnj5HZLScQaozAcFSD/vSR8khqSoFNOfxuXgwJS6ZABTB7+v+iMD5z6Mmxw6OfqITUBuI7OQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.4.0.tgz", + "integrity": "sha512-Q/LGhJrmJEhT0dbV60J4hCkVSeOM6/r7xJS/ccmkXzTWMjo+UPAYX9zlQmGlEjotstZ0U9GtQSJSgbB2Z+TJDg==", + "license": "MIT", "dependencies": { "@types/cors": "^2.8.5", "@types/express": "^4.17.21", diff --git a/functions/package.json b/functions/package.json index 334660d..099daf5 100644 --- a/functions/package.json +++ b/functions/package.json @@ -22,7 +22,7 @@ "cors": "^2.8.5", "date-fns": "^4.1.0", "firebase-admin": "^12.6.0", - "firebase-functions": "^6.0.1", + "firebase-functions": "^6.4.0", "form-data": "^4.0.1", "functions": "file:", "html-to-text": "^9.0.5", diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index b0bc379..0000000 --- a/package-lock.json +++ /dev/null @@ -1,242 +0,0 @@ -{ - "name": "fitlien-services", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@types/busboy": "^1.5.4", - "@types/nodemailer": "^6.4.17", - "@types/pdfkit": "^0.13.9", - "busboy": "^1.6.0", - "date-fns": "^4.1.0", - "nodemailer": "^7.0.3", - "pdfkit": "^0.17.1" - } - }, - "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@types/busboy": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.4.tgz", - "integrity": "sha512-kG7WrUuAKK0NoyxfQHsVE6j1m01s6kMma64E+OZenQABMQyTJop1DumUWcLwAQ2JzpefU7PDYoRDKl8uZosFjw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/nodemailer": { - "version": "6.4.17", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz", - "integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/pdfkit": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/@types/pdfkit/-/pdfkit-0.13.9.tgz", - "integrity": "sha512-RDG8Yb1zT7I01FfpwK7nMSA433XWpblMqSCtA5vJlSyavWZb303HUYPCel6JTiDDFqwGLvtAnYbH8N/e0Cb89g==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/brotli": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", - "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", - "dependencies": { - "base64-js": "^1.1.2" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" - }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/dfa": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", - "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fontkit": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", - "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", - "dependencies": { - "@swc/helpers": "^0.5.12", - "brotli": "^1.3.2", - "clone": "^2.1.2", - "dfa": "^1.2.0", - "fast-deep-equal": "^3.1.3", - "restructure": "^3.0.0", - "tiny-inflate": "^1.0.3", - "unicode-properties": "^1.4.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/jpeg-exif": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz", - "integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==" - }, - "node_modules/linebreak": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", - "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", - "dependencies": { - "base64-js": "0.0.8", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/linebreak/node_modules/base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/nodemailer": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.3.tgz", - "integrity": "sha512-Ajq6Sz1x7cIK3pN6KesGTah+1gnwMnx5gKl3piQlQQE/PwyJ4Mbc8is2psWYxK3RJTVeqsDaCv8ZzXLCDHMTZw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" - }, - "node_modules/pdfkit": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.17.1.tgz", - "integrity": "sha512-Kkf1I9no14O/uo593DYph5u3QwiMfby7JsBSErN1WqeyTgCBNJE3K4pXBn3TgkdKUIVu+buSl4bYUNC+8Up4xg==", - "dependencies": { - "crypto-js": "^4.2.0", - "fontkit": "^2.0.4", - "jpeg-exif": "^1.1.4", - "linebreak": "^1.1.0", - "png-js": "^1.0.0" - } - }, - "node_modules/png-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", - "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" - }, - "node_modules/restructure": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", - "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==" - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" - }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index da0eb6c..0000000 --- a/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "dependencies": { - "@types/busboy": "^1.5.4", - "busboy": "^1.6.0", - "date-fns": "^4.1.0" - } -} From 7259e67833fe976699608aad98b4b8c804de2932 Mon Sep 17 00:00:00 2001 From: Benoy Bose Date: Mon, 18 Aug 2025 19:20:36 +0530 Subject: [PATCH 03/24] REMOVED clean install from project root --- .gitea/workflows/deploy-dev.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitea/workflows/deploy-dev.yaml b/.gitea/workflows/deploy-dev.yaml index cbb62b4..05c02dc 100644 --- a/.gitea/workflows/deploy-dev.yaml +++ b/.gitea/workflows/deploy-dev.yaml @@ -19,9 +19,6 @@ jobs: with: node-version: 22 - - name: Clean install - run: npm clean-install - - name: Copy .env.example to .env run: cp functions/.env.example functions/.env From 5ff7b8bb84d06e7c0f3073a8134c70d6789383ed Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 04:30:40 +0000 Subject: [PATCH 04/24] notification-bug-fix (#88) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/88 Reviewed-by: Allen T J Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 29 +----- .../membershipStatusNotifications.ts | 96 +++++++++++++++++++ 2 files changed, 97 insertions(+), 28 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 0530c8b..2d8dc7b 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -56,34 +56,7 @@ } ] }, - { - "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", 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 { From 8f5956a825fe8328d1e83b9eb1ef84b444f4fcc7 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 04:49:31 +0000 Subject: [PATCH 05/24] notification-bug-fix (#89) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/89 Reviewed-by: Allen T J Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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", From 7c494154bac724cee63bf106426d4c4e41c32b49 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 04:59:34 +0000 Subject: [PATCH 06/24] notification-bug-fix (#90) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/90 Reviewed-by: Allen T J Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 0bae7a0..ef951a9 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -24,20 +24,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" } ] From 939567f7c09e1b7bfb551e5f12271c9211608959 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 05:39:54 +0000 Subject: [PATCH 07/24] notification-bug-fix (#91) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/91 Reviewed-by: Allen T J Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index ef951a9..c4bf41d 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,15 +1,15 @@ { "indexes": [ { - "collectionGroup": "day_pass_entries", + "collectionGroup": "gyms", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "bookingId", + "fieldPath": "userId", "order": "ASCENDING" }, { - "fieldPath": "entryDate", + "fieldPath": "name", "order": "ASCENDING" } ] @@ -24,20 +24,20 @@ }, { "fieldPath": "createdAt", - "order": "ASCENDING" + "order": "DESCENDING" } ] }, { "collectionGroup": "gyms", - "queryScope": "COLLECTION", + "queryScope": "COLLECTION_GROUP", "fields": [ { - "fieldPath": "userId", + "fieldPath": "isApproved", "order": "ASCENDING" }, { - "fieldPath": "name", + "fieldPath": "createdAt", "order": "ASCENDING" } ] From cd59b9890dfe29bd8b1b7c807cb5a795cd46bd0f Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 06:23:43 +0000 Subject: [PATCH 08/24] notification-bug-fix (#92) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/92 Reviewed-by: Allen T J Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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 From e483b7ad462d9d05e25dc7e7105864eafa349257 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 06:42:11 +0000 Subject: [PATCH 09/24] notification-bug-fix (#93) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/93 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 259 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index e69de29..9e692cc 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": [] +} From 5e48f695f88db7f4d15d323592020b42cb946029 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 06:51:02 +0000 Subject: [PATCH 10/24] notification-bug-fix (#94) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/94 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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": [] From 1e09f7a6764edbb0d0c561cb0bea5e2eb8d89c7d Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 06:54:45 +0000 Subject: [PATCH 11/24] notification-bug-fix (#95) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/95 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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" } ] } From 5f43a86036d95f696effc958ef140e7f26aff6f9 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 07:06:26 +0000 Subject: [PATCH 12/24] notification-bug-fix (#96) Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/96 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 116 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 980f655..6f214a4 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,21 +1,121 @@ { "indexes": [ -{ - "collectionGroup": "notifications", + { + "collectionGroup": "day_pass_bookings", "queryScope": "COLLECTION", "fields": [ { - "fieldPath": "data.trainerId", + "fieldPath": "userId", "order": "ASCENDING" }, { - "fieldPath": "timestamp", + "fieldPath": "createdAt", "order": "DESCENDING" } ] }, { - "collectionGroup": "notifications", + "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": [ { @@ -23,8 +123,8 @@ "order": "ASCENDING" }, { - "fieldPath": "timestamp", - "order": "DESCENDING" + "fieldPath": "date", + "order": "ASCENDING" } ] }, @@ -90,4 +190,4 @@ } ], "fieldOverrides": [] -} +} \ No newline at end of file From 835f47866549def82b4c60be801659ae94878797 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 07:11:25 +0000 Subject: [PATCH 13/24] notification-bug-fix (#97) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/97 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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 From abf7a0463311e9fe9834cd4a0331e10477318e7d Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 07:21:41 +0000 Subject: [PATCH 14/24] notification-bug-fix (#98) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/98 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 142 ++++------------------------------------- 1 file changed, 14 insertions(+), 128 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ffd217..2ea301e 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,6 +59,20 @@ "order": "ASCENDING" } ] + }, + { + "collectionGroup": "notifications", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "recipientId", + "order": "ASCENDING" + }, + { + "fieldPath": "timestamp", + "order": "DESCENDING" + } + ] } ], From 5d6824a6f484f1fd4b6e73f8b429ad9349d8c1b1 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 09:43:44 +0000 Subject: [PATCH 15/24] notification-bug-fix (#99) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/99 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 107 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ea301e..077a143 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", From 5543ba5e7a3cf091794160080064f7bd906fda41 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 09:52:14 +0000 Subject: [PATCH 16/24] notification-bug-fix (#100) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/100 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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 From b190a371b6abd28ce516788bf51c83d06b295d55 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 10:21:00 +0000 Subject: [PATCH 17/24] notification-bug-fix (#101) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/101 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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 From 165cd74a17c5773f744c918ddd297b93e645635a Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 11:18:53 +0000 Subject: [PATCH 18/24] notification-bug-fix (#102) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/102 Reviewed-by: Dhansh A S Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- .../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 { From 308cb0fab69e5c53b236f67b9684e721e7510ff9 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 11:43:38 +0000 Subject: [PATCH 19/24] notification-bug-fix (#103) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/103 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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 From 70d76bab2e2da251af3c389e015b8c111e832427 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Tue, 19 Aug 2025 11:51:37 +0000 Subject: [PATCH 20/24] notification-bug-fix (#104) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/104 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- 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 From f93931867c544d726db1bc7a0cad91556d627da3 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 20 Aug 2025 13:22:29 +0000 Subject: [PATCH 21/24] notification-bug-fix (#105) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/105 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 28 +++++++++++++++++++ .../membershipStatusNotifications.ts | 17 ++++------- 2 files changed, 33 insertions(+), 12 deletions(-) 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", 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 From d0c00d817211b51643e6c0519174e1f25a128226 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 20 Aug 2025 13:30:53 +0000 Subject: [PATCH 22/24] notification-bug-fix (#106) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/106 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 193 +---------------------------------------- 1 file changed, 1 insertion(+), 192 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 54f5709..2ddb5ce 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,195 +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": "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", - "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 From 172fa2edaef36f1b674330c605d7dbbc22ba9add Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Wed, 20 Aug 2025 13:38:54 +0000 Subject: [PATCH 23/24] notification-bug-fix (#107) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/107 Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 193 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 192 insertions(+), 1 deletion(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 2ddb5ce..54f5709 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,4 +1,195 @@ { - "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": "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", + "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 From 0672a19a60927c6d71db19b89c22185ed4d14931 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Fri, 22 Aug 2025 11:13:19 +0000 Subject: [PATCH 24/24] notification-bug-fix (#108) Co-authored-by: Dhansh A S Reviewed-on: https://git.cosqnet.com/cosqnet/fitlien-services/pulls/108 Reviewed-by: Dhansh A S Co-authored-by: Sharon Dcruz Co-committed-by: Sharon Dcruz --- firestore.indexes.json | 193 +---------------------------------------- 1 file changed, 1 insertion(+), 192 deletions(-) diff --git a/firestore.indexes.json b/firestore.indexes.json index 54f5709..2ddb5ce 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,195 +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": "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", - "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