kyc user and upload partial update encrypt nik and picture

This commit is contained in:
2026-04-27 21:48:24 +07:00
parent b31fe675ae
commit a92b4a8fd9
51 changed files with 5180 additions and 452 deletions
+77
View File
@@ -0,0 +1,77 @@
import { organizerRepo } from "@/server/repositories/organizer.repo";
type SubmitInput = {
fullName: string;
nik: string;
birthDate: Date;
address: string;
ktpImageUrl: string;
selfieUrl: string;
bankName: string;
bankAccountNumber: string;
bankAccountName: string;
};
export const organizerService = {
async submitVerification(userId: string, data: SubmitInput) {
const existing = await organizerRepo.findByUserId(userId);
if (existing && existing.status === "APPROVED") {
throw new Error("Akun kamu sudah terverifikasi");
}
if (existing && existing.status === "PENDING") {
throw new Error("Pengajuan kamu masih dalam proses review");
}
const dupNik = await organizerRepo.findByNik(data.nik);
if (dupNik && dupNik.userId !== userId) {
throw new Error("NIK ini sudah dipakai akun lain");
}
return organizerRepo.upsertForUser(userId, {
fullName: data.fullName,
nik: data.nik,
birthDate: data.birthDate,
address: data.address,
ktpImageUrl: data.ktpImageUrl,
selfieUrl: data.selfieUrl,
bankName: data.bankName,
bankAccountNumber: data.bankAccountNumber,
bankAccountName: data.bankAccountName,
status: "PENDING",
rejectionReason: null,
reviewedAt: null,
reviewedById: null,
verifiedAt: null,
});
},
async reviewVerification(input: {
verificationId: string;
decision: "APPROVED" | "REJECTED";
rejectionReason?: string;
reviewerId: string;
}) {
const verification = await organizerRepo.findById(input.verificationId);
if (!verification) {
throw new Error("Pengajuan tidak ditemukan");
}
if (verification.status !== "PENDING") {
throw new Error("Pengajuan ini sudah diproses");
}
return organizerRepo.updateReview(input.verificationId, {
status: input.decision,
rejectionReason: input.decision === "REJECTED" ? input.rejectionReason ?? null : null,
reviewedById: input.reviewerId,
});
},
async getStatusForUser(userId: string) {
return organizerRepo.findByUserId(userId);
},
async isApproved(userId: string) {
const v = await organizerRepo.findByUserId(userId);
return v?.status === "APPROVED";
},
};