112 lines
2.9 KiB
TypeScript
112 lines
2.9 KiB
TypeScript
import { prisma } from "@/lib/prisma";
|
|
import { Prisma } from "@/app/generated/prisma/client";
|
|
|
|
const refundListInclude = {
|
|
booking: {
|
|
include: {
|
|
trip: { select: { id: true, title: true, date: true, organizerId: true } },
|
|
user: { select: { id: true, name: true, email: true, image: true } },
|
|
payments: {
|
|
orderBy: { createdAt: "desc" },
|
|
select: {
|
|
id: true,
|
|
provider: true,
|
|
method: true,
|
|
amount: true,
|
|
status: true,
|
|
paidAt: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
payment: {
|
|
select: {
|
|
id: true,
|
|
provider: true,
|
|
method: true,
|
|
amount: true,
|
|
status: true,
|
|
},
|
|
},
|
|
reviewedBy: { select: { id: true, name: true, email: true } },
|
|
} satisfies Prisma.RefundInclude;
|
|
|
|
export const refundRepo = {
|
|
async findById(id: string) {
|
|
return prisma.refund.findUnique({
|
|
where: { id },
|
|
include: refundListInclude,
|
|
});
|
|
},
|
|
|
|
async listByStatus(
|
|
status?: "PENDING" | "APPROVED" | "REJECTED" | "PROCESSING" | "SUCCEEDED" | "FAILED"
|
|
) {
|
|
return prisma.refund.findMany({
|
|
where: status ? { status } : undefined,
|
|
orderBy: { createdAt: "desc" },
|
|
include: refundListInclude,
|
|
});
|
|
},
|
|
|
|
async listByBooking(bookingId: string) {
|
|
return prisma.refund.findMany({
|
|
where: { bookingId },
|
|
orderBy: { createdAt: "desc" },
|
|
});
|
|
},
|
|
|
|
/** Total nominal yang sudah SUCCEEDED untuk satu booking. Dipakai service untuk
|
|
* validasi `SUM(SUCCEEDED) + new.amount <= payment.amount`. */
|
|
async sumSucceededAmount(bookingId: string, tx?: Prisma.TransactionClient): Promise<number> {
|
|
const client = tx ?? prisma;
|
|
const agg = await client.refund.aggregate({
|
|
where: { bookingId, status: "SUCCEEDED" },
|
|
_sum: { amount: true },
|
|
});
|
|
return agg._sum.amount ?? 0;
|
|
},
|
|
|
|
/** Pending + approved + processing — refund yang "in-flight" (belum settled).
|
|
* Dipakai untuk cek apakah booking masih punya refund aktif. */
|
|
async hasActiveRefund(bookingId: string, tx?: Prisma.TransactionClient): Promise<boolean> {
|
|
const client = tx ?? prisma;
|
|
const count = await client.refund.count({
|
|
where: {
|
|
bookingId,
|
|
status: { in: ["PENDING", "APPROVED", "PROCESSING"] },
|
|
},
|
|
});
|
|
return count > 0;
|
|
},
|
|
|
|
async create(
|
|
data: Pick<
|
|
Prisma.RefundUncheckedCreateInput,
|
|
| "bookingId"
|
|
| "paymentId"
|
|
| "amount"
|
|
| "reason"
|
|
| "reportedBy"
|
|
| "reportNote"
|
|
| "initiatedBy"
|
|
| "idempotencyKey"
|
|
>,
|
|
tx?: Prisma.TransactionClient
|
|
) {
|
|
const client = tx ?? prisma;
|
|
return client.refund.create({ data });
|
|
},
|
|
|
|
async update(
|
|
id: string,
|
|
data: Prisma.RefundUncheckedUpdateInput,
|
|
tx?: Prisma.TransactionClient
|
|
) {
|
|
const client = tx ?? prisma;
|
|
return client.refund.update({ where: { id }, data });
|
|
},
|
|
};
|
|
|
|
export type RefundWithRelations = Awaited<ReturnType<typeof refundRepo.findById>>;
|