"use server"; import { getServerSession } from "next-auth"; import { revalidatePath } from "next/cache"; import { authOptions } from "@/lib/auth"; import { isAdminEmail } from "@/lib/admin"; import { refundService } from "@/server/services/refund.service"; import { auditLog } from "@/server/services/audit-log.service"; import { createRefundSchema, refundDecisionSchema } from "./schemas"; async function requireAdmin() { const session = await getServerSession(authOptions); if (!session?.user || !isAdminEmail(session.user.email)) { return null; } return session.user; } export async function createRefundAction(formData: FormData) { const admin = await requireAdmin(); if (!admin) return { error: "Tidak memiliki akses admin" }; const parsed = createRefundSchema.safeParse({ bookingId: formData.get("bookingId") as string, reason: formData.get("reason") as string, reportedBy: formData.get("reportedBy") as string, reportNote: formData.get("reportNote") as string, amount: (formData.get("amount") as string) || undefined, }); if (!parsed.success) { return { error: parsed.error.issues[0].message }; } try { const refund = await refundService.requestRefund({ bookingId: parsed.data.bookingId, reason: parsed.data.reason, reportedBy: parsed.data.reportedBy, reportNote: parsed.data.reportNote, amount: parsed.data.amount, initiatedByAdminId: admin.id, }); await auditLog.record({ admin: { id: admin.id, email: admin.email }, action: "REFUND_CREATE", entityType: "Refund", entityId: refund.id, payload: { bookingId: parsed.data.bookingId, amount: parsed.data.amount, reason: parsed.data.reason, }, }); revalidatePath("/admin/refunds"); return { success: true }; } catch (err) { return { error: (err as Error).message }; } } export async function decideRefundAction(formData: FormData) { const admin = await requireAdmin(); if (!admin) return { error: "Tidak memiliki akses admin" }; const parsed = refundDecisionSchema.safeParse({ refundId: formData.get("refundId") as string, decision: formData.get("decision") as string, adminNote: (formData.get("adminNote") as string) || undefined, }); if (!parsed.success) { return { error: parsed.error.issues[0].message }; } const { refundId, decision, adminNote } = parsed.data; const needsNote = decision === "REJECT" || decision === "SUCCEEDED" || decision === "FAILED"; if (needsNote && (!adminNote || !adminNote.trim())) { return { error: "Catatan/alasan admin wajib diisi untuk tindakan ini" }; } try { if (decision === "APPROVE") { await refundService.approveRefund({ refundId, adminId: admin.id, adminNote, }); } else if (decision === "REJECT") { await refundService.rejectRefund({ refundId, adminId: admin.id, adminNote: adminNote!, }); } else if (decision === "SUCCEEDED") { await refundService.markSucceededManual({ refundId, adminId: admin.id, adminNote: adminNote!, }); } else { await refundService.markFailed({ refundId, adminId: admin.id, adminNote: adminNote!, }); } await auditLog.record({ admin: { id: admin.id, email: admin.email }, action: `REFUND_${decision}`, entityType: "Refund", entityId: refundId, payload: adminNote ? { adminNote } : undefined, }); revalidatePath("/admin/refunds"); return { success: true }; } catch (err) { return { error: (err as Error).message }; } }