Files
setrip/server/repositories/payout.repo.ts
T

140 lines
3.6 KiB
TypeScript

import { prisma } from "@/lib/prisma";
import { Prisma } from "@/app/generated/prisma/client";
import type { PayoutStatus } from "@/app/generated/prisma/enums";
const payoutListInclude = {
booking: {
select: {
id: true,
amount: true,
status: true,
user: { select: { id: true, name: true, email: true } },
},
},
trip: {
select: { id: true, title: true, date: true, endDate: true, status: true },
},
organizer: { select: { id: true, name: true, email: true } },
processedBy: { select: { id: true, name: true, email: true } },
} satisfies Prisma.PayoutInclude;
export const payoutRepo = {
async findById(id: string) {
return prisma.payout.findUnique({
where: { id },
include: payoutListInclude,
});
},
async findByBookingId(bookingId: string, tx?: Prisma.TransactionClient) {
const client = tx ?? prisma;
return client.payout.findUnique({ where: { bookingId } });
},
async listByStatus(
status: PayoutStatus,
filters?: {
dateFrom?: Date;
dateTo?: Date;
processorEmail?: string;
}
) {
const where: Prisma.PayoutWhereInput = { status };
if (filters?.dateFrom || filters?.dateTo) {
where.createdAt = {
...(filters.dateFrom && { gte: filters.dateFrom }),
...(filters.dateTo && { lte: filters.dateTo }),
};
}
if (filters?.processorEmail) {
where.processedBy = { email: filters.processorEmail };
}
return prisma.payout.findMany({
where,
orderBy: { heldUntil: "asc" },
include: payoutListInclude,
});
},
async listForOrganizer(organizerId: string) {
return prisma.payout.findMany({
where: { organizerId },
orderBy: { createdAt: "desc" },
include: {
trip: {
select: { id: true, title: true, date: true, endDate: true, status: true },
},
booking: {
select: {
id: true,
amount: true,
user: { select: { id: true, name: true } },
},
},
},
});
},
async countByStatus(status: PayoutStatus) {
return prisma.payout.count({ where: { status } });
},
/** Payout terbaru untuk satu status — dipakai dashboard admin. */
async listRecent(status: PayoutStatus, limit = 3) {
return prisma.payout.findMany({
where: { status },
orderBy: status === "HELD" ? { heldUntil: "asc" } : { updatedAt: "desc" },
take: limit,
select: {
id: true,
amount: true,
heldUntil: true,
releasedAt: true,
organizer: { select: { id: true, name: true } },
trip: { select: { id: true, title: true } },
},
});
},
async create(
data: Pick<
Prisma.PayoutUncheckedCreateInput,
| "bookingId"
| "tripId"
| "organizerId"
| "amount"
| "heldUntil"
| "bankName"
| "bankAccountNumber"
| "bankAccountName"
>,
tx?: Prisma.TransactionClient
) {
const client = tx ?? prisma;
return client.payout.create({ data });
},
async update(
id: string,
data: Prisma.PayoutUncheckedUpdateInput,
tx?: Prisma.TransactionClient
) {
const client = tx ?? prisma;
return client.payout.update({ where: { id }, data });
},
/** Cari semua HELD payout yang sudah lewat heldUntil & trip-nya COMPLETED. */
async findEligibleForRelease(now: Date) {
return prisma.payout.findMany({
where: {
status: "HELD",
heldUntil: { lte: now },
trip: { status: "COMPLETED" },
},
select: { id: true },
});
},
};
export type PayoutWithRelations = Awaited<ReturnType<typeof payoutRepo.findById>>;