Files

130 lines
3.4 KiB
TypeScript

import { prisma } from "@/lib/prisma";
import type { ParticipantStatus } from "@/app/generated/prisma/client";
export const participantRepo = {
async findByTripAndUser(tripId: string, userId: string) {
return prisma.tripParticipant.findUnique({
where: { tripId_userId: { tripId, userId } },
});
},
async findById(id: string) {
return prisma.tripParticipant.findUnique({ where: { id } });
},
async create(tripId: string, userId: string) {
return prisma.tripParticipant.create({
data: { tripId, userId, status: "PENDING" },
});
},
async setStatus(id: string, status: ParticipantStatus) {
return prisma.tripParticipant.update({
where: { id },
data: { status },
});
},
async setStatusAndClearPayment(id: string, status: ParticipantStatus) {
return prisma.tripParticipant.update({
where: { id },
data: {
status,
markedPaidAt: null,
paymentConfirmedAt: null,
},
});
},
async countByTrip(tripId: string) {
return prisma.tripParticipant.count({
where: { tripId, status: { not: "CANCELLED" } },
});
},
async cancel(tripId: string, userId: string) {
return prisma.tripParticipant.update({
where: { tripId_userId: { tripId, userId } },
data: {
status: "CANCELLED",
markedPaidAt: null,
paymentConfirmedAt: null,
},
});
},
async reactivate(tripId: string, userId: string) {
return prisma.tripParticipant.update({
where: { tripId_userId: { tripId, userId } },
data: {
status: "PENDING",
markedPaidAt: null,
paymentConfirmedAt: null,
},
});
},
async markPaidByUser(tripId: string, userId: string) {
return prisma.tripParticipant.update({
where: { tripId_userId: { tripId, userId } },
data: { markedPaidAt: new Date() },
});
},
/**
* Satu baris update atomik — aman dari double-submit / race saat tandai bayar.
*/
async tryMarkPaidByUser(tripId: string, userId: string) {
return prisma.tripParticipant.updateMany({
where: {
tripId,
userId,
status: { not: "CANCELLED" },
markedPaidAt: null,
paymentConfirmedAt: null,
},
data: { markedPaidAt: new Date() },
});
},
async confirmPaymentByOrganizer(participantId: string) {
return prisma.tripParticipant.update({
where: { id: participantId },
data: { paymentConfirmedAt: new Date() },
});
},
/** Konfirmasi pembayaran hanya jika masih eligible — idempotent terhadap double klik. */
async tryConfirmPaymentByOrganizer(participantId: string) {
return prisma.tripParticipant.updateMany({
where: {
id: participantId,
markedPaidAt: { not: null },
paymentConfirmedAt: null,
status: { not: "CANCELLED" },
},
data: { paymentConfirmedAt: new Date() },
});
},
/** Partisipasi user beserta trip (untuk profil & riwayat). */
async findWithTripForProfile(userId: string) {
return prisma.tripParticipant.findMany({
where: { userId },
include: {
trip: {
include: {
organizer: { select: { id: true, name: true } },
images: { orderBy: { order: "asc" }, take: 1 },
reviews: {
where: { userId },
select: { id: true, rating: true },
},
},
},
},
orderBy: { createdAt: "desc" },
});
},
};