add booking and payment schema

This commit is contained in:
2026-05-08 20:59:01 +07:00
parent c9c4c0e683
commit 2223a4630e
23 changed files with 5618 additions and 184 deletions
+21 -15
View File
@@ -49,9 +49,9 @@ Selesai. `tsc --noEmit` lulus. Tanpa schema baru, tanpa migration.
---
## PR B — Refactor schema ke `Booking` + `Payment` (provider MANUAL only)
## PR B — Refactor schema ke `Booking` + `Payment` (provider MANUAL only)
Pondasi untuk Midtrans tanpa lompat ke gateway dulu. UI tetap, sumber kebenaran pindah dari timestamp di `TripParticipant` ke tabel `Booking`/`Payment`.
Selesai. `tsc --noEmit` lulus. Pondasi untuk Midtrans sudah siap.
### Schema (target)
@@ -134,21 +134,27 @@ enum PaymentStatus {
### Tugas
| # | Item | Status | Catatan |
| # | Item | Status | File |
|---|---|---|---|
| B1 | Update [prisma/schema.prisma](prisma/schema.prisma) — tambah `Booking`, `Payment`, 3 enum | ⏳ | Relasi 1-1 ke `TripParticipant` via `participantId` unique. |
| B2 | Migration baru `add_booking_payment` | ⏳ | CreateTable Booking & Payment + CreateEnum + index. |
| B3 | Data backfill migration: bikin `Booking` + `Payment` untuk semua `TripParticipant` aktif yang sudah punya `markedPaidAt` atau `paymentConfirmedAt` | | Provider `MANUAL`. Status mapping: `paymentConfirmedAt → PAID`, `markedPaidAt only → AWAITING`, none → PENDING. Trip gratis → Booking PAID, tanpa Payment row. |
| B4 | `server/repositories/booking.repo.ts` + `payment.repo.ts` | ⏳ | findByTrip, findByUser, findByExternalOrderId. |
| B5 | `server/services/booking.service.ts` | ⏳ | `createForParticipant`, `markPaid (manual)`, `confirmPaid (organizer)`, `expireOldPending`. Idempotent. |
| B6 | Refactor `tripService.markParticipantPayment` → delegate ke `bookingService` | ⏳ | Backward compat: tetap update `TripParticipant` timestamp untuk transisi UI. |
| B7 | Refactor `confirmParticipantPayment` → delegate ke `bookingService` | | Sama. |
| B8 | Update halaman payment (PR A) untuk baca dari `Booking`/`Payment` | | Status timeline lebih kaya: dibuat → menunggu bayar → menunggu konfirmasi → lunas. |
| B9 | Update `OrganizerPaymentQueue` query | ⏳ | List Booking dengan Payment status AWAITING (manual) vs status sebelumnya. |
| B10 | Deprecate `TripParticipant.markedPaidAt` + `paymentConfirmedAt` | | Tetap ada di DB untuk transisi. Hapus di PR berikutnya setelah UI fully cutover. |
| B11 | Index optimization | ⏳ | `@@index([tripId, status])` di Booking, `@@index([provider, status])` di Payment. |
| B1 | Schema: tambah `Booking`, `Payment`, 3 enum (`BookingStatus`, `PaymentProvider`, `PaymentStatus`) + relasi di `User`, `Trip`, `TripParticipant` | ✅ | [prisma/schema.prisma](prisma/schema.prisma) |
| B2 | Migration `add_booking_payment` (CreateEnum + CreateTable + Index + FK) | ✅ | [prisma/migrations/20260508150000_add_booking_payment/migration.sql](prisma/migrations/20260508150000_add_booking_payment/migration.sql) |
| B3 | Backfill script TS (idempotent, skip baris yang sudah punya Booking) | | [prisma/backfill-bookings.ts](prisma/backfill-bookings.ts) |
| B4 | `bookingRepo` + `paymentRepo` | ✅ | [server/repositories/booking.repo.ts](server/repositories/booking.repo.ts), [server/repositories/payment.repo.ts](server/repositories/payment.repo.ts) |
| B5 | `bookingService` `markPaidManual`, `confirmPaidManual`, `getByTripAndUser`, `getAwaitingManualForTrip` (idempotent, transactional dengan retry serialisasi) | ✅ | [server/services/booking.service.ts](server/services/booking.service.ts) |
| B6 | `tripService.markParticipantPayment` → delegate ke `bookingService.markPaidManual`. Tetap update `TripParticipant.markedPaidAt` untuk backcompat. | ✅ | [server/services/trip.service.ts](server/services/trip.service.ts) |
| B7 | `tripService.confirmParticipantPayment` → delegate ke `bookingService.confirmPaidManual`. Tetap update `paymentConfirmedAt`. | | [server/services/trip.service.ts](server/services/trip.service.ts) |
| B+ | `tripService.joinTrip` → upsert Booking PENDING (handle re-join dari CANCELLED) | | [server/services/trip.service.ts](server/services/trip.service.ts) |
| B+ | `tripService.confirmParticipant` → transition Booking PENDING → AWAITING_PAY (paid) atau PAID (free) | ✅ | [server/services/trip.service.ts](server/services/trip.service.ts) |
| B+ | `tripService.cancelJoin` & `rejectParticipant` → Booking → CANCELLED | | [server/services/trip.service.ts](server/services/trip.service.ts) |
| B8 | Halaman `/trips/[id]/payment` baca dari Booking + Payment (bukan timestamp lama) | ✅ | [app/trips/[id]/payment/page.tsx](app/trips/%5Bid%5D/payment/page.tsx) |
| B9 | `OrganizerPaymentQueue` di trip detail dapat data dari `bookingService.getAwaitingManualForTrip` | ✅ | [app/trips/[id]/page.tsx](app/trips/%5Bid%5D/page.tsx) |
| B10 | Deprecate `TripParticipant.markedPaidAt` + `paymentConfirmedAt` (komen `@deprecated`, tetap di-update untuk backcompat) | ✅ | [prisma/schema.prisma](prisma/schema.prisma) |
| B11 | Index optimization (`@@index([tripId, status])` di Booking, `@@index([provider, status])` di Payment, `@@index([userId])` di Booking) | ✅ | [prisma/schema.prisma](prisma/schema.prisma) |
**Tindakan manual:** `npx prisma migrate deploy` + jalankan backfill script (B3 bisa dimasukkan ke migration SQL atau script TS terpisah).
**Tindakan manual (urutan penting):**
1. `npx prisma migrate deploy` — apply schema migration `20260508150000_add_booking_payment`.
2. `npx tsx prisma/backfill-bookings.ts` — populate Booking + Payment dari `TripParticipant` lama. Idempotent, aman dijalankan ulang.
3. Verifikasi: jumlah Booking aktif = jumlah TripParticipant aktif setelah backfill.
---
+16
View File
@@ -59,3 +59,19 @@ export type TripImage = Prisma.TripImageModel
*
*/
export type TripParticipant = Prisma.TripParticipantModel
/**
* Model Booking
* Booking 1-1 ke TripParticipant. Lifecycle ikut peserta:
* - join → Booking PENDING (menunggu approve organizer)
* - organizer confirm → AWAITING_PAY (paid trip) atau PAID (free trip)
* - peserta + organizer rampungkan pembayaran → PAID
* - cancel/reject → CANCELLED
* `amount` adalah snapshot harga saat booking dibuat — protect dari perubahan trip.price.
*/
export type Booking = Prisma.BookingModel
/**
* Model Payment
* Satu attempt pembayaran. Satu Booking bisa punya banyak Payment kalau retry
* (di Phase MIDTRANS nanti). Untuk MANUAL biasanya cukup 1 Payment.
*/
export type Payment = Prisma.PaymentModel
+16
View File
@@ -83,3 +83,19 @@ export type TripImage = Prisma.TripImageModel
*
*/
export type TripParticipant = Prisma.TripParticipantModel
/**
* Model Booking
* Booking 1-1 ke TripParticipant. Lifecycle ikut peserta:
* - join → Booking PENDING (menunggu approve organizer)
* - organizer confirm → AWAITING_PAY (paid trip) atau PAID (free trip)
* - peserta + organizer rampungkan pembayaran → PAID
* - cancel/reject → CANCELLED
* `amount` adalah snapshot harga saat booking dibuat — protect dari perubahan trip.price.
*/
export type Booking = Prisma.BookingModel
/**
* Model Payment
* Satu attempt pembayaran. Satu Booking bisa punya banyak Payment kalau retry
* (di Phase MIDTRANS nanti). Untuk MANUAL biasanya cukup 1 Payment.
*/
export type Payment = Prisma.PaymentModel
+177
View File
@@ -287,6 +287,108 @@ export type EnumParticipantStatusWithAggregatesFilter<$PrismaModel = never> = {
_max?: Prisma.NestedEnumParticipantStatusFilter<$PrismaModel>
}
export type EnumBookingStatusFilter<$PrismaModel = never> = {
equals?: $Enums.BookingStatus | Prisma.EnumBookingStatusFieldRefInput<$PrismaModel>
in?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumBookingStatusFilter<$PrismaModel> | $Enums.BookingStatus
}
export type EnumBookingStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.BookingStatus | Prisma.EnumBookingStatusFieldRefInput<$PrismaModel>
in?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumBookingStatusWithAggregatesFilter<$PrismaModel> | $Enums.BookingStatus
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumBookingStatusFilter<$PrismaModel>
_max?: Prisma.NestedEnumBookingStatusFilter<$PrismaModel>
}
export type EnumPaymentProviderFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentProvider | Prisma.EnumPaymentProviderFieldRefInput<$PrismaModel>
in?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentProviderFilter<$PrismaModel> | $Enums.PaymentProvider
}
export type EnumPaymentStatusFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentStatus | Prisma.EnumPaymentStatusFieldRefInput<$PrismaModel>
in?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentStatusFilter<$PrismaModel> | $Enums.PaymentStatus
}
export type JsonNullableFilter<$PrismaModel = never> =
| Prisma.PatchUndefined<
Prisma.Either<Required<JsonNullableFilterBase<$PrismaModel>>, Exclude<keyof Required<JsonNullableFilterBase<$PrismaModel>>, 'path'>>,
Required<JsonNullableFilterBase<$PrismaModel>>
>
| Prisma.OptionalFlat<Omit<Required<JsonNullableFilterBase<$PrismaModel>>, 'path'>>
export type JsonNullableFilterBase<$PrismaModel = never> = {
equals?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter
path?: string[]
mode?: Prisma.QueryMode | Prisma.EnumQueryModeFieldRefInput<$PrismaModel>
string_contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
string_starts_with?: string | Prisma.StringFieldRefInput<$PrismaModel>
string_ends_with?: string | Prisma.StringFieldRefInput<$PrismaModel>
array_starts_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
array_ends_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
array_contains?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
lt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
lte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
gt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
gte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
not?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter
}
export type EnumPaymentProviderWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentProvider | Prisma.EnumPaymentProviderFieldRefInput<$PrismaModel>
in?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentProviderWithAggregatesFilter<$PrismaModel> | $Enums.PaymentProvider
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumPaymentProviderFilter<$PrismaModel>
_max?: Prisma.NestedEnumPaymentProviderFilter<$PrismaModel>
}
export type EnumPaymentStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentStatus | Prisma.EnumPaymentStatusFieldRefInput<$PrismaModel>
in?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentStatusWithAggregatesFilter<$PrismaModel> | $Enums.PaymentStatus
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumPaymentStatusFilter<$PrismaModel>
_max?: Prisma.NestedEnumPaymentStatusFilter<$PrismaModel>
}
export type JsonNullableWithAggregatesFilter<$PrismaModel = never> =
| Prisma.PatchUndefined<
Prisma.Either<Required<JsonNullableWithAggregatesFilterBase<$PrismaModel>>, Exclude<keyof Required<JsonNullableWithAggregatesFilterBase<$PrismaModel>>, 'path'>>,
Required<JsonNullableWithAggregatesFilterBase<$PrismaModel>>
>
| Prisma.OptionalFlat<Omit<Required<JsonNullableWithAggregatesFilterBase<$PrismaModel>>, 'path'>>
export type JsonNullableWithAggregatesFilterBase<$PrismaModel = never> = {
equals?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter
path?: string[]
mode?: Prisma.QueryMode | Prisma.EnumQueryModeFieldRefInput<$PrismaModel>
string_contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
string_starts_with?: string | Prisma.StringFieldRefInput<$PrismaModel>
string_ends_with?: string | Prisma.StringFieldRefInput<$PrismaModel>
array_starts_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
array_ends_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
array_contains?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
lt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
lte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
gt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
gte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
not?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedJsonNullableFilter<$PrismaModel>
_max?: Prisma.NestedJsonNullableFilter<$PrismaModel>
}
export type NestedStringFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
@@ -573,4 +675,79 @@ export type NestedEnumParticipantStatusWithAggregatesFilter<$PrismaModel = never
_max?: Prisma.NestedEnumParticipantStatusFilter<$PrismaModel>
}
export type NestedEnumBookingStatusFilter<$PrismaModel = never> = {
equals?: $Enums.BookingStatus | Prisma.EnumBookingStatusFieldRefInput<$PrismaModel>
in?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumBookingStatusFilter<$PrismaModel> | $Enums.BookingStatus
}
export type NestedEnumBookingStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.BookingStatus | Prisma.EnumBookingStatusFieldRefInput<$PrismaModel>
in?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.BookingStatus[] | Prisma.ListEnumBookingStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumBookingStatusWithAggregatesFilter<$PrismaModel> | $Enums.BookingStatus
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumBookingStatusFilter<$PrismaModel>
_max?: Prisma.NestedEnumBookingStatusFilter<$PrismaModel>
}
export type NestedEnumPaymentProviderFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentProvider | Prisma.EnumPaymentProviderFieldRefInput<$PrismaModel>
in?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentProviderFilter<$PrismaModel> | $Enums.PaymentProvider
}
export type NestedEnumPaymentStatusFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentStatus | Prisma.EnumPaymentStatusFieldRefInput<$PrismaModel>
in?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentStatusFilter<$PrismaModel> | $Enums.PaymentStatus
}
export type NestedEnumPaymentProviderWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentProvider | Prisma.EnumPaymentProviderFieldRefInput<$PrismaModel>
in?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentProvider[] | Prisma.ListEnumPaymentProviderFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentProviderWithAggregatesFilter<$PrismaModel> | $Enums.PaymentProvider
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumPaymentProviderFilter<$PrismaModel>
_max?: Prisma.NestedEnumPaymentProviderFilter<$PrismaModel>
}
export type NestedEnumPaymentStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.PaymentStatus | Prisma.EnumPaymentStatusFieldRefInput<$PrismaModel>
in?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.PaymentStatus[] | Prisma.ListEnumPaymentStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumPaymentStatusWithAggregatesFilter<$PrismaModel> | $Enums.PaymentStatus
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumPaymentStatusFilter<$PrismaModel>
_max?: Prisma.NestedEnumPaymentStatusFilter<$PrismaModel>
}
export type NestedJsonNullableFilter<$PrismaModel = never> =
| Prisma.PatchUndefined<
Prisma.Either<Required<NestedJsonNullableFilterBase<$PrismaModel>>, Exclude<keyof Required<NestedJsonNullableFilterBase<$PrismaModel>>, 'path'>>,
Required<NestedJsonNullableFilterBase<$PrismaModel>>
>
| Prisma.OptionalFlat<Omit<Required<NestedJsonNullableFilterBase<$PrismaModel>>, 'path'>>
export type NestedJsonNullableFilterBase<$PrismaModel = never> = {
equals?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter
path?: string[]
mode?: Prisma.QueryMode | Prisma.EnumQueryModeFieldRefInput<$PrismaModel>
string_contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
string_starts_with?: string | Prisma.StringFieldRefInput<$PrismaModel>
string_ends_with?: string | Prisma.StringFieldRefInput<$PrismaModel>
array_starts_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
array_ends_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
array_contains?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null
lt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
lte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
gt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
gte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel>
not?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter
}
+33
View File
@@ -60,3 +60,36 @@ export const ParticipantStatus = {
} as const
export type ParticipantStatus = (typeof ParticipantStatus)[keyof typeof ParticipantStatus]
export const BookingStatus = {
PENDING: 'PENDING',
AWAITING_PAY: 'AWAITING_PAY',
PAID: 'PAID',
CANCELLED: 'CANCELLED',
REFUNDED: 'REFUNDED',
EXPIRED: 'EXPIRED'
} as const
export type BookingStatus = (typeof BookingStatus)[keyof typeof BookingStatus]
export const PaymentProvider = {
MANUAL: 'MANUAL',
MIDTRANS: 'MIDTRANS'
} as const
export type PaymentProvider = (typeof PaymentProvider)[keyof typeof PaymentProvider]
export const PaymentStatus = {
PENDING: 'PENDING',
AWAITING: 'AWAITING',
PAID: 'PAID',
FAILED: 'FAILED',
EXPIRED: 'EXPIRED',
CANCELLED: 'CANCELLED',
REFUNDED: 'REFUNDED'
} as const
export type PaymentStatus = (typeof PaymentStatus)[keyof typeof PaymentStatus]
File diff suppressed because one or more lines are too long
@@ -391,7 +391,9 @@ export const ModelName = {
Trip: 'Trip',
TripReview: 'TripReview',
TripImage: 'TripImage',
TripParticipant: 'TripParticipant'
TripParticipant: 'TripParticipant',
Booking: 'Booking',
Payment: 'Payment'
} as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
@@ -407,7 +409,7 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
omit: GlobalOmitOptions
}
meta: {
modelProps: "user" | "userProfile" | "account" | "organizerVerification" | "trip" | "tripReview" | "tripImage" | "tripParticipant"
modelProps: "user" | "userProfile" | "account" | "organizerVerification" | "trip" | "tripReview" | "tripImage" | "tripParticipant" | "booking" | "payment"
txIsolationLevel: TransactionIsolationLevel
}
model: {
@@ -1003,6 +1005,154 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
}
}
}
Booking: {
payload: Prisma.$BookingPayload<ExtArgs>
fields: Prisma.BookingFieldRefs
operations: {
findUnique: {
args: Prisma.BookingFindUniqueArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload> | null
}
findUniqueOrThrow: {
args: Prisma.BookingFindUniqueOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>
}
findFirst: {
args: Prisma.BookingFindFirstArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload> | null
}
findFirstOrThrow: {
args: Prisma.BookingFindFirstOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>
}
findMany: {
args: Prisma.BookingFindManyArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>[]
}
create: {
args: Prisma.BookingCreateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>
}
createMany: {
args: Prisma.BookingCreateManyArgs<ExtArgs>
result: BatchPayload
}
createManyAndReturn: {
args: Prisma.BookingCreateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>[]
}
delete: {
args: Prisma.BookingDeleteArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>
}
update: {
args: Prisma.BookingUpdateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>
}
deleteMany: {
args: Prisma.BookingDeleteManyArgs<ExtArgs>
result: BatchPayload
}
updateMany: {
args: Prisma.BookingUpdateManyArgs<ExtArgs>
result: BatchPayload
}
updateManyAndReturn: {
args: Prisma.BookingUpdateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>[]
}
upsert: {
args: Prisma.BookingUpsertArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$BookingPayload>
}
aggregate: {
args: Prisma.BookingAggregateArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AggregateBooking>
}
groupBy: {
args: Prisma.BookingGroupByArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.BookingGroupByOutputType>[]
}
count: {
args: Prisma.BookingCountArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.BookingCountAggregateOutputType> | number
}
}
}
Payment: {
payload: Prisma.$PaymentPayload<ExtArgs>
fields: Prisma.PaymentFieldRefs
operations: {
findUnique: {
args: Prisma.PaymentFindUniqueArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload> | null
}
findUniqueOrThrow: {
args: Prisma.PaymentFindUniqueOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>
}
findFirst: {
args: Prisma.PaymentFindFirstArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload> | null
}
findFirstOrThrow: {
args: Prisma.PaymentFindFirstOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>
}
findMany: {
args: Prisma.PaymentFindManyArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>[]
}
create: {
args: Prisma.PaymentCreateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>
}
createMany: {
args: Prisma.PaymentCreateManyArgs<ExtArgs>
result: BatchPayload
}
createManyAndReturn: {
args: Prisma.PaymentCreateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>[]
}
delete: {
args: Prisma.PaymentDeleteArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>
}
update: {
args: Prisma.PaymentUpdateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>
}
deleteMany: {
args: Prisma.PaymentDeleteManyArgs<ExtArgs>
result: BatchPayload
}
updateMany: {
args: Prisma.PaymentUpdateManyArgs<ExtArgs>
result: BatchPayload
}
updateManyAndReturn: {
args: Prisma.PaymentUpdateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>[]
}
upsert: {
args: Prisma.PaymentUpsertArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$PaymentPayload>
}
aggregate: {
args: Prisma.PaymentAggregateArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AggregatePayment>
}
groupBy: {
args: Prisma.PaymentGroupByArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.PaymentGroupByOutputType>[]
}
count: {
args: Prisma.PaymentCountArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.PaymentCountAggregateOutputType> | number
}
}
}
}
} & {
other: {
@@ -1178,6 +1328,43 @@ export const TripParticipantScalarFieldEnum = {
export type TripParticipantScalarFieldEnum = (typeof TripParticipantScalarFieldEnum)[keyof typeof TripParticipantScalarFieldEnum]
export const BookingScalarFieldEnum = {
id: 'id',
tripId: 'tripId',
userId: 'userId',
participantId: 'participantId',
amount: 'amount',
currency: 'currency',
status: 'status',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type BookingScalarFieldEnum = (typeof BookingScalarFieldEnum)[keyof typeof BookingScalarFieldEnum]
export const PaymentScalarFieldEnum = {
id: 'id',
bookingId: 'bookingId',
provider: 'provider',
externalOrderId: 'externalOrderId',
externalTxId: 'externalTxId',
method: 'method',
amount: 'amount',
status: 'status',
rawCallback: 'rawCallback',
snapToken: 'snapToken',
expiresAt: 'expiresAt',
paidAt: 'paidAt',
failedAt: 'failedAt',
rejectionReason: 'rejectionReason',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type PaymentScalarFieldEnum = (typeof PaymentScalarFieldEnum)[keyof typeof PaymentScalarFieldEnum]
export const SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -1186,6 +1373,14 @@ export const SortOrder = {
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]
export const NullableJsonNullValueInput = {
DbNull: DbNull,
JsonNull: JsonNull
} as const
export type NullableJsonNullValueInput = (typeof NullableJsonNullValueInput)[keyof typeof NullableJsonNullValueInput]
export const QueryMode = {
default: 'default',
insensitive: 'insensitive'
@@ -1202,6 +1397,15 @@ export const NullsOrder = {
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]
export const JsonNullValueFilter = {
DbNull: DbNull,
JsonNull: JsonNull,
AnyNull: AnyNull
} as const
export type JsonNullValueFilter = (typeof JsonNullValueFilter)[keyof typeof JsonNullValueFilter]
/**
* Field references
@@ -1327,6 +1531,62 @@ export type ListEnumParticipantStatusFieldRefInput<$PrismaModel> = FieldRefInput
/**
* Reference to a field of type 'BookingStatus'
*/
export type EnumBookingStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'BookingStatus'>
/**
* Reference to a field of type 'BookingStatus[]'
*/
export type ListEnumBookingStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'BookingStatus[]'>
/**
* Reference to a field of type 'PaymentProvider'
*/
export type EnumPaymentProviderFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'PaymentProvider'>
/**
* Reference to a field of type 'PaymentProvider[]'
*/
export type ListEnumPaymentProviderFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'PaymentProvider[]'>
/**
* Reference to a field of type 'PaymentStatus'
*/
export type EnumPaymentStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'PaymentStatus'>
/**
* Reference to a field of type 'PaymentStatus[]'
*/
export type ListEnumPaymentStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'PaymentStatus[]'>
/**
* Reference to a field of type 'Json'
*/
export type JsonFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Json'>
/**
* Reference to a field of type 'QueryMode'
*/
export type EnumQueryModeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'QueryMode'>
/**
* Reference to a field of type 'Float'
*/
@@ -1458,6 +1718,8 @@ export type GlobalOmitConfig = {
tripReview?: Prisma.TripReviewOmit
tripImage?: Prisma.TripImageOmit
tripParticipant?: Prisma.TripParticipantOmit
booking?: Prisma.BookingOmit
payment?: Prisma.PaymentOmit
}
/* Types for Logging */
@@ -58,7 +58,9 @@ export const ModelName = {
Trip: 'Trip',
TripReview: 'TripReview',
TripImage: 'TripImage',
TripParticipant: 'TripParticipant'
TripParticipant: 'TripParticipant',
Booking: 'Booking',
Payment: 'Payment'
} as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
@@ -213,6 +215,43 @@ export const TripParticipantScalarFieldEnum = {
export type TripParticipantScalarFieldEnum = (typeof TripParticipantScalarFieldEnum)[keyof typeof TripParticipantScalarFieldEnum]
export const BookingScalarFieldEnum = {
id: 'id',
tripId: 'tripId',
userId: 'userId',
participantId: 'participantId',
amount: 'amount',
currency: 'currency',
status: 'status',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type BookingScalarFieldEnum = (typeof BookingScalarFieldEnum)[keyof typeof BookingScalarFieldEnum]
export const PaymentScalarFieldEnum = {
id: 'id',
bookingId: 'bookingId',
provider: 'provider',
externalOrderId: 'externalOrderId',
externalTxId: 'externalTxId',
method: 'method',
amount: 'amount',
status: 'status',
rawCallback: 'rawCallback',
snapToken: 'snapToken',
expiresAt: 'expiresAt',
paidAt: 'paidAt',
failedAt: 'failedAt',
rejectionReason: 'rejectionReason',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type PaymentScalarFieldEnum = (typeof PaymentScalarFieldEnum)[keyof typeof PaymentScalarFieldEnum]
export const SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -221,6 +260,14 @@ export const SortOrder = {
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]
export const NullableJsonNullValueInput = {
DbNull: DbNull,
JsonNull: JsonNull
} as const
export type NullableJsonNullValueInput = (typeof NullableJsonNullValueInput)[keyof typeof NullableJsonNullValueInput]
export const QueryMode = {
default: 'default',
insensitive: 'insensitive'
@@ -236,3 +283,12 @@ export const NullsOrder = {
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]
export const JsonNullValueFilter = {
DbNull: DbNull,
JsonNull: JsonNull,
AnyNull: AnyNull
} as const
export type JsonNullValueFilter = (typeof JsonNullValueFilter)[keyof typeof JsonNullValueFilter]
+2
View File
@@ -16,4 +16,6 @@ export type * from './models/Trip'
export type * from './models/TripReview'
export type * from './models/TripImage'
export type * from './models/TripParticipant'
export type * from './models/Booking'
export type * from './models/Payment'
export type * from './commonInputTypes'
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+190
View File
@@ -336,6 +336,7 @@ export type TripWhereInput = {
participants?: Prisma.TripParticipantListRelationFilter
images?: Prisma.TripImageListRelationFilter
reviews?: Prisma.TripReviewListRelationFilter
bookings?: Prisma.BookingListRelationFilter
}
export type TripOrderByWithRelationInput = {
@@ -362,6 +363,7 @@ export type TripOrderByWithRelationInput = {
participants?: Prisma.TripParticipantOrderByRelationAggregateInput
images?: Prisma.TripImageOrderByRelationAggregateInput
reviews?: Prisma.TripReviewOrderByRelationAggregateInput
bookings?: Prisma.BookingOrderByRelationAggregateInput
}
export type TripWhereUniqueInput = Prisma.AtLeast<{
@@ -391,6 +393,7 @@ export type TripWhereUniqueInput = Prisma.AtLeast<{
participants?: Prisma.TripParticipantListRelationFilter
images?: Prisma.TripImageListRelationFilter
reviews?: Prisma.TripReviewListRelationFilter
bookings?: Prisma.BookingListRelationFilter
}, "id">
export type TripOrderByWithAggregationInput = {
@@ -468,6 +471,7 @@ export type TripCreateInput = {
participants?: Prisma.TripParticipantCreateNestedManyWithoutTripInput
images?: Prisma.TripImageCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingCreateNestedManyWithoutTripInput
}
export type TripUncheckedCreateInput = {
@@ -493,6 +497,7 @@ export type TripUncheckedCreateInput = {
participants?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutTripInput
images?: Prisma.TripImageUncheckedCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutTripInput
}
export type TripUpdateInput = {
@@ -518,6 +523,7 @@ export type TripUpdateInput = {
participants?: Prisma.TripParticipantUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateInput = {
@@ -543,6 +549,7 @@ export type TripUncheckedUpdateInput = {
participants?: Prisma.TripParticipantUncheckedUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUncheckedUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUncheckedUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutTripNestedInput
}
export type TripCreateManyInput = {
@@ -801,6 +808,20 @@ export type TripUpdateOneRequiredWithoutParticipantsNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.TripUpdateToOneWithWhereWithoutParticipantsInput, Prisma.TripUpdateWithoutParticipantsInput>, Prisma.TripUncheckedUpdateWithoutParticipantsInput>
}
export type TripCreateNestedOneWithoutBookingsInput = {
create?: Prisma.XOR<Prisma.TripCreateWithoutBookingsInput, Prisma.TripUncheckedCreateWithoutBookingsInput>
connectOrCreate?: Prisma.TripCreateOrConnectWithoutBookingsInput
connect?: Prisma.TripWhereUniqueInput
}
export type TripUpdateOneRequiredWithoutBookingsNestedInput = {
create?: Prisma.XOR<Prisma.TripCreateWithoutBookingsInput, Prisma.TripUncheckedCreateWithoutBookingsInput>
connectOrCreate?: Prisma.TripCreateOrConnectWithoutBookingsInput
upsert?: Prisma.TripUpsertWithoutBookingsInput
connect?: Prisma.TripWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.TripUpdateToOneWithWhereWithoutBookingsInput, Prisma.TripUpdateWithoutBookingsInput>, Prisma.TripUncheckedUpdateWithoutBookingsInput>
}
export type TripCreateWithoutOrganizerInput = {
id?: string
title: string
@@ -823,6 +844,7 @@ export type TripCreateWithoutOrganizerInput = {
participants?: Prisma.TripParticipantCreateNestedManyWithoutTripInput
images?: Prisma.TripImageCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingCreateNestedManyWithoutTripInput
}
export type TripUncheckedCreateWithoutOrganizerInput = {
@@ -847,6 +869,7 @@ export type TripUncheckedCreateWithoutOrganizerInput = {
participants?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutTripInput
images?: Prisma.TripImageUncheckedCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutTripInput
}
export type TripCreateOrConnectWithoutOrganizerInput = {
@@ -922,6 +945,7 @@ export type TripCreateWithoutReviewsInput = {
organizer: Prisma.UserCreateNestedOneWithoutTripsInput
participants?: Prisma.TripParticipantCreateNestedManyWithoutTripInput
images?: Prisma.TripImageCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingCreateNestedManyWithoutTripInput
}
export type TripUncheckedCreateWithoutReviewsInput = {
@@ -946,6 +970,7 @@ export type TripUncheckedCreateWithoutReviewsInput = {
organizerId: string
participants?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutTripInput
images?: Prisma.TripImageUncheckedCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutTripInput
}
export type TripCreateOrConnectWithoutReviewsInput = {
@@ -986,6 +1011,7 @@ export type TripUpdateWithoutReviewsInput = {
organizer?: Prisma.UserUpdateOneRequiredWithoutTripsNestedInput
participants?: Prisma.TripParticipantUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateWithoutReviewsInput = {
@@ -1010,6 +1036,7 @@ export type TripUncheckedUpdateWithoutReviewsInput = {
organizerId?: Prisma.StringFieldUpdateOperationsInput | string
participants?: Prisma.TripParticipantUncheckedUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUncheckedUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutTripNestedInput
}
export type TripCreateWithoutImagesInput = {
@@ -1034,6 +1061,7 @@ export type TripCreateWithoutImagesInput = {
organizer: Prisma.UserCreateNestedOneWithoutTripsInput
participants?: Prisma.TripParticipantCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingCreateNestedManyWithoutTripInput
}
export type TripUncheckedCreateWithoutImagesInput = {
@@ -1058,6 +1086,7 @@ export type TripUncheckedCreateWithoutImagesInput = {
organizerId: string
participants?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutTripInput
}
export type TripCreateOrConnectWithoutImagesInput = {
@@ -1098,6 +1127,7 @@ export type TripUpdateWithoutImagesInput = {
organizer?: Prisma.UserUpdateOneRequiredWithoutTripsNestedInput
participants?: Prisma.TripParticipantUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateWithoutImagesInput = {
@@ -1122,6 +1152,7 @@ export type TripUncheckedUpdateWithoutImagesInput = {
organizerId?: Prisma.StringFieldUpdateOperationsInput | string
participants?: Prisma.TripParticipantUncheckedUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUncheckedUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutTripNestedInput
}
export type TripCreateWithoutParticipantsInput = {
@@ -1146,6 +1177,7 @@ export type TripCreateWithoutParticipantsInput = {
organizer: Prisma.UserCreateNestedOneWithoutTripsInput
images?: Prisma.TripImageCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingCreateNestedManyWithoutTripInput
}
export type TripUncheckedCreateWithoutParticipantsInput = {
@@ -1170,6 +1202,7 @@ export type TripUncheckedCreateWithoutParticipantsInput = {
organizerId: string
images?: Prisma.TripImageUncheckedCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutTripInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutTripInput
}
export type TripCreateOrConnectWithoutParticipantsInput = {
@@ -1210,6 +1243,7 @@ export type TripUpdateWithoutParticipantsInput = {
organizer?: Prisma.UserUpdateOneRequiredWithoutTripsNestedInput
images?: Prisma.TripImageUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateWithoutParticipantsInput = {
@@ -1234,6 +1268,123 @@ export type TripUncheckedUpdateWithoutParticipantsInput = {
organizerId?: Prisma.StringFieldUpdateOperationsInput | string
images?: Prisma.TripImageUncheckedUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUncheckedUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutTripNestedInput
}
export type TripCreateWithoutBookingsInput = {
id?: string
title: string
description?: string | null
category?: $Enums.ActivityCategory
destination: string
location: string
meetingPoint?: string | null
itinerary?: string | null
whatsIncluded?: string | null
whatsExcluded?: string | null
date: Date | string
endDate?: Date | string | null
maxParticipants: number
price: number
vibe?: $Enums.Vibe | null
status?: $Enums.TripStatus
createdAt?: Date | string
updatedAt?: Date | string
organizer: Prisma.UserCreateNestedOneWithoutTripsInput
participants?: Prisma.TripParticipantCreateNestedManyWithoutTripInput
images?: Prisma.TripImageCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewCreateNestedManyWithoutTripInput
}
export type TripUncheckedCreateWithoutBookingsInput = {
id?: string
title: string
description?: string | null
category?: $Enums.ActivityCategory
destination: string
location: string
meetingPoint?: string | null
itinerary?: string | null
whatsIncluded?: string | null
whatsExcluded?: string | null
date: Date | string
endDate?: Date | string | null
maxParticipants: number
price: number
vibe?: $Enums.Vibe | null
status?: $Enums.TripStatus
createdAt?: Date | string
updatedAt?: Date | string
organizerId: string
participants?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutTripInput
images?: Prisma.TripImageUncheckedCreateNestedManyWithoutTripInput
reviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutTripInput
}
export type TripCreateOrConnectWithoutBookingsInput = {
where: Prisma.TripWhereUniqueInput
create: Prisma.XOR<Prisma.TripCreateWithoutBookingsInput, Prisma.TripUncheckedCreateWithoutBookingsInput>
}
export type TripUpsertWithoutBookingsInput = {
update: Prisma.XOR<Prisma.TripUpdateWithoutBookingsInput, Prisma.TripUncheckedUpdateWithoutBookingsInput>
create: Prisma.XOR<Prisma.TripCreateWithoutBookingsInput, Prisma.TripUncheckedCreateWithoutBookingsInput>
where?: Prisma.TripWhereInput
}
export type TripUpdateToOneWithWhereWithoutBookingsInput = {
where?: Prisma.TripWhereInput
data: Prisma.XOR<Prisma.TripUpdateWithoutBookingsInput, Prisma.TripUncheckedUpdateWithoutBookingsInput>
}
export type TripUpdateWithoutBookingsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
title?: Prisma.StringFieldUpdateOperationsInput | string
description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
category?: Prisma.EnumActivityCategoryFieldUpdateOperationsInput | $Enums.ActivityCategory
destination?: Prisma.StringFieldUpdateOperationsInput | string
location?: Prisma.StringFieldUpdateOperationsInput | string
meetingPoint?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
itinerary?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
whatsIncluded?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
whatsExcluded?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
date?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
endDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
maxParticipants?: Prisma.IntFieldUpdateOperationsInput | number
price?: Prisma.IntFieldUpdateOperationsInput | number
vibe?: Prisma.NullableEnumVibeFieldUpdateOperationsInput | $Enums.Vibe | null
status?: Prisma.EnumTripStatusFieldUpdateOperationsInput | $Enums.TripStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
organizer?: Prisma.UserUpdateOneRequiredWithoutTripsNestedInput
participants?: Prisma.TripParticipantUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateWithoutBookingsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
title?: Prisma.StringFieldUpdateOperationsInput | string
description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
category?: Prisma.EnumActivityCategoryFieldUpdateOperationsInput | $Enums.ActivityCategory
destination?: Prisma.StringFieldUpdateOperationsInput | string
location?: Prisma.StringFieldUpdateOperationsInput | string
meetingPoint?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
itinerary?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
whatsIncluded?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
whatsExcluded?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
date?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
endDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
maxParticipants?: Prisma.IntFieldUpdateOperationsInput | number
price?: Prisma.IntFieldUpdateOperationsInput | number
vibe?: Prisma.NullableEnumVibeFieldUpdateOperationsInput | $Enums.Vibe | null
status?: Prisma.EnumTripStatusFieldUpdateOperationsInput | $Enums.TripStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
organizerId?: Prisma.StringFieldUpdateOperationsInput | string
participants?: Prisma.TripParticipantUncheckedUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUncheckedUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUncheckedUpdateManyWithoutTripNestedInput
}
export type TripCreateManyOrganizerInput = {
@@ -1279,6 +1430,7 @@ export type TripUpdateWithoutOrganizerInput = {
participants?: Prisma.TripParticipantUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateWithoutOrganizerInput = {
@@ -1303,6 +1455,7 @@ export type TripUncheckedUpdateWithoutOrganizerInput = {
participants?: Prisma.TripParticipantUncheckedUpdateManyWithoutTripNestedInput
images?: Prisma.TripImageUncheckedUpdateManyWithoutTripNestedInput
reviews?: Prisma.TripReviewUncheckedUpdateManyWithoutTripNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutTripNestedInput
}
export type TripUncheckedUpdateManyWithoutOrganizerInput = {
@@ -1335,12 +1488,14 @@ export type TripCountOutputType = {
participants: number
images: number
reviews: number
bookings: number
}
export type TripCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
participants?: boolean | TripCountOutputTypeCountParticipantsArgs
images?: boolean | TripCountOutputTypeCountImagesArgs
reviews?: boolean | TripCountOutputTypeCountReviewsArgs
bookings?: boolean | TripCountOutputTypeCountBookingsArgs
}
/**
@@ -1374,6 +1529,13 @@ export type TripCountOutputTypeCountReviewsArgs<ExtArgs extends runtime.Types.Ex
where?: Prisma.TripReviewWhereInput
}
/**
* TripCountOutputType without action
*/
export type TripCountOutputTypeCountBookingsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.BookingWhereInput
}
export type TripSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
@@ -1399,6 +1561,7 @@ export type TripSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = r
participants?: boolean | Prisma.Trip$participantsArgs<ExtArgs>
images?: boolean | Prisma.Trip$imagesArgs<ExtArgs>
reviews?: boolean | Prisma.Trip$reviewsArgs<ExtArgs>
bookings?: boolean | Prisma.Trip$bookingsArgs<ExtArgs>
_count?: boolean | Prisma.TripCountOutputTypeDefaultArgs<ExtArgs>
}, ExtArgs["result"]["trip"]>
@@ -1476,6 +1639,7 @@ export type TripInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs =
participants?: boolean | Prisma.Trip$participantsArgs<ExtArgs>
images?: boolean | Prisma.Trip$imagesArgs<ExtArgs>
reviews?: boolean | Prisma.Trip$reviewsArgs<ExtArgs>
bookings?: boolean | Prisma.Trip$bookingsArgs<ExtArgs>
_count?: boolean | Prisma.TripCountOutputTypeDefaultArgs<ExtArgs>
}
export type TripIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
@@ -1492,6 +1656,7 @@ export type $TripPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
participants: Prisma.$TripParticipantPayload<ExtArgs>[]
images: Prisma.$TripImagePayload<ExtArgs>[]
reviews: Prisma.$TripReviewPayload<ExtArgs>[]
bookings: Prisma.$BookingPayload<ExtArgs>[]
}
scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string
@@ -1932,6 +2097,7 @@ export interface Prisma__TripClient<T, Null = never, ExtArgs extends runtime.Typ
participants<T extends Prisma.Trip$participantsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Trip$participantsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$TripParticipantPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
images<T extends Prisma.Trip$imagesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Trip$imagesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$TripImagePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
reviews<T extends Prisma.Trip$reviewsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Trip$reviewsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$TripReviewPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
bookings<T extends Prisma.Trip$bookingsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Trip$bookingsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$BookingPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
@@ -2452,6 +2618,30 @@ export type Trip$reviewsArgs<ExtArgs extends runtime.Types.Extensions.InternalAr
distinct?: Prisma.TripReviewScalarFieldEnum | Prisma.TripReviewScalarFieldEnum[]
}
/**
* Trip.bookings
*/
export type Trip$bookingsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the Booking
*/
select?: Prisma.BookingSelect<ExtArgs> | null
/**
* Omit specific fields from the Booking
*/
omit?: Prisma.BookingOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.BookingInclude<ExtArgs> | null
where?: Prisma.BookingWhereInput
orderBy?: Prisma.BookingOrderByWithRelationInput | Prisma.BookingOrderByWithRelationInput[]
cursor?: Prisma.BookingWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.BookingScalarFieldEnum | Prisma.BookingScalarFieldEnum[]
}
/**
* Trip without action
*/
+117 -2
View File
@@ -200,6 +200,7 @@ export type TripParticipantWhereInput = {
userId?: Prisma.StringFilter<"TripParticipant"> | string
trip?: Prisma.XOR<Prisma.TripScalarRelationFilter, Prisma.TripWhereInput>
user?: Prisma.XOR<Prisma.UserScalarRelationFilter, Prisma.UserWhereInput>
booking?: Prisma.XOR<Prisma.BookingNullableScalarRelationFilter, Prisma.BookingWhereInput> | null
}
export type TripParticipantOrderByWithRelationInput = {
@@ -212,6 +213,7 @@ export type TripParticipantOrderByWithRelationInput = {
userId?: Prisma.SortOrder
trip?: Prisma.TripOrderByWithRelationInput
user?: Prisma.UserOrderByWithRelationInput
booking?: Prisma.BookingOrderByWithRelationInput
}
export type TripParticipantWhereUniqueInput = Prisma.AtLeast<{
@@ -228,6 +230,7 @@ export type TripParticipantWhereUniqueInput = Prisma.AtLeast<{
userId?: Prisma.StringFilter<"TripParticipant"> | string
trip?: Prisma.XOR<Prisma.TripScalarRelationFilter, Prisma.TripWhereInput>
user?: Prisma.XOR<Prisma.UserScalarRelationFilter, Prisma.UserWhereInput>
booking?: Prisma.XOR<Prisma.BookingNullableScalarRelationFilter, Prisma.BookingWhereInput> | null
}, "id" | "tripId_userId">
export type TripParticipantOrderByWithAggregationInput = {
@@ -264,6 +267,7 @@ export type TripParticipantCreateInput = {
paymentConfirmedAt?: Date | string | null
trip: Prisma.TripCreateNestedOneWithoutParticipantsInput
user: Prisma.UserCreateNestedOneWithoutParticipationsInput
booking?: Prisma.BookingCreateNestedOneWithoutParticipantInput
}
export type TripParticipantUncheckedCreateInput = {
@@ -274,6 +278,7 @@ export type TripParticipantUncheckedCreateInput = {
paymentConfirmedAt?: Date | string | null
tripId: string
userId: string
booking?: Prisma.BookingUncheckedCreateNestedOneWithoutParticipantInput
}
export type TripParticipantUpdateInput = {
@@ -284,6 +289,7 @@ export type TripParticipantUpdateInput = {
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
trip?: Prisma.TripUpdateOneRequiredWithoutParticipantsNestedInput
user?: Prisma.UserUpdateOneRequiredWithoutParticipationsNestedInput
booking?: Prisma.BookingUpdateOneWithoutParticipantNestedInput
}
export type TripParticipantUncheckedUpdateInput = {
@@ -294,6 +300,7 @@ export type TripParticipantUncheckedUpdateInput = {
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
tripId?: Prisma.StringFieldUpdateOperationsInput | string
userId?: Prisma.StringFieldUpdateOperationsInput | string
booking?: Prisma.BookingUncheckedUpdateOneWithoutParticipantNestedInput
}
export type TripParticipantCreateManyInput = {
@@ -369,6 +376,11 @@ export type TripParticipantMinOrderByAggregateInput = {
userId?: Prisma.SortOrder
}
export type TripParticipantScalarRelationFilter = {
is?: Prisma.TripParticipantWhereInput
isNot?: Prisma.TripParticipantWhereInput
}
export type TripParticipantCreateNestedManyWithoutUserInput = {
create?: Prisma.XOR<Prisma.TripParticipantCreateWithoutUserInput, Prisma.TripParticipantUncheckedCreateWithoutUserInput> | Prisma.TripParticipantCreateWithoutUserInput[] | Prisma.TripParticipantUncheckedCreateWithoutUserInput[]
connectOrCreate?: Prisma.TripParticipantCreateOrConnectWithoutUserInput | Prisma.TripParticipantCreateOrConnectWithoutUserInput[]
@@ -457,6 +469,20 @@ export type EnumParticipantStatusFieldUpdateOperationsInput = {
set?: $Enums.ParticipantStatus
}
export type TripParticipantCreateNestedOneWithoutBookingInput = {
create?: Prisma.XOR<Prisma.TripParticipantCreateWithoutBookingInput, Prisma.TripParticipantUncheckedCreateWithoutBookingInput>
connectOrCreate?: Prisma.TripParticipantCreateOrConnectWithoutBookingInput
connect?: Prisma.TripParticipantWhereUniqueInput
}
export type TripParticipantUpdateOneRequiredWithoutBookingNestedInput = {
create?: Prisma.XOR<Prisma.TripParticipantCreateWithoutBookingInput, Prisma.TripParticipantUncheckedCreateWithoutBookingInput>
connectOrCreate?: Prisma.TripParticipantCreateOrConnectWithoutBookingInput
upsert?: Prisma.TripParticipantUpsertWithoutBookingInput
connect?: Prisma.TripParticipantWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.TripParticipantUpdateToOneWithWhereWithoutBookingInput, Prisma.TripParticipantUpdateWithoutBookingInput>, Prisma.TripParticipantUncheckedUpdateWithoutBookingInput>
}
export type TripParticipantCreateWithoutUserInput = {
id?: string
status?: $Enums.ParticipantStatus
@@ -464,6 +490,7 @@ export type TripParticipantCreateWithoutUserInput = {
markedPaidAt?: Date | string | null
paymentConfirmedAt?: Date | string | null
trip: Prisma.TripCreateNestedOneWithoutParticipantsInput
booking?: Prisma.BookingCreateNestedOneWithoutParticipantInput
}
export type TripParticipantUncheckedCreateWithoutUserInput = {
@@ -473,6 +500,7 @@ export type TripParticipantUncheckedCreateWithoutUserInput = {
markedPaidAt?: Date | string | null
paymentConfirmedAt?: Date | string | null
tripId: string
booking?: Prisma.BookingUncheckedCreateNestedOneWithoutParticipantInput
}
export type TripParticipantCreateOrConnectWithoutUserInput = {
@@ -521,6 +549,7 @@ export type TripParticipantCreateWithoutTripInput = {
markedPaidAt?: Date | string | null
paymentConfirmedAt?: Date | string | null
user: Prisma.UserCreateNestedOneWithoutParticipationsInput
booking?: Prisma.BookingCreateNestedOneWithoutParticipantInput
}
export type TripParticipantUncheckedCreateWithoutTripInput = {
@@ -530,6 +559,7 @@ export type TripParticipantUncheckedCreateWithoutTripInput = {
markedPaidAt?: Date | string | null
paymentConfirmedAt?: Date | string | null
userId: string
booking?: Prisma.BookingUncheckedCreateNestedOneWithoutParticipantInput
}
export type TripParticipantCreateOrConnectWithoutTripInput = {
@@ -558,6 +588,62 @@ export type TripParticipantUpdateManyWithWhereWithoutTripInput = {
data: Prisma.XOR<Prisma.TripParticipantUpdateManyMutationInput, Prisma.TripParticipantUncheckedUpdateManyWithoutTripInput>
}
export type TripParticipantCreateWithoutBookingInput = {
id?: string
status?: $Enums.ParticipantStatus
createdAt?: Date | string
markedPaidAt?: Date | string | null
paymentConfirmedAt?: Date | string | null
trip: Prisma.TripCreateNestedOneWithoutParticipantsInput
user: Prisma.UserCreateNestedOneWithoutParticipationsInput
}
export type TripParticipantUncheckedCreateWithoutBookingInput = {
id?: string
status?: $Enums.ParticipantStatus
createdAt?: Date | string
markedPaidAt?: Date | string | null
paymentConfirmedAt?: Date | string | null
tripId: string
userId: string
}
export type TripParticipantCreateOrConnectWithoutBookingInput = {
where: Prisma.TripParticipantWhereUniqueInput
create: Prisma.XOR<Prisma.TripParticipantCreateWithoutBookingInput, Prisma.TripParticipantUncheckedCreateWithoutBookingInput>
}
export type TripParticipantUpsertWithoutBookingInput = {
update: Prisma.XOR<Prisma.TripParticipantUpdateWithoutBookingInput, Prisma.TripParticipantUncheckedUpdateWithoutBookingInput>
create: Prisma.XOR<Prisma.TripParticipantCreateWithoutBookingInput, Prisma.TripParticipantUncheckedCreateWithoutBookingInput>
where?: Prisma.TripParticipantWhereInput
}
export type TripParticipantUpdateToOneWithWhereWithoutBookingInput = {
where?: Prisma.TripParticipantWhereInput
data: Prisma.XOR<Prisma.TripParticipantUpdateWithoutBookingInput, Prisma.TripParticipantUncheckedUpdateWithoutBookingInput>
}
export type TripParticipantUpdateWithoutBookingInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumParticipantStatusFieldUpdateOperationsInput | $Enums.ParticipantStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
markedPaidAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
trip?: Prisma.TripUpdateOneRequiredWithoutParticipantsNestedInput
user?: Prisma.UserUpdateOneRequiredWithoutParticipationsNestedInput
}
export type TripParticipantUncheckedUpdateWithoutBookingInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumParticipantStatusFieldUpdateOperationsInput | $Enums.ParticipantStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
markedPaidAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
tripId?: Prisma.StringFieldUpdateOperationsInput | string
userId?: Prisma.StringFieldUpdateOperationsInput | string
}
export type TripParticipantCreateManyUserInput = {
id?: string
status?: $Enums.ParticipantStatus
@@ -574,6 +660,7 @@ export type TripParticipantUpdateWithoutUserInput = {
markedPaidAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
trip?: Prisma.TripUpdateOneRequiredWithoutParticipantsNestedInput
booking?: Prisma.BookingUpdateOneWithoutParticipantNestedInput
}
export type TripParticipantUncheckedUpdateWithoutUserInput = {
@@ -583,6 +670,7 @@ export type TripParticipantUncheckedUpdateWithoutUserInput = {
markedPaidAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
tripId?: Prisma.StringFieldUpdateOperationsInput | string
booking?: Prisma.BookingUncheckedUpdateOneWithoutParticipantNestedInput
}
export type TripParticipantUncheckedUpdateManyWithoutUserInput = {
@@ -610,6 +698,7 @@ export type TripParticipantUpdateWithoutTripInput = {
markedPaidAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
user?: Prisma.UserUpdateOneRequiredWithoutParticipationsNestedInput
booking?: Prisma.BookingUpdateOneWithoutParticipantNestedInput
}
export type TripParticipantUncheckedUpdateWithoutTripInput = {
@@ -619,6 +708,7 @@ export type TripParticipantUncheckedUpdateWithoutTripInput = {
markedPaidAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
paymentConfirmedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
userId?: Prisma.StringFieldUpdateOperationsInput | string
booking?: Prisma.BookingUncheckedUpdateOneWithoutParticipantNestedInput
}
export type TripParticipantUncheckedUpdateManyWithoutTripInput = {
@@ -642,6 +732,7 @@ export type TripParticipantSelect<ExtArgs extends runtime.Types.Extensions.Inter
userId?: boolean
trip?: boolean | Prisma.TripDefaultArgs<ExtArgs>
user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
booking?: boolean | Prisma.TripParticipant$bookingArgs<ExtArgs>
}, ExtArgs["result"]["tripParticipant"]>
export type TripParticipantSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
@@ -682,6 +773,7 @@ export type TripParticipantOmit<ExtArgs extends runtime.Types.Extensions.Interna
export type TripParticipantInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
trip?: boolean | Prisma.TripDefaultArgs<ExtArgs>
user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
booking?: boolean | Prisma.TripParticipant$bookingArgs<ExtArgs>
}
export type TripParticipantIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
trip?: boolean | Prisma.TripDefaultArgs<ExtArgs>
@@ -697,17 +789,20 @@ export type $TripParticipantPayload<ExtArgs extends runtime.Types.Extensions.Int
objects: {
trip: Prisma.$TripPayload<ExtArgs>
user: Prisma.$UserPayload<ExtArgs>
booking: Prisma.$BookingPayload<ExtArgs> | null
}
scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string
status: $Enums.ParticipantStatus
createdAt: Date
/**
* Peserta menekan "Saya sudah bayar" (pembayaran manual)
* @deprecated — sumber kebenaran pindah ke Booking/Payment. Tetap di-update
* untuk backward-compat selama transisi UI lama. Akan dihapus PR berikutnya.
*/
markedPaidAt: Date | null
/**
* Organizer mengonfirmasi uang sudah masuk
* @deprecated — sumber kebenaran pindah ke Booking/Payment. Tetap di-update
* untuk backward-compat selama transisi UI lama. Akan dihapus PR berikutnya.
*/
paymentConfirmedAt: Date | null
tripId: string
@@ -1108,6 +1203,7 @@ export interface Prisma__TripParticipantClient<T, Null = never, ExtArgs extends
readonly [Symbol.toStringTag]: "PrismaPromise"
trip<T extends Prisma.TripDefaultArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.TripDefaultArgs<ExtArgs>>): Prisma.Prisma__TripClient<runtime.Types.Result.GetResult<Prisma.$TripPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions>
user<T extends Prisma.UserDefaultArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.UserDefaultArgs<ExtArgs>>): Prisma.Prisma__UserClient<runtime.Types.Result.GetResult<Prisma.$UserPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions>
booking<T extends Prisma.TripParticipant$bookingArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.TripParticipant$bookingArgs<ExtArgs>>): Prisma.Prisma__BookingClient<runtime.Types.Result.GetResult<Prisma.$BookingPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
@@ -1544,6 +1640,25 @@ export type TripParticipantDeleteManyArgs<ExtArgs extends runtime.Types.Extensio
limit?: number
}
/**
* TripParticipant.booking
*/
export type TripParticipant$bookingArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the Booking
*/
select?: Prisma.BookingSelect<ExtArgs> | null
/**
* Omit specific fields from the Booking
*/
omit?: Prisma.BookingOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.BookingInclude<ExtArgs> | null
where?: Prisma.BookingWhereInput
}
/**
* TripParticipant without action
*/
+182
View File
@@ -226,6 +226,7 @@ export type UserWhereInput = {
trips?: Prisma.TripListRelationFilter
participations?: Prisma.TripParticipantListRelationFilter
tripReviews?: Prisma.TripReviewListRelationFilter
bookings?: Prisma.BookingListRelationFilter
organizerVerification?: Prisma.XOR<Prisma.OrganizerVerificationNullableScalarRelationFilter, Prisma.OrganizerVerificationWhereInput> | null
reviewedVerifications?: Prisma.OrganizerVerificationListRelationFilter
profile?: Prisma.XOR<Prisma.UserProfileNullableScalarRelationFilter, Prisma.UserProfileWhereInput> | null
@@ -246,6 +247,7 @@ export type UserOrderByWithRelationInput = {
trips?: Prisma.TripOrderByRelationAggregateInput
participations?: Prisma.TripParticipantOrderByRelationAggregateInput
tripReviews?: Prisma.TripReviewOrderByRelationAggregateInput
bookings?: Prisma.BookingOrderByRelationAggregateInput
organizerVerification?: Prisma.OrganizerVerificationOrderByWithRelationInput
reviewedVerifications?: Prisma.OrganizerVerificationOrderByRelationAggregateInput
profile?: Prisma.UserProfileOrderByWithRelationInput
@@ -269,6 +271,7 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{
trips?: Prisma.TripListRelationFilter
participations?: Prisma.TripParticipantListRelationFilter
tripReviews?: Prisma.TripReviewListRelationFilter
bookings?: Prisma.BookingListRelationFilter
organizerVerification?: Prisma.XOR<Prisma.OrganizerVerificationNullableScalarRelationFilter, Prisma.OrganizerVerificationWhereInput> | null
reviewedVerifications?: Prisma.OrganizerVerificationListRelationFilter
profile?: Prisma.XOR<Prisma.UserProfileNullableScalarRelationFilter, Prisma.UserProfileWhereInput> | null
@@ -321,6 +324,7 @@ export type UserCreateInput = {
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
@@ -341,6 +345,7 @@ export type UserUncheckedCreateInput = {
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
@@ -361,6 +366,7 @@ export type UserUpdateInput = {
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
@@ -381,6 +387,7 @@ export type UserUncheckedUpdateInput = {
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
@@ -594,6 +601,20 @@ export type UserUpdateOneRequiredWithoutParticipationsNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutParticipationsInput, Prisma.UserUpdateWithoutParticipationsInput>, Prisma.UserUncheckedUpdateWithoutParticipationsInput>
}
export type UserCreateNestedOneWithoutBookingsInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutBookingsInput, Prisma.UserUncheckedCreateWithoutBookingsInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutBookingsInput
connect?: Prisma.UserWhereUniqueInput
}
export type UserUpdateOneRequiredWithoutBookingsNestedInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutBookingsInput, Prisma.UserUncheckedCreateWithoutBookingsInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutBookingsInput
upsert?: Prisma.UserUpsertWithoutBookingsInput
connect?: Prisma.UserWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutBookingsInput, Prisma.UserUpdateWithoutBookingsInput>, Prisma.UserUncheckedUpdateWithoutBookingsInput>
}
export type UserCreateWithoutProfileInput = {
id?: string
name: string
@@ -609,6 +630,7 @@ export type UserCreateWithoutProfileInput = {
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
}
@@ -628,6 +650,7 @@ export type UserUncheckedCreateWithoutProfileInput = {
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
}
@@ -663,6 +686,7 @@ export type UserUpdateWithoutProfileInput = {
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
}
@@ -682,6 +706,7 @@ export type UserUncheckedUpdateWithoutProfileInput = {
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
}
@@ -700,6 +725,7 @@ export type UserCreateWithoutAccountsInput = {
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
@@ -719,6 +745,7 @@ export type UserUncheckedCreateWithoutAccountsInput = {
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
@@ -754,6 +781,7 @@ export type UserUpdateWithoutAccountsInput = {
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
@@ -773,6 +801,7 @@ export type UserUncheckedUpdateWithoutAccountsInput = {
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
@@ -793,6 +822,7 @@ export type UserCreateWithoutOrganizerVerificationInput = {
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
}
@@ -812,6 +842,7 @@ export type UserUncheckedCreateWithoutOrganizerVerificationInput = {
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
}
@@ -836,6 +867,7 @@ export type UserCreateWithoutReviewedVerificationsInput = {
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
}
@@ -855,6 +887,7 @@ export type UserUncheckedCreateWithoutReviewedVerificationsInput = {
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
}
@@ -890,6 +923,7 @@ export type UserUpdateWithoutOrganizerVerificationInput = {
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
}
@@ -909,6 +943,7 @@ export type UserUncheckedUpdateWithoutOrganizerVerificationInput = {
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
}
@@ -939,6 +974,7 @@ export type UserUpdateWithoutReviewedVerificationsInput = {
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
}
@@ -958,6 +994,7 @@ export type UserUncheckedUpdateWithoutReviewedVerificationsInput = {
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
}
@@ -976,6 +1013,7 @@ export type UserCreateWithoutTripsInput = {
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
@@ -995,6 +1033,7 @@ export type UserUncheckedCreateWithoutTripsInput = {
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
@@ -1030,6 +1069,7 @@ export type UserUpdateWithoutTripsInput = {
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
@@ -1049,6 +1089,7 @@ export type UserUncheckedUpdateWithoutTripsInput = {
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
@@ -1068,6 +1109,7 @@ export type UserCreateWithoutTripReviewsInput = {
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
@@ -1087,6 +1129,7 @@ export type UserUncheckedCreateWithoutTripReviewsInput = {
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
@@ -1122,6 +1165,7 @@ export type UserUpdateWithoutTripReviewsInput = {
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
@@ -1141,6 +1185,7 @@ export type UserUncheckedUpdateWithoutTripReviewsInput = {
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
@@ -1160,6 +1205,7 @@ export type UserCreateWithoutParticipationsInput = {
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
@@ -1179,6 +1225,7 @@ export type UserUncheckedCreateWithoutParticipationsInput = {
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
bookings?: Prisma.BookingUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
@@ -1214,6 +1261,7 @@ export type UserUpdateWithoutParticipationsInput = {
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
@@ -1233,6 +1281,103 @@ export type UserUncheckedUpdateWithoutParticipationsInput = {
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
bookings?: Prisma.BookingUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
}
export type UserCreateWithoutBookingsInput = {
id?: string
name: string
email: string
password?: string | null
image?: string | null
emailVerified?: Date | string | null
acceptedTermsAndPrivacy?: boolean
acceptedAt?: Date | string | null
createdAt?: Date | string
updatedAt?: Date | string
accounts?: Prisma.AccountCreateNestedManyWithoutUserInput
trips?: Prisma.TripCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileCreateNestedOneWithoutUserInput
}
export type UserUncheckedCreateWithoutBookingsInput = {
id?: string
name: string
email: string
password?: string | null
image?: string | null
emailVerified?: Date | string | null
acceptedTermsAndPrivacy?: boolean
acceptedAt?: Date | string | null
createdAt?: Date | string
updatedAt?: Date | string
accounts?: Prisma.AccountUncheckedCreateNestedManyWithoutUserInput
trips?: Prisma.TripUncheckedCreateNestedManyWithoutOrganizerInput
participations?: Prisma.TripParticipantUncheckedCreateNestedManyWithoutUserInput
tripReviews?: Prisma.TripReviewUncheckedCreateNestedManyWithoutUserInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedCreateNestedOneWithoutUserInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedCreateNestedManyWithoutReviewedByInput
profile?: Prisma.UserProfileUncheckedCreateNestedOneWithoutUserInput
}
export type UserCreateOrConnectWithoutBookingsInput = {
where: Prisma.UserWhereUniqueInput
create: Prisma.XOR<Prisma.UserCreateWithoutBookingsInput, Prisma.UserUncheckedCreateWithoutBookingsInput>
}
export type UserUpsertWithoutBookingsInput = {
update: Prisma.XOR<Prisma.UserUpdateWithoutBookingsInput, Prisma.UserUncheckedUpdateWithoutBookingsInput>
create: Prisma.XOR<Prisma.UserCreateWithoutBookingsInput, Prisma.UserUncheckedCreateWithoutBookingsInput>
where?: Prisma.UserWhereInput
}
export type UserUpdateToOneWithWhereWithoutBookingsInput = {
where?: Prisma.UserWhereInput
data: Prisma.XOR<Prisma.UserUpdateWithoutBookingsInput, Prisma.UserUncheckedUpdateWithoutBookingsInput>
}
export type UserUpdateWithoutBookingsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
email?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
acceptedTermsAndPrivacy?: Prisma.BoolFieldUpdateOperationsInput | boolean
acceptedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
accounts?: Prisma.AccountUpdateManyWithoutUserNestedInput
trips?: Prisma.TripUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUpdateOneWithoutUserNestedInput
}
export type UserUncheckedUpdateWithoutBookingsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
email?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
emailVerified?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
acceptedTermsAndPrivacy?: Prisma.BoolFieldUpdateOperationsInput | boolean
acceptedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
accounts?: Prisma.AccountUncheckedUpdateManyWithoutUserNestedInput
trips?: Prisma.TripUncheckedUpdateManyWithoutOrganizerNestedInput
participations?: Prisma.TripParticipantUncheckedUpdateManyWithoutUserNestedInput
tripReviews?: Prisma.TripReviewUncheckedUpdateManyWithoutUserNestedInput
organizerVerification?: Prisma.OrganizerVerificationUncheckedUpdateOneWithoutUserNestedInput
reviewedVerifications?: Prisma.OrganizerVerificationUncheckedUpdateManyWithoutReviewedByNestedInput
profile?: Prisma.UserProfileUncheckedUpdateOneWithoutUserNestedInput
@@ -1248,6 +1393,7 @@ export type UserCountOutputType = {
trips: number
participations: number
tripReviews: number
bookings: number
reviewedVerifications: number
}
@@ -1256,6 +1402,7 @@ export type UserCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.I
trips?: boolean | UserCountOutputTypeCountTripsArgs
participations?: boolean | UserCountOutputTypeCountParticipationsArgs
tripReviews?: boolean | UserCountOutputTypeCountTripReviewsArgs
bookings?: boolean | UserCountOutputTypeCountBookingsArgs
reviewedVerifications?: boolean | UserCountOutputTypeCountReviewedVerificationsArgs
}
@@ -1297,6 +1444,13 @@ export type UserCountOutputTypeCountTripReviewsArgs<ExtArgs extends runtime.Type
where?: Prisma.TripReviewWhereInput
}
/**
* UserCountOutputType without action
*/
export type UserCountOutputTypeCountBookingsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.BookingWhereInput
}
/**
* UserCountOutputType without action
*/
@@ -1320,6 +1474,7 @@ export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = r
trips?: boolean | Prisma.User$tripsArgs<ExtArgs>
participations?: boolean | Prisma.User$participationsArgs<ExtArgs>
tripReviews?: boolean | Prisma.User$tripReviewsArgs<ExtArgs>
bookings?: boolean | Prisma.User$bookingsArgs<ExtArgs>
organizerVerification?: boolean | Prisma.User$organizerVerificationArgs<ExtArgs>
reviewedVerifications?: boolean | Prisma.User$reviewedVerificationsArgs<ExtArgs>
profile?: boolean | Prisma.User$profileArgs<ExtArgs>
@@ -1371,6 +1526,7 @@ export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs =
trips?: boolean | Prisma.User$tripsArgs<ExtArgs>
participations?: boolean | Prisma.User$participationsArgs<ExtArgs>
tripReviews?: boolean | Prisma.User$tripReviewsArgs<ExtArgs>
bookings?: boolean | Prisma.User$bookingsArgs<ExtArgs>
organizerVerification?: boolean | Prisma.User$organizerVerificationArgs<ExtArgs>
reviewedVerifications?: boolean | Prisma.User$reviewedVerificationsArgs<ExtArgs>
profile?: boolean | Prisma.User$profileArgs<ExtArgs>
@@ -1386,6 +1542,7 @@ export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
trips: Prisma.$TripPayload<ExtArgs>[]
participations: Prisma.$TripParticipantPayload<ExtArgs>[]
tripReviews: Prisma.$TripReviewPayload<ExtArgs>[]
bookings: Prisma.$BookingPayload<ExtArgs>[]
organizerVerification: Prisma.$OrganizerVerificationPayload<ExtArgs> | null
reviewedVerifications: Prisma.$OrganizerVerificationPayload<ExtArgs>[]
profile: Prisma.$UserProfilePayload<ExtArgs> | null
@@ -1811,6 +1968,7 @@ export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Typ
trips<T extends Prisma.User$tripsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$tripsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$TripPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
participations<T extends Prisma.User$participationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$participationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$TripParticipantPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
tripReviews<T extends Prisma.User$tripReviewsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$tripReviewsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$TripReviewPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
bookings<T extends Prisma.User$bookingsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$bookingsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$BookingPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
organizerVerification<T extends Prisma.User$organizerVerificationArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$organizerVerificationArgs<ExtArgs>>): Prisma.Prisma__OrganizerVerificationClient<runtime.Types.Result.GetResult<Prisma.$OrganizerVerificationPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
reviewedVerifications<T extends Prisma.User$reviewedVerificationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$reviewedVerificationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$OrganizerVerificationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
profile<T extends Prisma.User$profileArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$profileArgs<ExtArgs>>): Prisma.Prisma__UserProfileClient<runtime.Types.Result.GetResult<Prisma.$UserProfilePayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
@@ -2341,6 +2499,30 @@ export type User$tripReviewsArgs<ExtArgs extends runtime.Types.Extensions.Intern
distinct?: Prisma.TripReviewScalarFieldEnum | Prisma.TripReviewScalarFieldEnum[]
}
/**
* User.bookings
*/
export type User$bookingsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the Booking
*/
select?: Prisma.BookingSelect<ExtArgs> | null
/**
* Omit specific fields from the Booking
*/
omit?: Prisma.BookingOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.BookingInclude<ExtArgs> | null
where?: Prisma.BookingWhereInput
orderBy?: Prisma.BookingOrderByWithRelationInput | Prisma.BookingOrderByWithRelationInput[]
cursor?: Prisma.BookingWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.BookingScalarFieldEnum | Prisma.BookingScalarFieldEnum[]
}
/**
* User.organizerVerification
*/
+13 -11
View File
@@ -5,6 +5,7 @@ import Link from "next/link";
import Image from "next/image";
import { authOptions } from "@/lib/auth";
import { tripService } from "@/server/services/trip.service";
import { bookingService } from "@/server/services/booking.service";
import { trustService } from "@/server/services/trust.service";
import { formatRupiah } from "@/lib/utils";
import { formatTripCalendarDateRangeLong } from "@/lib/trip-dates";
@@ -128,11 +129,13 @@ export default async function TripDetailPage({
: null;
const tripIsFree = isFreeTrip(trip);
const paymentPendingParticipants = tripIsFree
? []
: activeParticipants.filter(
(p) => p.markedPaidAt && !p.paymentConfirmedAt
);
// Antrian konfirmasi pembayaran: source dari Booking + Payment (B9).
// Hanya organizer yang butuh data ini, dan hanya untuk trip berbayar.
const paymentPendingBookings =
!tripIsFree && isOrganizer
? await bookingService.getAwaitingManualForTrip(trip.id)
: [];
const catMeta = categoryMeta(trip.category);
@@ -412,14 +415,13 @@ export default async function TripDetailPage({
/>
)}
{isOrganizer && paymentPendingParticipants.length > 0 && (
{isOrganizer && paymentPendingBookings.length > 0 && (
<OrganizerPaymentQueue
tripId={trip.id}
items={paymentPendingParticipants.map((p) => ({
id: p.id,
user: p.user,
joinStatus:
p.status === "PENDING" ? ("PENDING" as const) : ("CONFIRMED" as const),
items={paymentPendingBookings.map((b) => ({
id: b.participantId,
user: { name: b.user.name, image: b.user.image },
joinStatus: "CONFIRMED" as const,
}))}
/>
)}
+48 -48
View File
@@ -5,6 +5,7 @@ import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { tripService } from "@/server/services/trip.service";
import { organizerService } from "@/server/services/organizer.service";
import { bookingService } from "@/server/services/booking.service";
import { formatRupiah } from "@/lib/utils";
import { formatTripCalendarDateRangeLong } from "@/lib/trip-dates";
import { isFreeTrip } from "@/lib/trip-pricing";
@@ -40,17 +41,18 @@ export default async function PaymentPage({ params }: PageProps) {
redirect(`/trips/${id}`);
}
const myParticipation = trip.participants.find(
(p) => p.userId === session.user.id && p.status !== "CANCELLED"
const booking = await bookingService.getByTripAndUser(
trip.id,
session.user.id
);
if (!myParticipation || myParticipation.status === "CANCELLED") {
return (
<NotJoinedNotice tripId={trip.id} title={trip.title} />
);
if (!booking || booking.status === "CANCELLED") {
return <NotJoinedNotice tripId={trip.id} title={trip.title} />;
}
// Narrowed: status sudah pasti PENDING atau CONFIRMED
const activeStatus: "PENDING" | "CONFIRMED" = myParticipation.status;
const latestManualPayment = booking.payments.find(
(p) => p.provider === "MANUAL"
);
const tripIsFree = isFreeTrip(trip);
const catMeta = categoryMeta(trip.category);
@@ -109,7 +111,7 @@ export default async function PaymentPage({ params }: PageProps) {
{tripIsFree ? (
<FreeTripSection
tripId={trip.id}
participationStatus={activeStatus}
bookingStatus={booking.status}
/>
) : (
<PaidTripSection
@@ -117,9 +119,13 @@ export default async function PaymentPage({ params }: PageProps) {
organizerId={trip.organizerId}
organizerName={trip.organizer.name}
price={trip.price}
participationStatus={activeStatus}
markedPaidAt={myParticipation.markedPaidAt}
paymentConfirmedAt={myParticipation.paymentConfirmedAt}
bookingStatus={booking.status}
paymentMarkedAt={
latestManualPayment?.status === "AWAITING"
? latestManualPayment.updatedAt
: null
}
paymentPaidAt={latestManualPayment?.paidAt ?? null}
/>
)}
</div>
@@ -148,10 +154,10 @@ function NotJoinedNotice({ tripId, title }: { tripId: string; title: string }) {
function FreeTripSection({
tripId,
participationStatus,
bookingStatus,
}: {
tripId: string;
participationStatus: "PENDING" | "CONFIRMED";
bookingStatus: "PENDING" | "AWAITING_PAY" | "PAID" | "CANCELLED" | "REFUNDED" | "EXPIRED";
}) {
return (
<section className="rounded-2xl border border-emerald-200 bg-emerald-50/60 p-6 text-center shadow-sm sm:p-8">
@@ -170,7 +176,7 @@ function FreeTripSection({
Status keikutsertaan
</p>
<p className="text-sm font-bold text-neutral-800">
{participationStatus === "CONFIRMED"
{bookingStatus === "PAID"
? "✅ Terkonfirmasi sebagai peserta"
: "⏳ Menunggu persetujuan organizer"}
</p>
@@ -193,30 +199,33 @@ async function PaidTripSection({
organizerId,
organizerName,
price,
participationStatus,
markedPaidAt,
paymentConfirmedAt,
bookingStatus,
paymentMarkedAt,
paymentPaidAt,
}: {
tripId: string;
organizerId: string;
organizerName: string;
price: number;
participationStatus: "PENDING" | "CONFIRMED";
markedPaidAt: Date | null;
paymentConfirmedAt: Date | null;
bookingStatus: "PENDING" | "AWAITING_PAY" | "PAID" | "CANCELLED" | "REFUNDED" | "EXPIRED";
paymentMarkedAt: Date | null;
paymentPaidAt: Date | null;
}) {
const verification = await organizerService.getStatusForUser(organizerId);
const bankAvailable = verification?.status === "APPROVED";
const canMarkPaid =
participationStatus === "CONFIRMED" && !markedPaidAt && !paymentConfirmedAt;
const showStatusOnly = !!markedPaidAt;
const isApproved = bookingStatus === "AWAITING_PAY" || bookingStatus === "PAID";
const isPendingApproval = bookingStatus === "PENDING";
const hasMarkedPaid = !!paymentMarkedAt || !!paymentPaidAt;
const isFullyPaid = bookingStatus === "PAID";
const canMarkPaid = bookingStatus === "AWAITING_PAY" && !paymentMarkedAt;
return (
<div className="space-y-5">
<PaymentTimeline
participationStatus={participationStatus}
markedPaidAt={markedPaidAt}
paymentConfirmedAt={paymentConfirmedAt}
approved={isApproved}
markedPaid={hasMarkedPaid}
confirmedPaid={isFullyPaid}
/>
{!bankAvailable && (
@@ -277,7 +286,7 @@ async function PaidTripSection({
</section>
)}
{participationStatus === "PENDING" && (
{isPendingApproval && (
<div className="rounded-2xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
Kamu belum disetujui organizer untuk ikut trip ini. Tunggu persetujuan
dulu sebelum transfer supaya tidak perlu refund kalau ditolak.
@@ -288,9 +297,9 @@ async function PaidTripSection({
<MarkPaidButton tripId={tripId} />
)}
{showStatusOnly && (
{hasMarkedPaid && (
<div className="rounded-2xl border border-neutral-200 bg-white p-4 text-sm text-neutral-600 shadow-sm sm:p-5">
{paymentConfirmedAt ? (
{isFullyPaid ? (
<p>
Pembayaran kamu sudah dikonfirmasi oleh{" "}
<span className="font-semibold text-neutral-800">
@@ -320,27 +329,18 @@ async function PaidTripSection({
}
function PaymentTimeline({
participationStatus,
markedPaidAt,
paymentConfirmedAt,
approved,
markedPaid,
confirmedPaid,
}: {
participationStatus: "PENDING" | "CONFIRMED";
markedPaidAt: Date | null;
paymentConfirmedAt: Date | null;
approved: boolean;
markedPaid: boolean;
confirmedPaid: boolean;
}) {
const steps = [
{
label: "Disetujui organizer",
done: participationStatus === "CONFIRMED",
},
{
label: "Kamu menandai sudah bayar",
done: !!markedPaidAt,
},
{
label: "Organizer konfirmasi pembayaran",
done: !!paymentConfirmedAt,
},
{ label: "Disetujui organizer", done: approved },
{ label: "Kamu menandai sudah bayar", done: markedPaid },
{ label: "Organizer konfirmasi pembayaran", done: confirmedPaid },
];
return (
+101
View File
@@ -0,0 +1,101 @@
/**
* Backfill Booking + Payment dari TripParticipant lama.
*
* Idempotent — jalan ulang aman. Skip baris yang sudah punya Booking.
*
* Mapping:
* - participant.status === "CANCELLED" → Booking CANCELLED, no Payment
* - participant.status === "PENDING" → Booking PENDING, no Payment
* - participant.status === "CONFIRMED" + free → Booking PAID, no Payment
* - participant.status === "CONFIRMED" + paid:
* - paymentConfirmedAt set → Booking PAID, Payment PAID (paidAt = paymentConfirmedAt)
* - markedPaidAt set, no confirm → Booking AWAITING_PAY, Payment AWAITING
* - neither → Booking AWAITING_PAY, no Payment
*
* Jalankan: `npx tsx prisma/backfill-bookings.ts`
*/
import { PrismaClient, Prisma } from "../app/generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});
const prisma = new PrismaClient({ adapter });
async function main() {
const participants = await prisma.tripParticipant.findMany({
include: {
trip: { select: { price: true } },
booking: { select: { id: true } },
},
orderBy: { createdAt: "asc" },
});
let createdBookings = 0;
let createdPayments = 0;
let skipped = 0;
for (const p of participants) {
if (p.booking) {
skipped++;
continue;
}
const isFree = p.trip.price <= 0;
let bookingStatus: Prisma.BookingCreateInput["status"];
if (p.status === "CANCELLED") {
bookingStatus = "CANCELLED";
} else if (p.status === "PENDING") {
bookingStatus = "PENDING";
} else if (isFree) {
bookingStatus = "PAID";
} else if (p.paymentConfirmedAt) {
bookingStatus = "PAID";
} else {
bookingStatus = "AWAITING_PAY";
}
const booking = await prisma.booking.create({
data: {
tripId: p.tripId,
userId: p.userId,
participantId: p.id,
amount: p.trip.price,
status: bookingStatus,
},
});
createdBookings++;
// Payment row hanya kalau ada jejak pembayaran manual
if (!isFree && (p.markedPaidAt || p.paymentConfirmedAt)) {
const paymentStatus: Prisma.PaymentCreateInput["status"] =
p.paymentConfirmedAt ? "PAID" : "AWAITING";
await prisma.payment.create({
data: {
bookingId: booking.id,
provider: "MANUAL",
externalOrderId: `manual-${booking.id}`,
amount: p.trip.price,
status: paymentStatus,
method: "manual_transfer",
paidAt: p.paymentConfirmedAt ?? null,
},
});
createdPayments++;
}
}
console.log(
`✅ Backfill selesai. Booking dibuat: ${createdBookings}, Payment dibuat: ${createdPayments}, dilewati (sudah ada): ${skipped}`
);
}
main()
.catch((e) => {
console.error("❌ Backfill gagal:", e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
@@ -0,0 +1,75 @@
-- CreateEnum
CREATE TYPE "BookingStatus" AS ENUM ('PENDING', 'AWAITING_PAY', 'PAID', 'CANCELLED', 'REFUNDED', 'EXPIRED');
-- CreateEnum
CREATE TYPE "PaymentProvider" AS ENUM ('MANUAL', 'MIDTRANS');
-- CreateEnum
CREATE TYPE "PaymentStatus" AS ENUM ('PENDING', 'AWAITING', 'PAID', 'FAILED', 'EXPIRED', 'CANCELLED', 'REFUNDED');
-- CreateTable
CREATE TABLE "Booking" (
"id" TEXT NOT NULL,
"tripId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"participantId" TEXT NOT NULL,
"amount" INTEGER NOT NULL,
"currency" TEXT NOT NULL DEFAULT 'IDR',
"status" "BookingStatus" NOT NULL DEFAULT 'PENDING',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Booking_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Payment" (
"id" TEXT NOT NULL,
"bookingId" TEXT NOT NULL,
"provider" "PaymentProvider" NOT NULL,
"externalOrderId" TEXT NOT NULL,
"externalTxId" TEXT,
"method" TEXT,
"amount" INTEGER NOT NULL,
"status" "PaymentStatus" NOT NULL DEFAULT 'PENDING',
"rawCallback" JSONB,
"snapToken" TEXT,
"expiresAt" TIMESTAMP(3),
"paidAt" TIMESTAMP(3),
"failedAt" TIMESTAMP(3),
"rejectionReason" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Payment_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "Booking_participantId_key" ON "Booking"("participantId");
-- CreateIndex
CREATE INDEX "Booking_tripId_status_idx" ON "Booking"("tripId", "status");
-- CreateIndex
CREATE INDEX "Booking_userId_idx" ON "Booking"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "Payment_externalOrderId_key" ON "Payment"("externalOrderId");
-- CreateIndex
CREATE INDEX "Payment_bookingId_status_idx" ON "Payment"("bookingId", "status");
-- CreateIndex
CREATE INDEX "Payment_provider_status_idx" ON "Payment"("provider", "status");
-- AddForeignKey
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_tripId_fkey" FOREIGN KEY ("tripId") REFERENCES "Trip"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_participantId_fkey" FOREIGN KEY ("participantId") REFERENCES "TripParticipant"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+136 -42
View File
@@ -8,38 +8,39 @@ datasource db {
}
model User {
id String @id @default(cuid())
name String
email String @unique
id String @id @default(cuid())
name String
email String @unique
/// Hash bcrypt. Null untuk user yang sign-in via OAuth (mis. Google).
password String?
image String?
password String?
image String?
/// Diisi PrismaAdapter NextAuth saat email diverifikasi provider OAuth (Google selalu sudah verified).
emailVerified DateTime?
emailVerified DateTime?
/// Apakah user telah menyetujui Syarat & Ketentuan dan Kebijakan Privasi
acceptedTermsAndPrivacy Boolean @default(false)
acceptedTermsAndPrivacy Boolean @default(false)
/// Waktu user menyetujui Syarat & Ketentuan dan Kebijakan Privasi
acceptedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
acceptedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
accounts Account[]
trips Trip[]
participations TripParticipant[]
tripReviews TripReview[]
bookings Booking[]
organizerVerification OrganizerVerification? @relation("OrganizerVerificationOwner")
reviewedVerifications OrganizerVerification[] @relation("OrganizerVerificationReviewer")
organizerVerification OrganizerVerification? @relation("OrganizerVerificationOwner")
reviewedVerifications OrganizerVerification[] @relation("OrganizerVerificationReviewer")
profile UserProfile?
profile UserProfile?
}
/// Profil sosial publik. Berisi info yang user pilih untuk dibagikan ke peserta lain
/// (bio, kota, minat, vibe). Tidak menyimpan data sensitif — KYC tetap di OrganizerVerification.
model UserProfile {
id String @id @default(cuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
id String @id @default(cuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
/// Bio singkat, teks bebas
bio String?
@@ -89,13 +90,13 @@ model OrganizerVerification {
user User @relation("OrganizerVerificationOwner", fields: [userId], references: [id], onDelete: Cascade)
/// Nama lengkap sesuai KTP
fullName String
fullName String
/// NIK terenkripsi (AES-256-GCM, base64). Plaintext tidak disimpan.
nikEncrypted String
/// HMAC-SHA256(NIK + pepper) untuk uniqueness lookup tanpa membuka plaintext.
nikHash String @unique
birthDate DateTime
address String
nikHash String @unique
birthDate DateTime
address String
/// Storage key foto KTP (mis. `ktp/<id>.jpg`). File disimpan terenkripsi di luar /public.
ktpImageKey String
@@ -111,7 +112,7 @@ model OrganizerVerification {
rejectionReason String?
reviewedAt DateTime?
reviewedById String?
reviewedBy User? @relation("OrganizerVerificationReviewer", fields: [reviewedById], references: [id])
reviewedBy User? @relation("OrganizerVerificationReviewer", fields: [reviewedById], references: [id])
verifiedAt DateTime?
createdAt DateTime @default(now())
@@ -125,7 +126,7 @@ enum VerificationStatus {
}
model Trip {
id String @id @default(cuid())
id String @id @default(cuid())
title String
description String?
/// Kategori aktivitas.
@@ -147,16 +148,17 @@ model Trip {
price Int
/// Ritme/energi trip — dipakai untuk matching dengan vibe user.
vibe Vibe?
status TripStatus @default(OPEN)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
status TripStatus @default(OPEN)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizerId String
organizer User @relation(fields: [organizerId], references: [id])
organizer User @relation(fields: [organizerId], references: [id])
participants TripParticipant[]
images TripImage[]
reviews TripReview[]
bookings Booking[]
@@index([category, status, date])
@@index([vibe, status, date])
@@ -170,38 +172,42 @@ model TripReview {
updatedAt DateTime @updatedAt
tripId String
trip Trip @relation(fields: [tripId], references: [id], onDelete: Cascade)
trip Trip @relation(fields: [tripId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([tripId, userId])
}
model TripImage {
id String @id @default(cuid())
url String
caption String?
order Int @default(0)
id String @id @default(cuid())
url String
caption String?
order Int @default(0)
tripId String
trip Trip @relation(fields: [tripId], references: [id], onDelete: Cascade)
trip Trip @relation(fields: [tripId], references: [id], onDelete: Cascade)
}
model TripParticipant {
id String @id @default(cuid())
status ParticipantStatus @default(PENDING)
createdAt DateTime @default(now())
/// Peserta menekan "Saya sudah bayar" (pembayaran manual)
markedPaidAt DateTime?
/// Organizer mengonfirmasi uang sudah masuk
paymentConfirmedAt DateTime?
id String @id @default(cuid())
status ParticipantStatus @default(PENDING)
createdAt DateTime @default(now())
/// @deprecated — sumber kebenaran pindah ke Booking/Payment. Tetap di-update
/// untuk backward-compat selama transisi UI lama. Akan dihapus PR berikutnya.
markedPaidAt DateTime?
/// @deprecated — sumber kebenaran pindah ke Booking/Payment. Tetap di-update
/// untuk backward-compat selama transisi UI lama. Akan dihapus PR berikutnya.
paymentConfirmedAt DateTime?
tripId String
trip Trip @relation(fields: [tripId], references: [id])
trip Trip @relation(fields: [tripId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
user User @relation(fields: [userId], references: [id])
booking Booking?
@@unique([tripId, userId])
}
@@ -231,3 +237,91 @@ enum ParticipantStatus {
CONFIRMED
CANCELLED
}
/// Booking 1-1 ke TripParticipant. Lifecycle ikut peserta:
/// - join → Booking PENDING (menunggu approve organizer)
/// - organizer confirm → AWAITING_PAY (paid trip) atau PAID (free trip)
/// - peserta + organizer rampungkan pembayaran → PAID
/// - cancel/reject → CANCELLED
/// `amount` adalah snapshot harga saat booking dibuat — protect dari perubahan trip.price.
model Booking {
id String @id @default(cuid())
tripId String
trip Trip @relation(fields: [tripId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
participantId String @unique
participant TripParticipant @relation(fields: [participantId], references: [id], onDelete: Cascade)
amount Int
currency String @default("IDR")
status BookingStatus @default(PENDING)
payments Payment[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([tripId, status])
@@index([userId])
}
enum BookingStatus {
PENDING
AWAITING_PAY
PAID
CANCELLED
REFUNDED
EXPIRED
}
/// Satu attempt pembayaran. Satu Booking bisa punya banyak Payment kalau retry
/// (di Phase MIDTRANS nanti). Untuk MANUAL biasanya cukup 1 Payment.
model Payment {
id String @id @default(cuid())
bookingId String
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
provider PaymentProvider
/// order_id eksternal (unik per attempt). Format MANUAL: `manual-<bookingId>`.
/// Format MIDTRANS nanti: `midtrans-<bookingId>-<retry>`.
externalOrderId String @unique
/// transaction_id dari gateway. Kosong untuk MANUAL atau sebelum first callback.
externalTxId String?
/// Metode konkret: bca_va, gopay, qris, manual_transfer, dst.
method String?
amount Int
status PaymentStatus @default(PENDING)
/// Snapshot mentah callback gateway (untuk audit & dispute).
rawCallback Json?
/// Snap token Midtrans / redirect URL.
snapToken String?
/// Kapan attempt ini kadaluarsa (Midtrans default 24 jam).
expiresAt DateTime?
paidAt DateTime?
failedAt DateTime?
rejectionReason String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([bookingId, status])
@@index([provider, status])
}
enum PaymentProvider {
MANUAL
MIDTRANS
}
enum PaymentStatus {
PENDING
AWAITING
PAID
FAILED
EXPIRED
CANCELLED
REFUNDED
}
+74
View File
@@ -0,0 +1,74 @@
import { prisma } from "@/lib/prisma";
import { Prisma } from "@/app/generated/prisma/client";
export const bookingRepo = {
async findById(id: string) {
return prisma.booking.findUnique({ where: { id } });
},
async findByParticipantId(participantId: string) {
return prisma.booking.findUnique({
where: { participantId },
include: { payments: { orderBy: { createdAt: "desc" } } },
});
},
async findByTripAndUser(tripId: string, userId: string) {
return prisma.booking.findFirst({
where: { tripId, userId },
include: { payments: { orderBy: { createdAt: "desc" } } },
});
},
/**
* Daftar booking di trip ini yang masih menunggu konfirmasi pembayaran
* dari organizer (Payment MANUAL status AWAITING).
*/
async findAwaitingManualConfirmation(tripId: string) {
return prisma.booking.findMany({
where: {
tripId,
status: "AWAITING_PAY",
payments: {
some: { provider: "MANUAL", status: "AWAITING" },
},
},
include: {
participant: true,
user: { select: { id: true, name: true, image: true } },
payments: {
where: { provider: "MANUAL", status: "AWAITING" },
orderBy: { createdAt: "desc" },
take: 1,
},
},
orderBy: { updatedAt: "asc" },
});
},
async create(
data: Pick<
Prisma.BookingUncheckedCreateInput,
"tripId" | "userId" | "participantId" | "amount" | "status"
>
) {
return prisma.booking.create({ data });
},
async updateStatus(id: string, status: Prisma.BookingUpdateInput["status"]) {
return prisma.booking.update({
where: { id },
data: { status },
});
},
async updateStatusByParticipantId(
participantId: string,
status: Prisma.BookingUpdateInput["status"]
) {
return prisma.booking.updateMany({
where: { participantId },
data: { status },
});
},
};
+42
View File
@@ -0,0 +1,42 @@
import { prisma } from "@/lib/prisma";
import { Prisma } from "@/app/generated/prisma/client";
export const paymentRepo = {
async findById(id: string) {
return prisma.payment.findUnique({ where: { id } });
},
async findByExternalOrderId(externalOrderId: string) {
return prisma.payment.findUnique({ where: { externalOrderId } });
},
async findActiveManualForBooking(bookingId: string) {
return prisma.payment.findFirst({
where: {
bookingId,
provider: "MANUAL",
status: { in: ["PENDING", "AWAITING"] },
},
orderBy: { createdAt: "desc" },
});
},
async create(
data: Pick<
Prisma.PaymentUncheckedCreateInput,
| "bookingId"
| "provider"
| "externalOrderId"
| "amount"
| "status"
| "method"
| "expiresAt"
>
) {
return prisma.payment.create({ data });
},
async update(id: string, data: Prisma.PaymentUpdateInput) {
return prisma.payment.update({ where: { id }, data });
},
};
+216
View File
@@ -0,0 +1,216 @@
import { Prisma } from "@/app/generated/prisma/client";
import { prisma } from "@/lib/prisma";
import { bookingRepo } from "@/server/repositories/booking.repo";
import { paymentRepo } from "@/server/repositories/payment.repo";
const SERIAL_TX_ATTEMPTS = 6;
function isSerializationConflict(err: unknown): boolean {
return (
typeof err === "object" &&
err !== null &&
"code" in err &&
(err as { code: string }).code === "P2034"
);
}
function manualOrderId(bookingId: string): string {
return `manual-${bookingId}`;
}
export const bookingService = {
async getByParticipantId(participantId: string) {
return bookingRepo.findByParticipantId(participantId);
},
async getByTripAndUser(tripId: string, userId: string) {
return bookingRepo.findByTripAndUser(tripId, userId);
},
/**
* Peserta tandai sudah transfer manual. Idempotent: kalau sudah ada Payment
* MANUAL aktif, biarkan; kalau Booking sudah PAID, tolak.
*/
async markPaidManual(bookingId: string, userId: string) {
let lastErr: unknown;
for (let attempt = 0; attempt < SERIAL_TX_ATTEMPTS; attempt++) {
try {
return await prisma.$transaction(
async (tx) => {
const booking = await tx.booking.findUnique({
where: { id: bookingId },
include: { trip: { select: { price: true } } },
});
if (!booking) {
throw new Error("Booking tidak ditemukan");
}
if (booking.userId !== userId) {
throw new Error("Booking ini bukan milikmu");
}
if (booking.amount <= 0) {
throw new Error(
"Booking ini tidak butuh pembayaran (gratis)"
);
}
if (booking.status === "PAID") {
throw new Error("Pembayaran sudah dikonfirmasi");
}
if (booking.status !== "AWAITING_PAY") {
throw new Error(
"Booking belum siap menerima pembayaran (tunggu approve organizer)"
);
}
const existing = await tx.payment.findFirst({
where: {
bookingId,
provider: "MANUAL",
status: { in: ["PENDING", "AWAITING"] },
},
orderBy: { createdAt: "desc" },
});
if (existing && existing.status === "AWAITING") {
return existing;
}
const payment = existing
? await tx.payment.update({
where: { id: existing.id },
data: { status: "AWAITING" },
})
: await tx.payment.create({
data: {
bookingId,
provider: "MANUAL",
externalOrderId: manualOrderId(bookingId),
amount: booking.amount,
status: "AWAITING",
},
});
// Backward-compat: tetap update timestamp di TripParticipant
// selama UI lama masih membaca kolom ini.
await tx.tripParticipant.update({
where: { id: booking.participantId },
data: { markedPaidAt: new Date() },
});
return payment;
},
{
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
maxWait: 5000,
timeout: 15000,
}
);
} catch (e) {
lastErr = e;
if (isSerializationConflict(e) && attempt < SERIAL_TX_ATTEMPTS - 1) {
continue;
}
throw e;
}
}
throw lastErr instanceof Error
? lastErr
: new Error("Gagal menandai pembayaran. Coba lagi sebentar.");
},
/**
* Organizer konfirmasi pembayaran manual masuk.
* Idempotent: kalau sudah PAID, tolak (UI lama bisa muncul tombol dua kali).
*/
async confirmPaidManual(bookingId: string, organizerId: string) {
let lastErr: unknown;
for (let attempt = 0; attempt < SERIAL_TX_ATTEMPTS; attempt++) {
try {
return await prisma.$transaction(
async (tx) => {
const booking = await tx.booking.findUnique({
where: { id: bookingId },
include: { trip: { select: { organizerId: true, price: true } } },
});
if (!booking) {
throw new Error("Booking tidak ditemukan");
}
if (booking.trip.organizerId !== organizerId) {
throw new Error(
"Hanya organizer trip ini yang bisa mengonfirmasi pembayaran"
);
}
if (booking.amount <= 0) {
throw new Error(
"Booking ini gratis — tidak ada pembayaran yang perlu dikonfirmasi"
);
}
if (booking.status === "PAID") {
throw new Error("Pembayaran sudah dikonfirmasi sebelumnya");
}
const awaitingPayment = await tx.payment.findFirst({
where: {
bookingId,
provider: "MANUAL",
status: "AWAITING",
},
orderBy: { createdAt: "desc" },
});
if (!awaitingPayment) {
throw new Error(
"Peserta belum menandai sudah membayar"
);
}
const now = new Date();
await tx.payment.update({
where: { id: awaitingPayment.id },
data: {
status: "PAID",
paidAt: now,
method: "manual_transfer",
},
});
await tx.booking.update({
where: { id: bookingId },
data: { status: "PAID" },
});
// Backward-compat: tetap update timestamp di TripParticipant.
await tx.tripParticipant.update({
where: { id: booking.participantId },
data: { paymentConfirmedAt: now },
});
return { ok: true as const };
},
{
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
maxWait: 5000,
timeout: 15000,
}
);
} catch (e) {
lastErr = e;
if (isSerializationConflict(e) && attempt < SERIAL_TX_ATTEMPTS - 1) {
continue;
}
throw e;
}
}
throw lastErr instanceof Error
? lastErr
: new Error("Gagal mengonfirmasi pembayaran. Coba lagi sebentar.");
},
/**
* Daftar booking yang masih menunggu konfirmasi organizer di trip tertentu.
* Dipakai OrganizerPaymentQueue.
*/
async getAwaitingManualForTrip(tripId: string) {
return bookingRepo.findAwaitingManualConfirmation(tripId);
},
};
+68 -59
View File
@@ -3,6 +3,8 @@ import type { ActivityCategory, Vibe } from "@/app/generated/prisma/enums";
import { prisma } from "@/lib/prisma";
import { tripRepo, type TripFilters } from "@/server/repositories/trip.repo";
import { participantRepo } from "@/server/repositories/participant.repo";
import { bookingRepo } from "@/server/repositories/booking.repo";
import { bookingService } from "@/server/services/booking.service";
import { LIMITS } from "@/lib/limits";
import { utcStartOfDay, isTripDepartureDayPast } from "@/lib/trip-dates";
import { isFreeTrip } from "@/lib/trip-pricing";
@@ -140,6 +142,7 @@ export const tripService = {
date: true,
organizerId: true,
maxParticipants: true,
price: true,
},
});
@@ -186,6 +189,22 @@ export const tripService = {
data: { tripId, userId, status: "PENDING" },
});
// Booking 1-1 ke participant. Upsert untuk handle re-join setelah CANCELLED.
await tx.booking.upsert({
where: { participantId: participant.id },
create: {
tripId,
userId,
participantId: participant.id,
amount: trip.price,
status: "PENDING",
},
update: {
status: "PENDING",
amount: trip.price,
},
});
const newCount = await tx.tripParticipant.count({
where: { tripId, status: { not: "CANCELLED" } },
});
@@ -234,7 +253,21 @@ export const tripService = {
throw new Error("Kamu tidak terdaftar di trip ini");
}
const result = await participantRepo.cancel(tripId, userId);
const result = await prisma.$transaction(async (tx) => {
const cancelled = await tx.tripParticipant.update({
where: { tripId_userId: { tripId, userId } },
data: {
status: "CANCELLED",
markedPaidAt: null,
paymentConfirmedAt: null,
},
});
await tx.booking.updateMany({
where: { participantId: existing.id },
data: { status: "CANCELLED" },
});
return cancelled;
});
if (trip.status === "FULL") {
const count = await participantRepo.countByTrip(tripId);
@@ -267,7 +300,19 @@ export const tripService = {
throw new Error("Peserta ini tidak dalam status menunggu persetujuan");
}
return participantRepo.setStatus(participantId, "CONFIRMED");
// Trip gratis: Booking langsung PAID. Trip berbayar: AWAITING_PAY (tinggal bayar).
const nextBookingStatus = isFreeTrip(trip) ? "PAID" : "AWAITING_PAY";
return prisma.$transaction(async (tx) => {
await tx.booking.updateMany({
where: { participantId },
data: { status: nextBookingStatus },
});
return tx.tripParticipant.update({
where: { id: participantId },
data: { status: "CONFIRMED" },
});
});
},
async rejectParticipant(
@@ -291,10 +336,20 @@ export const tripService = {
throw new Error("Hanya permintaan yang masih menunggu yang bisa ditolak");
}
await participantRepo.setStatusAndClearPayment(
participantId,
"CANCELLED"
);
await prisma.$transaction(async (tx) => {
await tx.tripParticipant.update({
where: { id: participantId },
data: {
status: "CANCELLED",
markedPaidAt: null,
paymentConfirmedAt: null,
},
});
await tx.booking.updateMany({
where: { participantId },
data: { status: "CANCELLED" },
});
});
if (trip.status === "FULL") {
const count = await participantRepo.countByTrip(tripId);
@@ -322,40 +377,12 @@ export const tripService = {
throw new Error("Trip sudah lewat — pembayaran tidak perlu ditandai");
}
const p = await participantRepo.findByTripAndUser(tripId, userId);
if (!p || p.status === "CANCELLED") {
const booking = await bookingRepo.findByTripAndUser(tripId, userId);
if (!booking || booking.status === "CANCELLED") {
throw new Error("Kamu tidak terdaftar di trip ini");
}
if (p.paymentConfirmedAt) {
throw new Error("Pembayaran kamu sudah dikonfirmasi organizer");
}
if (p.markedPaidAt) {
throw new Error("Kamu sudah menandai sudah bayar — tunggu konfirmasi organizer");
}
const updated = await participantRepo.tryMarkPaidByUser(tripId, userId);
if (updated.count === 0) {
const again = await participantRepo.findByTripAndUser(tripId, userId);
if (!again || again.status === "CANCELLED") {
throw new Error("Kamu tidak terdaftar di trip ini");
}
if (again.paymentConfirmedAt) {
throw new Error("Pembayaran kamu sudah dikonfirmasi organizer");
}
if (again.markedPaidAt) {
throw new Error(
"Kamu sudah menandai sudah bayar — tunggu konfirmasi organizer"
);
}
throw new Error("Tidak bisa menandai pembayaran. Coba lagi sebentar.");
}
const row = await participantRepo.findByTripAndUser(tripId, userId);
if (!row) {
throw new Error("Data peserta tidak ditemukan setelah update");
}
return row;
return bookingService.markPaidManual(booking.id, userId);
},
async confirmParticipantPayment(
@@ -374,29 +401,11 @@ export const tripService = {
throw new Error("Trip ini gratis — tidak ada pembayaran yang perlu dikonfirmasi");
}
const participant = await participantRepo.findById(participantId);
if (!participant || participant.tripId !== tripId) {
throw new Error("Peserta tidak ditemukan");
}
if (participant.status === "CANCELLED") {
throw new Error("Peserta sudah tidak aktif");
}
if (!participant.markedPaidAt) {
throw new Error("Peserta belum menandai sudah membayar");
}
if (participant.paymentConfirmedAt) {
throw new Error("Pembayaran peserta ini sudah dikonfirmasi");
const booking = await bookingRepo.findByParticipantId(participantId);
if (!booking || booking.tripId !== tripId) {
throw new Error("Booking tidak ditemukan");
}
const updated = await participantRepo.tryConfirmPaymentByOrganizer(
participantId
);
if (updated.count === 0) {
throw new Error(
"Konfirmasi tidak diproses — mungkin sudah dikonfirmasi atau pembayaran belum ditandai peserta."
);
}
return participantRepo.findById(participantId);
return bookingService.confirmPaidManual(booking.id, organizerId);
},
};