Add paginated payment history to user dashboard

Users can now view their own payments (excluding donations) with
server-side pagination (25/page), date range, method, and
payment/refund filters, both on the API and the new client page.
This commit is contained in:
2026-07-23 18:02:53 +02:00
parent 9f7785e660
commit 37681aec50
5 changed files with 257 additions and 21 deletions
+46 -19
View File
@@ -349,30 +349,57 @@ const getPayments = async (req, res) => {
}
};
// @desc Get user payments
// @desc Get user payments (paginated, excludes donations, supports date range/method/kind filters)
// @route GET /api/payments/mypayments
// @access Private
const getUserPayments = async (req, res) => {
try {
// Users should see payments they made (donations) and payments tied to their registrations
const payments = await prisma.payment.findMany({
where: {
OR: [
{ userId: req.user.id }, // payments made by the user (includes donations)
{ registration: { userId: req.user.id } } // payments tied to the user's registrations
]
},
include: {
registration: {
include: {
event: true
}
},
event: true
}
});
const page = Math.max(1, parseInt(req.query.page) || 1);
const limit = Math.min(25, Math.max(1, parseInt(req.query.limit) || 25));
const skip = (page - 1) * limit;
res.json(payments);
// Users should see payments they made and payments tied to their registrations,
// excluding donations.
const where = {
isDonation: false,
OR: [
{ userId: req.user.id },
{ registration: { userId: req.user.id } }
]
};
if (req.query.method) {
where.method = { startsWith: String(req.query.method), mode: 'insensitive' };
}
if (req.query.kind === 'refund') {
where.amount = { lt: 0 };
} else if (req.query.kind === 'payment') {
where.amount = { gte: 0 };
}
if (req.query.startDate || req.query.endDate) {
where.createdAt = {
...(req.query.startDate && { gte: new Date(req.query.startDate) }),
...(req.query.endDate && { lte: new Date(req.query.endDate) })
};
}
const [payments, total] = await prisma.$transaction([
prisma.payment.findMany({
where,
include: {
registration: { include: { event: true } },
event: true
},
orderBy: { createdAt: 'desc' },
skip,
take: limit
}),
prisma.payment.count({ where })
]);
res.json({ data: payments, total, page, limit, pages: Math.ceil(total / limit) });
} catch (error) {
res.status(res.statusCode === 200 ? 400 : res.statusCode).json({ message: safeErrorMessage(error) });
}