97 lines
2.6 KiB
TypeScript
97 lines
2.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { getServerSession } from "next-auth";
|
|
import { authOptions } from "@/lib/auth";
|
|
import { isAdminEmail } from "@/lib/admin";
|
|
import { payoutRepo } from "@/server/repositories/payout.repo";
|
|
import { buildCsv, csvDateJakarta, csvResponse } from "@/lib/csv";
|
|
import type { PayoutStatus } from "@/app/generated/prisma/enums";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const VALID_STATUS = new Set<PayoutStatus>([
|
|
"HELD",
|
|
"RELEASED",
|
|
"PAID",
|
|
"CANCELLED",
|
|
]);
|
|
|
|
function parseDate(value: string | null): Date | undefined {
|
|
if (!value) return undefined;
|
|
const d = new Date(value);
|
|
return Number.isNaN(d.getTime()) ? undefined : d;
|
|
}
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const session = await getServerSession(authOptions);
|
|
if (!session?.user || !isAdminEmail(session.user.email)) {
|
|
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
}
|
|
|
|
const params = req.nextUrl.searchParams;
|
|
const statusParam = params.get("status");
|
|
if (!statusParam || !VALID_STATUS.has(statusParam as PayoutStatus)) {
|
|
return NextResponse.json(
|
|
{ error: "status param wajib (HELD/RELEASED/PAID/CANCELLED)" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
const status = statusParam as PayoutStatus;
|
|
|
|
const rows = await payoutRepo.listByStatus(status, {
|
|
dateFrom: parseDate(params.get("dateFrom")),
|
|
dateTo: parseDate(params.get("dateTo")),
|
|
processorEmail: params.get("reviewer") || undefined,
|
|
});
|
|
|
|
const csv = buildCsv(
|
|
[
|
|
"Payout ID",
|
|
"Status",
|
|
"Nominal (IDR)",
|
|
"Currency",
|
|
"Held until",
|
|
"Released at",
|
|
"Paid at",
|
|
"Cancelled at",
|
|
"Processor email",
|
|
"Admin note",
|
|
"Dibuat",
|
|
"Organizer nama",
|
|
"Organizer email",
|
|
"Bank nama",
|
|
"Bank rekening",
|
|
"Bank atas nama",
|
|
"Trip ID",
|
|
"Trip judul",
|
|
"Booking ID",
|
|
"Peserta nama",
|
|
],
|
|
rows.map((p) => [
|
|
p.id,
|
|
p.status,
|
|
p.amount,
|
|
p.currency,
|
|
csvDateJakarta(p.heldUntil),
|
|
csvDateJakarta(p.releasedAt),
|
|
csvDateJakarta(p.paidAt),
|
|
csvDateJakarta(p.cancelledAt),
|
|
p.processedBy?.email ?? "",
|
|
p.adminNote ?? "",
|
|
csvDateJakarta(p.createdAt),
|
|
p.organizer.name,
|
|
p.organizer.email,
|
|
p.bankName ?? "",
|
|
p.bankAccountNumber ?? "",
|
|
p.bankAccountName ?? "",
|
|
p.trip.id,
|
|
p.trip.title,
|
|
p.booking.id,
|
|
p.booking.user.name,
|
|
])
|
|
);
|
|
|
|
const today = new Date().toISOString().slice(0, 10);
|
|
return csvResponse(`payouts-${status}-${today}.csv`, csv);
|
|
}
|