create public layout and admin and fix escrow and refund
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PayoutStatus" AS ENUM ('HELD', 'RELEASED', 'PAID', 'CANCELLED');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Payout" (
|
||||
"id" TEXT NOT NULL,
|
||||
"bookingId" TEXT NOT NULL,
|
||||
"tripId" TEXT NOT NULL,
|
||||
"organizerId" TEXT NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'IDR',
|
||||
"status" "PayoutStatus" NOT NULL DEFAULT 'HELD',
|
||||
"heldUntil" TIMESTAMP(3) NOT NULL,
|
||||
"releasedAt" TIMESTAMP(3),
|
||||
"paidAt" TIMESTAMP(3),
|
||||
"cancelledAt" TIMESTAMP(3),
|
||||
"bankName" TEXT,
|
||||
"bankAccountNumber" TEXT,
|
||||
"bankAccountName" TEXT,
|
||||
"adminNote" TEXT,
|
||||
"processedById" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Payout_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Payout_bookingId_key" ON "Payout"("bookingId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Payout_organizerId_status_idx" ON "Payout"("organizerId", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Payout_status_heldUntil_idx" ON "Payout"("status", "heldUntil");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payout" ADD CONSTRAINT "Payout_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payout" ADD CONSTRAINT "Payout_tripId_fkey" FOREIGN KEY ("tripId") REFERENCES "Trip"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payout" ADD CONSTRAINT "Payout_organizerId_fkey" FOREIGN KEY ("organizerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payout" ADD CONSTRAINT "Payout_processedById_fkey" FOREIGN KEY ("processedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -34,6 +34,11 @@ model User {
|
||||
|
||||
reviewedRefunds Refund[] @relation("RefundReviewer")
|
||||
|
||||
/// Payout yang diterima user ini sebagai organizer (escrow trip selesai).
|
||||
payouts Payout[] @relation("PayoutOrganizer")
|
||||
/// Payout yang ditandai admin sebagai PAID/CANCELLED oleh user ini.
|
||||
processedPayouts Payout[] @relation("PayoutProcessor")
|
||||
|
||||
profile UserProfile?
|
||||
}
|
||||
|
||||
@@ -161,6 +166,7 @@ model Trip {
|
||||
images TripImage[]
|
||||
reviews TripReview[]
|
||||
bookings Booking[]
|
||||
payouts Payout[]
|
||||
|
||||
@@index([category, status, date])
|
||||
@@index([vibe, status, date])
|
||||
@@ -261,6 +267,7 @@ model Booking {
|
||||
|
||||
payments Payment[]
|
||||
refunds Refund[]
|
||||
payout Payout?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -436,3 +443,71 @@ enum RefundReporter {
|
||||
PARTICIPANT
|
||||
ORGANIZER
|
||||
}
|
||||
|
||||
/// Escrow payout ke organizer. Uang peserta ditahan sejak Booking → PAID sampai
|
||||
/// trip selesai + buffer beberapa hari, baru di-release untuk ditransfer admin.
|
||||
///
|
||||
/// State machine:
|
||||
/// HELD → diciptakan saat booking PAID, heldUntil = endDate/date + 3 hari
|
||||
/// RELEASED → cron flip setelah heldUntil lewat + trip COMPLETED
|
||||
/// PAID → admin sudah transfer manual ke rekening organizer
|
||||
/// CANCELLED → booking di-refund / trip dibatalkan; payout tidak jadi
|
||||
///
|
||||
/// Audit: 1-1 dengan Booking (unique). Refund SUCCEEDED mengurangi amount
|
||||
/// (partial) atau membatalkan payout (full).
|
||||
model Payout {
|
||||
id String @id @default(cuid())
|
||||
bookingId String @unique
|
||||
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Restrict)
|
||||
|
||||
tripId String
|
||||
trip Trip @relation(fields: [tripId], references: [id])
|
||||
|
||||
organizerId String
|
||||
organizer User @relation("PayoutOrganizer", fields: [organizerId], references: [id])
|
||||
|
||||
/// Nominal yg organizer terima (IDR integer). Default = booking.amount saat
|
||||
/// payout dibuat. Refund SUCCEEDED memotong nilai ini supaya total payout +
|
||||
/// total refund = uang yang dibayar peserta.
|
||||
amount Int
|
||||
currency String @default("IDR")
|
||||
|
||||
status PayoutStatus @default(HELD)
|
||||
|
||||
/// Tanggal payout boleh di-release ke organizer
|
||||
/// (= trip.endDate ?? trip.date + buffer days).
|
||||
heldUntil DateTime
|
||||
releasedAt DateTime?
|
||||
paidAt DateTime?
|
||||
cancelledAt DateTime?
|
||||
|
||||
/// Snapshot bank info organizer dari OrganizerVerification saat payout dibuat.
|
||||
/// Disimpan inline supaya audit-friendly walau organizer ganti bank nanti.
|
||||
bankName String?
|
||||
bankAccountNumber String?
|
||||
bankAccountName String?
|
||||
|
||||
/// Catatan admin: referensi transfer manual, alasan cancel, dst.
|
||||
adminNote String?
|
||||
|
||||
/// Admin yang menandai PAID/CANCELLED.
|
||||
processedById String?
|
||||
processedBy User? @relation("PayoutProcessor", fields: [processedById], references: [id])
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizerId, status])
|
||||
@@index([status, heldUntil])
|
||||
}
|
||||
|
||||
enum PayoutStatus {
|
||||
/// Menunggu trip selesai + buffer beberapa hari sebelum boleh ditransfer.
|
||||
HELD
|
||||
/// Buffer lewat & trip COMPLETED, siap di-transfer admin ke rekening organizer.
|
||||
RELEASED
|
||||
/// Admin sudah transfer ke rekening organizer.
|
||||
PAID
|
||||
/// Booking di-refund penuh / trip dibatalkan — uang tidak jadi ke organizer.
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user