Files
gameno-api/jobs/paymentReminderJob.js
T
kavehhn f04c797be6 Initial commit: teaching institution management API.
Express/MongoDB backend with JWT auth, RBAC, S3 uploads, notifications, and scheduled jobs.
2026-08-09 04:18:08 +02:00

67 lines
1.9 KiB
JavaScript

// /jobs/paymentReminderJob.js
const cron = require('node-cron');
const Payment = require('../components/payments/paymentModel');
const eventEmitter = require('../events/eventEmitter');
const EVENT_NAMES = require('../constants/eventNames');
const logger = require('../utils/logger');
const runPaymentReminderJob = async () => {
try {
const now = new Date();
const threeDaysFromNow = new Date();
threeDaysFromNow.setDate(now.getDate() + 3);
// Find pending/partiallyPaid payments due in the next 3 days
const upcomingPayments = await Payment.find({
status: { $in: ['pending', 'partiallyPaid'] },
dueDate: { $gte: now, $lte: threeDaysFromNow }
}).populate('user');
for (const payment of upcomingPayments) {
if (payment.user) {
eventEmitter.emit(EVENT_NAMES.PAYMENT_REMINDER_DUE, {
paymentId: payment._id,
userId: payment.user._id,
amountDue: payment.amount - payment.amountPaid,
dueDate: payment.dueDate
});
}
}
// Find overdue payments and update status to overdue
const overduePayments = await Payment.find({
status: { $in: ['pending', 'partiallyPaid'] },
dueDate: { $lt: now }
});
for (const payment of overduePayments) {
payment.status = 'overdue';
await payment.save();
if (payment.user) {
eventEmitter.emit(EVENT_NAMES.PAYMENT_STATUS_CHANGED, {
paymentId: payment._id,
userId: payment.user,
oldStatus: 'pending',
newStatus: 'overdue'
});
}
}
} catch (error) {
logger.error(`[PaymentReminderJob ERROR]: ${error.message}`);
}
};
const startPaymentReminderJob = () => {
// Run daily at midnight
cron.schedule('0 0 * * *', async () => {
await runPaymentReminderJob();
});
logger.info('[PaymentReminderJob] Scheduled to run daily at midnight.');
};
module.exports = {
startPaymentReminderJob,
runPaymentReminderJob
};