From 05912a1c325f496fde5b06afc210e4babef5012f Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Mon, 25 Aug 2025 07:03:33 +0530 Subject: [PATCH] Changes Updated For expirydate --- .../membershipStatusNotifications.ts | 102 +++++++++++++++--- 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/functions/src/notifications/membershipStatusNotifications.ts b/functions/src/notifications/membershipStatusNotifications.ts index 85799cf..e8c3b01 100644 --- a/functions/src/notifications/membershipStatusNotifications.ts +++ b/functions/src/notifications/membershipStatusNotifications.ts @@ -11,6 +11,7 @@ interface MembershipData { userId: string; gymId: string; status: string; + expirationDate?: admin.firestore.Timestamp; subscription?: { name: string; frequency: string; @@ -56,14 +57,16 @@ export const checkExpiredMemberships = onSchedule( await updateDaysUntilExpiryForAllMemberships(); const expiredMemberships = await findExpiredMemberships(); const expiringMemberships = await findMembershipsExpiringIn10Days(); + + const expiredMembershipsWithoutExpiryDate = await findExpiredMembershipsWithoutExpiryDate(); - if (expiredMemberships.length === 0 && expiringMemberships.length === 0) { - logger.info("No expired or expiring memberships found."); + if (expiredMemberships.length === 0 && expiringMemberships.length === 0 && expiredMembershipsWithoutExpiryDate.length === 0) { + logger.info("No expired, expiring, or unprocessed expired memberships found."); return; } logger.info( - `Found ${expiredMemberships.length} expired memberships and ${expiringMemberships.length} memberships expiring in 10 days to process.` + `Found ${expiredMemberships.length} expired memberships, ${expiringMemberships.length} memberships expiring in 10 days, and ${expiredMembershipsWithoutExpiryDate.length} expired memberships without expiry dates to process.` ); const expiredResults = await Promise.allSettled( @@ -74,21 +77,19 @@ 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 updateResults = await Promise.allSettled( + expiredMembershipsWithoutExpiryDate.map((m) => updateExpiryDateForExpiredMembership(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 updateSuccessful = updateResults.filter(r => r.status === "fulfilled").length; + const updateFailed = updateResults.filter(r => r.status === "rejected").length; logger.info( - `Completed processing. Expired - Success: ${expiredSuccessful}, Failed: ${expiredFailed}. Expiring - Success: ${expiringSuccessful}, Failed: ${expiringFailed}` + `Completed processing. Expired - Success: ${expiredSuccessful}, Failed: ${expiredFailed}. Expiring - Success: ${expiringSuccessful}, Failed: ${expiringFailed}. Updates - Success: ${updateSuccessful}, Failed: ${updateFailed}` ); } catch (error) { logger.error("Error in scheduled membership expiry check:", error); @@ -96,6 +97,72 @@ export const checkExpiredMemberships = onSchedule( } ); + + + +async function findExpiredMembershipsWithoutExpiryDate(): Promise< + Array<{ id: string; data: MembershipData }> +> { + try { + const snapshot = await app + .firestore() + .collection("memberships") + .where("status", "==", "EXPIRED") + .get(); + + const membershipsWithoutExpiryDate: Array<{ id: string; data: MembershipData }> = []; + + snapshot.docs.forEach((doc) => { + const data = doc.data() as MembershipData; + if (!data.expirationDate) { + membershipsWithoutExpiryDate.push({ id: doc.id, data }); + } + }); + + return membershipsWithoutExpiryDate; + } catch (error) { + logger.error("Error finding expired memberships without expiry date:", error); + throw error; + } +} +async function updateExpiryDateForExpiredMembership( + membershipId: string, + membershipData: MembershipData +): Promise { + try { + if (!membershipData.subscription || !membershipData.subscription.frequency) { + logger.warn(`Skipping membership ${membershipId} - no subscription data`); + return; + } + + const payments = await getPaymentsForMembership(membershipId); + if (payments.length === 0) { + logger.warn(`No payments found for membership ${membershipId}`); + return; + } + + const latestPayment = payments[0]; + const expiryDate = calculateExpiryDate( + latestPayment.dateTimestamp, + membershipData.subscription.frequency + ); + + await app + .firestore() + .collection("memberships") + .doc(membershipId) + .update({ + expirationDate: admin.firestore.Timestamp.fromDate(expiryDate), + updatedAt: admin.firestore.FieldValue.serverTimestamp(), + }); + + logger.info(`Updated expiry date for expired membership ${membershipId}: ${expiryDate.toISOString()}`); + } catch (error) { + logger.error(`Error updating expiry date for membership ${membershipId}:`, error); + throw error; + } +} + async function findExpiredMemberships(): Promise< Array<{ id: string; data: MembershipData }> > { @@ -923,6 +990,7 @@ async function sendPlanExpiringNotification( ); } } + async function getClientName( membershipId: string, clientId: string @@ -966,4 +1034,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