Cache Updated
This commit is contained in:
parent
7438431c11
commit
1896b3fb44
@ -5,6 +5,7 @@ import * as admin from "firebase-admin";
|
|||||||
const app = getAdmin();
|
const app = getAdmin();
|
||||||
const logger = getLogger();
|
const logger = getLogger();
|
||||||
const kTrainerRole = "Trainer";
|
const kTrainerRole = "Trainer";
|
||||||
|
const CACHE_FOLDER = "gym_member_cache";
|
||||||
|
|
||||||
interface MembershipData {
|
interface MembershipData {
|
||||||
id?: string;
|
id?: string;
|
||||||
@ -44,6 +45,183 @@ interface PersonalTrainerAssign {
|
|||||||
gymId: string;
|
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(
|
export const checkExpiredMemberships = onSchedule(
|
||||||
{
|
{
|
||||||
schedule: "0 8,14,20 * * *",
|
schedule: "0 8,14,20 * * *",
|
||||||
@ -150,6 +328,7 @@ async function findExpiredMembershipsWithoutExpiryDate(): Promise<
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateExpiryDateForExpiredMembership(
|
async function updateExpiryDateForExpiredMembership(
|
||||||
membershipId: string,
|
membershipId: string,
|
||||||
membershipData: MembershipData
|
membershipData: MembershipData
|
||||||
@ -184,6 +363,8 @@ async function updateExpiryDateForExpiredMembership(
|
|||||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await updateCacheForMembership(membershipData.gymId, membershipId);
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`Updated expiry date for expired membership ${membershipId}: ${expiryDate.toISOString()}`
|
`Updated expiry date for expired membership ${membershipId}: ${expiryDate.toISOString()}`
|
||||||
);
|
);
|
||||||
@ -513,6 +694,8 @@ async function updateDaysUntilExpiryForAllMemberships(): Promise<void> {
|
|||||||
.doc(doc.id)
|
.doc(doc.id)
|
||||||
.update(updateData);
|
.update(updateData);
|
||||||
|
|
||||||
|
await updateCacheForMembership(data.gymId, doc.id);
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`Updated membership ${doc.id} with daysUntilExpiry: ${daysUntilExpiry}`
|
`Updated membership ${doc.id} with daysUntilExpiry: ${daysUntilExpiry}`
|
||||||
);
|
);
|
||||||
@ -665,6 +848,8 @@ async function processExpiredMembership(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await updateCacheForMembership(membershipData.gymId, membershipId);
|
||||||
|
|
||||||
logger.info(`Marked membership ${membershipId} as EXPIRED`);
|
logger.info(`Marked membership ${membershipId} as EXPIRED`);
|
||||||
|
|
||||||
await sendPlanExpiredNotification(membershipId, membershipData);
|
await sendPlanExpiredNotification(membershipId, membershipData);
|
||||||
@ -697,6 +882,8 @@ async function processExpiringMembership(
|
|||||||
expirationDate: admin.firestore.Timestamp.fromDate(expiryDate),
|
expirationDate: admin.firestore.Timestamp.fromDate(expiryDate),
|
||||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await updateCacheForMembership(membershipData.gymId, membershipId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendPlanExpiringNotification(membershipId, membershipData);
|
await sendPlanExpiringNotification(membershipId, membershipData);
|
||||||
@ -1067,4 +1254,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