import { prisma } from "@/lib/prisma"; import { Prisma } from "@/app/generated/prisma/client"; export const organizerRepo = { async findByUserId(userId: string) { return prisma.organizerVerification.findUnique({ where: { userId } }); }, async findById(id: string) { return prisma.organizerVerification.findUnique({ where: { id } }); }, async findByNikHash(nikHash: string) { return prisma.organizerVerification.findUnique({ where: { nikHash } }); }, async upsertForUser( userId: string, data: Omit ) { return prisma.organizerVerification.upsert({ where: { userId }, create: { userId, ...data }, update: data, }); }, async listByStatus( status?: "PENDING" | "APPROVED" | "REJECTED", filters?: { dateFrom?: Date; dateTo?: Date; reviewerEmail?: string; } ) { const where: Prisma.OrganizerVerificationWhereInput = {}; if (status) where.status = status; if (filters?.dateFrom || filters?.dateTo) { where.createdAt = { ...(filters.dateFrom && { gte: filters.dateFrom }), ...(filters.dateTo && { lte: filters.dateTo }), }; } if (filters?.reviewerEmail) { where.reviewedBy = { email: filters.reviewerEmail }; } return prisma.organizerVerification.findMany({ where, orderBy: { createdAt: "desc" }, include: { user: { select: { id: true, name: true, email: true } }, reviewedBy: { select: { id: true, name: true, email: true } }, }, }); }, async countByStatus(status: "PENDING" | "APPROVED" | "REJECTED") { return prisma.organizerVerification.count({ where: { status } }); }, /** Verifikasi terbaru (default PENDING) untuk preview di dashboard admin. */ async listRecent(status: "PENDING" | "APPROVED" | "REJECTED", limit = 3) { return prisma.organizerVerification.findMany({ where: { status }, orderBy: { createdAt: "desc" }, take: limit, select: { id: true, fullName: true, createdAt: true, user: { select: { id: true, name: true, email: true } }, }, }); }, /** * Phase 2: minta organizer upload ulang field tertentu. Reset status ke * PENDING tapi sengaja TIDAK clear data lama (organizer ganti field saat * submit ulang via /verify). Service `submitVerification` auto-clear flag. */ async requestReupload( id: string, data: { fields: string[]; note: string } ) { return prisma.organizerVerification.update({ where: { id }, data: { status: "PENDING", reuploadRequested: true, reuploadFields: data.fields, reuploadNote: data.note, // Clear review state supaya muncul lagi di tab PENDING. reviewedById: null, reviewedAt: null, }, }); }, /** * Phase 4: bikin verifikasi APPROVED tanpa upload KYC (manual override admin). * Placeholder NIK & no image keys — `isManualOverride = true` jadi marker. */ async createManualOverride(input: { userId: string; adminId: string; note: string; fullName: string; nikEncrypted: string; nikHash: string; bankName: string; bankAccountNumber: string; bankAccountName: string; verifiedAt: Date; }) { return prisma.organizerVerification.create({ data: { userId: input.userId, fullName: input.fullName, nikEncrypted: input.nikEncrypted, nikHash: input.nikHash, birthDate: new Date("1970-01-01"), address: "(manual override — tidak diisi)", ktpImageKey: "(manual override)", livenessKey: "(manual override)", bankName: input.bankName, bankAccountNumber: input.bankAccountNumber, bankAccountName: input.bankAccountName, status: "APPROVED", verifiedAt: input.verifiedAt, reviewedById: input.adminId, reviewedAt: input.verifiedAt, isManualOverride: true, manualOverrideById: input.adminId, manualOverrideNote: input.note, }, }); }, /** * Reopen pengajuan REJECTED ke PENDING. Simpan rejection reason lama * sebagai catatan history (di-overwrite kalau di-reject lagi nanti). */ async reopen(id: string, reopenNote: string) { return prisma.organizerVerification.update({ where: { id }, data: { status: "PENDING", reviewedById: null, reviewedAt: null, verifiedAt: null, // Pertahankan rejectionReason lama di field, append note reopen. rejectionReason: `[Dibuka kembali admin: ${reopenNote}]`, }, }); }, async updateReview( id: string, data: { status: "APPROVED" | "REJECTED"; rejectionReason?: string | null; reviewedById: string; } ) { const now = new Date(); return prisma.organizerVerification.update({ where: { id }, data: { status: data.status, rejectionReason: data.rejectionReason ?? null, reviewedById: data.reviewedById, reviewedAt: now, verifiedAt: data.status === "APPROVED" ? now : null, }, }); }, };