From ebac135d08801a46387fe1551bc4388a9e036345 Mon Sep 17 00:00:00 2001 From: Sharon Dcruz Date: Mon, 28 Jul 2025 17:37:45 +0530 Subject: [PATCH] Changes Updated --- .../src/notifications/processNotification.ts | 258 +++++++++--------- 1 file changed, 123 insertions(+), 135 deletions(-) diff --git a/functions/src/notifications/processNotification.ts b/functions/src/notifications/processNotification.ts index 0f80d70..a9a5563 100644 --- a/functions/src/notifications/processNotification.ts +++ b/functions/src/notifications/processNotification.ts @@ -12,31 +12,9 @@ interface NotificationData { ownerId?: string; type?: string; notificationSent?: boolean; - userId?: string; - clientId?: string; - invitorId?: string; - phoneNumber?: string; - message?: string; - status?: string; - gymName?: string; - trainerName?: string; - membershipId?: string; - subscriptionName?: string; - name?: string; - clientEmail?: string; - invitationId?: string; - gymId?: string; - trainerId?: string; - timeSlots?: Array<{[key: string]: any}>; - timestamp?: any; + timestamp?: admin.firestore.FieldValue; read?: boolean; - title?: string; - updatedBy?: string; - oldTimeSlot?: string; - newTimeSlot?: string; - formattedDate?: string; - logTime?: string; - [key: string]: any; + data?: { [key: string]: any }; } export const processNotificationOnCreate = onDocumentCreated( @@ -79,10 +57,7 @@ export const processNotificationOnCreate = onDocumentCreated( const message = prepareNotificationMessage(notification, fcmToken); try { - const fcmResponse = await app.messaging().send({ - ...message, - token: fcmToken, - }); + const fcmResponse = await app.messaging().send(message); logger.info(`FCM notification sent successfully: ${fcmResponse}`); await markNotificationAsSent(notificationId); @@ -102,57 +77,58 @@ export const processNotificationOnCreate = onDocumentCreated( async function getUserAndFCMToken( notification: NotificationData ): Promise<{ userId: string | null; fcmToken: string | null }> { - let userId: string | null = null; + let targetUserId: string | null = null; let fcmToken: string | null = null; if (notification.recipientId) { - userId = notification.recipientId; - fcmToken = await getFCMTokenFromUserDoc(userId); - logger.info(`Using recipientId: ${userId}`); + targetUserId = notification.recipientId; + logger.info(`Using top-level recipientId: ${targetUserId}`); } else if (notification.ownerId) { - userId = notification.ownerId; - fcmToken = await getFCMTokenFromUserDoc(userId); - logger.info(`Using ownerId: ${userId}`); - } else if (notification.userId) { - userId = notification.userId; - fcmToken = await getFCMTokenFromUserDoc(userId); - logger.info(`Using userId: ${userId}`); - } else if (notification.clientId) { - userId = notification.clientId; - fcmToken = await getFCMTokenFromUserDoc(userId); - logger.info(`Using clientId: ${userId}`); - } else if (notification.invitorId) { - userId = notification.invitorId; - fcmToken = await getFCMTokenFromUserDoc(userId); - logger.info(`Using invitorId: ${userId}`); - } else if (notification.phoneNumber) { - logger.info(`Looking up user by phone number: ${notification.phoneNumber}`); + targetUserId = notification.ownerId; + logger.info(`Using top-level ownerId: ${targetUserId}`); + } else if (notification.data?.userId) { + targetUserId = notification.data.userId; + logger.info(`Using data.userId: ${targetUserId}`); + } else if (notification.data?.clientId) { + targetUserId = notification.data.clientId; + logger.info(`Using data.clientId: ${targetUserId}`); + } else if (notification.data?.invitorId) { + targetUserId = notification.data.invitorId; + logger.info(`Using data.invitorId: ${targetUserId}`); + } else if (notification.data?.phoneNumber) { + logger.info( + `Looking up user by phone number from data: ${notification.data.phoneNumber}` + ); const userQuery = await app .firestore() .collection("users") - .where("phoneNumber", "==", notification.phoneNumber) + .where("phoneNumber", "==", notification.data.phoneNumber) .limit(1) .get(); if (!userQuery.empty) { const userDoc = userQuery.docs[0]; - userId = userDoc.id; + targetUserId = userDoc.id; fcmToken = userDoc.data()?.fcmToken; - logger.info(`Found user by phone: ${userId}`); + logger.info(`Found user by phone: ${targetUserId}`); } else { logger.warn( - `No user found with phone number: ${notification.phoneNumber}` + `No user found with phone number from data: ${notification.data.phoneNumber}` ); } } else { - logger.error("No valid user identifier found in notification"); + logger.error("No valid user identifier found in notification or its data"); } - if (userId && !fcmToken) { - logger.warn(`User ${userId} found but no FCM token available`); + if (targetUserId && !fcmToken) { + fcmToken = await getFCMTokenFromUserDoc(targetUserId); } - return { userId, fcmToken }; + if (targetUserId && !fcmToken) { + logger.warn(`User ${targetUserId} found but no FCM token available`); + } + + return { userId: targetUserId, fcmToken }; } async function getFCMTokenFromUserDoc(userId: string): Promise { @@ -178,135 +154,146 @@ async function getFCMTokenFromUserDoc(userId: string): Promise { function prepareNotificationMessage( notification: NotificationData, fcmToken: string -): admin.messaging.Message { - let title = notification.title || "New Notification"; - let body = notification.message || "You have a new notification"; - let data: Record = { +): admin.messaging.TokenMessage { + let title = notification.data?.title || "New Notification"; + let body = notification.data?.message || "You have a new notification"; + + let fcmData: Record = { type: notification.type || "general", - notificationId: "notification_" + Date.now(), + notificationId: "notification_" + Date.now().toString(), }; - if (notification.senderId) data.senderId = notification.senderId; - if (notification.recipientId) data.recipientId = notification.recipientId; - if (notification.ownerId) data.ownerId = notification.ownerId; - if (notification.userId) data.userId = notification.userId; - if (notification.clientId) data.clientId = notification.clientId; - if (notification.gymId) data.gymId = notification.gymId; - if (notification.trainerId) data.trainerId = notification.trainerId; - if (notification.membershipId) data.membershipId = notification.membershipId; - if (notification.invitationId) data.invitationId = notification.invitationId; - if (notification.phoneNumber) data.phoneNumber = notification.phoneNumber; - if (notification.gymName) data.gymName = notification.gymName; - if (notification.trainerName) data.trainerName = notification.trainerName; - if (notification.subscriptionName) data.subscriptionName = notification.subscriptionName; - if (notification.name) data.name = notification.name; - if (notification.clientEmail) data.clientEmail = notification.clientEmail; - if (notification.status) data.status = notification.status; - if (notification.updatedBy) data.updatedBy = notification.updatedBy; - if (notification.oldTimeSlot) data.oldTimeSlot = notification.oldTimeSlot; - if (notification.newTimeSlot) data.newTimeSlot = notification.newTimeSlot; - if (notification.formattedDate) data.formattedDate = notification.formattedDate; - if (notification.logTime) data.logTime = notification.logTime; - if (notification.timeSlots) data.timeSlots = JSON.stringify(notification.timeSlots); + if (notification.senderId) fcmData.senderId = notification.senderId; + if (notification.recipientId) fcmData.recipientId = notification.recipientId; + if (notification.ownerId) fcmData.ownerId = notification.ownerId; + if (notification.read !== undefined) fcmData.read = String(notification.read); + + if (notification.data) { + for (const key in notification.data) { + if (Object.prototype.hasOwnProperty.call(notification.data, key)) { + const value = notification.data[key]; + if (typeof value === "object" && value !== null) { + fcmData[key] = JSON.stringify(value); + } else { + fcmData[key] = String(value); + } + } + } + } switch (notification.type) { case "trainer_response": - title = notification.title || - (notification.status === "ACCEPTED" + title = + notification.data?.title || + (notification.data?.status === "ACCEPTED" ? "Trainer Request Accepted" : "Trainer Request Update"); body = - notification.message || + notification.data?.message || `${ - notification.trainerName - } has ${notification.status?.toLowerCase()} your request`; + notification.data?.trainerName + } has ${notification.data?.status?.toLowerCase()} your request`; break; case "trainer_assignment": - title = notification.title || "New Client Assignment"; + title = notification.data?.title || "New Client Assignment"; body = - notification.message || - `You have been assigned to ${notification.name}`; + notification.data?.message || + `You have been assigned to ${notification.data?.name}`; break; case "trainer_assigned_to_client": - title = notification.title || "Trainer Assigned"; + title = notification.data?.title || "Trainer Assigned"; body = - notification.message || - `${notification.trainerName} has been assigned as your trainer`; + notification.data?.message || + `${notification.data?.trainerName} has been assigned as your trainer`; break; case "trainer_update_owner": - title = notification.title || "Trainer Schedule Update"; - body = notification.message || "A trainer has updated their schedule"; + title = notification.data?.title || "Trainer Schedule Update"; + body = + notification.data?.message || "A trainer has updated their schedule"; break; case "trainer_update_client": - title = notification.title || "Schedule Update"; - body = notification.message || "Your training schedule has been updated"; + title = notification.data?.title || "Schedule Update"; + body = + notification.data?.message || "Your training schedule has been updated"; + if (notification.data?.oldTimeSlot && notification.data?.newTimeSlot) { + body += ` from ${notification.data.oldTimeSlot} to ${notification.data.newTimeSlot}`; + if (notification.data?.formattedDate) { + body += ` on ${notification.data.formattedDate}`; + } + } break; case "plan_renewal": - title = notification.title || "Plan Renewal"; + title = notification.data?.title || "Plan Renewal"; body = - notification.message || - `Plan ${notification.subscriptionName} has been renewed`; + notification.data?.message || + `Plan ${notification.data?.subscriptionName} has been renewed`; break; case "plan_assigned": - title = notification.title || "New Plan Assigned"; + title = notification.data?.title || "New Plan Assigned"; body = - notification.message || - `You have been assigned ${notification.subscriptionName} at ${notification.gymName}`; + notification.data?.message || + `You have been assigned ${notification.data?.subscriptionName} at ${notification.data?.gymName}`; break; case "schedule_update": - title = notification.title || "Schedule Update"; - body = notification.message || "Your training schedule has been updated"; - if (notification.oldTimeSlot && notification.newTimeSlot) { - body += ` from ${notification.oldTimeSlot} to ${notification.newTimeSlot}`; - if (notification.formattedDate) { - body += ` on ${notification.formattedDate}`; + title = notification.data?.title || "Schedule Update"; + body = + notification.data?.message || "Your training schedule has been updated"; + if (notification.data?.oldTimeSlot && notification.data?.newTimeSlot) { + body += ` from ${notification.data.oldTimeSlot} to ${notification.data.newTimeSlot}`; + if (notification.data?.formattedDate) { + body += ` on ${notification.data.formattedDate}`; } } break; case "attendance_dispute": - title = notification.title || "Attendance Dispute"; + title = notification.data?.title || "Attendance Dispute"; body = - notification.message || - `${notification.name} has disputed an attendance record`; - if (notification.logTime) { - body += ` for ${notification.logTime}`; + notification.data?.message || + `${notification.data?.name} has disputed an attendance record`; + if (notification.data?.logTime) { + body += ` for ${notification.data.logTime}`; } break; case "day_pass_entry": - const isAccepted = notification.status === "ACCEPTED"; - title = notification.title || (isAccepted ? "Day Pass Approved" : "Day Pass Denied"); + const isAccepted = notification.data?.status === "ACCEPTED"; + title = + notification.data?.title || + (isAccepted ? "Day Pass Approved" : "Day Pass Denied"); body = - notification.message || + notification.data?.message || (isAccepted ? "Your day pass has been approved" : "Your day pass has been denied"); break; case "client_invitations": - if (notification.userId || notification.invitorId) { - const isAccept = notification.status === "ACCEPTED"; - title = notification.title || (isAccept ? "Invitation Accepted" : "Invitation Rejected"); + if (notification.data?.userId || notification.data?.invitorId) { + const isAccept = notification.data?.status === "ACCEPTED"; + title = + notification.data?.title || + (isAccept ? "Invitation Accepted" : "Invitation Rejected"); body = - notification.message || + notification.data?.message || (isAccept - ? `The invitation for ${notification.subscriptionName} you shared with ${notification.name} has been accepted` - : `The invitation for ${notification.subscriptionName} you shared with ${notification.name} has been rejected`); - } else if (notification.phoneNumber) { - const invitationStatus = getInvitationStatus(notification.status); - title = notification.title || getInvitationTitle(invitationStatus); + ? `The invitation for ${notification.data?.subscriptionName} you shared with ${notification.data?.name} has been accepted` + : `The invitation for ${notification.data?.subscriptionName} you shared with ${notification.data?.name} has been rejected`); + } else if (notification.data?.phoneNumber) { + const invitationStatus = getInvitationStatus(notification.data?.status); + title = + notification.data?.title || getInvitationTitle(invitationStatus); body = - notification.message || - getInvitationBody(invitationStatus, notification.name); - data.status = invitationStatus; + notification.data?.message || + getInvitationBody(invitationStatus, notification.data?.name); + fcmData.status = invitationStatus; } break; @@ -314,16 +301,17 @@ function prepareNotificationMessage( logger.info( `Using default handling for notification type: ${notification.type}` ); - title = notification.title || + title = + notification.data?.title || (notification.type ? `${notification.type.replace("_", " ").toUpperCase()}` : "Notification"); break; } - const notificationMessage: admin.messaging.Message = { + const notificationMessage: admin.messaging.TokenMessage = { notification: { title, body }, - data, + data: fcmData, android: { priority: "high", notification: { @@ -417,4 +405,4 @@ async function updateNotificationWithError( } catch (updateError) { logger.error(`Error updating notification with error: ${updateError}`); } -} \ No newline at end of file +}