expiry-using-payment #79

Merged
dhanshas merged 2 commits from expiry-using-payment into dev 2025-08-05 06:16:48 +00:00
Showing only changes of commit 690732d515 - Show all commits

View File

@ -13,7 +13,6 @@ interface MembershipData {
subscription?: { subscription?: {
name: string; name: string;
frequency: string; frequency: string;
assignedAt?: admin.firestore.Timestamp;
}; };
} }
@ -85,7 +84,7 @@ async function findExpiredMemberships(): Promise<
const batchSize = 10; const batchSize = 10;
const docs = snapshot.docs; const docs = snapshot.docs;
for (let i = 0; i < docs.length; i += batchSize) { for (let i = 0; i < docs.length; i += batchSize) {
const batch = docs.slice(i, i + batchSize); const batch = docs.slice(i, i + batchSize);
const batchResults = await Promise.allSettled( const batchResults = await Promise.allSettled(
@ -113,7 +112,10 @@ async function findExpiredMemberships(): Promise<
} }
} }
async function checkIfMembershipExpired(membershipId: string, data: MembershipData): Promise<boolean> { async function checkIfMembershipExpired(
membershipId: string,
data: MembershipData
): Promise<boolean> {
try { try {
if (!data.subscription || !data.subscription.frequency) { if (!data.subscription || !data.subscription.frequency) {
logger.warn( logger.warn(
@ -123,41 +125,49 @@ async function checkIfMembershipExpired(membershipId: string, data: MembershipDa
} }
let startDate: Date; let startDate: Date;
if (data.subscription.assignedAt) {
startDate = (data.subscription.assignedAt as admin.firestore.Timestamp).toDate();
} else {
logger.info(`Using payment logic for membership ${membershipId} as assignedAt is missing`);
const payments = await getPaymentsForMembership(membershipId);
if (payments.length === 0) {
logger.warn(`No payments found for membership ${membershipId}, cannot determine expiry`);
return false;
}
const latestPayment = payments[0]; const payments = await getPaymentsForMembership(membershipId);
startDate = latestPayment.dateTimestamp; if (payments.length === 0) {
logger.warn(
logger.info(`Using latest payment date ${startDate.toISOString()} for membership ${membershipId}`); `No payments found for membership ${membershipId}, cannot determine expiry`
);
return false;
} }
const expiryDate = calculateExpiryDate(startDate, data.subscription.frequency); const latestPayment = payments[0];
startDate = latestPayment.dateTimestamp;
logger.info(
`Using latest payment date ${startDate.toISOString()} for membership ${membershipId}`
);
const expiryDate = calculateExpiryDate(
startDate,
data.subscription.frequency
);
const now = new Date(); const now = new Date();
const isExpired = now > expiryDate; const isExpired = now > expiryDate;
if (isExpired) { if (isExpired) {
logger.info(`Membership ${membershipId} expired on ${expiryDate.toISOString()}`); logger.info(
`Membership ${membershipId} expired on ${expiryDate.toISOString()}`
);
} }
return isExpired; return isExpired;
} catch (error) { } catch (error) {
logger.error(`Error checking expiry for membership ${membershipId}:`, error); logger.error(
`Error checking expiry for membership ${membershipId}:`,
error
);
return false; return false;
} }
} }
async function getPaymentsForMembership(membershipId: string): Promise<PaymentData[]> { async function getPaymentsForMembership(
membershipId: string
): Promise<PaymentData[]> {
try { try {
const docSnapshot = await app const docSnapshot = await app
.firestore() .firestore()
@ -178,16 +188,23 @@ async function getPaymentsForMembership(membershipId: string): Promise<PaymentDa
amount: payment.amount, amount: payment.amount,
paymentMethod: payment.paymentMethod, paymentMethod: payment.paymentMethod,
referenceNumber: payment.referenceNumber, referenceNumber: payment.referenceNumber,
dateTimestamp: payment.dateTimestamp.toDate ? payment.dateTimestamp.toDate() : new Date(payment.dateTimestamp), dateTimestamp: payment.dateTimestamp.toDate
createdAt: payment.createdAt.toDate ? payment.createdAt.toDate() : new Date(payment.createdAt), ? payment.dateTimestamp.toDate()
discount: payment.discount : new Date(payment.dateTimestamp),
createdAt: payment.createdAt.toDate
? payment.createdAt.toDate()
: new Date(payment.createdAt),
discount: payment.discount,
})); }));
payments.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); payments.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
return payments; return payments;
} catch (error) { } catch (error) {
logger.error(`Error getting payments for membership ${membershipId}:`, error); logger.error(
`Error getting payments for membership ${membershipId}:`,
error
);
return []; return [];
} }
} }
@ -208,32 +225,35 @@ function calculateExpiryDate(startDate: Date, frequency: string): Date {
expiry.setFullYear(expiry.getFullYear() + 1); expiry.setFullYear(expiry.getFullYear() + 1);
break; break;
default: default:
expiry.setMonth(expiry.getMonth() + 1); expiry.setMonth(expiry.getMonth() + 1);
} }
return expiry; return expiry;
} }
function calculateRenewalDateFromPayment(subscription: any, paymentDate: Date): Date { function calculateRenewalDateFromPayment(
subscription: any,
paymentDate: Date
): Date {
const renewalDate = new Date(paymentDate); const renewalDate = new Date(paymentDate);
const frequency = subscription.frequency || 'Monthly'; const frequency = subscription.frequency || "Monthly";
switch (frequency.toLowerCase()) { switch (frequency.toLowerCase()) {
case 'monthly': case "monthly":
renewalDate.setMonth(renewalDate.getMonth() + 1); renewalDate.setMonth(renewalDate.getMonth() + 1);
break; break;
case 'quarterly': case "quarterly":
renewalDate.setMonth(renewalDate.getMonth() + 3); renewalDate.setMonth(renewalDate.getMonth() + 3);
break; break;
case 'half-yearly': case "half-yearly":
renewalDate.setMonth(renewalDate.getMonth() + 6); renewalDate.setMonth(renewalDate.getMonth() + 6);
break; break;
case 'yearly': case "yearly":
renewalDate.setFullYear(renewalDate.getFullYear() + 1); renewalDate.setFullYear(renewalDate.getFullYear() + 1);
break; break;
default: default:
renewalDate.setMonth(renewalDate.getMonth() + 1); renewalDate.setMonth(renewalDate.getMonth() + 1);
} }
return renewalDate; return renewalDate;
} }
@ -279,27 +299,18 @@ async function sendPlanExpiredNotification(
let expiryDate: Date | undefined; let expiryDate: Date | undefined;
let formattedDate = "Unknown Date"; let formattedDate = "Unknown Date";
if (membershipData.subscription?.assignedAt) { const payments = await getPaymentsForMembership(membershipId);
expiryDate = membershipData.subscription.assignedAt.toDate(); if (payments.length > 0) {
const latestPayment = payments[0];
expiryDate = calculateRenewalDateFromPayment(
membershipData.subscription,
latestPayment.dateTimestamp
);
formattedDate = expiryDate.toLocaleDateString("en-US", { formattedDate = expiryDate.toLocaleDateString("en-US", {
year: "numeric", year: "numeric",
month: "long", month: "long",
day: "numeric", day: "numeric",
}); });
} else {
const payments = await getPaymentsForMembership(membershipId);
if (payments.length > 0) {
const latestPayment = payments[0];
expiryDate = calculateRenewalDateFromPayment(
membershipData.subscription,
latestPayment.dateTimestamp
);
formattedDate = expiryDate.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
}
} }
await app await app
@ -379,4 +390,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";
} }
} }