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
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "User" ADD COLUMN "acceptedAt" TIMESTAMP(3),
ADD COLUMN "acceptedTermsAndPrivacy" BOOLEAN NOT NULL DEFAULT false;
@@ -0,0 +1,38 @@
-- CreateEnum
CREATE TYPE "VerificationStatus" AS ENUM ('PENDING', 'APPROVED', 'REJECTED');
-- CreateTable
CREATE TABLE "OrganizerVerification" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"fullName" TEXT NOT NULL,
"nik" TEXT NOT NULL,
"birthDate" TIMESTAMP(3) NOT NULL,
"address" TEXT NOT NULL,
"ktpImageUrl" TEXT NOT NULL,
"selfieUrl" TEXT NOT NULL,
"bankName" TEXT NOT NULL,
"bankAccountNumber" TEXT NOT NULL,
"bankAccountName" TEXT NOT NULL,
"status" "VerificationStatus" NOT NULL DEFAULT 'PENDING',
"rejectionReason" TEXT,
"reviewedAt" TIMESTAMP(3),
"reviewedById" TEXT,
"verifiedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "OrganizerVerification_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "OrganizerVerification_userId_key" ON "OrganizerVerification"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "OrganizerVerification_nik_key" ON "OrganizerVerification"("nik");
-- AddForeignKey
ALTER TABLE "OrganizerVerification" ADD CONSTRAINT "OrganizerVerification_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OrganizerVerification" ADD CONSTRAINT "OrganizerVerification_reviewedById_fkey" FOREIGN KEY ("reviewedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1,8 @@
/*
Warnings:
- You are about to drop the column `isVerified` on the `User` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "User" DROP COLUMN "isVerified";
+45 -2
View File
@@ -13,14 +13,57 @@ model User {
email String @unique
password String
image String?
/// Akun diverifikasi tim SeTrip (manual / admin) — tampil sebagai badge kepercayaan
isVerified Boolean @default(false)
/// Apakah user telah menyetujui Syarat & Ketentuan dan Kebijakan Privasi
acceptedTermsAndPrivacy Boolean @default(false)
/// Waktu user menyetujui Syarat & Ketentuan dan Kebijakan Privasi
acceptedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
trips Trip[]
participations TripParticipant[]
tripReviews TripReview[]
organizerVerification OrganizerVerification? @relation("OrganizerVerificationOwner")
reviewedVerifications OrganizerVerification[] @relation("OrganizerVerificationReviewer")
}
model OrganizerVerification {
id String @id @default(cuid())
userId String @unique
user User @relation("OrganizerVerificationOwner", fields: [userId], references: [id], onDelete: Cascade)
/// Nama lengkap sesuai KTP
fullName String
/// Nomor Induk Kependudukan (PII — perlakukan sensitif)
nik String @unique
birthDate DateTime
address String
/// URL foto KTP (untuk MVP pakai hosting; pindah ke storage privat untuk produksi)
ktpImageUrl String
/// URL selfie memegang KTP
selfieUrl String
bankName String
bankAccountNumber String
bankAccountName String
status VerificationStatus @default(PENDING)
rejectionReason String?
reviewedAt DateTime?
reviewedById String?
reviewedBy User? @relation("OrganizerVerificationReviewer", fields: [reviewedById], references: [id])
verifiedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum VerificationStatus {
PENDING
APPROVED
REJECTED
}
model Trip {
+40 -2
View File
@@ -16,6 +16,7 @@ async function main() {
await prisma.tripParticipant.deleteMany();
await prisma.tripImage.deleteMany();
await prisma.trip.deleteMany();
await prisma.organizerVerification.deleteMany();
await prisma.user.deleteMany();
// ==================== USERS ====================
@@ -28,7 +29,6 @@ async function main() {
name: "Dede Inoen",
email: "dede.inoen@setrip.id",
password,
isVerified: true,
},
});
@@ -37,7 +37,6 @@ async function main() {
name: "Panji Petualang",
email: "panji@setrip.id",
password,
isVerified: true,
},
});
@@ -95,6 +94,45 @@ async function main() {
console.log(" Peserta: budi, sari, doni, maya, raka @gmail.com");
console.log(" Password semua: password123\n");
// ==================== ORGANIZER VERIFICATIONS ====================
const verifiedAt = new Date();
await prisma.organizerVerification.createMany({
data: [
{
userId: dede.id,
fullName: "Dede Inoen",
nik: "3201010101010001",
birthDate: new Date(Date.UTC(1990, 0, 1)),
address: "Jl. Pendaki No. 1, Garut, Jawa Barat",
ktpImageUrl: "https://placehold.co/600x400/png?text=KTP+Dede",
selfieUrl: "https://placehold.co/600x400/png?text=Selfie+Dede",
bankName: "BCA",
bankAccountNumber: "1234567890",
bankAccountName: "Dede Inoen",
status: "APPROVED",
reviewedAt: verifiedAt,
verifiedAt,
},
{
userId: panji.id,
fullName: "Panji Petualang",
nik: "3201010101010002",
birthDate: new Date(Date.UTC(1985, 5, 15)),
address: "Jl. Adventure No. 7, Kuningan, Jawa Barat",
ktpImageUrl: "https://placehold.co/600x400/png?text=KTP+Panji",
selfieUrl: "https://placehold.co/600x400/png?text=Selfie+Panji",
bankName: "Mandiri",
bankAccountNumber: "9876543210",
bankAccountName: "Panji Petualang",
status: "APPROVED",
reviewedAt: verifiedAt,
verifiedAt,
},
],
});
console.log("✅ OrganizerVerification (APPROVED) untuk Dede & Panji\n");
// ==================== TRIPS + IMAGES ====================
/**
* Tanggal disimpan eksplisit di UTC agar filter `from`/`to` (YYYY-MM-DD UTC)