This commit is contained in:
Sharon Dcruz 2025-09-23 13:05:52 +05:30
parent 5ebd5d770b
commit 14e52eaa89

View File

@ -5,7 +5,40 @@ import * as admin from "firebase-admin";
const app = getAdmin();
const logger = getLogger();
const kTrainerRole = "Trainer";
const CACHE_FOLDER = "gym_member_cache";
async function updateCacheForMembership(
gymId: string,
membershipId: string
): Promise<void> {
try {
const response = await fetch(
`https://updatemembercache-2k7djjvd3q-el.a.run.app/updateMemberCache`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
gymId: gymId,
incrementalUpdate: true,
membershipIds: [membershipId],
}),
}
);
if (response.ok) {
logger.info(
`Cache updated successfully for membership ${membershipId} in gym ${gymId}`
);
} else {
logger.warn(
`Cache update failed for membership ${membershipId}: ${response.status}`
);
}
} catch (error) {
logger.error(`Error updating cache for membership ${membershipId}:`, error);
}
}
interface MembershipData {
id?: string;
@ -45,183 +78,6 @@ interface PersonalTrainerAssign {
gymId: string;
}
interface MinimalCacheEntry {
membershipId: string;
userId: string;
status: string;
displayName: string;
email?: string | null;
phoneNumber?: string | null;
alternateContact?: string | null;
renewalDate?: string | null;
expirationDate?: string | null;
createdAt?: string | null;
daysUntilExpiry?: number | null;
hasPersonalTraining: boolean;
hasPartialPayment: boolean;
remainingAmount: number;
subscriptionId?: string | null;
lastUpdated: string;
}
interface MinimalJsonCacheData {
gymId: string;
members: MinimalCacheEntry[];
totalMembers: number;
lastUpdated: string;
cacheVersion: string;
}
async function updateCacheForMembership(gymId: string, membershipId: string): Promise<void> {
try {
const fileName = `${CACHE_FOLDER}/${gymId}.json`;
const file = app.storage().bucket().file(fileName);
let existingData: MinimalJsonCacheData | null = null;
try {
const [fileBuffer] = await file.download();
existingData = JSON.parse(fileBuffer.toString());
} catch (error) {
logger.warn(`Could not load existing cache for gym ${gymId}, skipping cache update: ${error}`);
return;
}
if (!existingData || !existingData.members) {
logger.warn(`Invalid cache data for gym ${gymId}, skipping cache update`);
return;
}
const membershipDoc = await app
.firestore()
.collection("memberships")
.doc(membershipId)
.get();
if (!membershipDoc.exists) {
logger.warn(`Membership ${membershipId} not found, skipping cache update`);
return;
}
const membershipData = membershipDoc.data();
const updatedEntry = await generateMinimalCacheEntry(
membershipData!.userId,
membershipId,
membershipData!,
gymId
);
const memberIndex = existingData.members.findIndex(
member => member.membershipId === membershipId
);
if (memberIndex >= 0) {
existingData.members[memberIndex] = updatedEntry;
} else {
existingData.members.push(updatedEntry);
}
existingData.lastUpdated = new Date().toISOString();
existingData.totalMembers = existingData.members.length;
await file.save(JSON.stringify(existingData, null, 2), {
metadata: {
contentType: "application/json",
metadata: {
gymId: gymId,
totalMembers: existingData.totalMembers.toString(),
generatedAt: existingData.lastUpdated,
cacheVersion: existingData.cacheVersion,
},
},
});
logger.info(`Cache updated for membership ${membershipId} in gym ${gymId}`);
} catch (error) {
logger.error(`Error updating cache for membership ${membershipId}:`, error);
}
}
async function generateMinimalCacheEntry(
userId: string,
membershipId: string,
membershipData: any,
gymId: string
): Promise<MinimalCacheEntry> {
try {
let firstName = "";
let lastName = "";
let email = "";
let phoneNumber = "";
let alternateContact = "";
try {
const clientFieldsSnapshot = await app
.firestore()
.collection("client_profiles")
.where("uid", "==", userId)
.get();
if (!clientFieldsSnapshot.empty) {
const fieldDoc = clientFieldsSnapshot.docs[0];
const fieldData = fieldDoc.data();
const fields = fieldData.fields || {};
firstName = fields["first-name"] || fieldData["first-name"] || "";
lastName = fields["last-name"] || fieldData["last-name"] || "";
email = fields["email"] || fieldData["email"] || "";
phoneNumber = fields["phone-number"] || fieldData["phone-number"] || "";
alternateContact =
fields["alternate-contact"] || fieldData["alternate-contact"] || "";
}
} catch (error) {
logger.error(`Error getting fields for user ${userId}:`, error);
}
const daysUntilExpiry = membershipData.daysUntilExpiry || null;
const displayName =
firstName.length === 0
? "Unknown"
: lastName.length === 0
? firstName
: `${firstName} ${lastName}`;
const isPartial = membershipData.isPartialPayment === true;
const remaining = membershipData.remainingAmount || 0;
const hasPartialPayment = isPartial && remaining > 0;
const minimalEntry: MinimalCacheEntry = {
membershipId,
userId,
status: membershipData.status || "N/A",
displayName,
email: email || null,
phoneNumber: phoneNumber || null,
alternateContact: alternateContact || null,
renewalDate: null,
expirationDate: membershipData.expirationDate
? membershipData.expirationDate.toDate().toISOString()
: null,
createdAt: membershipData.createdAt
? membershipData.createdAt.toDate().toISOString()
: null,
daysUntilExpiry,
hasPersonalTraining:
membershipData.subscription?.hasPersonalTraining === true,
hasPartialPayment,
remainingAmount: remaining,
subscriptionId: membershipData.subscriptionId || null,
lastUpdated: new Date().toISOString(),
};
return minimalEntry;
} catch (error) {
logger.error("Error generating minimal cache entry:", error);
throw error;
}
}
export const checkExpiredMemberships = onSchedule(
{
schedule: "0 8,14,20 * * *",
@ -718,7 +574,6 @@ async function updateDaysUntilExpiryForAllMemberships(): Promise<void> {
throw error;
}
}
async function calculateDaysUntilExpiry(
membershipId: string,
data: MembershipData
@ -1254,4 +1109,4 @@ async function getGymName(gymId: string): Promise<string> {
logger.error(`Error getting gym name for gym ${gymId}:`, error);
return "Unknown Gym";
}
}
}