notification-bug-fix #111
| @ -11,6 +11,7 @@ interface MembershipData { | |||||||
|   userId: string; |   userId: string; | ||||||
|   gymId: string; |   gymId: string; | ||||||
|   status: string; |   status: string; | ||||||
|  |   expirationDate?: admin.firestore.Timestamp; | ||||||
|   subscription?: { |   subscription?: { | ||||||
|     name: string; |     name: string; | ||||||
|     frequency: string; |     frequency: string; | ||||||
| @ -56,14 +57,16 @@ export const checkExpiredMemberships = onSchedule( | |||||||
|       await updateDaysUntilExpiryForAllMemberships(); |       await updateDaysUntilExpiryForAllMemberships(); | ||||||
|       const expiredMemberships = await findExpiredMemberships(); |       const expiredMemberships = await findExpiredMemberships(); | ||||||
|       const expiringMemberships = await findMembershipsExpiringIn10Days(); |       const expiringMemberships = await findMembershipsExpiringIn10Days(); | ||||||
|  |        | ||||||
|  |       const expiredMembershipsWithoutExpiryDate = await findExpiredMembershipsWithoutExpiryDate(); | ||||||
| 
 | 
 | ||||||
|       if (expiredMemberships.length === 0 && expiringMemberships.length === 0) { |       if (expiredMemberships.length === 0 && expiringMemberships.length === 0 && expiredMembershipsWithoutExpiryDate.length === 0) { | ||||||
|         logger.info("No expired or expiring memberships found."); |         logger.info("No expired, expiring, or unprocessed expired memberships found."); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       logger.info( |       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( |       const expiredResults = await Promise.allSettled( | ||||||
| @ -74,21 +77,19 @@ export const checkExpiredMemberships = onSchedule( | |||||||
|         expiringMemberships.map((m) => processExpiringMembership(m.id, m.data)) |         expiringMemberships.map((m) => processExpiringMembership(m.id, m.data)) | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|       const expiredSuccessful = expiredResults.filter( |       const updateResults = await Promise.allSettled( | ||||||
|         (r) => r.status === "fulfilled" |         expiredMembershipsWithoutExpiryDate.map((m) => updateExpiryDateForExpiredMembership(m.id, m.data)) | ||||||
|       ).length; |       ); | ||||||
|       const expiredFailed = expiredResults.filter( | 
 | ||||||
|         (r) => r.status === "rejected" |       const expiredSuccessful = expiredResults.filter(r => r.status === "fulfilled").length; | ||||||
|       ).length; |       const expiredFailed = expiredResults.filter(r => r.status === "rejected").length; | ||||||
|       const expiringSuccessful = expiringResults.filter( |       const expiringSuccessful = expiringResults.filter(r => r.status === "fulfilled").length; | ||||||
|         (r) => r.status === "fulfilled" |       const expiringFailed = expiringResults.filter(r => r.status === "rejected").length; | ||||||
|       ).length; |       const updateSuccessful = updateResults.filter(r => r.status === "fulfilled").length; | ||||||
|       const expiringFailed = expiringResults.filter( |       const updateFailed = updateResults.filter(r => r.status === "rejected").length; | ||||||
|         (r) => r.status === "rejected" |  | ||||||
|       ).length; |  | ||||||
| 
 | 
 | ||||||
|       logger.info( |       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) { |     } catch (error) { | ||||||
|       logger.error("Error in scheduled membership expiry check:", 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<void> { | ||||||
|  |   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< | async function findExpiredMemberships(): Promise< | ||||||
|   Array<{ id: string; data: MembershipData }> |   Array<{ id: string; data: MembershipData }> | ||||||
| > { | > { | ||||||
| @ -923,6 +990,7 @@ async function sendPlanExpiringNotification( | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| async function getClientName( | async function getClientName( | ||||||
|   membershipId: string, |   membershipId: string, | ||||||
|   clientId: string |   clientId: string | ||||||
| @ -966,4 +1034,4 @@ async function getGymName(gymId: string): Promise<string> { | |||||||
|     logger.error(`Error getting gym name for gym ${gymId}:`, error); |     logger.error(`Error getting gym name for gym ${gymId}:`, error); | ||||||
|     return "Unknown Gym"; |     return "Unknown Gym"; | ||||||
|   } |   } | ||||||
| } | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user