Speed up payment/refund processing on the supervisor dashboard
Reconciling a Yoco payment and sending payment links blocked the HTTP response on ticket-PDF generation and email/WhatsApp sends; they now run in the background like the other payment flows already did. Registration/payment option loops (pricing, stock checks, ticket generation) now resolve concurrently instead of sequentially. The Payments page dropped a per-registration N+1 fetch and now refreshes its lists in parallel after each action. Added missing indexes for dashboard stats and donation-leg lookups, and made GET /api/registrations optionally paginated. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -164,7 +164,10 @@ const reconcileYocoTransaction = async (req, res) => {
|
||||
const createdAt = ytx.createdDate || ytx.createdAt || new Date();
|
||||
const payment = await prisma.payment.create({ data: { ...paymentData, createdAt } });
|
||||
|
||||
// Optionally update registration status when applicable and generate/email tickets if paid
|
||||
// Optionally update registration status when applicable and generate tickets if paid.
|
||||
// Ticket generation stays synchronous so `generatedTickets` can be included in the response;
|
||||
// emailing/WhatsApp-ing the tickets and payment confirmation are backgrounded below since
|
||||
// they involve slow PDF rendering + SMTP/WAWP round trips that shouldn't block this request.
|
||||
let generatedTickets = [];
|
||||
if (registration) {
|
||||
try {
|
||||
@@ -172,15 +175,6 @@ const reconcileYocoTransaction = async (req, res) => {
|
||||
if (updatedReg && updatedReg.status === 'paid') {
|
||||
try {
|
||||
generatedTickets = await generateTicketsForRegistration(registration.id);
|
||||
if (Array.isArray(generatedTickets) && generatedTickets.length > 0) {
|
||||
try {
|
||||
const mockReq = { user: { id: registration.userId }, body: { registrationId: registration.id } };
|
||||
const mockRes = { status: () => mockRes, json: () => {} };
|
||||
await emailTickets(mockReq, mockRes);
|
||||
} catch (emailErr) {
|
||||
console.error('Error emailing tickets after Yoco reconciliation:', emailErr);
|
||||
}
|
||||
}
|
||||
} catch (genErr) {
|
||||
console.error('Error generating tickets after Yoco reconciliation:', genErr);
|
||||
}
|
||||
@@ -191,13 +185,20 @@ const reconcileYocoTransaction = async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Send emails for the reconciled payment
|
||||
try {
|
||||
const { sendPaymentEmails } = require('../utils/notifications');
|
||||
await sendPaymentEmails(payment.id);
|
||||
} catch (e) {
|
||||
console.error('Failed to send payment emails after reconciliation:', e);
|
||||
}
|
||||
// Fire-and-forget: payment confirmation email, then ticket email/WhatsApp (guarantees order)
|
||||
const { sendPaymentEmails } = require('../utils/notifications');
|
||||
const _rxPaymentId = payment.id;
|
||||
const _rxUserId = registration?.userId;
|
||||
const _rxRegId = registration?.id;
|
||||
const _rxShouldEmailTickets = Array.isArray(generatedTickets) && generatedTickets.length > 0;
|
||||
(async () => {
|
||||
try { await sendPaymentEmails(_rxPaymentId); } catch (e) { console.error('Failed to send payment emails after reconciliation:', e); }
|
||||
if (_rxShouldEmailTickets && _rxUserId) {
|
||||
const mockReq = { user: { id: _rxUserId }, body: { registrationId: _rxRegId } };
|
||||
const mockRes = { status: () => mockRes, json: () => {} };
|
||||
try { await emailTickets(mockReq, mockRes); } catch (e) { console.error('Error emailing tickets after Yoco reconciliation:', e); }
|
||||
}
|
||||
})();
|
||||
|
||||
// Update yoco transaction as reconciled
|
||||
const updatedTx = await Yoco.update({
|
||||
|
||||
Reference in New Issue
Block a user