diff --git a/apps/backend/prisma/auth.prisma b/apps/backend/prisma/auth.prisma index 56c93c9..3c8bfe7 100644 --- a/apps/backend/prisma/auth.prisma +++ b/apps/backend/prisma/auth.prisma @@ -5,6 +5,9 @@ model User { emailVerified Boolean @default(false) image String? phone String? + banned Boolean @default(false) + bannedAt DateTime? + banReason String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt sessions Session[] diff --git a/apps/backend/prisma/court.prisma b/apps/backend/prisma/court.prisma index c973dc9..4dbe350 100644 --- a/apps/backend/prisma/court.prisma +++ b/apps/backend/prisma/court.prisma @@ -34,6 +34,8 @@ model Court { name String slotDurationMinutes Int @map("slot_duration_minutes") basePrice Decimal @map("base_price") @db.Decimal(19, 2) + isUnderMaintenance Boolean @default(false) @map("is_under_maintenance") + maintenanceReason String? @map("maintenance_reason") @db.VarChar(500) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade) @@ -41,12 +43,28 @@ model Court { availabilities CourtAvailability[] priceRules CourtPriceRule[] bookings CourtBooking[] + maintenances CourtMaintenance[] @@index([complexId]) @@index([sportId]) @@map("courts") } +model CourtMaintenance { + id String @id @db.Uuid + courtId String @map("court_id") @db.Uuid + startDate DateTime @map("start_date") @db.Date + startTime String? @map("start_time") @db.VarChar(5) + endTime String? @map("end_time") @db.VarChar(5) + reason String? @db.VarChar(500) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + court Court @relation(fields: [courtId], references: [id], onDelete: Cascade) + + @@index([courtId, startDate]) + @@map("court_maintenances") +} + model CourtAvailability { id String @id @db.Uuid courtId String @map("court_id") @db.Uuid diff --git a/apps/backend/prisma/migrations/20260608180226_maintenance_mode/migration.sql b/apps/backend/prisma/migrations/20260608180226_maintenance_mode/migration.sql new file mode 100644 index 0000000..adfb718 --- /dev/null +++ b/apps/backend/prisma/migrations/20260608180226_maintenance_mode/migration.sql @@ -0,0 +1,23 @@ +-- CreateTable +CREATE TABLE "court_maintenances" ( + "id" UUID NOT NULL, + "court_id" UUID NOT NULL, + "start_date" DATE NOT NULL, + "start_time" VARCHAR(5), + "end_time" VARCHAR(5), + "reason" VARCHAR(500), + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "court_maintenances_pkey" PRIMARY KEY ("id") +); + +-- AlterTable +ALTER TABLE "courts" ADD COLUMN "is_under_maintenance" BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE "courts" ADD COLUMN "maintenance_reason" VARCHAR(500); + +-- CreateIndex +CREATE INDEX "court_maintenances_court_id_start_date_idx" ON "court_maintenances"("court_id", "start_date"); + +-- AddForeignKey +ALTER TABLE "court_maintenances" ADD CONSTRAINT "court_maintenances_court_id_fkey" FOREIGN KEY ("court_id") REFERENCES "courts"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/backend/prisma/migrations/20260609221056_add_user_banned_fields/migration.sql b/apps/backend/prisma/migrations/20260609221056_add_user_banned_fields/migration.sql new file mode 100644 index 0000000..316a507 --- /dev/null +++ b/apps/backend/prisma/migrations/20260609221056_add_user_banned_fields/migration.sql @@ -0,0 +1,4 @@ +-- AlterTable +ALTER TABLE "users" ADD COLUMN "banReason" TEXT, +ADD COLUMN "banned" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "bannedAt" TIMESTAMP(3); diff --git a/apps/backend/src/generated/prisma/browser.ts b/apps/backend/src/generated/prisma/browser.ts index 57c9172..5e1069b 100644 --- a/apps/backend/src/generated/prisma/browser.ts +++ b/apps/backend/src/generated/prisma/browser.ts @@ -62,6 +62,11 @@ export type Sport = Prisma.SportModel * */ export type Court = Prisma.CourtModel +/** + * Model CourtMaintenance + * + */ +export type CourtMaintenance = Prisma.CourtMaintenanceModel /** * Model CourtAvailability * diff --git a/apps/backend/src/generated/prisma/client.ts b/apps/backend/src/generated/prisma/client.ts index c5e75b2..8577f9a 100644 --- a/apps/backend/src/generated/prisma/client.ts +++ b/apps/backend/src/generated/prisma/client.ts @@ -86,6 +86,11 @@ export type Sport = Prisma.SportModel * */ export type Court = Prisma.CourtModel +/** + * Model CourtMaintenance + * + */ +export type CourtMaintenance = Prisma.CourtMaintenanceModel /** * Model CourtAvailability * diff --git a/apps/backend/src/generated/prisma/commonInputTypes.ts b/apps/backend/src/generated/prisma/commonInputTypes.ts index 6787d9c..8a9fe7a 100644 --- a/apps/backend/src/generated/prisma/commonInputTypes.ts +++ b/apps/backend/src/generated/prisma/commonInputTypes.ts @@ -49,6 +49,17 @@ export type StringNullableFilter<$PrismaModel = never> = { not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null } +export type DateTimeNullableFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null +} + export type DateTimeFilter<$PrismaModel = never> = { equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> @@ -109,31 +120,6 @@ export type StringNullableWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedStringNullableFilter<$PrismaModel> } -export type DateTimeWithAggregatesFilter<$PrismaModel = never> = { - equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> - notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> - lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string - _count?: Prisma.NestedIntFilter<$PrismaModel> - _min?: Prisma.NestedDateTimeFilter<$PrismaModel> - _max?: Prisma.NestedDateTimeFilter<$PrismaModel> -} - -export type DateTimeNullableFilter<$PrismaModel = never> = { - equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null - in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null - notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null - lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null -} - export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null @@ -148,6 +134,20 @@ export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> } +export type DateTimeWithAggregatesFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedDateTimeFilter<$PrismaModel> + _max?: Prisma.NestedDateTimeFilter<$PrismaModel> +} + export type UuidFilter<$PrismaModel = never> = { equals?: string | Prisma.StringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> @@ -381,6 +381,17 @@ export type NestedStringNullableFilter<$PrismaModel = never> = { not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null } +export type NestedDateTimeNullableFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null +} + export type NestedDateTimeFilter<$PrismaModel = never> = { equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> @@ -456,31 +467,6 @@ export type NestedIntNullableFilter<$PrismaModel = never> = { not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null } -export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = { - equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> - notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> - lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string - _count?: Prisma.NestedIntFilter<$PrismaModel> - _min?: Prisma.NestedDateTimeFilter<$PrismaModel> - _max?: Prisma.NestedDateTimeFilter<$PrismaModel> -} - -export type NestedDateTimeNullableFilter<$PrismaModel = never> = { - equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null - in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null - notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null - lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> - not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null -} - export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null @@ -495,6 +481,20 @@ export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> } +export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = { + equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> + lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> + not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedDateTimeFilter<$PrismaModel> + _max?: Prisma.NestedDateTimeFilter<$PrismaModel> +} + export type NestedUuidFilter<$PrismaModel = never> = { equals?: string | Prisma.StringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> diff --git a/apps/backend/src/generated/prisma/internal/class.ts b/apps/backend/src/generated/prisma/internal/class.ts index 2bc22be..9a4bc7c 100644 --- a/apps/backend/src/generated/prisma/internal/class.ts +++ b/apps/backend/src/generated/prisma/internal/class.ts @@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = { "clientVersion": "7.6.0", "engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711", "activeProvider": "postgresql", - "inlineSchema": "model User {\n id String @id\n name String\n email String\n emailVerified Boolean @default(false)\n image String?\n phone String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n sessions Session[]\n accounts Account[]\n role String @default(\"member\")\n complexes ComplexUser[]\n\n @@unique([email])\n @@map(\"users\")\n}\n\nmodel Session {\n id String @id\n expiresAt DateTime\n token String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n ipAddress String?\n userAgent String?\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@unique([token])\n @@index([userId])\n @@map(\"sessions\")\n}\n\nmodel Account {\n id String @id\n accountId String\n providerId String\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n accessToken String?\n refreshToken String?\n idToken String?\n accessTokenExpiresAt DateTime?\n refreshTokenExpiresAt DateTime?\n scope String?\n password String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@map(\"accounts\")\n}\n\nmodel Verification {\n id String @id\n identifier String\n value String\n expiresAt DateTime\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([identifier])\n @@map(\"verification\")\n}\n\nmodel Complex {\n id String @id @db.Uuid\n complexName String @map(\"complex_name\")\n physicalAddress String? @map(\"physical_address\") @db.VarChar(200)\n city String? @map(\"city\") @db.VarChar(100)\n state String? @map(\"state\") @db.VarChar(100)\n country String? @map(\"country\") @db.VarChar(100)\n complexSlug String @unique @map(\"complex_slug\")\n adminEmail String @map(\"admin_email\")\n planCode String? @map(\"plan_code\") @db.VarChar(10)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n plan Plan? @relation(fields: [planCode], references: [code])\n users ComplexUser[]\n invitations ComplexInvitation[]\n courts Court[]\n\n @@index([planCode])\n @@index([complexSlug])\n @@map(\"complexes\")\n}\n\nenum ComplexUserRole {\n ADMIN\n EMPLOYEE\n}\n\nmodel ComplexUser {\n complexId String @map(\"complex_id\") @db.Uuid\n userId String @map(\"user_id\")\n role ComplexUserRole @default(ADMIN)\n createdAt DateTime @default(now()) @map(\"created_at\")\n complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([complexId, userId])\n @@index([userId])\n @@map(\"complex_users\")\n}\n\nmodel ComplexInvitation {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n email String @db.VarChar(255)\n tokenHash String @unique @map(\"token_hash\")\n expiresAt DateTime @map(\"expires_at\")\n acceptedAt DateTime? @map(\"accepted_at\")\n revokedAt DateTime? @map(\"revoked_at\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n\n @@index([complexId, email])\n @@index([email])\n @@map(\"complex_invitations\")\n}\n\nenum DayOfWeek {\n MONDAY\n TUESDAY\n WEDNESDAY\n THURSDAY\n FRIDAY\n SATURDAY\n SUNDAY\n}\n\nenum CourtBookingStatus {\n CONFIRMED\n CANCELLED\n COMPLETED\n NOSHOW\n}\n\nmodel Sport {\n id String @id @db.Uuid\n name String @unique\n slug String @unique\n isActive Boolean @default(true) @map(\"is_active\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n courts Court[]\n\n @@map(\"sports\")\n}\n\nmodel Court {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n sportId String @map(\"sport_id\") @db.Uuid\n name String\n slotDurationMinutes Int @map(\"slot_duration_minutes\")\n basePrice Decimal @map(\"base_price\") @db.Decimal(19, 2)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n sport Sport @relation(fields: [sportId], references: [id])\n availabilities CourtAvailability[]\n priceRules CourtPriceRule[]\n bookings CourtBooking[]\n\n @@index([complexId])\n @@index([sportId])\n @@map(\"courts\")\n}\n\nmodel CourtAvailability {\n id String @id @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n dayOfWeek DayOfWeek @map(\"day_of_week\")\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n createdAt DateTime @default(now()) @map(\"created_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@index([courtId, dayOfWeek])\n @@map(\"court_availabilities\")\n}\n\nmodel CourtPriceRule {\n id String @id @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n dayOfWeek DayOfWeek? @map(\"day_of_week\")\n startTime String? @map(\"start_time\") @db.VarChar(5)\n endTime String? @map(\"end_time\") @db.VarChar(5)\n price Decimal @db.Decimal(19, 2)\n isActive Boolean @default(true) @map(\"is_active\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@index([courtId, isActive])\n @@map(\"court_price_rules\")\n}\n\nmodel CourtBooking {\n id String @id @db.Uuid\n bookingCode String @unique @map(\"booking_code\") @db.VarChar(8)\n courtId String @map(\"court_id\") @db.Uuid\n bookingDate DateTime @map(\"booking_date\") @db.Date\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n customerName String @map(\"customer_name\") @db.VarChar(120)\n customerPhone String @map(\"customer_phone\") @db.VarChar(30)\n customerEmail String @map(\"customer_email\") @db.VarChar(254)\n status CourtBookingStatus @default(CONFIRMED)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@unique([courtId, bookingDate, startTime])\n @@index([courtId, bookingDate])\n @@index([bookingDate])\n @@map(\"court_bookings\")\n}\n\nmodel CourtBookingLog {\n id String @id @db.Uuid\n bookingCode String @map(\"booking_code\") @db.VarChar(8)\n courtId String @map(\"court_id\") @db.Uuid\n bookingDate DateTime @map(\"booking_date\") @db.Date\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n previousStatus CourtBookingStatus @map(\"previous_status\")\n newStatus CourtBookingStatus @map(\"new_status\")\n customerName String @map(\"customer_name\") @db.VarChar(120)\n customerPhone String @map(\"customer_phone\") @db.VarChar(30)\n customerEmail String @map(\"customer_email\") @db.VarChar(254)\n changedAt DateTime @default(now()) @map(\"changed_at\")\n\n @@index([courtId, newStatus])\n @@map(\"court_booking_logs\")\n}\n\nmodel PasswordResetRequest {\n id String @id @db.Uuid\n email String\n otpHash String @map(\"otp_hash\")\n otpExpiresAt DateTime @map(\"otp_expires_at\")\n otpAttempts Int @default(0) @map(\"otp_attempts\")\n otpLastSentAt DateTime @map(\"otp_last_sent_at\")\n otpResendCount Int @default(0) @map(\"otp_resend_count\")\n usedAt DateTime? @map(\"used_at\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n @@index([email])\n @@index([otpExpiresAt])\n @@map(\"password_reset_requests\")\n}\n\nmodel Plan {\n code String @id @db.VarChar(10)\n name String @db.VarChar(30)\n price Decimal @db.Decimal(19, 2)\n rules Json\n lastUpdatedAt DateTime @default(now()) @map(\"last_updated_at\")\n complexes Complex[]\n\n @@map(\"plans\")\n}\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\n// User model is defined in auth.prisma (Better Auth schema).\n", + "inlineSchema": "model User {\n id String @id\n name String\n email String\n emailVerified Boolean @default(false)\n image String?\n phone String?\n banned Boolean @default(false)\n bannedAt DateTime?\n banReason String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n sessions Session[]\n accounts Account[]\n role String @default(\"member\")\n complexes ComplexUser[]\n\n @@unique([email])\n @@map(\"users\")\n}\n\nmodel Session {\n id String @id\n expiresAt DateTime\n token String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n ipAddress String?\n userAgent String?\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@unique([token])\n @@index([userId])\n @@map(\"sessions\")\n}\n\nmodel Account {\n id String @id\n accountId String\n providerId String\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n accessToken String?\n refreshToken String?\n idToken String?\n accessTokenExpiresAt DateTime?\n refreshTokenExpiresAt DateTime?\n scope String?\n password String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@map(\"accounts\")\n}\n\nmodel Verification {\n id String @id\n identifier String\n value String\n expiresAt DateTime\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([identifier])\n @@map(\"verification\")\n}\n\nmodel Complex {\n id String @id @db.Uuid\n complexName String @map(\"complex_name\")\n physicalAddress String? @map(\"physical_address\") @db.VarChar(200)\n city String? @map(\"city\") @db.VarChar(100)\n state String? @map(\"state\") @db.VarChar(100)\n country String? @map(\"country\") @db.VarChar(100)\n complexSlug String @unique @map(\"complex_slug\")\n adminEmail String @map(\"admin_email\")\n planCode String? @map(\"plan_code\") @db.VarChar(10)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n plan Plan? @relation(fields: [planCode], references: [code])\n users ComplexUser[]\n invitations ComplexInvitation[]\n courts Court[]\n\n @@index([planCode])\n @@index([complexSlug])\n @@map(\"complexes\")\n}\n\nenum ComplexUserRole {\n ADMIN\n EMPLOYEE\n}\n\nmodel ComplexUser {\n complexId String @map(\"complex_id\") @db.Uuid\n userId String @map(\"user_id\")\n role ComplexUserRole @default(ADMIN)\n createdAt DateTime @default(now()) @map(\"created_at\")\n complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([complexId, userId])\n @@index([userId])\n @@map(\"complex_users\")\n}\n\nmodel ComplexInvitation {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n email String @db.VarChar(255)\n tokenHash String @unique @map(\"token_hash\")\n expiresAt DateTime @map(\"expires_at\")\n acceptedAt DateTime? @map(\"accepted_at\")\n revokedAt DateTime? @map(\"revoked_at\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n\n @@index([complexId, email])\n @@index([email])\n @@map(\"complex_invitations\")\n}\n\nenum DayOfWeek {\n MONDAY\n TUESDAY\n WEDNESDAY\n THURSDAY\n FRIDAY\n SATURDAY\n SUNDAY\n}\n\nenum CourtBookingStatus {\n CONFIRMED\n CANCELLED\n COMPLETED\n NOSHOW\n}\n\nmodel Sport {\n id String @id @db.Uuid\n name String @unique\n slug String @unique\n isActive Boolean @default(true) @map(\"is_active\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n courts Court[]\n\n @@map(\"sports\")\n}\n\nmodel Court {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n sportId String @map(\"sport_id\") @db.Uuid\n name String\n slotDurationMinutes Int @map(\"slot_duration_minutes\")\n basePrice Decimal @map(\"base_price\") @db.Decimal(19, 2)\n isUnderMaintenance Boolean @default(false) @map(\"is_under_maintenance\")\n maintenanceReason String? @map(\"maintenance_reason\") @db.VarChar(500)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n sport Sport @relation(fields: [sportId], references: [id])\n availabilities CourtAvailability[]\n priceRules CourtPriceRule[]\n bookings CourtBooking[]\n maintenances CourtMaintenance[]\n\n @@index([complexId])\n @@index([sportId])\n @@map(\"courts\")\n}\n\nmodel CourtMaintenance {\n id String @id @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n startDate DateTime @map(\"start_date\") @db.Date\n startTime String? @map(\"start_time\") @db.VarChar(5)\n endTime String? @map(\"end_time\") @db.VarChar(5)\n reason String? @db.VarChar(500)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@index([courtId, startDate])\n @@map(\"court_maintenances\")\n}\n\nmodel CourtAvailability {\n id String @id @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n dayOfWeek DayOfWeek @map(\"day_of_week\")\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n createdAt DateTime @default(now()) @map(\"created_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@index([courtId, dayOfWeek])\n @@map(\"court_availabilities\")\n}\n\nmodel CourtPriceRule {\n id String @id @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n dayOfWeek DayOfWeek? @map(\"day_of_week\")\n startTime String? @map(\"start_time\") @db.VarChar(5)\n endTime String? @map(\"end_time\") @db.VarChar(5)\n price Decimal @db.Decimal(19, 2)\n isActive Boolean @default(true) @map(\"is_active\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@index([courtId, isActive])\n @@map(\"court_price_rules\")\n}\n\nmodel CourtBooking {\n id String @id @db.Uuid\n bookingCode String @unique @map(\"booking_code\") @db.VarChar(8)\n courtId String @map(\"court_id\") @db.Uuid\n bookingDate DateTime @map(\"booking_date\") @db.Date\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n customerName String @map(\"customer_name\") @db.VarChar(120)\n customerPhone String @map(\"customer_phone\") @db.VarChar(30)\n customerEmail String @map(\"customer_email\") @db.VarChar(254)\n status CourtBookingStatus @default(CONFIRMED)\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)\n\n @@unique([courtId, bookingDate, startTime])\n @@index([courtId, bookingDate])\n @@index([bookingDate])\n @@map(\"court_bookings\")\n}\n\nmodel CourtBookingLog {\n id String @id @db.Uuid\n bookingCode String @map(\"booking_code\") @db.VarChar(8)\n courtId String @map(\"court_id\") @db.Uuid\n bookingDate DateTime @map(\"booking_date\") @db.Date\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n previousStatus CourtBookingStatus @map(\"previous_status\")\n newStatus CourtBookingStatus @map(\"new_status\")\n customerName String @map(\"customer_name\") @db.VarChar(120)\n customerPhone String @map(\"customer_phone\") @db.VarChar(30)\n customerEmail String @map(\"customer_email\") @db.VarChar(254)\n changedAt DateTime @default(now()) @map(\"changed_at\")\n\n @@index([courtId, newStatus])\n @@map(\"court_booking_logs\")\n}\n\nmodel PasswordResetRequest {\n id String @id @db.Uuid\n email String\n otpHash String @map(\"otp_hash\")\n otpExpiresAt DateTime @map(\"otp_expires_at\")\n otpAttempts Int @default(0) @map(\"otp_attempts\")\n otpLastSentAt DateTime @map(\"otp_last_sent_at\")\n otpResendCount Int @default(0) @map(\"otp_resend_count\")\n usedAt DateTime? @map(\"used_at\")\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n\n @@index([email])\n @@index([otpExpiresAt])\n @@map(\"password_reset_requests\")\n}\n\nmodel Plan {\n code String @id @db.VarChar(10)\n name String @db.VarChar(30)\n price Decimal @db.Decimal(19, 2)\n rules Json\n lastUpdatedAt DateTime @default(now()) @map(\"last_updated_at\")\n complexes Complex[]\n\n @@map(\"plans\")\n}\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\n// User model is defined in auth.prisma (Better Auth schema).\n", "runtimeDataModel": { "models": {}, "enums": {}, @@ -32,10 +32,10 @@ const config: runtime.GetPrismaClientConfig = { } } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"accounts\",\"kind\":\"object\",\"type\":\"Account\",\"relationName\":\"AccountToUser\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexes\",\"kind\":\"object\",\"type\":\"ComplexUser\",\"relationName\":\"ComplexUserToUser\"}],\"dbName\":\"users\"},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"}],\"dbName\":\"sessions\"},\"Account\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accountId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"providerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AccountToUser\"},{\"name\":\"accessToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"idToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scope\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"accounts\"},\"Verification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"identifier\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"verification\"},\"Complex\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexName\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_name\"},{\"name\":\"physicalAddress\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"physical_address\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"city\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"state\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"country\"},{\"name\":\"complexSlug\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_slug\"},{\"name\":\"adminEmail\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"admin_email\"},{\"name\":\"planCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"plan_code\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"Plan\",\"relationName\":\"ComplexToPlan\"},{\"name\":\"users\",\"kind\":\"object\",\"type\":\"ComplexUser\",\"relationName\":\"ComplexToComplexUser\"},{\"name\":\"invitations\",\"kind\":\"object\",\"type\":\"ComplexInvitation\",\"relationName\":\"ComplexToComplexInvitation\"},{\"name\":\"courts\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"ComplexToCourt\"}],\"dbName\":\"complexes\"},\"ComplexUser\":{\"fields\":[{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"user_id\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"ComplexUserRole\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToComplexUser\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ComplexUserToUser\"}],\"dbName\":\"complex_users\"},\"ComplexInvitation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tokenHash\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"token_hash\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"expires_at\"},{\"name\":\"acceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"accepted_at\"},{\"name\":\"revokedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"revoked_at\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToComplexInvitation\"}],\"dbName\":\"complex_invitations\"},\"Sport\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slug\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\",\"dbName\":\"is_active\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"courts\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToSport\"}],\"dbName\":\"sports\"},\"Court\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"sportId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"sport_id\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slotDurationMinutes\",\"kind\":\"scalar\",\"type\":\"Int\",\"dbName\":\"slot_duration_minutes\"},{\"name\":\"basePrice\",\"kind\":\"scalar\",\"type\":\"Decimal\",\"dbName\":\"base_price\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToCourt\"},{\"name\":\"sport\",\"kind\":\"object\",\"type\":\"Sport\",\"relationName\":\"CourtToSport\"},{\"name\":\"availabilities\",\"kind\":\"object\",\"type\":\"CourtAvailability\",\"relationName\":\"CourtToCourtAvailability\"},{\"name\":\"priceRules\",\"kind\":\"object\",\"type\":\"CourtPriceRule\",\"relationName\":\"CourtToCourtPriceRule\"},{\"name\":\"bookings\",\"kind\":\"object\",\"type\":\"CourtBooking\",\"relationName\":\"CourtToCourtBooking\"}],\"dbName\":\"courts\"},\"CourtAvailability\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"dayOfWeek\",\"kind\":\"enum\",\"type\":\"DayOfWeek\",\"dbName\":\"day_of_week\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtAvailability\"}],\"dbName\":\"court_availabilities\"},\"CourtPriceRule\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"dayOfWeek\",\"kind\":\"enum\",\"type\":\"DayOfWeek\",\"dbName\":\"day_of_week\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Decimal\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\",\"dbName\":\"is_active\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtPriceRule\"}],\"dbName\":\"court_price_rules\"},\"CourtBooking\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bookingCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"booking_code\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"bookingDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"booking_date\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"customerName\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_name\"},{\"name\":\"customerPhone\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_phone\"},{\"name\":\"customerEmail\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_email\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"CourtBookingStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtBooking\"}],\"dbName\":\"court_bookings\"},\"CourtBookingLog\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bookingCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"booking_code\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"bookingDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"booking_date\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"previousStatus\",\"kind\":\"enum\",\"type\":\"CourtBookingStatus\",\"dbName\":\"previous_status\"},{\"name\":\"newStatus\",\"kind\":\"enum\",\"type\":\"CourtBookingStatus\",\"dbName\":\"new_status\"},{\"name\":\"customerName\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_name\"},{\"name\":\"customerPhone\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_phone\"},{\"name\":\"customerEmail\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_email\"},{\"name\":\"changedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"changed_at\"}],\"dbName\":\"court_booking_logs\"},\"PasswordResetRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"otpHash\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"otp_hash\"},{\"name\":\"otpExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"otp_expires_at\"},{\"name\":\"otpAttempts\",\"kind\":\"scalar\",\"type\":\"Int\",\"dbName\":\"otp_attempts\"},{\"name\":\"otpLastSentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"otp_last_sent_at\"},{\"name\":\"otpResendCount\",\"kind\":\"scalar\",\"type\":\"Int\",\"dbName\":\"otp_resend_count\"},{\"name\":\"usedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"used_at\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"}],\"dbName\":\"password_reset_requests\"},\"Plan\":{\"fields\":[{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Decimal\"},{\"name\":\"rules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"lastUpdatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"last_updated_at\"},{\"name\":\"complexes\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToPlan\"}],\"dbName\":\"plans\"}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"bannedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"banReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"accounts\",\"kind\":\"object\",\"type\":\"Account\",\"relationName\":\"AccountToUser\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexes\",\"kind\":\"object\",\"type\":\"ComplexUser\",\"relationName\":\"ComplexUserToUser\"}],\"dbName\":\"users\"},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"}],\"dbName\":\"sessions\"},\"Account\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accountId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"providerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AccountToUser\"},{\"name\":\"accessToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"idToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scope\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"accounts\"},\"Verification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"identifier\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"verification\"},\"Complex\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexName\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_name\"},{\"name\":\"physicalAddress\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"physical_address\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"city\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"state\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"country\"},{\"name\":\"complexSlug\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_slug\"},{\"name\":\"adminEmail\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"admin_email\"},{\"name\":\"planCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"plan_code\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"Plan\",\"relationName\":\"ComplexToPlan\"},{\"name\":\"users\",\"kind\":\"object\",\"type\":\"ComplexUser\",\"relationName\":\"ComplexToComplexUser\"},{\"name\":\"invitations\",\"kind\":\"object\",\"type\":\"ComplexInvitation\",\"relationName\":\"ComplexToComplexInvitation\"},{\"name\":\"courts\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"ComplexToCourt\"}],\"dbName\":\"complexes\"},\"ComplexUser\":{\"fields\":[{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"user_id\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"ComplexUserRole\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToComplexUser\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ComplexUserToUser\"}],\"dbName\":\"complex_users\"},\"ComplexInvitation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tokenHash\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"token_hash\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"expires_at\"},{\"name\":\"acceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"accepted_at\"},{\"name\":\"revokedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"revoked_at\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToComplexInvitation\"}],\"dbName\":\"complex_invitations\"},\"Sport\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slug\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\",\"dbName\":\"is_active\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"courts\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToSport\"}],\"dbName\":\"sports\"},\"Court\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"sportId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"sport_id\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slotDurationMinutes\",\"kind\":\"scalar\",\"type\":\"Int\",\"dbName\":\"slot_duration_minutes\"},{\"name\":\"basePrice\",\"kind\":\"scalar\",\"type\":\"Decimal\",\"dbName\":\"base_price\"},{\"name\":\"isUnderMaintenance\",\"kind\":\"scalar\",\"type\":\"Boolean\",\"dbName\":\"is_under_maintenance\"},{\"name\":\"maintenanceReason\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"maintenance_reason\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToCourt\"},{\"name\":\"sport\",\"kind\":\"object\",\"type\":\"Sport\",\"relationName\":\"CourtToSport\"},{\"name\":\"availabilities\",\"kind\":\"object\",\"type\":\"CourtAvailability\",\"relationName\":\"CourtToCourtAvailability\"},{\"name\":\"priceRules\",\"kind\":\"object\",\"type\":\"CourtPriceRule\",\"relationName\":\"CourtToCourtPriceRule\"},{\"name\":\"bookings\",\"kind\":\"object\",\"type\":\"CourtBooking\",\"relationName\":\"CourtToCourtBooking\"},{\"name\":\"maintenances\",\"kind\":\"object\",\"type\":\"CourtMaintenance\",\"relationName\":\"CourtToCourtMaintenance\"}],\"dbName\":\"courts\"},\"CourtMaintenance\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"start_date\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtMaintenance\"}],\"dbName\":\"court_maintenances\"},\"CourtAvailability\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"dayOfWeek\",\"kind\":\"enum\",\"type\":\"DayOfWeek\",\"dbName\":\"day_of_week\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtAvailability\"}],\"dbName\":\"court_availabilities\"},\"CourtPriceRule\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"dayOfWeek\",\"kind\":\"enum\",\"type\":\"DayOfWeek\",\"dbName\":\"day_of_week\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Decimal\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\",\"dbName\":\"is_active\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtPriceRule\"}],\"dbName\":\"court_price_rules\"},\"CourtBooking\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bookingCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"booking_code\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"bookingDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"booking_date\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"customerName\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_name\"},{\"name\":\"customerPhone\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_phone\"},{\"name\":\"customerEmail\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_email\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"CourtBookingStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToCourtBooking\"}],\"dbName\":\"court_bookings\"},\"CourtBookingLog\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bookingCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"booking_code\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"bookingDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"booking_date\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"previousStatus\",\"kind\":\"enum\",\"type\":\"CourtBookingStatus\",\"dbName\":\"previous_status\"},{\"name\":\"newStatus\",\"kind\":\"enum\",\"type\":\"CourtBookingStatus\",\"dbName\":\"new_status\"},{\"name\":\"customerName\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_name\"},{\"name\":\"customerPhone\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_phone\"},{\"name\":\"customerEmail\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"customer_email\"},{\"name\":\"changedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"changed_at\"}],\"dbName\":\"court_booking_logs\"},\"PasswordResetRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"otpHash\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"otp_hash\"},{\"name\":\"otpExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"otp_expires_at\"},{\"name\":\"otpAttempts\",\"kind\":\"scalar\",\"type\":\"Int\",\"dbName\":\"otp_attempts\"},{\"name\":\"otpLastSentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"otp_last_sent_at\"},{\"name\":\"otpResendCount\",\"kind\":\"scalar\",\"type\":\"Int\",\"dbName\":\"otp_resend_count\"},{\"name\":\"usedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"used_at\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"}],\"dbName\":\"password_reset_requests\"},\"Plan\":{\"fields\":[{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Decimal\"},{\"name\":\"rules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"lastUpdatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"last_updated_at\"},{\"name\":\"complexes\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToPlan\"}],\"dbName\":\"plans\"}},\"enums\":{},\"types\":{}}") config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"sessions\",\"accounts\",\"complexes\",\"_count\",\"plan\",\"users\",\"complex\",\"invitations\",\"courts\",\"sport\",\"court\",\"availabilities\",\"priceRules\",\"bookings\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Account.findUnique\",\"Account.findUniqueOrThrow\",\"Account.findFirst\",\"Account.findFirstOrThrow\",\"Account.findMany\",\"Account.createOne\",\"Account.createMany\",\"Account.createManyAndReturn\",\"Account.updateOne\",\"Account.updateMany\",\"Account.updateManyAndReturn\",\"Account.upsertOne\",\"Account.deleteOne\",\"Account.deleteMany\",\"Account.groupBy\",\"Account.aggregate\",\"Verification.findUnique\",\"Verification.findUniqueOrThrow\",\"Verification.findFirst\",\"Verification.findFirstOrThrow\",\"Verification.findMany\",\"Verification.createOne\",\"Verification.createMany\",\"Verification.createManyAndReturn\",\"Verification.updateOne\",\"Verification.updateMany\",\"Verification.updateManyAndReturn\",\"Verification.upsertOne\",\"Verification.deleteOne\",\"Verification.deleteMany\",\"Verification.groupBy\",\"Verification.aggregate\",\"Complex.findUnique\",\"Complex.findUniqueOrThrow\",\"Complex.findFirst\",\"Complex.findFirstOrThrow\",\"Complex.findMany\",\"Complex.createOne\",\"Complex.createMany\",\"Complex.createManyAndReturn\",\"Complex.updateOne\",\"Complex.updateMany\",\"Complex.updateManyAndReturn\",\"Complex.upsertOne\",\"Complex.deleteOne\",\"Complex.deleteMany\",\"Complex.groupBy\",\"Complex.aggregate\",\"ComplexUser.findUnique\",\"ComplexUser.findUniqueOrThrow\",\"ComplexUser.findFirst\",\"ComplexUser.findFirstOrThrow\",\"ComplexUser.findMany\",\"ComplexUser.createOne\",\"ComplexUser.createMany\",\"ComplexUser.createManyAndReturn\",\"ComplexUser.updateOne\",\"ComplexUser.updateMany\",\"ComplexUser.updateManyAndReturn\",\"ComplexUser.upsertOne\",\"ComplexUser.deleteOne\",\"ComplexUser.deleteMany\",\"ComplexUser.groupBy\",\"ComplexUser.aggregate\",\"ComplexInvitation.findUnique\",\"ComplexInvitation.findUniqueOrThrow\",\"ComplexInvitation.findFirst\",\"ComplexInvitation.findFirstOrThrow\",\"ComplexInvitation.findMany\",\"ComplexInvitation.createOne\",\"ComplexInvitation.createMany\",\"ComplexInvitation.createManyAndReturn\",\"ComplexInvitation.updateOne\",\"ComplexInvitation.updateMany\",\"ComplexInvitation.updateManyAndReturn\",\"ComplexInvitation.upsertOne\",\"ComplexInvitation.deleteOne\",\"ComplexInvitation.deleteMany\",\"ComplexInvitation.groupBy\",\"ComplexInvitation.aggregate\",\"Sport.findUnique\",\"Sport.findUniqueOrThrow\",\"Sport.findFirst\",\"Sport.findFirstOrThrow\",\"Sport.findMany\",\"Sport.createOne\",\"Sport.createMany\",\"Sport.createManyAndReturn\",\"Sport.updateOne\",\"Sport.updateMany\",\"Sport.updateManyAndReturn\",\"Sport.upsertOne\",\"Sport.deleteOne\",\"Sport.deleteMany\",\"Sport.groupBy\",\"Sport.aggregate\",\"Court.findUnique\",\"Court.findUniqueOrThrow\",\"Court.findFirst\",\"Court.findFirstOrThrow\",\"Court.findMany\",\"Court.createOne\",\"Court.createMany\",\"Court.createManyAndReturn\",\"Court.updateOne\",\"Court.updateMany\",\"Court.updateManyAndReturn\",\"Court.upsertOne\",\"Court.deleteOne\",\"Court.deleteMany\",\"_avg\",\"_sum\",\"Court.groupBy\",\"Court.aggregate\",\"CourtAvailability.findUnique\",\"CourtAvailability.findUniqueOrThrow\",\"CourtAvailability.findFirst\",\"CourtAvailability.findFirstOrThrow\",\"CourtAvailability.findMany\",\"CourtAvailability.createOne\",\"CourtAvailability.createMany\",\"CourtAvailability.createManyAndReturn\",\"CourtAvailability.updateOne\",\"CourtAvailability.updateMany\",\"CourtAvailability.updateManyAndReturn\",\"CourtAvailability.upsertOne\",\"CourtAvailability.deleteOne\",\"CourtAvailability.deleteMany\",\"CourtAvailability.groupBy\",\"CourtAvailability.aggregate\",\"CourtPriceRule.findUnique\",\"CourtPriceRule.findUniqueOrThrow\",\"CourtPriceRule.findFirst\",\"CourtPriceRule.findFirstOrThrow\",\"CourtPriceRule.findMany\",\"CourtPriceRule.createOne\",\"CourtPriceRule.createMany\",\"CourtPriceRule.createManyAndReturn\",\"CourtPriceRule.updateOne\",\"CourtPriceRule.updateMany\",\"CourtPriceRule.updateManyAndReturn\",\"CourtPriceRule.upsertOne\",\"CourtPriceRule.deleteOne\",\"CourtPriceRule.deleteMany\",\"CourtPriceRule.groupBy\",\"CourtPriceRule.aggregate\",\"CourtBooking.findUnique\",\"CourtBooking.findUniqueOrThrow\",\"CourtBooking.findFirst\",\"CourtBooking.findFirstOrThrow\",\"CourtBooking.findMany\",\"CourtBooking.createOne\",\"CourtBooking.createMany\",\"CourtBooking.createManyAndReturn\",\"CourtBooking.updateOne\",\"CourtBooking.updateMany\",\"CourtBooking.updateManyAndReturn\",\"CourtBooking.upsertOne\",\"CourtBooking.deleteOne\",\"CourtBooking.deleteMany\",\"CourtBooking.groupBy\",\"CourtBooking.aggregate\",\"CourtBookingLog.findUnique\",\"CourtBookingLog.findUniqueOrThrow\",\"CourtBookingLog.findFirst\",\"CourtBookingLog.findFirstOrThrow\",\"CourtBookingLog.findMany\",\"CourtBookingLog.createOne\",\"CourtBookingLog.createMany\",\"CourtBookingLog.createManyAndReturn\",\"CourtBookingLog.updateOne\",\"CourtBookingLog.updateMany\",\"CourtBookingLog.updateManyAndReturn\",\"CourtBookingLog.upsertOne\",\"CourtBookingLog.deleteOne\",\"CourtBookingLog.deleteMany\",\"CourtBookingLog.groupBy\",\"CourtBookingLog.aggregate\",\"PasswordResetRequest.findUnique\",\"PasswordResetRequest.findUniqueOrThrow\",\"PasswordResetRequest.findFirst\",\"PasswordResetRequest.findFirstOrThrow\",\"PasswordResetRequest.findMany\",\"PasswordResetRequest.createOne\",\"PasswordResetRequest.createMany\",\"PasswordResetRequest.createManyAndReturn\",\"PasswordResetRequest.updateOne\",\"PasswordResetRequest.updateMany\",\"PasswordResetRequest.updateManyAndReturn\",\"PasswordResetRequest.upsertOne\",\"PasswordResetRequest.deleteOne\",\"PasswordResetRequest.deleteMany\",\"PasswordResetRequest.groupBy\",\"PasswordResetRequest.aggregate\",\"Plan.findUnique\",\"Plan.findUniqueOrThrow\",\"Plan.findFirst\",\"Plan.findFirstOrThrow\",\"Plan.findMany\",\"Plan.createOne\",\"Plan.createMany\",\"Plan.createManyAndReturn\",\"Plan.updateOne\",\"Plan.updateMany\",\"Plan.updateManyAndReturn\",\"Plan.upsertOne\",\"Plan.deleteOne\",\"Plan.deleteMany\",\"Plan.groupBy\",\"Plan.aggregate\",\"AND\",\"OR\",\"NOT\",\"code\",\"name\",\"price\",\"rules\",\"lastUpdatedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"contains\",\"startsWith\",\"endsWith\",\"every\",\"some\",\"none\",\"id\",\"email\",\"otpHash\",\"otpExpiresAt\",\"otpAttempts\",\"otpLastSentAt\",\"otpResendCount\",\"usedAt\",\"createdAt\",\"updatedAt\",\"bookingCode\",\"courtId\",\"bookingDate\",\"startTime\",\"endTime\",\"CourtBookingStatus\",\"previousStatus\",\"newStatus\",\"customerName\",\"customerPhone\",\"customerEmail\",\"changedAt\",\"status\",\"DayOfWeek\",\"dayOfWeek\",\"isActive\",\"complexId\",\"sportId\",\"slotDurationMinutes\",\"basePrice\",\"slug\",\"tokenHash\",\"expiresAt\",\"acceptedAt\",\"revokedAt\",\"userId\",\"ComplexUserRole\",\"role\",\"complexName\",\"physicalAddress\",\"city\",\"state\",\"country\",\"complexSlug\",\"adminEmail\",\"planCode\",\"identifier\",\"value\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"idToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"password\",\"token\",\"ipAddress\",\"userAgent\",\"emailVerified\",\"image\",\"phone\",\"courtId_bookingDate_startTime\",\"complexId_userId\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "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-AgAA4wO-AiIBDgAA5AUAIAoOAADfAwAgigIAAOIDADCLAgAAIQAQjAIAAOIDADCmAgEAAAABrgJAAKIDACGxAgEArwMAIbMCAQCfAwAhtAIBAJ8DACG-AgAA4wO-AiIDAAAAIQAgAQAAIgAwAgAAIwAgDQ4AAN8DACCKAgAA4AMAMIsCAAAlABCMAgAA4AMAMI8CEACgAwAhpgIBAK8DACGuAkAAogMAIa8CQACiAwAhsQIBAK8DACGzAgEA2QMAIbQCAQDZAwAhvgIAAOEDvgIjvwIgAMsDACEEDgAA5AUAILMCAADrBAAgtAIAAOsEACC-AgAA6wQAIA0OAADfAwAgigIAAOADADCLAgAAJQAQjAIAAOADADCPAhAAoAMAIaYCAQAAAAGuAkAAogMAIa8CQACiAwAhsQIBAK8DACGzAgEA2QMAIbQCAQDZAwAhvgIAAOEDvgIjvwIgAMsDACEDAAAAJQAgAQAAJgAwAgAAJwAgEA4AAN8DACCKAgAA3gMAMIsCAAApABCMAgAA3gMAMKYCAQCvAwAhrgJAAKIDACGvAkAAogMAIbACAQCfAwAhsQIBAK8DACGyAkAAogMAIbMCAQCfAwAhtAIBAJ8DACG4AgEAnwMAIbkCAQCfAwAhugIBAJ8DACG8AgAAuAO2AiIBDgAA5AUAIBEOAADfAwAgigIAAN4DADCLAgAAKQAQjAIAAN4DADCmAgEAAAABrgJAAKIDACGvAkAAogMAIbACAQAAAAGxAgEArwMAIbICQACiAwAhswIBAJ8DACG0AgEAnwMAIbgCAQCfAwAhuQIBAJ8DACG6AgEAnwMAIbwCAAC4A7YCIuUCAADdAwAgAwAAACkAIAEAACoAMAIAACsAIAEAAAAhACABAAAAJQAgAQAAACkAIAEAAAALACABAAAAFwAgAQAAABsAIAEAAAADACABAAAABwAgAQAAAAsAIAEAAAABACAPBAAA2gMAIAUAANsDACAGAADcAwAgigIAANgDADCLAgAANwAQjAIAANgDADCOAgEAnwMAIaYCAQCfAwAhpwIBAJ8DACGuAkAAogMAIa8CQACiAwAhywIBAJ8DACHiAiAAywMAIeMCAQDZAwAh5AIBANkDACEFBAAA4QUAIAUAAOIFACAGAADjBQAg4wIAAOsEACDkAgAA6wQAIAMAAAA3ACABAAA4ADACAAABACADAAAANwAgAQAAOAAwAgAAAQAgAwAAADcAIAEAADgAMAIAAAEAIAwEAADeBQAgBQAA3wUAIAYAAOAFACCOAgEAAAABpgIBAAAAAacCAQAAAAGuAkAAAAABrwJAAAAAAcsCAQAAAAHiAiAAAAAB4wIBAAAAAeQCAQAAAAEBFwAAPAAgCY4CAQAAAAGmAgEAAAABpwIBAAAAAa4CQAAAAAGvAkAAAAABywIBAAAAAeICIAAAAAHjAgEAAAAB5AIBAAAAAQEXAAA-ADABFwAAPgAwDAQAALoFACAFAAC7BQAgBgAAvAUAII4CAQD5AwAhpgIBAPkDACGnAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHLAgEA-QMAIeICIAC0BAAh4wIBAIcEACHkAgEAhwQAIQIAAAABACAXAABBACAJjgIBAPkDACGmAgEA-QMAIacCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcsCAQD5AwAh4gIgALQEACHjAgEAhwQAIeQCAQCHBAAhAgAAADcAIBcAAEMAIAIAAAA3ACAXAABDACADAAAAAQAgHgAAPAAgHwAAQQAgAQAAAAEAIAEAAAA3ACAFBwAAtwUAICQAALkFACAlAAC4BQAg4wIAAOsEACDkAgAA6wQAIAyKAgAA1wMAMIsCAABKABCMAgAA1wMAMI4CAQCSAwAhpgIBAJIDACGnAgEAkgMAIa4CQACVAwAhrwJAAJUDACHLAgEAkgMAIeICIAC9AwAh4wIBALwDACHkAgEAvAMAIQMAAAA3ACABAABJADAjAABKACADAAAANwAgAQAAOAAwAgAAAQAgAQAAAAUAIAEAAAAFACADAAAAAwAgAQAABAAwAgAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACAJAwAAtgUAIKYCAQAAAAGuAkAAAAABrwJAAAAAAcYCQAAAAAHJAgEAAAAB3wIBAAAAAeACAQAAAAHhAgEAAAABARcAAFIAIAimAgEAAAABrgJAAAAAAa8CQAAAAAHGAkAAAAAByQIBAAAAAd8CAQAAAAHgAgEAAAAB4QIBAAAAAQEXAABUADABFwAAVAAwCQMAALUFACCmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHGAkAA-wMAIckCAQD5AwAh3wIBAPkDACHgAgEAhwQAIeECAQCHBAAhAgAAAAUAIBcAAFcAIAimAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHGAkAA-wMAIckCAQD5AwAh3wIBAPkDACHgAgEAhwQAIeECAQCHBAAhAgAAAAMAIBcAAFkAIAIAAAADACAXAABZACADAAAABQAgHgAAUgAgHwAAVwAgAQAAAAUAIAEAAAADACAFBwAAsgUAICQAALQFACAlAACzBQAg4AIAAOsEACDhAgAA6wQAIAuKAgAA1gMAMIsCAABgABCMAgAA1gMAMKYCAQCSAwAhrgJAAJUDACGvAkAAlQMAIcYCQACVAwAhyQIBAJIDACHfAgEAkgMAIeACAQC8AwAh4QIBALwDACEDAAAAAwAgAQAAXwAwIwAAYAAgAwAAAAMAIAEAAAQAMAIAAAUAIAEAAAAJACABAAAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACADAAAABwAgAQAACAAwAgAACQAgDgMAALEFACCmAgEAAAABrgJAAAAAAa8CQAAAAAHJAgEAAAAB1gIBAAAAAdcCAQAAAAHYAgEAAAAB2QIBAAAAAdoCAQAAAAHbAkAAAAAB3AJAAAAAAd0CAQAAAAHeAgEAAAABARcAAGgAIA2mAgEAAAABrgJAAAAAAa8CQAAAAAHJAgEAAAAB1gIBAAAAAdcCAQAAAAHYAgEAAAAB2QIBAAAAAdoCAQAAAAHbAkAAAAAB3AJAAAAAAd0CAQAAAAHeAgEAAAABARcAAGoAMAEXAABqADAOAwAAsAUAIKYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIckCAQD5AwAh1gIBAPkDACHXAgEA-QMAIdgCAQCHBAAh2QIBAIcEACHaAgEAhwQAIdsCQADTBAAh3AJAANMEACHdAgEAhwQAId4CAQCHBAAhAgAAAAkAIBcAAG0AIA2mAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHJAgEA-QMAIdYCAQD5AwAh1wIBAPkDACHYAgEAhwQAIdkCAQCHBAAh2gIBAIcEACHbAkAA0wQAIdwCQADTBAAh3QIBAIcEACHeAgEAhwQAIQIAAAAHACAXAABvACACAAAABwAgFwAAbwAgAwAAAAkAIB4AAGgAIB8AAG0AIAEAAAAJACABAAAABwAgCgcAAK0FACAkAACvBQAgJQAArgUAINgCAADrBAAg2QIAAOsEACDaAgAA6wQAINsCAADrBAAg3AIAAOsEACDdAgAA6wQAIN4CAADrBAAgEIoCAADVAwAwiwIAAHYAEIwCAADVAwAwpgIBAJIDACGuAkAAlQMAIa8CQACVAwAhyQIBAJIDACHWAgEAkgMAIdcCAQCSAwAh2AIBALwDACHZAgEAvAMAIdoCAQC8AwAh2wJAAKcDACHcAkAApwMAId0CAQC8AwAh3gIBALwDACEDAAAABwAgAQAAdQAwIwAAdgAgAwAAAAcAIAEAAAgAMAIAAAkAIAmKAgAA1AMAMIsCAAB8ABCMAgAA1AMAMKYCAQAAAAGuAkAAogMAIa8CQACiAwAhxgJAAKIDACHUAgEAnwMAIdUCAQCfAwAhAQAAAHkAIAEAAAB5ACAJigIAANQDADCLAgAAfAAQjAIAANQDADCmAgEAnwMAIa4CQACiAwAhrwJAAKIDACHGAkAAogMAIdQCAQCfAwAh1QIBAJ8DACEAAwAAAHwAIAEAAH0AMAIAAHkAIAMAAAB8ACABAAB9ADACAAB5ACADAAAAfAAgAQAAfQAwAgAAeQAgBqYCAQAAAAGuAkAAAAABrwJAAAAAAcYCQAAAAAHUAgEAAAAB1QIBAAAAAQEXAACBAQAgBqYCAQAAAAGuAkAAAAABrwJAAAAAAcYCQAAAAAHUAgEAAAAB1QIBAAAAAQEXAACDAQAwARcAAIMBADAGpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhxgJAAPsDACHUAgEA-QMAIdUCAQD5AwAhAgAAAHkAIBcAAIYBACAGpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhxgJAAPsDACHUAgEA-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-wMAIa8CQAD7AwAhwAIBAPkDACHFAgEA-QMAIcYCQAD7AwAhxwJAANMEACHIAkAA0wQAIQIAAAAZACAXAADKAQAgCaYCAQD5AwAhpwIBAPkDACGuAkAA-wMAIa8CQAD7AwAhwAIBAPkDACHFAgEA-QMAIcYCQAD7AwAhxwJAANMEACHIAkAA0wQAIQIAAAAXACAXAADMAQAgAgAAABcAIBcAAMwBACADAAAAGQAgHgAAxQEAIB8AAMoBACABAAAAGQAgAQAAABcAIAUHAACbBQAgJAAAnQUAICUAAJwFACDHAgAA6wQAIMgCAADrBAAgDIoCAADNAwAwiwIAANMBABCMAgAAzQMAMKYCAQClAwAhpwIBAJIDACGuAkAAlQMAIa8CQACVAwAhwAIBAKUDACHFAgEAkgMAIcYCQACVAwAhxwJAAKcDACHIAkAApwMAIQMAAAAXACABAADSAQAwIwAA0wEAIAMAAAAXACABAAAYADACAAAZACAKDAAAzAMAIIoCAADKAwAwiwIAANkBABCMAgAAygMAMI4CAQAAAAGmAgEAAAABrgJAAKIDACGvAkAAogMAIb8CIADLAwAhxAIBAAAAAQEAAADWAQAgAQAAANYBACAKDAAAzAMAIIoCAADKAwAwiwIAANkBABCMAgAAygMAMI4CAQCfAwAhpgIBAK8DACGuAkAAogMAIa8CQACiAwAhvwIgAMsDACHEAgEAnwMAIQEMAACaBQAgAwAAANkBACABAADaAQAwAgAA1gEAIAMAAADZAQAgAQAA2gEAMAIAANYBACADAAAA2QEAIAEAANoBADACAADWAQAgBwwAAJkFACCOAgEAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABvwIgAAAAAcQCAQAAAAEBFwAA3gEAIAaOAgEAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABvwIgAAAAAcQCAQAAAAEBFwAA4AEAMAEXAADgAQAwBwwAAI8FACCOAgEA-QMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIb8CIAC0BAAhxAIBAPkDACECAAAA1gEAIBcAAOMBACAGjgIBAPkDACGmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACG_AiAAtAQAIcQCAQD5AwAhAgAAANkBACAXAADlAQAgAgAAANkBACAXAADlAQAgAwAAANYBACAeAADeAQAgHwAA4wEAIAEAAADWAQAgAQAAANkBACADBwAAjAUAICQAAI4FACAlAACNBQAgCYoCAADJAwAwiwIAAOwBABCMAgAAyQMAMI4CAQCSAwAhpgIBAKUDACGuAkAAlQMAIa8CQACVAwAhvwIgAL0DACHEAgEAkgMAIQMAAADZAQAgAQAA6wEAMCMAAOwBACADAAAA2QEAIAEAANoBADACAADWAQAgAQAAAB0AIAEAAAAdACADAAAAGwAgAQAAHAAwAgAAHQAgAwAAABsAIAEAABwAMAIAAB0AIAMAAAAbACABAAAcADACAAAdACANCgAAiwUAIA0AAMUEACAPAADGBAAgEAAAxwQAIBEAAMgEACCOAgEAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABwAIBAAAAAcECAQAAAAHCAgIAAAABwwIQAAAAAQEXAAD0AQAgCI4CAQAAAAGmAgEAAAABrgJAAAAAAa8CQAAAAAHAAgEAAAABwQIBAAAAAcICAgAAAAHDAhAAAAABARcAAPYBADABFwAA9gEAMA0KAACKBQAgDQAAmAQAIA8AAJkEACAQAACaBAAgEQAAmwQAII4CAQD5AwAhpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhwAIBAPkDACHBAgEA-QMAIcICAgCWBAAhwwIQAPoDACECAAAAHQAgFwAA-QEAIAiOAgEA-QMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcACAQD5AwAhwQIBAPkDACHCAgIAlgQAIcMCEAD6AwAhAgAAABsAIBcAAPsBACACAAAAGwAgFwAA-wEAIAMAAAAdACAeAAD0AQAgHwAA-QEAIAEAAAAdACABAAAAGwAgBQcAAIUFACAkAACIBQAgJQAAhwUAIKYBAACGBQAgpwEAAIkFACALigIAAMgDADCLAgAAggIAEIwCAADIAwAwjgIBAJIDACGmAgEApQMAIa4CQACVAwAhrwJAAJUDACHAAgEApQMAIcECAQClAwAhwgICAKYDACHDAhAAkwMAIQMAAAAbACABAACBAgAwIwAAggIAIAMAAAAbACABAAAcADACAAAdACABAAAAIwAgAQAAACMAIAMAAAAhACABAAAiADACAAAjACADAAAAIQAgAQAAIgAwAgAAIwAgAwAAACEAIAEAACIAMAIAACMAIAcOAACEBQAgpgIBAAAAAa4CQAAAAAGxAgEAAAABswIBAAAAAbQCAQAAAAG-AgAAAL4CAgEXAACKAgAgBqYCAQAAAAGuAkAAAAABsQIBAAAAAbMCAQAAAAG0AgEAAAABvgIAAAC-AgIBFwAAjAIAMAEXAACMAgAwBw4AAIMFACCmAgEA-QMAIa4CQAD7AwAhsQIBAPkDACGzAgEA-QMAIbQCAQD5AwAhvgIAAMEEvgIiAgAAACMAIBcAAI8CACAGpgIBAPkDACGuAkAA-wMAIbECAQD5AwAhswIBAPkDACG0AgEA-QMAIb4CAADBBL4CIgIAAAAhACAXAACRAgAgAgAAACEAIBcAAJECACADAAAAIwAgHgAAigIAIB8AAI8CACABAAAAIwAgAQAAACEAIAMHAACABQAgJAAAggUAICUAAIEFACAJigIAAMQDADCLAgAAmAIAEIwCAADEAwAwpgIBAKUDACGuAkAAlQMAIbECAQClAwAhswIBAJIDACG0AgEAkgMAIb4CAADFA74CIgMAAAAhACABAACXAgAwIwAAmAIAIAMAAAAhACABAAAiADACAAAjACABAAAAJwAgAQAAACcAIAMAAAAlACABAAAmADACAAAnACADAAAAJQAgAQAAJgAwAgAAJwAgAwAAACUAIAEAACYAMAIAACcAIAoOAAD_BAAgjwIQAAAAAaYCAQAAAAGuAkAAAAABrwJAAAAAAbECAQAAAAGzAgEAAAABtAIBAAAAAb4CAAAAvgIDvwIgAAAAAQEXAACgAgAgCY8CEAAAAAGmAgEAAAABrgJAAAAAAa8CQAAAAAGxAgEAAAABswIBAAAAAbQCAQAAAAG-AgAAAL4CA78CIAAAAAEBFwAAogIAMAEXAACiAgAwCg4AAP4EACCPAhAA-gMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIbECAQD5AwAhswIBAIcEACG0AgEAhwQAIb4CAACzBL4CI78CIAC0BAAhAgAAACcAIBcAAKUCACAJjwIQAPoDACGmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACGxAgEA-QMAIbMCAQCHBAAhtAIBAIcEACG-AgAAswS-AiO_AiAAtAQAIQIAAAAlACAXAACnAgAgAgAAACUAIBcAAKcCACADAAAAJwAgHgAAoAIAIB8AAKUCACABAAAAJwAgAQAAACUAIAgHAAD5BAAgJAAA_AQAICUAAPsEACCmAQAA-gQAIKcBAAD9BAAgswIAAOsEACC0AgAA6wQAIL4CAADrBAAgDIoCAAC6AwAwiwIAAK4CABCMAgAAugMAMI8CEACTAwAhpgIBAKUDACGuAkAAlQMAIa8CQACVAwAhsQIBAKUDACGzAgEAvAMAIbQCAQC8AwAhvgIAALsDvgIjvwIgAL0DACEDAAAAJQAgAQAArQIAMCMAAK4CACADAAAAJQAgAQAAJgAwAgAAJwAgAQAAACsAIAEAAAArACADAAAAKQAgAQAAKgAwAgAAKwAgAwAAACkAIAEAACoAMAIAACsAIAMAAAApACABAAAqADACAAArACANDgAA-AQAIKYCAQAAAAGuAkAAAAABrwJAAAAAAbACAQAAAAGxAgEAAAABsgJAAAAAAbMCAQAAAAG0AgEAAAABuAIBAAAAAbkCAQAAAAG6AgEAAAABvAIAAAC2AgIBFwAAtgIAIAymAgEAAAABrgJAAAAAAa8CQAAAAAGwAgEAAAABsQIBAAAAAbICQAAAAAGzAgEAAAABtAIBAAAAAbgCAQAAAAG5AgEAAAABugIBAAAAAbwCAAAAtgICARcAALgCADABFwAAuAIAMA0OAAD3BAAgpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhsAIBAPkDACGxAgEA-QMAIbICQAD7AwAhswIBAPkDACG0AgEA-QMAIbgCAQD5AwAhuQIBAPkDACG6AgEA-QMAIbwCAACmBLYCIgIAAAArACAXAAC7AgAgDKYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIbACAQD5AwAhsQIBAPkDACGyAkAA-wMAIbMCAQD5AwAhtAIBAPkDACG4AgEA-QMAIbkCAQD5AwAhugIBAPkDACG8AgAApgS2AiICAAAAKQAgFwAAvQIAIAIAAAApACAXAAC9AgAgAwAAACsAIB4AALYCACAfAAC7AgAgAQAAACsAIAEAAAApACADBwAA9AQAICQAAPYEACAlAAD1BAAgD4oCAAC5AwAwiwIAAMQCABCMAgAAuQMAMKYCAQClAwAhrgJAAJUDACGvAkAAlQMAIbACAQCSAwAhsQIBAKUDACGyAkAAlQMAIbMCAQCSAwAhtAIBAJIDACG4AgEAkgMAIbkCAQCSAwAhugIBAJIDACG8AgAAtAO2AiIDAAAAKQAgAQAAwwIAMCMAAMQCACADAAAAKQAgAQAAKgAwAgAAKwAgD4oCAAC3AwAwiwIAAMoCABCMAgAAtwMAMKYCAQAAAAGwAgEAnwMAIbECAQCvAwAhsgJAAKIDACGzAgEAnwMAIbQCAQCfAwAhtgIAALgDtgIitwIAALgDtgIiuAIBAJ8DACG5AgEAnwMAIboCAQCfAwAhuwJAAKIDACEBAAAAxwIAIAEAAADHAgAgD4oCAAC3AwAwiwIAAMoCABCMAgAAtwMAMKYCAQCvAwAhsAIBAJ8DACGxAgEArwMAIbICQACiAwAhswIBAJ8DACG0AgEAnwMAIbYCAAC4A7YCIrcCAAC4A7YCIrgCAQCfAwAhuQIBAJ8DACG6AgEAnwMAIbsCQACiAwAhAAMAAADKAgAgAQAAywIAMAIAAMcCACADAAAAygIAIAEAAMsCADACAADHAgAgAwAAAMoCACABAADLAgAwAgAAxwIAIAymAgEAAAABsAIBAAAAAbECAQAAAAGyAkAAAAABswIBAAAAAbQCAQAAAAG2AgAAALYCArcCAAAAtgICuAIBAAAAAbkCAQAAAAG6AgEAAAABuwJAAAAAAQEXAADPAgAgDKYCAQAAAAGwAgEAAAABsQIBAAAAAbICQAAAAAGzAgEAAAABtAIBAAAAAbYCAAAAtgICtwIAAAC2AgK4AgEAAAABuQIBAAAAAboCAQAAAAG7AkAAAAABARcAANECADABFwAA0QIAMAymAgEA-QMAIbACAQD5AwAhsQIBAPkDACGyAkAA-wMAIbMCAQD5AwAhtAIBAPkDACG2AgAApgS2AiK3AgAApgS2AiK4AgEA-QMAIbkCAQD5AwAhugIBAPkDACG7AkAA-wMAIQIAAADHAgAgFwAA1AIAIAymAgEA-QMAIbACAQD5AwAhsQIBAPkDACGyAkAA-wMAIbMCAQD5AwAhtAIBAPkDACG2AgAApgS2AiK3AgAApgS2AiK4AgEA-QMAIbkCAQD5AwAhugIBAPkDACG7AkAA-wMAIQIAAADKAgAgFwAA1gIAIAIAAADKAgAgFwAA1gIAIAMAAADHAgAgHgAAzwIAIB8AANQCACABAAAAxwIAIAEAAADKAgAgAwcAAPEEACAkAADzBAAgJQAA8gQAIA-KAgAAswMAMIsCAADdAgAQjAIAALMDADCmAgEApQMAIbACAQCSAwAhsQIBAKUDACGyAkAAlQMAIbMCAQCSAwAhtAIBAJIDACG2AgAAtAO2AiK3AgAAtAO2AiK4AgEAkgMAIbkCAQCSAwAhugIBAJIDACG7AkAAlQMAIQMAAADKAgAgAQAA3AIAMCMAAN0CACADAAAAygIAIAEAAMsCADACAADHAgAgDYoCAACuAwAwiwIAAOMCABCMAgAArgMAMKYCAQAAAAGnAgEAnwMAIagCAQCfAwAhqQJAAKIDACGqAgIAsAMAIasCQACiAwAhrAICALADACGtAkAAsQMAIa4CQACiAwAhrwJAAKIDACEBAAAA4AIAIAEAAADgAgAgDYoCAACuAwAwiwIAAOMCABCMAgAArgMAMKYCAQCvAwAhpwIBAJ8DACGoAgEAnwMAIakCQACiAwAhqgICALADACGrAkAAogMAIawCAgCwAwAhrQJAALEDACGuAkAAogMAIa8CQACiAwAhAa0CAADrBAAgAwAAAOMCACABAADkAgAwAgAA4AIAIAMAAADjAgAgAQAA5AIAMAIAAOACACADAAAA4wIAIAEAAOQCADACAADgAgAgCqYCAQAAAAGnAgEAAAABqAIBAAAAAakCQAAAAAGqAgIAAAABqwJAAAAAAawCAgAAAAGtAkAAAAABrgJAAAAAAa8CQAAAAAEBFwAA6AIAIAqmAgEAAAABpwIBAAAAAagCAQAAAAGpAkAAAAABqgICAAAAAasCQAAAAAGsAgIAAAABrQJAAAAAAa4CQAAAAAGvAkAAAAABARcAAOoCADABFwAA6gIAMAqmAgEA-QMAIacCAQD5AwAhqAIBAPkDACGpAkAA-wMAIaoCAgCWBAAhqwJAAPsDACGsAgIAlgQAIa0CQADTBAAhrgJAAPsDACGvAkAA-wMAIQIAAADgAgAgFwAA7QIAIAqmAgEA-QMAIacCAQD5AwAhqAIBAPkDACGpAkAA-wMAIaoCAgCWBAAhqwJAAPsDACGsAgIAlgQAIa0CQADTBAAhrgJAAPsDACGvAkAA-wMAIQIAAADjAgAgFwAA7wIAIAIAAADjAgAgFwAA7wIAIAMAAADgAgAgHgAA6AIAIB8AAO0CACABAAAA4AIAIAEAAADjAgAgBgcAAOwEACAkAADvBAAgJQAA7gQAIKYBAADtBAAgpwEAAPAEACCtAgAA6wQAIA2KAgAApAMAMIsCAAD2AgAQjAIAAKQDADCmAgEApQMAIacCAQCSAwAhqAIBAJIDACGpAkAAlQMAIaoCAgCmAwAhqwJAAJUDACGsAgIApgMAIa0CQACnAwAhrgJAAJUDACGvAkAAlQMAIQMAAADjAgAgAQAA9QIAMCMAAPYCACADAAAA4wIAIAEAAOQCADACAADgAgAgCQYAAKMDACCKAgAAngMAMIsCAAAPABCMAgAAngMAMI0CAQAAAAGOAgEAnwMAIY8CEACgAwAhkAIAAKEDACCRAkAAogMAIQEAAAD5AgAgAQAAAPkCACABBgAA6gQAIAMAAAAPACABAAD8AgAwAgAA-QIAIAMAAAAPACABAAD8AgAwAgAA-QIAIAMAAAAPACABAAD8AgAwAgAA-QIAIAYGAADpBAAgjQIBAAAAAY4CAQAAAAGPAhAAAAABkAKAAAAAAZECQAAAAAEBFwAAgAMAIAWNAgEAAAABjgIBAAAAAY8CEAAAAAGQAoAAAAABkQJAAAAAAQEXAACCAwAwARcAAIIDADAGBgAA_AMAII0CAQD5AwAhjgIBAPkDACGPAhAA-gMAIZACgAAAAAGRAkAA-wMAIQIAAAD5AgAgFwAAhQMAIAWNAgEA-QMAIY4CAQD5AwAhjwIQAPoDACGQAoAAAAABkQJAAPsDACECAAAADwAgFwAAhwMAIAIAAAAPACAXAACHAwAgAwAAAPkCACAeAACAAwAgHwAAhQMAIAEAAAD5AgAgAQAAAA8AIAUHAAD0AwAgJAAA9wMAICUAAPYDACCmAQAA9QMAIKcBAAD4AwAgCIoCAACRAwAwiwIAAI4DABCMAgAAkQMAMI0CAQCSAwAhjgIBAJIDACGPAhAAkwMAIZACAACUAwAgkQJAAJUDACEDAAAADwAgAQAAjQMAMCMAAI4DACADAAAADwAgAQAA_AIAMAIAAPkCACAIigIAAJEDADCLAgAAjgMAEIwCAACRAwAwjQIBAJIDACGOAgEAkgMAIY8CEACTAwAhkAIAAJQDACCRAkAAlQMAIQ4HAACXAwAgJAAAnQMAICUAAJ0DACCSAgEAAAABkwIBAAAABJQCAQAAAASVAgEAAAABlgIBAAAAAZcCAQAAAAGYAgEAAAABmQIBAJwDACGgAgEAAAABoQIBAAAAAaICAQAAAAENBwAAlwMAICQAAJsDACAlAACbAwAgpgEAAJsDACCnAQAAmwMAIJICEAAAAAGTAhAAAAAElAIQAAAABJUCEAAAAAGWAhAAAAABlwIQAAAAAZgCEAAAAAGZAhAAmgMAIQ8HAACXAwAgJAAAmQMAICUAAJkDACCSAoAAAAABlQKAAAAAAZYCgAAAAAGXAoAAAAABmAKAAAAAAZkCgAAAAAGaAgEAAAABmwIBAAAAAZwCAQAAAAGdAoAAAAABngKAAAAAAZ8CgAAAAAELBwAAlwMAICQAAJgDACAlAACYAwAgkgJAAAAAAZMCQAAAAASUAkAAAAAElQJAAAAAAZYCQAAAAAGXAkAAAAABmAJAAAAAAZkCQACWAwAhCwcAAJcDACAkAACYAwAgJQAAmAMAIJICQAAAAAGTAkAAAAAElAJAAAAABJUCQAAAAAGWAkAAAAABlwJAAAAAAZgCQAAAAAGZAkAAlgMAIQiSAgIAAAABkwICAAAABJQCAgAAAASVAgIAAAABlgICAAAAAZcCAgAAAAGYAgIAAAABmQICAJcDACEIkgJAAAAAAZMCQAAAAASUAkAAAAAElQJAAAAAAZYCQAAAAAGXAkAAAAABmAJAAAAAAZkCQACYAwAhDJICgAAAAAGVAoAAAAABlgKAAAAAAZcCgAAAAAGYAoAAAAABmQKAAAAAAZoCAQAAAAGbAgEAAAABnAIBAAAAAZ0CgAAAAAGeAoAAAAABnwKAAAAAAQ0HAACXAwAgJAAAmwMAICUAAJsDACCmAQAAmwMAIKcBAACbAwAgkgIQAAAAAZMCEAAAAASUAhAAAAAElQIQAAAAAZYCEAAAAAGXAhAAAAABmAIQAAAAAZkCEACaAwAhCJICEAAAAAGTAhAAAAAElAIQAAAABJUCEAAAAAGWAhAAAAABlwIQAAAAAZgCEAAAAAGZAhAAmwMAIQ4HAACXAwAgJAAAnQMAICUAAJ0DACCSAgEAAAABkwIBAAAABJQCAQAAAASVAgEAAAABlgIBAAAAAZcCAQAAAAGYAgEAAAABmQIBAJwDACGgAgEAAAABoQIBAAAAAaICAQAAAAELkgIBAAAAAZMCAQAAAASUAgEAAAAElQIBAAAAAZYCAQAAAAGXAgEAAAABmAIBAAAAAZkCAQCdAwAhoAIBAAAAAaECAQAAAAGiAgEAAAABCQYAAKMDACCKAgAAngMAMIsCAAAPABCMAgAAngMAMI0CAQCfAwAhjgIBAJ8DACGPAhAAoAMAIZACAAChAwAgkQJAAKIDACELkgIBAAAAAZMCAQAAAASUAgEAAAAElQIBAAAAAZYCAQAAAAGXAgEAAAABmAIBAAAAAZkCAQCdAwAhoAIBAAAAAaECAQAAAAGiAgEAAAABCJICEAAAAAGTAhAAAAAElAIQAAAABJUCEAAAAAGWAhAAAAABlwIQAAAAAZgCEAAAAAGZAhAAmwMAIQySAoAAAAABlQKAAAAAAZYCgAAAAAGXAoAAAAABmAKAAAAAAZkCgAAAAAGaAgEAAAABmwIBAAAAAZwCAQAAAAGdAoAAAAABngKAAAAAAZ8CgAAAAAEIkgJAAAAAAZMCQAAAAASUAkAAAAAElQJAAAAAAZYCQAAAAAGXAkAAAAABmAJAAAAAAZkCQACYAwAhA6MCAAARACCkAgAAEQAgpQIAABEAIA2KAgAApAMAMIsCAAD2AgAQjAIAAKQDADCmAgEApQMAIacCAQCSAwAhqAIBAJIDACGpAkAAlQMAIaoCAgCmAwAhqwJAAJUDACGsAgIApgMAIa0CQACnAwAhrgJAAJUDACGvAkAAlQMAIQsHAACXAwAgJAAAnQMAICUAAJ0DACCSAgEAAAABkwIBAAAABJQCAQAAAASVAgEAAAABlgIBAAAAAZcCAQAAAAGYAgEAAAABmQIBAK0DACENBwAAlwMAICQAAJcDACAlAACXAwAgpgEAAKwDACCnAQAAlwMAIJICAgAAAAGTAgIAAAAElAICAAAABJUCAgAAAAGWAgIAAAABlwICAAAAAZgCAgAAAAGZAgIAqwMAIQsHAACpAwAgJAAAqgMAICUAAKoDACCSAkAAAAABkwJAAAAABZQCQAAAAAWVAkAAAAABlgJAAAAAAZcCQAAAAAGYAkAAAAABmQJAAKgDACELBwAAqQMAICQAAKoDACAlAACqAwAgkgJAAAAAAZMCQAAAAAWUAkAAAAAFlQJAAAAAAZYCQAAAAAGXAkAAAAABmAJAAAAAAZkCQACoAwAhCJICAgAAAAGTAgIAAAAFlAICAAAABZUCAgAAAAGWAgIAAAABlwICAAAAAZgCAgAAAAGZAgIAqQMAIQiSAkAAAAABkwJAAAAABZQCQAAAAAWVAkAAAAABlgJAAAAAAZcCQAAAAAGYAkAAAAABmQJAAKoDACENBwAAlwMAICQAAJcDACAlAACXAwAgpgEAAKwDACCnAQAAlwMAIJICAgAAAAGTAgIAAAAElAICAAAABJUCAgAAAAGWAgIAAAABlwICAAAAAZgCAgAAAAGZAgIAqwMAIQiSAggAAAABkwIIAAAABJQCCAAAAASVAggAAAABlgIIAAAAAZcCCAAAAAGYAggAAAABmQIIAKwDACELBwAAlwMAICQAAJ0DACAlAACdAwAgkgIBAAAAAZMCAQAAAASUAgEAAAAElQIBAAAAAZYCAQAAAAGXAgEAAAABmAIBAAAAAZkCAQCtAwAhDYoCAACuAwAwiwIAAOMCABCMAgAArgMAMKYCAQCvAwAhpwIBAJ8DACGoAgEAnwMAIakCQACiAwAhqgICALADACGrAkAAogMAIawCAgCwAwAhrQJAALEDACGuAkAAogMAIa8CQACiAwAhCJICAQAAAAGTAgEAAAAElAIBAAAABJUCAQAAAAGWAgEAAAABlwIBAAAAAZgCAQAAAAGZAgEAsgMAIQiSAgIAAAABkwICAAAABJQCAgAAAASVAgIAAAABlgICAAAAAZcCAgAAAAGYAgIAAAABmQICAJcDACEIkgJAAAAAAZMCQAAAAAWUAkAAAAAFlQJAAAAAAZYCQAAAAAGXAkAAAAABmAJAAAAAAZkCQACqAwAhCJICAQAAAAGTAgEAAAAElAIBAAAABJUCAQAAAAGWAgEAAAABlwIBAAAAAZgCAQAAAAGZAgEAsgMAIQ-KAgAAswMAMIsCAADdAgAQjAIAALMDADCmAgEApQMAIbACAQCSAwAhsQIBAKUDACGyAkAAlQMAIbMCAQCSAwAhtAIBAJIDACG2AgAAtAO2AiK3AgAAtAO2AiK4AgEAkgMAIbkCAQCSAwAhugIBAJIDACG7AkAAlQMAIQcHAACXAwAgJAAAtgMAICUAALYDACCSAgAAALYCApMCAAAAtgIIlAIAAAC2AgiZAgAAtQO2AiIHBwAAlwMAICQAALYDACAlAAC2AwAgkgIAAAC2AgKTAgAAALYCCJQCAAAAtgIImQIAALUDtgIiBJICAAAAtgICkwIAAAC2AgiUAgAAALYCCJkCAAC2A7YCIg-KAgAAtwMAMIsCAADKAgAQjAIAALcDADCmAgEArwMAIbACAQCfAwAhsQIBAK8DACGyAkAAogMAIbMCAQCfAwAhtAIBAJ8DACG2AgAAuAO2AiK3AgAAuAO2AiK4AgEAnwMAIbkCAQCfAwAhugIBAJ8DACG7AkAAogMAIQSSAgAAALYCApMCAAAAtgIIlAIAAAC2AgiZAgAAtgO2AiIPigIAALkDADCLAgAAxAIAEIwCAAC5AwAwpgIBAKUDACGuAkAAlQMAIa8CQACVAwAhsAIBAJIDACGxAgEApQMAIbICQACVAwAhswIBAJIDACG0AgEAkgMAIbgCAQCSAwAhuQIBAJIDACG6AgEAkgMAIbwCAAC0A7YCIgyKAgAAugMAMIsCAACuAgAQjAIAALoDADCPAhAAkwMAIaYCAQClAwAhrgJAAJUDACGvAkAAlQMAIbECAQClAwAhswIBALwDACG0AgEAvAMAIb4CAAC7A74CI78CIAC9AwAhBwcAAKkDACAkAADDAwAgJQAAwwMAIJICAAAAvgIDkwIAAAC-AgmUAgAAAL4CCZkCAADCA74CIw4HAACpAwAgJAAAwQMAICUAAMEDACCSAgEAAAABkwIBAAAABZQCAQAAAAWVAgEAAAABlgIBAAAAAZcCAQAAAAGYAgEAAAABmQIBAMADACGgAgEAAAABoQIBAAAAAaICAQAAAAEFBwAAlwMAICQAAL8DACAlAAC_AwAgkgIgAAAAAZkCIAC-AwAhBQcAAJcDACAkAAC_AwAgJQAAvwMAIJICIAAAAAGZAiAAvgMAIQKSAiAAAAABmQIgAL8DACEOBwAAqQMAICQAAMEDACAlAADBAwAgkgIBAAAAAZMCAQAAAAWUAgEAAAAFlQIBAAAAAZYCAQAAAAGXAgEAAAABmAIBAAAAAZkCAQDAAwAhoAIBAAAAAaECAQAAAAGiAgEAAAABC5ICAQAAAAGTAgEAAAAFlAIBAAAABZUCAQAAAAGWAgEAAAABlwIBAAAAAZgCAQAAAAGZAgEAwQMAIaACAQAAAAGhAgEAAAABogIBAAAAAQcHAACpAwAgJAAAwwMAICUAAMMDACCSAgAAAL4CA5MCAAAAvgIJlAIAAAC-AgmZAgAAwgO-AiMEkgIAAAC-AgOTAgAAAL4CCZQCAAAAvgIJmQIAAMMDvgIjCYoCAADEAwAwiwIAAJgCABCMAgAAxAMAMKYCAQClAwAhrgJAAJUDACGxAgEApQMAIbMCAQCSAwAhtAIBAJIDACG-AgAAxQO-AiIHBwAAlwMAICQAAMcDACAlAADHAwAgkgIAAAC-AgKTAgAAAL4CCJQCAAAAvgIImQIAAMYDvgIiBwcAAJcDACAkAADHAwAgJQAAxwMAIJICAAAAvgICkwIAAAC-AgiUAgAAAL4CCJkCAADGA74CIgSSAgAAAL4CApMCAAAAvgIIlAIAAAC-AgiZAgAAxwO-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-AgAA4QO-AiO_AiAAywMAIQSSAgAAAL4CA5MCAAAAvgIJlAIAAAC-AgmZAgAAwwO-AiMKDgAA3wMAIIoCAADiAwAwiwIAACEAEIwCAADiAwAwpgIBAK8DACGuAkAAogMAIbECAQCvAwAhswIBAJ8DACG0AgEAnwMAIb4CAADjA74CIgSSAgAAAL4CApMCAAAAvgIIlAIAAAC-AgiZAgAAxwO-AiIQCgAA5QMAIA0AAOYDACAPAADnAwAgEAAA6AMAIBEAAOkDACCKAgAA5AMAMIsCAAAbABCMAgAA5AMAMI4CAQCfAwAhpgIBAK8DACGuAkAAogMAIa8CQACiAwAhwAIBAK8DACHBAgEArwMAIcICAgCwAwAhwwIQAKADACEUCAAA7AMAIAkAANwDACALAADtAwAgDAAAzAMAIIoCAADrAwAwiwIAABEAEIwCAADrAwAwpgIBAK8DACGuAkAAogMAIa8CQACiAwAhzAIBAJ8DACHNAgEA2QMAIc4CAQDZAwAhzwIBANkDACHQAgEA2QMAIdECAQCfAwAh0gIBAJ8DACHTAgEA2QMAIecCAAARACDoAgAAEQAgDAwAAMwDACCKAgAAygMAMIsCAADZAQAQjAIAAMoDADCOAgEAnwMAIaYCAQCvAwAhrgJAAKIDACGvAkAAogMAIb8CIADLAwAhxAIBAJ8DACHnAgAA2QEAIOgCAADZAQAgA6MCAAAhACCkAgAAIQAgpQIAACEAIAOjAgAAJQAgpAIAACUAIKUCAAAlACADowIAACkAIKQCAAApACClAgAAKQAgDQoAAOUDACCKAgAA6gMAMIsCAAAXABCMAgAA6gMAMKYCAQCvAwAhpwIBAJ8DACGuAkAAogMAIa8CQACiAwAhwAIBAK8DACHFAgEAnwMAIcYCQACiAwAhxwJAALEDACHIAkAAsQMAIRIIAADsAwAgCQAA3AMAIAsAAO0DACAMAADMAwAgigIAAOsDADCLAgAAEQAQjAIAAOsDADCmAgEArwMAIa4CQACiAwAhrwJAAKIDACHMAgEAnwMAIc0CAQDZAwAhzgIBANkDACHPAgEA2QMAIdACAQDZAwAh0QIBAJ8DACHSAgEAnwMAIdMCAQDZAwAhCwYAAKMDACCKAgAAngMAMIsCAAAPABCMAgAAngMAMI0CAQCfAwAhjgIBAJ8DACGPAhAAoAMAIZACAAChAwAgkQJAAKIDACHnAgAADwAg6AIAAA8AIAOjAgAAFwAgpAIAABcAIKUCAAAXACACwAIBAAAAAckCAQAAAAEJAwAA8QMAIAoAAOUDACCKAgAA7wMAMIsCAAALABCMAgAA7wMAMK4CQACiAwAhwAIBAK8DACHJAgEAnwMAIcsCAADwA8sCIgSSAgAAAMsCApMCAAAAywIIlAIAAADLAgiZAgAA0QPLAiIRBAAA2gMAIAUAANsDACAGAADcAwAgigIAANgDADCLAgAANwAQjAIAANgDADCOAgEAnwMAIaYCAQCfAwAhpwIBAJ8DACGuAkAAogMAIa8CQACiAwAhywIBAJ8DACHiAiAAywMAIeMCAQDZAwAh5AIBANkDACHnAgAANwAg6AIAADcAIBEDAADxAwAgigIAAPIDADCLAgAABwAQjAIAAPIDADCmAgEAnwMAIa4CQACiAwAhrwJAAKIDACHJAgEAnwMAIdYCAQCfAwAh1wIBAJ8DACHYAgEA2QMAIdkCAQDZAwAh2gIBANkDACHbAkAAsQMAIdwCQACxAwAh3QIBANkDACHeAgEA2QMAIQwDAADxAwAgigIAAPMDADCLAgAAAwAQjAIAAPMDADCmAgEAnwMAIa4CQACiAwAhrwJAAKIDACHGAkAAogMAIckCAQCfAwAh3wIBAJ8DACHgAgEA2QMAIeECAQDZAwAhAAAAAAAB7AIBAAAAAQXsAhAAAAAB8gIQAAAAAfMCEAAAAAH0AhAAAAAB9QIQAAAAAQHsAkAAAAABCx4AAP0DADAfAACCBAAw6QIAAP4DADDqAgAA_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-QMAIa4CQAD7AwAhrwJAAPsDACHBAgEA-QMAIcICAgCWBAAhwwIQAPoDACEF7AICAAAAAfICAgAAAAHzAgIAAAAB9AICAAAAAfUCAgAAAAELDQAAmAQAIA8AAJkEACAQAACaBAAgEQAAmwQAII4CAQD5AwAhpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhwQIBAPkDACHCAgIAlgQAIcMCEAD6AwAhBR4AAKUGACAfAACrBgAg6QIAAKYGACDqAgAAqgYAIO8CAADWAQAgCx4AALcEADAfAAC8BAAw6QIAALgEADDqAgAAuQQAMOsCAAC6BAAg7AIAALsEADDtAgAAuwQAMO4CAAC7BAAw7wIAALsEADDwAgAAvQQAMPECAAC-BAAwCx4AAKkEADAfAACuBAAw6QIAAKoEADDqAgAAqwQAMOsCAACsBAAg7AIAAK0EADDtAgAArQQAMO4CAACtBAAw7wIAAK0EADDwAgAArwQAMPECAACwBAAwCx4AAJwEADAfAAChBAAw6QIAAJ0EADDqAgAAngQAMOsCAACfBAAg7AIAAKAEADDtAgAAoAQAMO4CAACgBAAw7wIAAKAEADDwAgAAogQAMPECAACjBAAwC6YCAQAAAAGuAkAAAAABrwJAAAAAAbACAQAAAAGyAkAAAAABswIBAAAAAbQCAQAAAAG4AgEAAAABuQIBAAAAAboCAQAAAAG8AgAAALYCAgIAAAArACAeAACoBAAgAwAAACsAIB4AAKgEACAfAACnBAAgARcAAKkGADARDgAA3wMAIIoCAADeAwAwiwIAACkAEIwCAADeAwAwpgIBAAAAAa4CQACiAwAhrwJAAKIDACGwAgEAAAABsQIBAK8DACGyAkAAogMAIbMCAQCfAwAhtAIBAJ8DACG4AgEAnwMAIbkCAQCfAwAhugIBAJ8DACG8AgAAuAO2AiLlAgAA3QMAIAIAAAArACAXAACnBAAgAgAAAKQEACAXAAClBAAgD4oCAACjBAAwiwIAAKQEABCMAgAAowQAMKYCAQCvAwAhrgJAAKIDACGvAkAAogMAIbACAQCfAwAhsQIBAK8DACGyAkAAogMAIbMCAQCfAwAhtAIBAJ8DACG4AgEAnwMAIbkCAQCfAwAhugIBAJ8DACG8AgAAuAO2AiIPigIAAKMEADCLAgAApAQAEIwCAACjBAAwpgIBAK8DACGuAkAAogMAIa8CQACiAwAhsAIBAJ8DACGxAgEArwMAIbICQACiAwAhswIBAJ8DACG0AgEAnwMAIbgCAQCfAwAhuQIBAJ8DACG6AgEAnwMAIbwCAAC4A7YCIgumAgEA-QMAIa4CQAD7AwAhrwJAAPsDACGwAgEA-QMAIbICQAD7AwAhswIBAPkDACG0AgEA-QMAIbgCAQD5AwAhuQIBAPkDACG6AgEA-QMAIbwCAACmBLYCIgHsAgAAALYCAgumAgEA-QMAIa4CQAD7AwAhrwJAAPsDACGwAgEA-QMAIbICQAD7AwAhswIBAPkDACG0AgEA-QMAIbgCAQD5AwAhuQIBAPkDACG6AgEA-QMAIbwCAACmBLYCIgumAgEAAAABrgJAAAAAAa8CQAAAAAGwAgEAAAABsgJAAAAAAbMCAQAAAAG0AgEAAAABuAIBAAAAAbkCAQAAAAG6AgEAAAABvAIAAAC2AgIIjwIQAAAAAaYCAQAAAAGuAkAAAAABrwJAAAAAAbMCAQAAAAG0AgEAAAABvgIAAAC-AgO_AiAAAAABAgAAACcAIB4AALYEACADAAAAJwAgHgAAtgQAIB8AALUEACABFwAAqAYAMA0OAADfAwAgigIAAOADADCLAgAAJQAQjAIAAOADADCPAhAAoAMAIaYCAQAAAAGuAkAAogMAIa8CQACiAwAhsQIBAK8DACGzAgEA2QMAIbQCAQDZAwAhvgIAAOEDvgIjvwIgAMsDACECAAAAJwAgFwAAtQQAIAIAAACxBAAgFwAAsgQAIAyKAgAAsAQAMIsCAACxBAAQjAIAALAEADCPAhAAoAMAIaYCAQCvAwAhrgJAAKIDACGvAkAAogMAIbECAQCvAwAhswIBANkDACG0AgEA2QMAIb4CAADhA74CI78CIADLAwAhDIoCAACwBAAwiwIAALEEABCMAgAAsAQAMI8CEACgAwAhpgIBAK8DACGuAkAAogMAIa8CQACiAwAhsQIBAK8DACGzAgEA2QMAIbQCAQDZAwAhvgIAAOEDvgIjvwIgAMsDACEIjwIQAPoDACGmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACGzAgEAhwQAIbQCAQCHBAAhvgIAALMEvgIjvwIgALQEACEB7AIAAAC-AgMB7AIgAAAAAQiPAhAA-gMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIbMCAQCHBAAhtAIBAIcEACG-AgAAswS-AiO_AiAAtAQAIQiPAhAAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABswIBAAAAAbQCAQAAAAG-AgAAAL4CA78CIAAAAAEFpgIBAAAAAa4CQAAAAAGzAgEAAAABtAIBAAAAAb4CAAAAvgICAgAAACMAIB4AAMMEACADAAAAIwAgHgAAwwQAIB8AAMIEACABFwAApwYAMAoOAADfAwAgigIAAOIDADCLAgAAIQAQjAIAAOIDADCmAgEAAAABrgJAAKIDACGxAgEArwMAIbMCAQCfAwAhtAIBAJ8DACG-AgAA4wO-AiICAAAAIwAgFwAAwgQAIAIAAAC_BAAgFwAAwAQAIAmKAgAAvgQAMIsCAAC_BAAQjAIAAL4EADCmAgEArwMAIa4CQACiAwAhsQIBAK8DACGzAgEAnwMAIbQCAQCfAwAhvgIAAOMDvgIiCYoCAAC-BAAwiwIAAL8EABCMAgAAvgQAMKYCAQCvAwAhrgJAAKIDACGxAgEArwMAIbMCAQCfAwAhtAIBAJ8DACG-AgAA4wO-AiIFpgIBAPkDACGuAkAA-wMAIbMCAQD5AwAhtAIBAPkDACG-AgAAwQS-AiIB7AIAAAC-AgIFpgIBAPkDACGuAkAA-wMAIbMCAQD5AwAhtAIBAPkDACG-AgAAwQS-AiIFpgIBAAAAAa4CQAAAAAGzAgEAAAABtAIBAAAAAb4CAAAAvgICCw0AAMUEACAPAADGBAAgEAAAxwQAIBEAAMgEACCOAgEAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABwQIBAAAAAcICAgAAAAHDAhAAAAABAx4AAKUGACDpAgAApgYAIO8CAADWAQAgBB4AALcEADDpAgAAuAQAMOsCAAC6BAAg7wIAALsEADAEHgAAqQQAMOkCAACqBAAw6wIAAKwEACDvAgAArQQAMAQeAACcBAAw6QIAAJ0EADDrAgAAnwQAIO8CAACgBAAwCKYCAQAAAAGnAgEAAAABrgJAAAAAAa8CQAAAAAHFAgEAAAABxgJAAAAAAccCQAAAAAHIAkAAAAABAgAAABkAIB4AANUEACADAAAAGQAgHgAA1QQAIB8AANQEACABFwAApAYAMA0KAADlAwAgigIAAOoDADCLAgAAFwAQjAIAAOoDADCmAgEAAAABpwIBAJ8DACGuAkAAogMAIa8CQACiAwAhwAIBAK8DACHFAgEAAAABxgJAAKIDACHHAkAAsQMAIcgCQACxAwAhAgAAABkAIBcAANQEACACAAAA0QQAIBcAANIEACAMigIAANAEADCLAgAA0QQAEIwCAADQBAAwpgIBAK8DACGnAgEAnwMAIa4CQACiAwAhrwJAAKIDACHAAgEArwMAIcUCAQCfAwAhxgJAAKIDACHHAkAAsQMAIcgCQACxAwAhDIoCAADQBAAwiwIAANEEABCMAgAA0AQAMKYCAQCvAwAhpwIBAJ8DACGuAkAAogMAIa8CQACiAwAhwAIBAK8DACHFAgEAnwMAIcYCQACiAwAhxwJAALEDACHIAkAAsQMAIQimAgEA-QMAIacCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcUCAQD5AwAhxgJAAPsDACHHAkAA0wQAIcgCQADTBAAhAewCQAAAAAEIpgIBAPkDACGnAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHFAgEA-QMAIcYCQAD7AwAhxwJAANMEACHIAkAA0wQAIQimAgEAAAABpwIBAAAAAa4CQAAAAAGvAkAAAAABxQIBAAAAAcYCQAAAAAHHAkAAAAAByAJAAAAAAQQDAADkBAAgrgJAAAAAAckCAQAAAAHLAgAAAMsCAgIAAAANACAeAADjBAAgAwAAAA0AIB4AAOMEACAfAADhBAAgARcAAKMGADAKAwAA8QMAIAoAAOUDACCKAgAA7wMAMIsCAAALABCMAgAA7wMAMK4CQACiAwAhwAIBAK8DACHJAgEAnwMAIcsCAADwA8sCIuYCAADuAwAgAgAAAA0AIBcAAOEEACACAAAA3gQAIBcAAN8EACAHigIAAN0EADCLAgAA3gQAEIwCAADdBAAwrgJAAKIDACHAAgEArwMAIckCAQCfAwAhywIAAPADywIiB4oCAADdBAAwiwIAAN4EABCMAgAA3QQAMK4CQACiAwAhwAIBAK8DACHJAgEAnwMAIcsCAADwA8sCIgOuAkAA-wMAIckCAQD5AwAhywIAAOAEywIiAewCAAAAywICBAMAAOIEACCuAkAA-wMAIckCAQD5AwAhywIAAOAEywIiBR4AAJ4GACAfAAChBgAg6QIAAJ8GACDqAgAAoAYAIO8CAAABACAEAwAA5AQAIK4CQAAAAAHJAgEAAAABywIAAADLAgIDHgAAngYAIOkCAACfBgAg7wIAAAEAIA0JAADmBAAgCwAA5wQAIAwAAOgEACCmAgEAAAABrgJAAAAAAa8CQAAAAAHMAgEAAAABzQIBAAAAAc4CAQAAAAHPAgEAAAAB0AIBAAAAAdECAQAAAAHSAgEAAAABBB4AANYEADDpAgAA1wQAMOsCAADZBAAg7wIAANoEADAEHgAAyQQAMOkCAADKBAAw6wIAAMwEACDvAgAAzQQAMAQeAACMBAAw6QIAAI0EADDrAgAAjwQAIO8CAACQBAAwBB4AAP0DADDpAgAA_gMAMOsCAACABAAg7wIAAIEEADAAAAAAAAAAAAAAAAAABR4AAJkGACAfAACcBgAg6QIAAJoGACDqAgAAmwYAIO8CAAAdACADHgAAmQYAIOkCAACaBgAg7wIAAB0AIAAAAAAABR4AAJQGACAfAACXBgAg6QIAAJUGACDqAgAAlgYAIO8CAAAdACADHgAAlAYAIOkCAACVBgAg7wIAAB0AIAAAAAUeAACPBgAgHwAAkgYAIOkCAACQBgAg6gIAAJEGACDvAgAAHQAgAx4AAI8GACDpAgAAkAYAIO8CAAAdACAAAAAAAAUeAACKBgAgHwAAjQYAIOkCAACLBgAg6gIAAIwGACDvAgAAEwAgAx4AAIoGACDpAgAAiwYAIO8CAAATACAAAAALHgAAkAUAMB8AAJQFADDpAgAAkQUAMOoCAACSBQAw6wIAAJMFACDsAgAAkAQAMO0CAACQBAAw7gIAAJAEADDvAgAAkAQAMPACAACVBQAw8QIAAJMEADALCgAAiwUAIA8AAMYEACAQAADHBAAgEQAAyAQAII4CAQAAAAGmAgEAAAABrgJAAAAAAa8CQAAAAAHAAgEAAAABwgICAAAAAcMCEAAAAAECAAAAHQAgHgAAmAUAIAMAAAAdACAeAACYBQAgHwAAlwUAIAEXAACJBgAwAgAAAB0AIBcAAJcFACACAAAAlAQAIBcAAJYFACAHjgIBAPkDACGmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHAAgEA-QMAIcICAgCWBAAhwwIQAPoDACELCgAAigUAIA8AAJkEACAQAACaBAAgEQAAmwQAII4CAQD5AwAhpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhwAIBAPkDACHCAgIAlgQAIcMCEAD6AwAhCwoAAIsFACAPAADGBAAgEAAAxwQAIBEAAMgEACCOAgEAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABwAIBAAAAAcICAgAAAAHDAhAAAAABBB4AAJAFADDpAgAAkQUAMOsCAACTBQAg7wIAAJAEADAAAAAABR4AAIQGACAfAACHBgAg6QIAAIUGACDqAgAAhgYAIO8CAAATACADHgAAhAYAIOkCAACFBgAg7wIAABMAIAAAAAUeAAD_BQAgHwAAggYAIOkCAACABgAg6gIAAIEGACDvAgAAEwAgAx4AAP8FACDpAgAAgAYAIO8CAAATACAAAAAHHgAA-gUAIB8AAP0FACDpAgAA-wUAIOoCAAD8BQAg7QIAAA8AIO4CAAAPACDvAgAA-QIAIAMeAAD6BQAg6QIAAPsFACDvAgAA-QIAIAAAAAAAAAUeAAD1BQAgHwAA-AUAIOkCAAD2BQAg6gIAAPcFACDvAgAAAQAgAx4AAPUFACDpAgAA9gUAIO8CAAABACAAAAAFHgAA8AUAIB8AAPMFACDpAgAA8QUAIOoCAADyBQAg7wIAAAEAIAMeAADwBQAg6QIAAPEFACDvAgAAAQAgAAAACx4AANIFADAfAADXBQAw6QIAANMFADDqAgAA1AUAMOsCAADVBQAg7AIAANYFADDtAgAA1gUAMO4CAADWBQAw7wIAANYFADDwAgAA2AUAMPECAADZBQAwCx4AAMYFADAfAADLBQAw6QIAAMcFADDqAgAAyAUAMOsCAADJBQAg7AIAAMoFADDtAgAAygUAMO4CAADKBQAw7wIAAMoFADDwAgAAzAUAMPECAADNBQAwCx4AAL0FADAfAADBBQAw6QIAAL4FADDqAgAAvwUAMOsCAADABQAg7AIAANoEADDtAgAA2gQAMO4CAADaBAAw7wIAANoEADDwAgAAwgUAMPECAADdBAAwBAoAAKQFACCuAkAAAAABwAIBAAAAAcsCAAAAywICAgAAAA0AIB4AAMUFACADAAAADQAgHgAAxQUAIB8AAMQFACABFwAA7wUAMAIAAAANACAXAADEBQAgAgAAAN4EACAXAADDBQAgA64CQAD7AwAhwAIBAPkDACHLAgAA4ATLAiIECgAAowUAIK4CQAD7AwAhwAIBAPkDACHLAgAA4ATLAiIECgAApAUAIK4CQAAAAAHAAgEAAAABywIAAADLAgIMpgIBAAAAAa4CQAAAAAGvAkAAAAAB1gIBAAAAAdcCAQAAAAHYAgEAAAAB2QIBAAAAAdoCAQAAAAHbAkAAAAAB3AJAAAAAAd0CAQAAAAHeAgEAAAABAgAAAAkAIB4AANEFACADAAAACQAgHgAA0QUAIB8AANAFACABFwAA7gUAMBEDAADxAwAgigIAAPIDADCLAgAABwAQjAIAAPIDADCmAgEAAAABrgJAAKIDACGvAkAAogMAIckCAQCfAwAh1gIBAJ8DACHXAgEAnwMAIdgCAQDZAwAh2QIBANkDACHaAgEA2QMAIdsCQACxAwAh3AJAALEDACHdAgEA2QMAId4CAQDZAwAhAgAAAAkAIBcAANAFACACAAAAzgUAIBcAAM8FACAQigIAAM0FADCLAgAAzgUAEIwCAADNBQAwpgIBAJ8DACGuAkAAogMAIa8CQACiAwAhyQIBAJ8DACHWAgEAnwMAIdcCAQCfAwAh2AIBANkDACHZAgEA2QMAIdoCAQDZAwAh2wJAALEDACHcAkAAsQMAId0CAQDZAwAh3gIBANkDACEQigIAAM0FADCLAgAAzgUAEIwCAADNBQAwpgIBAJ8DACGuAkAAogMAIa8CQACiAwAhyQIBAJ8DACHWAgEAnwMAIdcCAQCfAwAh2AIBANkDACHZAgEA2QMAIdoCAQDZAwAh2wJAALEDACHcAkAAsQMAId0CAQDZAwAh3gIBANkDACEMpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAh1gIBAPkDACHXAgEA-QMAIdgCAQCHBAAh2QIBAIcEACHaAgEAhwQAIdsCQADTBAAh3AJAANMEACHdAgEAhwQAId4CAQCHBAAhDKYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIdYCAQD5AwAh1wIBAPkDACHYAgEAhwQAIdkCAQCHBAAh2gIBAIcEACHbAkAA0wQAIdwCQADTBAAh3QIBAIcEACHeAgEAhwQAIQymAgEAAAABrgJAAAAAAa8CQAAAAAHWAgEAAAAB1wIBAAAAAdgCAQAAAAHZAgEAAAAB2gIBAAAAAdsCQAAAAAHcAkAAAAAB3QIBAAAAAd4CAQAAAAEHpgIBAAAAAa4CQAAAAAGvAkAAAAABxgJAAAAAAd8CAQAAAAHgAgEAAAAB4QIBAAAAAQIAAAAFACAeAADdBQAgAwAAAAUAIB4AAN0FACAfAADcBQAgARcAAO0FADAMAwAA8QMAIIoCAADzAwAwiwIAAAMAEIwCAADzAwAwpgIBAAAAAa4CQACiAwAhrwJAAKIDACHGAkAAogMAIckCAQCfAwAh3wIBAAAAAeACAQDZAwAh4QIBANkDACECAAAABQAgFwAA3AUAIAIAAADaBQAgFwAA2wUAIAuKAgAA2QUAMIsCAADaBQAQjAIAANkFADCmAgEAnwMAIa4CQACiAwAhrwJAAKIDACHGAkAAogMAIckCAQCfAwAh3wIBAJ8DACHgAgEA2QMAIeECAQDZAwAhC4oCAADZBQAwiwIAANoFABCMAgAA2QUAMKYCAQCfAwAhrgJAAKIDACGvAkAAogMAIcYCQACiAwAhyQIBAJ8DACHfAgEAnwMAIeACAQDZAwAh4QIBANkDACEHpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhxgJAAPsDACHfAgEA-QMAIeACAQCHBAAh4QIBAIcEACEHpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhxgJAAPsDACHfAgEA-QMAIeACAQCHBAAh4QIBAIcEACEHpgIBAAAAAa4CQAAAAAGvAkAAAAABxgJAAAAAAd8CAQAAAAHgAgEAAAAB4QIBAAAAAQQeAADSBQAw6QIAANMFADDrAgAA1QUAIO8CAADWBQAwBB4AAMYFADDpAgAAxwUAMOsCAADJBQAg7wIAAMoFADAEHgAAvQUAMOkCAAC-BQAw6wIAAMAFACDvAgAA2gQAMAAAAAUKAADlBQAgDQAA5gUAIA8AAOcFACAQAADoBQAgEQAA6QUAIAkIAADqBQAgCQAA4wUAIAsAAOsFACAMAACaBQAgzQIAAOsEACDOAgAA6wQAIM8CAADrBAAg0AIAAOsEACDTAgAA6wQAIAEMAACaBQAgAAAAAQYAAOoEACAABQQAAOEFACAFAADiBQAgBgAA4wUAIOMCAADrBAAg5AIAAOsEACAHpgIBAAAAAa4CQAAAAAGvAkAAAAABxgJAAAAAAd8CAQAAAAHgAgEAAAAB4QIBAAAAAQymAgEAAAABrgJAAAAAAa8CQAAAAAHWAgEAAAAB1wIBAAAAAdgCAQAAAAHZAgEAAAAB2gIBAAAAAdsCQAAAAAHcAkAAAAAB3QIBAAAAAd4CAQAAAAEDrgJAAAAAAcACAQAAAAHLAgAAAMsCAgsFAADfBQAgBgAA4AUAII4CAQAAAAGmAgEAAAABpwIBAAAAAa4CQAAAAAGvAkAAAAABywIBAAAAAeICIAAAAAHjAgEAAAAB5AIBAAAAAQIAAAABACAeAADwBQAgAwAAADcAIB4AAPAFACAfAAD0BQAgDQAAADcAIAUAALsFACAGAAC8BQAgFwAA9AUAII4CAQD5AwAhpgIBAPkDACGnAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHLAgEA-QMAIeICIAC0BAAh4wIBAIcEACHkAgEAhwQAIQsFAAC7BQAgBgAAvAUAII4CAQD5AwAhpgIBAPkDACGnAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHLAgEA-QMAIeICIAC0BAAh4wIBAIcEACHkAgEAhwQAIQsEAADeBQAgBgAA4AUAII4CAQAAAAGmAgEAAAABpwIBAAAAAa4CQAAAAAGvAkAAAAABywIBAAAAAeICIAAAAAHjAgEAAAAB5AIBAAAAAQIAAAABACAeAAD1BQAgAwAAADcAIB4AAPUFACAfAAD5BQAgDQAAADcAIAQAALoFACAGAAC8BQAgFwAA-QUAII4CAQD5AwAhpgIBAPkDACGnAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHLAgEA-QMAIeICIAC0BAAh4wIBAIcEACHkAgEAhwQAIQsEAAC6BQAgBgAAvAUAII4CAQD5AwAhpgIBAPkDACGnAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHLAgEA-QMAIeICIAC0BAAh4wIBAIcEACHkAgEAhwQAIQWNAgEAAAABjgIBAAAAAY8CEAAAAAGQAoAAAAABkQJAAAAAAQIAAAD5AgAgHgAA-gUAIAMAAAAPACAeAAD6BQAgHwAA_gUAIAcAAAAPACAXAAD-BQAgjQIBAPkDACGOAgEA-QMAIY8CEAD6AwAhkAKAAAAAAZECQAD7AwAhBY0CAQD5AwAhjgIBAPkDACGPAhAA-gMAIZACgAAAAAGRAkAA-wMAIQ4IAACpBQAgCwAA5wQAIAwAAOgEACCmAgEAAAABrgJAAAAAAa8CQAAAAAHMAgEAAAABzQIBAAAAAc4CAQAAAAHPAgEAAAAB0AIBAAAAAdECAQAAAAHSAgEAAAAB0wIBAAAAAQIAAAATACAeAAD_BQAgAwAAABEAIB4AAP8FACAfAACDBgAgEAAAABEAIAgAAKgFACALAACKBAAgDAAAiwQAIBcAAIMGACCmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHMAgEA-QMAIc0CAQCHBAAhzgIBAIcEACHPAgEAhwQAIdACAQCHBAAh0QIBAPkDACHSAgEA-QMAIdMCAQCHBAAhDggAAKgFACALAACKBAAgDAAAiwQAIKYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcwCAQD5AwAhzQIBAIcEACHOAgEAhwQAIc8CAQCHBAAh0AIBAIcEACHRAgEA-QMAIdICAQD5AwAh0wIBAIcEACEOCAAAqQUAIAkAAOYEACAMAADoBAAgpgIBAAAAAa4CQAAAAAGvAkAAAAABzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAECAAAAEwAgHgAAhAYAIAMAAAARACAeAACEBgAgHwAAiAYAIBAAAAARACAIAACoBQAgCQAAiQQAIAwAAIsEACAXAACIBgAgpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhzAIBAPkDACHNAgEAhwQAIc4CAQCHBAAhzwIBAIcEACHQAgEAhwQAIdECAQD5AwAh0gIBAPkDACHTAgEAhwQAIQ4IAACoBQAgCQAAiQQAIAwAAIsEACCmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHMAgEA-QMAIc0CAQCHBAAhzgIBAIcEACHPAgEAhwQAIdACAQCHBAAh0QIBAPkDACHSAgEA-QMAIdMCAQCHBAAhB44CAQAAAAGmAgEAAAABrgJAAAAAAa8CQAAAAAHAAgEAAAABwgICAAAAAcMCEAAAAAEOCAAAqQUAIAkAAOYEACALAADnBAAgpgIBAAAAAa4CQAAAAAGvAkAAAAABzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAECAAAAEwAgHgAAigYAIAMAAAARACAeAACKBgAgHwAAjgYAIBAAAAARACAIAACoBQAgCQAAiQQAIAsAAIoEACAXAACOBgAgpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhzAIBAPkDACHNAgEAhwQAIc4CAQCHBAAhzwIBAIcEACHQAgEAhwQAIdECAQD5AwAh0gIBAPkDACHTAgEAhwQAIQ4IAACoBQAgCQAAiQQAIAsAAIoEACCmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHMAgEA-QMAIc0CAQCHBAAhzgIBAIcEACHPAgEAhwQAIdACAQCHBAAh0QIBAPkDACHSAgEA-QMAIdMCAQCHBAAhDAoAAIsFACANAADFBAAgEAAAxwQAIBEAAMgEACCOAgEAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABwAIBAAAAAcECAQAAAAHCAgIAAAABwwIQAAAAAQIAAAAdACAeAACPBgAgAwAAABsAIB4AAI8GACAfAACTBgAgDgAAABsAIAoAAIoFACANAACYBAAgEAAAmgQAIBEAAJsEACAXAACTBgAgjgIBAPkDACGmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHAAgEA-QMAIcECAQD5AwAhwgICAJYEACHDAhAA-gMAIQwKAACKBQAgDQAAmAQAIBAAAJoEACARAACbBAAgjgIBAPkDACGmAgEA-QMAIa4CQAD7AwAhrwJAAPsDACHAAgEA-QMAIcECAQD5AwAhwgICAJYEACHDAhAA-gMAIQwKAACLBQAgDQAAxQQAIA8AAMYEACARAADIBAAgjgIBAAAAAaYCAQAAAAGuAkAAAAABrwJAAAAAAcACAQAAAAHBAgEAAAABwgICAAAAAcMCEAAAAAECAAAAHQAgHgAAlAYAIAMAAAAbACAeAACUBgAgHwAAmAYAIA4AAAAbACAKAACKBQAgDQAAmAQAIA8AAJkEACARAACbBAAgFwAAmAYAII4CAQD5AwAhpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhwAIBAPkDACHBAgEA-QMAIcICAgCWBAAhwwIQAPoDACEMCgAAigUAIA0AAJgEACAPAACZBAAgEQAAmwQAII4CAQD5AwAhpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhwAIBAPkDACHBAgEA-QMAIcICAgCWBAAhwwIQAPoDACEMCgAAiwUAIA0AAMUEACAPAADGBAAgEAAAxwQAII4CAQAAAAGmAgEAAAABrgJAAAAAAa8CQAAAAAHAAgEAAAABwQIBAAAAAcICAgAAAAHDAhAAAAABAgAAAB0AIB4AAJkGACADAAAAGwAgHgAAmQYAIB8AAJ0GACAOAAAAGwAgCgAAigUAIA0AAJgEACAPAACZBAAgEAAAmgQAIBcAAJ0GACCOAgEA-QMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcACAQD5AwAhwQIBAPkDACHCAgIAlgQAIcMCEAD6AwAhDAoAAIoFACANAACYBAAgDwAAmQQAIBAAAJoEACCOAgEA-QMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcACAQD5AwAhwQIBAPkDACHCAgIAlgQAIcMCEAD6AwAhCwQAAN4FACAFAADfBQAgjgIBAAAAAaYCAQAAAAGnAgEAAAABrgJAAAAAAa8CQAAAAAHLAgEAAAAB4gIgAAAAAeMCAQAAAAHkAgEAAAABAgAAAAEAIB4AAJ4GACADAAAANwAgHgAAngYAIB8AAKIGACANAAAANwAgBAAAugUAIAUAALsFACAXAACiBgAgjgIBAPkDACGmAgEA-QMAIacCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcsCAQD5AwAh4gIgALQEACHjAgEAhwQAIeQCAQCHBAAhCwQAALoFACAFAAC7BQAgjgIBAPkDACGmAgEA-QMAIacCAQD5AwAhrgJAAPsDACGvAkAA-wMAIcsCAQD5AwAh4gIgALQEACHjAgEAhwQAIeQCAQCHBAAhA64CQAAAAAHJAgEAAAABywIAAADLAgIIpgIBAAAAAacCAQAAAAGuAkAAAAABrwJAAAAAAcUCAQAAAAHGAkAAAAABxwJAAAAAAcgCQAAAAAEGjgIBAAAAAaYCAQAAAAGuAkAAAAABrwJAAAAAAb8CIAAAAAHEAgEAAAABAgAAANYBACAeAAClBgAgBaYCAQAAAAGuAkAAAAABswIBAAAAAbQCAQAAAAG-AgAAAL4CAgiPAhAAAAABpgIBAAAAAa4CQAAAAAGvAkAAAAABswIBAAAAAbQCAQAAAAG-AgAAAL4CA78CIAAAAAELpgIBAAAAAa4CQAAAAAGvAkAAAAABsAIBAAAAAbICQAAAAAGzAgEAAAABtAIBAAAAAbgCAQAAAAG5AgEAAAABugIBAAAAAbwCAAAAtgICAwAAANkBACAeAAClBgAgHwAArAYAIAgAAADZAQAgFwAArAYAII4CAQD5AwAhpgIBAPkDACGuAkAA-wMAIa8CQAD7AwAhvwIgALQEACHEAgEA-QMAIQaOAgEA-QMAIaYCAQD5AwAhrgJAAPsDACGvAkAA-wMAIb8CIAC0BAAhxAIBAPkDACEHjgIBAAAAAaYCAQAAAAGuAkAAAAABrwJAAAAAAcECAQAAAAHCAgIAAAABwwIQAAAAAQqmAgEAAAABrgJAAAAAAa8CQAAAAAHMAgEAAAABzQIBAAAAAc4CAQAAAAHPAgEAAAAB0AIBAAAAAdECAQAAAAHSAgEAAAABBAQGAgUKAwYOBAcAEQEDAAEBAwABAgMAAQoABQUHABAIEAYJFgQLGggMHgkCBhQFBwAHAQYVAAEKAAUGBwAPCgAFDQAKDyQMECgNESwOAgcACwwfCQEMIAABDgAJAQ4ACQEOAAkDDy0AEC4AES8AAwkwAAsxAAwyAAMEMwAFNAAGNQAAAAADBwAWJAAXJQAYAAAAAwcAFiQAFyUAGAEDAAEBAwABAwcAHSQAHiUAHwAAAAMHAB0kAB4lAB8BAwABAQMAAQMHACQkACUlACYAAAADBwAkJAAlJQAmAAAAAwcALCQALSUALgAAAAMHACwkAC0lAC4BCJwBBgEIogEGAwcAMyQANCUANQAAAAMHADMkADQlADUCAwABCgAFAgMAAQoABQMHADokADslADwAAAADBwA6JAA7JQA8AQoABQEKAAUDBwBBJABCJQBDAAAAAwcAQSQAQiUAQwAAAwcASCQASSUASgAAAAMHAEgkAEklAEoCCgAFDQAKAgoABQ0ACgUHAE8kAFIlAFOmAQBQpwEAUQAAAAAABQcATyQAUiUAU6YBAFCnAQBRAQ4ACQEOAAkDBwBYJABZJQBaAAAAAwcAWCQAWSUAWgEOAAkBDgAJBQcAXyQAYiUAY6YBAGCnAQBhAAAAAAAFBwBfJABiJQBjpgEAYKcBAGEBDgAJAQ4ACQMHAGgkAGklAGoAAAADBwBoJABpJQBqAAAAAwcAcCQAcSUAcgAAAAMHAHAkAHElAHIAAAAFBwB4JAB7JQB8pgEAeacBAHoAAAAAAAUHAHgkAHslAHymAQB5pwEAegAABQcAgQEkAIQBJQCFAaYBAIIBpwEAgwEAAAAAAAUHAIEBJACEASUAhQGmAQCCAacBAIMBEgIBEzYBFDkBFToBFjsBGD0BGT8SGkATG0IBHEQSHUUUIEYBIUcBIkgSJksVJ0wZKE0CKU4CKk8CK1ACLFECLVMCLlUSL1YaMFgCMVoSMlsbM1wCNF0CNV4SNmEcN2IgOGMDOWQDOmUDO2YDPGcDPWkDPmsSP2whQG4DQXASQnEiQ3IDRHMDRXQSRncjR3gnSHooSXsoSn4oS38oTIABKE2CAShOhAEST4UBKVCHAShRiQESUooBKlOLAShUjAEoVY0BElaQAStXkQEvWJIBBVmTAQValAEFW5UBBVyWAQVdmAEFXpoBEl-bATBgngEFYaABEmKhATFjowEFZKQBBWWlARJmqAEyZ6kBNmiqAQRpqwEEaqwBBGutAQRsrgEEbbABBG6yARJvswE3cLUBBHG3ARJyuAE4c7kBBHS6AQR1uwESdr4BOXe_AT14wAEIecEBCHrCAQh7wwEIfMQBCH3GAQh-yAESf8kBPoABywEIgQHNARKCAc4BP4MBzwEIhAHQAQiFAdEBEoYB1AFAhwHVAUSIAdcBCokB2AEKigHbAQqLAdwBCowB3QEKjQHfAQqOAeEBEo8B4gFFkAHkAQqRAeYBEpIB5wFGkwHoAQqUAekBCpUB6gESlgHtAUeXAe4BS5gB7wEJmQHwAQmaAfEBCZsB8gEJnAHzAQmdAfUBCZ4B9wESnwH4AUygAfoBCaEB_AESogH9AU2jAf4BCaQB_wEJpQGAAhKoAYMCTqkBhAJUqgGFAgyrAYYCDKwBhwIMrQGIAgyuAYkCDK8BiwIMsAGNAhKxAY4CVbIBkAIMswGSAhK0AZMCVrUBlAIMtgGVAgy3AZYCErgBmQJXuQGaAlu6AZsCDbsBnAINvAGdAg29AZ4CDb4BnwINvwGhAg3AAaMCEsEBpAJcwgGmAg3DAagCEsQBqQJdxQGqAg3GAasCDccBrAISyAGvAl7JAbACZMoBsQIOywGyAg7MAbMCDs0BtAIOzgG1Ag7PAbcCDtABuQIS0QG6AmXSAbwCDtMBvgIS1AG_AmbVAcACDtYBwQIO1wHCAhLYAcUCZ9kBxgJr2gHIAmzbAckCbNwBzAJs3QHNAmzeAc4CbN8B0AJs4AHSAhLhAdMCbeIB1QJs4wHXAhLkAdgCbuUB2QJs5gHaAmznAdsCEugB3gJv6QHfAnPqAeECdOsB4gJ07AHlAnTtAeYCdO4B5wJ07wHpAnTwAesCEvEB7AJ18gHuAnTzAfACEvQB8QJ29QHyAnT2AfMCdPcB9AIS-AH3Anf5AfgCffoB-gIG-wH7Agb8Af0CBv0B_gIG_gH_Agb_AYEDBoACgwMSgQKEA36CAoYDBoMCiAMShAKJA3-FAooDBoYCiwMGhwKMAxKIAo8DgAGJApADhgE" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"sessions\",\"accounts\",\"complexes\",\"_count\",\"plan\",\"users\",\"complex\",\"invitations\",\"courts\",\"sport\",\"court\",\"availabilities\",\"priceRules\",\"bookings\",\"maintenances\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Account.findUnique\",\"Account.findUniqueOrThrow\",\"Account.findFirst\",\"Account.findFirstOrThrow\",\"Account.findMany\",\"Account.createOne\",\"Account.createMany\",\"Account.createManyAndReturn\",\"Account.updateOne\",\"Account.updateMany\",\"Account.updateManyAndReturn\",\"Account.upsertOne\",\"Account.deleteOne\",\"Account.deleteMany\",\"Account.groupBy\",\"Account.aggregate\",\"Verification.findUnique\",\"Verification.findUniqueOrThrow\",\"Verification.findFirst\",\"Verification.findFirstOrThrow\",\"Verification.findMany\",\"Verification.createOne\",\"Verification.createMany\",\"Verification.createManyAndReturn\",\"Verification.updateOne\",\"Verification.updateMany\",\"Verification.updateManyAndReturn\",\"Verification.upsertOne\",\"Verification.deleteOne\",\"Verification.deleteMany\",\"Verification.groupBy\",\"Verification.aggregate\",\"Complex.findUnique\",\"Complex.findUniqueOrThrow\",\"Complex.findFirst\",\"Complex.findFirstOrThrow\",\"Complex.findMany\",\"Complex.createOne\",\"Complex.createMany\",\"Complex.createManyAndReturn\",\"Complex.updateOne\",\"Complex.updateMany\",\"Complex.updateManyAndReturn\",\"Complex.upsertOne\",\"Complex.deleteOne\",\"Complex.deleteMany\",\"Complex.groupBy\",\"Complex.aggregate\",\"ComplexUser.findUnique\",\"ComplexUser.findUniqueOrThrow\",\"ComplexUser.findFirst\",\"ComplexUser.findFirstOrThrow\",\"ComplexUser.findMany\",\"ComplexUser.createOne\",\"ComplexUser.createMany\",\"ComplexUser.createManyAndReturn\",\"ComplexUser.updateOne\",\"ComplexUser.updateMany\",\"ComplexUser.updateManyAndReturn\",\"ComplexUser.upsertOne\",\"ComplexUser.deleteOne\",\"ComplexUser.deleteMany\",\"ComplexUser.groupBy\",\"ComplexUser.aggregate\",\"ComplexInvitation.findUnique\",\"ComplexInvitation.findUniqueOrThrow\",\"ComplexInvitation.findFirst\",\"ComplexInvitation.findFirstOrThrow\",\"ComplexInvitation.findMany\",\"ComplexInvitation.createOne\",\"ComplexInvitation.createMany\",\"ComplexInvitation.createManyAndReturn\",\"ComplexInvitation.updateOne\",\"ComplexInvitation.updateMany\",\"ComplexInvitation.updateManyAndReturn\",\"ComplexInvitation.upsertOne\",\"ComplexInvitation.deleteOne\",\"ComplexInvitation.deleteMany\",\"ComplexInvitation.groupBy\",\"ComplexInvitation.aggregate\",\"Sport.findUnique\",\"Sport.findUniqueOrThrow\",\"Sport.findFirst\",\"Sport.findFirstOrThrow\",\"Sport.findMany\",\"Sport.createOne\",\"Sport.createMany\",\"Sport.createManyAndReturn\",\"Sport.updateOne\",\"Sport.updateMany\",\"Sport.updateManyAndReturn\",\"Sport.upsertOne\",\"Sport.deleteOne\",\"Sport.deleteMany\",\"Sport.groupBy\",\"Sport.aggregate\",\"Court.findUnique\",\"Court.findUniqueOrThrow\",\"Court.findFirst\",\"Court.findFirstOrThrow\",\"Court.findMany\",\"Court.createOne\",\"Court.createMany\",\"Court.createManyAndReturn\",\"Court.updateOne\",\"Court.updateMany\",\"Court.updateManyAndReturn\",\"Court.upsertOne\",\"Court.deleteOne\",\"Court.deleteMany\",\"_avg\",\"_sum\",\"Court.groupBy\",\"Court.aggregate\",\"CourtMaintenance.findUnique\",\"CourtMaintenance.findUniqueOrThrow\",\"CourtMaintenance.findFirst\",\"CourtMaintenance.findFirstOrThrow\",\"CourtMaintenance.findMany\",\"CourtMaintenance.createOne\",\"CourtMaintenance.createMany\",\"CourtMaintenance.createManyAndReturn\",\"CourtMaintenance.updateOne\",\"CourtMaintenance.updateMany\",\"CourtMaintenance.updateManyAndReturn\",\"CourtMaintenance.upsertOne\",\"CourtMaintenance.deleteOne\",\"CourtMaintenance.deleteMany\",\"CourtMaintenance.groupBy\",\"CourtMaintenance.aggregate\",\"CourtAvailability.findUnique\",\"CourtAvailability.findUniqueOrThrow\",\"CourtAvailability.findFirst\",\"CourtAvailability.findFirstOrThrow\",\"CourtAvailability.findMany\",\"CourtAvailability.createOne\",\"CourtAvailability.createMany\",\"CourtAvailability.createManyAndReturn\",\"CourtAvailability.updateOne\",\"CourtAvailability.updateMany\",\"CourtAvailability.updateManyAndReturn\",\"CourtAvailability.upsertOne\",\"CourtAvailability.deleteOne\",\"CourtAvailability.deleteMany\",\"CourtAvailability.groupBy\",\"CourtAvailability.aggregate\",\"CourtPriceRule.findUnique\",\"CourtPriceRule.findUniqueOrThrow\",\"CourtPriceRule.findFirst\",\"CourtPriceRule.findFirstOrThrow\",\"CourtPriceRule.findMany\",\"CourtPriceRule.createOne\",\"CourtPriceRule.createMany\",\"CourtPriceRule.createManyAndReturn\",\"CourtPriceRule.updateOne\",\"CourtPriceRule.updateMany\",\"CourtPriceRule.updateManyAndReturn\",\"CourtPriceRule.upsertOne\",\"CourtPriceRule.deleteOne\",\"CourtPriceRule.deleteMany\",\"CourtPriceRule.groupBy\",\"CourtPriceRule.aggregate\",\"CourtBooking.findUnique\",\"CourtBooking.findUniqueOrThrow\",\"CourtBooking.findFirst\",\"CourtBooking.findFirstOrThrow\",\"CourtBooking.findMany\",\"CourtBooking.createOne\",\"CourtBooking.createMany\",\"CourtBooking.createManyAndReturn\",\"CourtBooking.updateOne\",\"CourtBooking.updateMany\",\"CourtBooking.updateManyAndReturn\",\"CourtBooking.upsertOne\",\"CourtBooking.deleteOne\",\"CourtBooking.deleteMany\",\"CourtBooking.groupBy\",\"CourtBooking.aggregate\",\"CourtBookingLog.findUnique\",\"CourtBookingLog.findUniqueOrThrow\",\"CourtBookingLog.findFirst\",\"CourtBookingLog.findFirstOrThrow\",\"CourtBookingLog.findMany\",\"CourtBookingLog.createOne\",\"CourtBookingLog.createMany\",\"CourtBookingLog.createManyAndReturn\",\"CourtBookingLog.updateOne\",\"CourtBookingLog.updateMany\",\"CourtBookingLog.updateManyAndReturn\",\"CourtBookingLog.upsertOne\",\"CourtBookingLog.deleteOne\",\"CourtBookingLog.deleteMany\",\"CourtBookingLog.groupBy\",\"CourtBookingLog.aggregate\",\"PasswordResetRequest.findUnique\",\"PasswordResetRequest.findUniqueOrThrow\",\"PasswordResetRequest.findFirst\",\"PasswordResetRequest.findFirstOrThrow\",\"PasswordResetRequest.findMany\",\"PasswordResetRequest.createOne\",\"PasswordResetRequest.createMany\",\"PasswordResetRequest.createManyAndReturn\",\"PasswordResetRequest.updateOne\",\"PasswordResetRequest.updateMany\",\"PasswordResetRequest.updateManyAndReturn\",\"PasswordResetRequest.upsertOne\",\"PasswordResetRequest.deleteOne\",\"PasswordResetRequest.deleteMany\",\"PasswordResetRequest.groupBy\",\"PasswordResetRequest.aggregate\",\"Plan.findUnique\",\"Plan.findUniqueOrThrow\",\"Plan.findFirst\",\"Plan.findFirstOrThrow\",\"Plan.findMany\",\"Plan.createOne\",\"Plan.createMany\",\"Plan.createManyAndReturn\",\"Plan.updateOne\",\"Plan.updateMany\",\"Plan.updateManyAndReturn\",\"Plan.upsertOne\",\"Plan.deleteOne\",\"Plan.deleteMany\",\"Plan.groupBy\",\"Plan.aggregate\",\"AND\",\"OR\",\"NOT\",\"code\",\"name\",\"price\",\"rules\",\"lastUpdatedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"contains\",\"startsWith\",\"endsWith\",\"every\",\"some\",\"none\",\"id\",\"email\",\"otpHash\",\"otpExpiresAt\",\"otpAttempts\",\"otpLastSentAt\",\"otpResendCount\",\"usedAt\",\"createdAt\",\"updatedAt\",\"bookingCode\",\"courtId\",\"bookingDate\",\"startTime\",\"endTime\",\"CourtBookingStatus\",\"previousStatus\",\"newStatus\",\"customerName\",\"customerPhone\",\"customerEmail\",\"changedAt\",\"status\",\"DayOfWeek\",\"dayOfWeek\",\"isActive\",\"startDate\",\"reason\",\"complexId\",\"sportId\",\"slotDurationMinutes\",\"basePrice\",\"isUnderMaintenance\",\"maintenanceReason\",\"slug\",\"tokenHash\",\"expiresAt\",\"acceptedAt\",\"revokedAt\",\"userId\",\"ComplexUserRole\",\"role\",\"complexName\",\"physicalAddress\",\"city\",\"state\",\"country\",\"complexSlug\",\"adminEmail\",\"planCode\",\"identifier\",\"value\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"idToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"password\",\"token\",\"ipAddress\",\"userAgent\",\"emailVerified\",\"image\",\"phone\",\"banned\",\"bannedAt\",\"banReason\",\"courtId_bookingDate_startTime\",\"complexId_userId\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "5gaOAYACEgQAAPYDACAFAAD3AwAgBgAA-AMAIJsCAAD0AwAwnAIAADwAEJ0CAAD0AwAwnwIBALoDACG3AgEAAAABuAIBAAAAAb8CQAC9AwAhwAJAAL0DACHgAgEAugMAIfcCIADnAwAh-AIBAPUDACH5AgEA9QMAIfoCIADnAwAh-wJAAMwDACH8AgEA9QMAIQEAAAABACAMAwAAjwQAIJsCAACRBAAwnAIAAAMAEJ0CAACRBAAwtwIBALoDACG_AkAAvQMAIcACQAC9AwAh2wJAAL0DACHeAgEAugMAIfQCAQC6AwAh9QIBAPUDACH2AgEA9QMAIQMDAACeBgAg9QIAAJcFACD2AgAAlwUAIAwDAACPBAAgmwIAAJEEADCcAgAAAwAQnQIAAJEEADC3AgEAAAABvwJAAL0DACHAAkAAvQMAIdsCQAC9AwAh3gIBALoDACH0AgEAAAAB9QIBAPUDACH2AgEA9QMAIQMAAAADACABAAAEADACAAAFACARAwAAjwQAIJsCAACQBAAwnAIAAAcAEJ0CAACQBAAwtwIBALoDACG_AkAAvQMAIcACQAC9AwAh3gIBALoDACHrAgEAugMAIewCAQC6AwAh7QIBAPUDACHuAgEA9QMAIe8CAQD1AwAh8AJAAMwDACHxAkAAzAMAIfICAQD1AwAh8wIBAPUDACEIAwAAngYAIO0CAACXBQAg7gIAAJcFACDvAgAAlwUAIPACAACXBQAg8QIAAJcFACDyAgAAlwUAIPMCAACXBQAgEQMAAI8EACCbAgAAkAQAMJwCAAAHABCdAgAAkAQAMLcCAQAAAAG_AkAAvQMAIcACQAC9AwAh3gIBALoDACHrAgEAugMAIewCAQC6AwAh7QIBAPUDACHuAgEA9QMAIe8CAQD1AwAh8AJAAMwDACHxAkAAzAMAIfICAQD1AwAh8wIBAPUDACEDAAAABwAgAQAACAAwAgAACQAgCQMAAI8EACAKAACCBAAgmwIAAI0EADCcAgAACwAQnQIAAI0EADC_AkAAvQMAIdMCAQDKAwAh3gIBALoDACHgAgAAjgTgAiICAwAAngYAIAoAAJYGACAKAwAAjwQAIAoAAIIEACCbAgAAjQQAMJwCAAALABCdAgAAjQQAML8CQAC9AwAh0wIBAMoDACHeAgEAugMAIeACAACOBOACIv4CAACMBAAgAwAAAAsAIAEAAAwAMAIAAA0AIAkGAAC-AwAgmwIAALkDADCcAgAADwAQnQIAALkDADCeAgEAugMAIZ8CAQC6AwAhoAIQALsDACGhAgAAvAMAIKICQAC9AwAhAQAAAA8AIBIIAACKBAAgCQAA-AMAIAsAAIsEACAMAADoAwAgmwIAAIkEADCcAgAAEQAQnQIAAIkEADC3AgEAygMAIb8CQAC9AwAhwAJAAL0DACHhAgEAugMAIeICAQD1AwAh4wIBAPUDACHkAgEA9QMAIeUCAQD1AwAh5gIBALoDACHnAgEAugMAIegCAQD1AwAhCQgAAJwGACAJAACUBgAgCwAAnQYAIAwAAMsFACDiAgAAlwUAIOMCAACXBQAg5AIAAJcFACDlAgAAlwUAIOgCAACXBQAgEggAAIoEACAJAAD4AwAgCwAAiwQAIAwAAOgDACCbAgAAiQQAMJwCAAARABCdAgAAiQQAMLcCAQAAAAG_AkAAvQMAIcACQAC9AwAh4QIBALoDACHiAgEA9QMAIeMCAQD1AwAh5AIBAPUDACHlAgEA9QMAIeYCAQAAAAHnAgEAugMAIegCAQD1AwAhAwAAABEAIAEAABIAMAIAABMAIAEAAAARACADAAAACwAgAQAADAAwAgAADQAgDQoAAIIEACCbAgAAiAQAMJwCAAAXABCdAgAAiAQAMLcCAQDKAwAhuAIBALoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHaAgEAugMAIdsCQAC9AwAh3AJAAMwDACHdAkAAzAMAIQMKAACWBgAg3AIAAJcFACDdAgAAlwUAIA0KAACCBAAgmwIAAIgEADCcAgAAFwAQnQIAAIgEADC3AgEAAAABuAIBALoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHaAgEAAAAB2wJAAL0DACHcAkAAzAMAId0CQADMAwAhAwAAABcAIAEAABgAMAIAABkAIBMKAACCBAAgDQAAgwQAIA8AAIQEACAQAACFBAAgEQAAhgQAIBIAAIcEACCbAgAAgQQAMJwCAAAbABCdAgAAgQQAMJ8CAQC6AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHUAgEAygMAIdUCAgDLAwAh1gIQALsDACHXAiAA5wMAIdgCAQD1AwAhBwoAAJYGACANAACXBgAgDwAAmAYAIBAAAJkGACARAACaBgAgEgAAmwYAINgCAACXBQAgEwoAAIIEACANAACDBAAgDwAAhAQAIBAAAIUEACARAACGBAAgEgAAhwQAIJsCAACBBAAwnAIAABsAEJ0CAACBBAAwnwIBALoDACG3AgEAAAABvwJAAL0DACHAAkAAvQMAIdMCAQDKAwAh1AIBAMoDACHVAgIAywMAIdYCEAC7AwAh1wIgAOcDACHYAgEA9QMAIQMAAAAbACABAAAcADACAAAdACADAAAAGwAgAQAAHAAwAgAAHQAgAQAAABsAIAoOAAD6AwAgmwIAAP8DADCcAgAAIQAQnQIAAP8DADC3AgEAygMAIb8CQAC9AwAhwgIBAMoDACHEAgEAugMAIcUCAQC6AwAhzwIAAIAEzwIiAQ4AAJUGACAKDgAA-gMAIJsCAAD_AwAwnAIAACEAEJ0CAAD_AwAwtwIBAAAAAb8CQAC9AwAhwgIBAMoDACHEAgEAugMAIcUCAQC6AwAhzwIAAIAEzwIiAwAAACEAIAEAACIAMAIAACMAIA0OAAD6AwAgmwIAAP0DADCcAgAAJQAQnQIAAP0DADCgAhAAuwMAIbcCAQDKAwAhvwJAAL0DACHAAkAAvQMAIcICAQDKAwAhxAIBAPUDACHFAgEA9QMAIc8CAAD-A88CI9ACIADnAwAhBA4AAJUGACDEAgAAlwUAIMUCAACXBQAgzwIAAJcFACANDgAA-gMAIJsCAAD9AwAwnAIAACUAEJ0CAAD9AwAwoAIQALsDACG3AgEAAAABvwJAAL0DACHAAkAAvQMAIcICAQDKAwAhxAIBAPUDACHFAgEA9QMAIc8CAAD-A88CI9ACIADnAwAhAwAAACUAIAEAACYAMAIAACcAIBAOAAD6AwAgmwIAAPwDADCcAgAAKQAQnQIAAPwDADC3AgEAygMAIb8CQAC9AwAhwAJAAL0DACHBAgEAugMAIcICAQDKAwAhwwJAAL0DACHEAgEAugMAIcUCAQC6AwAhyQIBALoDACHKAgEAugMAIcsCAQC6AwAhzQIAANMDxwIiAQ4AAJUGACARDgAA-gMAIJsCAAD8AwAwnAIAACkAEJ0CAAD8AwAwtwIBAAAAAb8CQAC9AwAhwAJAAL0DACHBAgEAAAABwgIBAMoDACHDAkAAvQMAIcQCAQC6AwAhxQIBALoDACHJAgEAugMAIcoCAQC6AwAhywIBALoDACHNAgAA0wPHAiL9AgAA-wMAIAMAAAApACABAAAqADACAAArACAMDgAA-gMAIJsCAAD5AwAwnAIAAC0AEJ0CAAD5AwAwtwIBAMoDACG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAh0QJAAL0DACHSAgEA9QMAIQQOAACVBgAgxAIAAJcFACDFAgAAlwUAINICAACXBQAgDA4AAPoDACCbAgAA-QMAMJwCAAAtABCdAgAA-QMAMLcCAQAAAAG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAh0QJAAL0DACHSAgEA9QMAIQMAAAAtACABAAAuADACAAAvACABAAAAIQAgAQAAACUAIAEAAAApACABAAAALQAgAQAAAAsAIAEAAAAXACABAAAAGwAgAQAAAAMAIAEAAAAHACABAAAACwAgAQAAAAEAIBIEAAD2AwAgBQAA9wMAIAYAAPgDACCbAgAA9AMAMJwCAAA8ABCdAgAA9AMAMJ8CAQC6AwAhtwIBALoDACG4AgEAugMAIb8CQAC9AwAhwAJAAL0DACHgAgEAugMAIfcCIADnAwAh-AIBAPUDACH5AgEA9QMAIfoCIADnAwAh-wJAAMwDACH8AgEA9QMAIQcEAACSBgAgBQAAkwYAIAYAAJQGACD4AgAAlwUAIPkCAACXBQAg-wIAAJcFACD8AgAAlwUAIAMAAAA8ACABAAA9ADACAAABACADAAAAPAAgAQAAPQAwAgAAAQAgAwAAADwAIAEAAD0AMAIAAAEAIA8EAACPBgAgBQAAkAYAIAYAAJEGACCfAgEAAAABtwIBAAAAAbgCAQAAAAG_AkAAAAABwAJAAAAAAeACAQAAAAH3AiAAAAAB-AIBAAAAAfkCAQAAAAH6AiAAAAAB-wJAAAAAAfwCAQAAAAEBGAAAQQAgDJ8CAQAAAAG3AgEAAAABuAIBAAAAAb8CQAAAAAHAAkAAAAAB4AIBAAAAAfcCIAAAAAH4AgEAAAAB-QIBAAAAAfoCIAAAAAH7AkAAAAAB_AIBAAAAAQEYAABDADABGAAAQwAwDwQAAOsFACAFAADsBQAgBgAA7QUAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQIAAAABACAYAABGACAMnwIBAJcEACG3AgEAlwQAIbgCAQCXBAAhvwJAAJkEACHAAkAAmQQAIeACAQCXBAAh9wIgALUEACH4AgEApQQAIfkCAQClBAAh-gIgALUEACH7AkAA_wQAIfwCAQClBAAhAgAAADwAIBgAAEgAIAIAAAA8ACAYAABIACADAAAAAQAgHwAAQQAgIAAARgAgAQAAAAEAIAEAAAA8ACAHBwAA6AUAICUAAOoFACAmAADpBQAg-AIAAJcFACD5AgAAlwUAIPsCAACXBQAg_AIAAJcFACAPmwIAAPMDADCcAgAATwAQnQIAAPMDADCfAgEArQMAIbcCAQCtAwAhuAIBAK0DACG_AkAAsAMAIcACQACwAwAh4AIBAK0DACH3AiAA2AMAIfgCAQDXAwAh-QIBANcDACH6AiAA2AMAIfsCQADCAwAh_AIBANcDACEDAAAAPAAgAQAATgAwJAAATwAgAwAAADwAIAEAAD0AMAIAAAEAIAEAAAAFACABAAAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgCQMAAOcFACC3AgEAAAABvwJAAAAAAcACQAAAAAHbAkAAAAAB3gIBAAAAAfQCAQAAAAH1AgEAAAAB9gIBAAAAAQEYAABXACAItwIBAAAAAb8CQAAAAAHAAkAAAAAB2wJAAAAAAd4CAQAAAAH0AgEAAAAB9QIBAAAAAfYCAQAAAAEBGAAAWQAwARgAAFkAMAkDAADmBQAgtwIBAJcEACG_AkAAmQQAIcACQACZBAAh2wJAAJkEACHeAgEAlwQAIfQCAQCXBAAh9QIBAKUEACH2AgEApQQAIQIAAAAFACAYAABcACAItwIBAJcEACG_AkAAmQQAIcACQACZBAAh2wJAAJkEACHeAgEAlwQAIfQCAQCXBAAh9QIBAKUEACH2AgEApQQAIQIAAAADACAYAABeACACAAAAAwAgGAAAXgAgAwAAAAUAIB8AAFcAICAAAFwAIAEAAAAFACABAAAAAwAgBQcAAOMFACAlAADlBQAgJgAA5AUAIPUCAACXBQAg9gIAAJcFACALmwIAAPIDADCcAgAAZQAQnQIAAPIDADC3AgEArQMAIb8CQACwAwAhwAJAALADACHbAkAAsAMAId4CAQCtAwAh9AIBAK0DACH1AgEA1wMAIfYCAQDXAwAhAwAAAAMAIAEAAGQAMCQAAGUAIAMAAAADACABAAAEADACAAAFACABAAAACQAgAQAAAAkAIAMAAAAHACABAAAIADACAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIA4DAADiBQAgtwIBAAAAAb8CQAAAAAHAAkAAAAAB3gIBAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAHvAgEAAAAB8AJAAAAAAfECQAAAAAHyAgEAAAAB8wIBAAAAAQEYAABtACANtwIBAAAAAb8CQAAAAAHAAkAAAAAB3gIBAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAHvAgEAAAAB8AJAAAAAAfECQAAAAAHyAgEAAAAB8wIBAAAAAQEYAABvADABGAAAbwAwDgMAAOEFACC3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHeAgEAlwQAIesCAQCXBAAh7AIBAJcEACHtAgEApQQAIe4CAQClBAAh7wIBAKUEACHwAkAA_wQAIfECQAD_BAAh8gIBAKUEACHzAgEApQQAIQIAAAAJACAYAAByACANtwIBAJcEACG_AkAAmQQAIcACQACZBAAh3gIBAJcEACHrAgEAlwQAIewCAQCXBAAh7QIBAKUEACHuAgEApQQAIe8CAQClBAAh8AJAAP8EACHxAkAA_wQAIfICAQClBAAh8wIBAKUEACECAAAABwAgGAAAdAAgAgAAAAcAIBgAAHQAIAMAAAAJACAfAABtACAgAAByACABAAAACQAgAQAAAAcAIAoHAADeBQAgJQAA4AUAICYAAN8FACDtAgAAlwUAIO4CAACXBQAg7wIAAJcFACDwAgAAlwUAIPECAACXBQAg8gIAAJcFACDzAgAAlwUAIBCbAgAA8QMAMJwCAAB7ABCdAgAA8QMAMLcCAQCtAwAhvwJAALADACHAAkAAsAMAId4CAQCtAwAh6wIBAK0DACHsAgEArQMAIe0CAQDXAwAh7gIBANcDACHvAgEA1wMAIfACQADCAwAh8QJAAMIDACHyAgEA1wMAIfMCAQDXAwAhAwAAAAcAIAEAAHoAMCQAAHsAIAMAAAAHACABAAAIADACAAAJACAJmwIAAPADADCcAgAAgQEAEJ0CAADwAwAwtwIBAAAAAb8CQAC9AwAhwAJAAL0DACHbAkAAvQMAIekCAQC6AwAh6gIBALoDACEBAAAAfgAgAQAAAH4AIAmbAgAA8AMAMJwCAACBAQAQnQIAAPADADC3AgEAugMAIb8CQAC9AwAhwAJAAL0DACHbAkAAvQMAIekCAQC6AwAh6gIBALoDACEAAwAAAIEBACABAACCAQAwAgAAfgAgAwAAAIEBACABAACCAQAwAgAAfgAgAwAAAIEBACABAACCAQAwAgAAfgAgBrcCAQAAAAG_AkAAAAABwAJAAAAAAdsCQAAAAAHpAgEAAAAB6gIBAAAAAQEYAACGAQAgBrcCAQAAAAG_AkAAAAABwAJAAAAAAdsCQAAAAAHpAgEAAAAB6gIBAAAAAQEYAACIAQAwARgAAIgBADAGtwIBAJcEACG_AkAAmQQAIcACQACZBAAh2wJAAJkEACHpAgEAlwQAIeoCAQCXBAAhAgAAAH4AIBgAAIsBACAGtwIBAJcEACG_AkAAmQQAIcACQACZBAAh2wJAAJkEACHpAgEAlwQAIeoCAQCXBAAhAgAAAIEBACAYAACNAQAgAgAAAIEBACAYAACNAQAgAwAAAH4AIB8AAIYBACAgAACLAQAgAQAAAH4AIAEAAACBAQAgAwcAANsFACAlAADdBQAgJgAA3AUAIAmbAgAA7wMAMJwCAACUAQAQnQIAAO8DADC3AgEArQMAIb8CQACwAwAhwAJAALADACHbAkAAsAMAIekCAQCtAwAh6gIBAK0DACEDAAAAgQEAIAEAAJMBADAkAACUAQAgAwAAAIEBACABAACCAQAwAgAAfgAgAQAAABMAIAEAAAATACADAAAAEQAgAQAAEgAwAgAAEwAgAwAAABEAIAEAABIAMAIAABMAIAMAAAARACABAAASADACAAATACAPCAAA2gUAIAkAAJIFACALAACTBQAgDAAAlAUAILcCAQAAAAG_AkAAAAABwAJAAAAAAeECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAHoAgEAAAABARgAAJwBACALtwIBAAAAAb8CQAAAAAHAAkAAAAAB4QIBAAAAAeICAQAAAAHjAgEAAAAB5AIBAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAEBGAAAngEAMAEYAACeAQAwAQAAAA8AIA8IAADZBQAgCQAApwQAIAsAAKgEACAMAACpBAAgtwIBAJcEACG_AkAAmQQAIcACQACZBAAh4QIBAJcEACHiAgEApQQAIeMCAQClBAAh5AIBAKUEACHlAgEApQQAIeYCAQCXBAAh5wIBAJcEACHoAgEApQQAIQIAAAATACAYAACiAQAgC7cCAQCXBAAhvwJAAJkEACHAAkAAmQQAIeECAQCXBAAh4gIBAKUEACHjAgEApQQAIeQCAQClBAAh5QIBAKUEACHmAgEAlwQAIecCAQCXBAAh6AIBAKUEACECAAAAEQAgGAAApAEAIAIAAAARACAYAACkAQAgAQAAAA8AIAMAAAATACAfAACcAQAgIAAAogEAIAEAAAATACABAAAAEQAgCAcAANYFACAlAADYBQAgJgAA1wUAIOICAACXBQAg4wIAAJcFACDkAgAAlwUAIOUCAACXBQAg6AIAAJcFACAOmwIAAO4DADCcAgAArAEAEJ0CAADuAwAwtwIBAMADACG_AkAAsAMAIcACQACwAwAh4QIBAK0DACHiAgEA1wMAIeMCAQDXAwAh5AIBANcDACHlAgEA1wMAIeYCAQCtAwAh5wIBAK0DACHoAgEA1wMAIQMAAAARACABAACrAQAwJAAArAEAIAMAAAARACABAAASADACAAATACABAAAADQAgAQAAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAYDAACQBQAgCgAA1QUAIL8CQAAAAAHTAgEAAAAB3gIBAAAAAeACAAAA4AICARgAALQBACAEvwJAAAAAAdMCAQAAAAHeAgEAAAAB4AIAAADgAgIBGAAAtgEAMAEYAAC2AQAwBgMAAI4FACAKAADUBQAgvwJAAJkEACHTAgEAlwQAId4CAQCXBAAh4AIAAIwF4AIiAgAAAA0AIBgAALkBACAEvwJAAJkEACHTAgEAlwQAId4CAQCXBAAh4AIAAIwF4AIiAgAAAAsAIBgAALsBACACAAAACwAgGAAAuwEAIAMAAAANACAfAAC0AQAgIAAAuQEAIAEAAAANACABAAAACwAgAwcAANEFACAlAADTBQAgJgAA0gUAIAebAgAA6gMAMJwCAADCAQAQnQIAAOoDADC_AkAAsAMAIdMCAQDAAwAh3gIBAK0DACHgAgAA6wPgAiIDAAAACwAgAQAAwQEAMCQAAMIBACADAAAACwAgAQAADAAwAgAADQAgAQAAABkAIAEAAAAZACADAAAAFwAgAQAAGAAwAgAAGQAgAwAAABcAIAEAABgAMAIAABkAIAMAAAAXACABAAAYADACAAAZACAKCgAA0AUAILcCAQAAAAG4AgEAAAABvwJAAAAAAcACQAAAAAHTAgEAAAAB2gIBAAAAAdsCQAAAAAHcAkAAAAAB3QJAAAAAAQEYAADKAQAgCbcCAQAAAAG4AgEAAAABvwJAAAAAAcACQAAAAAHTAgEAAAAB2gIBAAAAAdsCQAAAAAHcAkAAAAAB3QJAAAAAAQEYAADMAQAwARgAAMwBADAKCgAAzwUAILcCAQCXBAAhuAIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHaAgEAlwQAIdsCQACZBAAh3AJAAP8EACHdAkAA_wQAIQIAAAAZACAYAADPAQAgCbcCAQCXBAAhuAIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHaAgEAlwQAIdsCQACZBAAh3AJAAP8EACHdAkAA_wQAIQIAAAAXACAYAADRAQAgAgAAABcAIBgAANEBACADAAAAGQAgHwAAygEAICAAAM8BACABAAAAGQAgAQAAABcAIAUHAADMBQAgJQAAzgUAICYAAM0FACDcAgAAlwUAIN0CAACXBQAgDJsCAADpAwAwnAIAANgBABCdAgAA6QMAMLcCAQDAAwAhuAIBAK0DACG_AkAAsAMAIcACQACwAwAh0wIBAMADACHaAgEArQMAIdsCQACwAwAh3AJAAMIDACHdAkAAwgMAIQMAAAAXACABAADXAQAwJAAA2AEAIAMAAAAXACABAAAYADACAAAZACAKDAAA6AMAIJsCAADmAwAwnAIAAN4BABCdAgAA5gMAMJ8CAQAAAAG3AgEAAAABvwJAAL0DACHAAkAAvQMAIdACIADnAwAh2QIBAAAAAQEAAADbAQAgAQAAANsBACAKDAAA6AMAIJsCAADmAwAwnAIAAN4BABCdAgAA5gMAMJ8CAQC6AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh0AIgAOcDACHZAgEAugMAIQEMAADLBQAgAwAAAN4BACABAADfAQAwAgAA2wEAIAMAAADeAQAgAQAA3wEAMAIAANsBACADAAAA3gEAIAEAAN8BADACAADbAQAgBwwAAMoFACCfAgEAAAABtwIBAAAAAb8CQAAAAAHAAkAAAAAB0AIgAAAAAdkCAQAAAAEBGAAA4wEAIAafAgEAAAABtwIBAAAAAb8CQAAAAAHAAkAAAAAB0AIgAAAAAdkCAQAAAAEBGAAA5QEAMAEYAADlAQAwBwwAAMAFACCfAgEAlwQAIbcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdACIAC1BAAh2QIBAJcEACECAAAA2wEAIBgAAOgBACAGnwIBAJcEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHQAiAAtQQAIdkCAQCXBAAhAgAAAN4BACAYAADqAQAgAgAAAN4BACAYAADqAQAgAwAAANsBACAfAADjAQAgIAAA6AEAIAEAAADbAQAgAQAAAN4BACADBwAAvQUAICUAAL8FACAmAAC-BQAgCZsCAADlAwAwnAIAAPEBABCdAgAA5QMAMJ8CAQCtAwAhtwIBAMADACG_AkAAsAMAIcACQACwAwAh0AIgANgDACHZAgEArQMAIQMAAADeAQAgAQAA8AEAMCQAAPEBACADAAAA3gEAIAEAAN8BADACAADbAQAgAQAAAB0AIAEAAAAdACADAAAAGwAgAQAAHAAwAgAAHQAgAwAAABsAIAEAABwAMAIAAB0AIAMAAAAbACABAAAcADACAAAdACAQCgAAvAUAIA0AAPAEACAPAADxBAAgEAAA8gQAIBEAAPMEACASAAD0BAAgnwIBAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAdMCAQAAAAHUAgEAAAAB1QICAAAAAdYCEAAAAAHXAiAAAAAB2AIBAAAAAQEYAAD5AQAgCp8CAQAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHTAgEAAAAB1AIBAAAAAdUCAgAAAAHWAhAAAAAB1wIgAAAAAdgCAQAAAAEBGAAA-wEAMAEYAAD7AQAwEAoAALsFACANAAC3BAAgDwAAuAQAIBAAALkEACARAAC6BAAgEgAAuwQAIJ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHUAgEAlwQAIdUCAgC0BAAh1gIQAJgEACHXAiAAtQQAIdgCAQClBAAhAgAAAB0AIBgAAP4BACAKnwIBAJcEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHTAgEAlwQAIdQCAQCXBAAh1QICALQEACHWAhAAmAQAIdcCIAC1BAAh2AIBAKUEACECAAAAGwAgGAAAgAIAIAIAAAAbACAYAACAAgAgAwAAAB0AIB8AAPkBACAgAAD-AQAgAQAAAB0AIAEAAAAbACAGBwAAtgUAICUAALkFACAmAAC4BQAgpwEAALcFACCoAQAAugUAINgCAACXBQAgDZsCAADkAwAwnAIAAIcCABCdAgAA5AMAMJ8CAQCtAwAhtwIBAMADACG_AkAAsAMAIcACQACwAwAh0wIBAMADACHUAgEAwAMAIdUCAgDBAwAh1gIQAK4DACHXAiAA2AMAIdgCAQDXAwAhAwAAABsAIAEAAIYCADAkAACHAgAgAwAAABsAIAEAABwAMAIAAB0AIAEAAAAvACABAAAALwAgAwAAAC0AIAEAAC4AMAIAAC8AIAMAAAAtACABAAAuADACAAAvACADAAAALQAgAQAALgAwAgAALwAgCQ4AALUFACC3AgEAAAABvwJAAAAAAcACQAAAAAHCAgEAAAABxAIBAAAAAcUCAQAAAAHRAkAAAAAB0gIBAAAAAQEYAACPAgAgCLcCAQAAAAG_AkAAAAABwAJAAAAAAcICAQAAAAHEAgEAAAABxQIBAAAAAdECQAAAAAHSAgEAAAABARgAAJECADABGAAAkQIAMAkOAAC0BQAgtwIBAJcEACG_AkAAmQQAIcACQACZBAAhwgIBAJcEACHEAgEApQQAIcUCAQClBAAh0QJAAJkEACHSAgEApQQAIQIAAAAvACAYAACUAgAgCLcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIcICAQCXBAAhxAIBAKUEACHFAgEApQQAIdECQACZBAAh0gIBAKUEACECAAAALQAgGAAAlgIAIAIAAAAtACAYAACWAgAgAwAAAC8AIB8AAI8CACAgAACUAgAgAQAAAC8AIAEAAAAtACAGBwAAsQUAICUAALMFACAmAACyBQAgxAIAAJcFACDFAgAAlwUAINICAACXBQAgC5sCAADjAwAwnAIAAJ0CABCdAgAA4wMAMLcCAQDAAwAhvwJAALADACHAAkAAsAMAIcICAQDAAwAhxAIBANcDACHFAgEA1wMAIdECQACwAwAh0gIBANcDACEDAAAALQAgAQAAnAIAMCQAAJ0CACADAAAALQAgAQAALgAwAgAALwAgAQAAACMAIAEAAAAjACADAAAAIQAgAQAAIgAwAgAAIwAgAwAAACEAIAEAACIAMAIAACMAIAMAAAAhACABAAAiADACAAAjACAHDgAAsAUAILcCAQAAAAG_AkAAAAABwgIBAAAAAcQCAQAAAAHFAgEAAAABzwIAAADPAgIBGAAApQIAIAa3AgEAAAABvwJAAAAAAcICAQAAAAHEAgEAAAABxQIBAAAAAc8CAAAAzwICARgAAKcCADABGAAApwIAMAcOAACvBQAgtwIBAJcEACG_AkAAmQQAIcICAQCXBAAhxAIBAJcEACHFAgEAlwQAIc8CAADsBM8CIgIAAAAjACAYAACqAgAgBrcCAQCXBAAhvwJAAJkEACHCAgEAlwQAIcQCAQCXBAAhxQIBAJcEACHPAgAA7ATPAiICAAAAIQAgGAAArAIAIAIAAAAhACAYAACsAgAgAwAAACMAIB8AAKUCACAgAACqAgAgAQAAACMAIAEAAAAhACADBwAArAUAICUAAK4FACAmAACtBQAgCZsCAADfAwAwnAIAALMCABCdAgAA3wMAMLcCAQDAAwAhvwJAALADACHCAgEAwAMAIcQCAQCtAwAhxQIBAK0DACHPAgAA4APPAiIDAAAAIQAgAQAAsgIAMCQAALMCACADAAAAIQAgAQAAIgAwAgAAIwAgAQAAACcAIAEAAAAnACADAAAAJQAgAQAAJgAwAgAAJwAgAwAAACUAIAEAACYAMAIAACcAIAMAAAAlACABAAAmADACAAAnACAKDgAAqwUAIKACEAAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHCAgEAAAABxAIBAAAAAcUCAQAAAAHPAgAAAM8CA9ACIAAAAAEBGAAAuwIAIAmgAhAAAAABtwIBAAAAAb8CQAAAAAHAAkAAAAABwgIBAAAAAcQCAQAAAAHFAgEAAAABzwIAAADPAgPQAiAAAAABARgAAL0CADABGAAAvQIAMAoOAACqBQAgoAIQAJgEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHCAgEAlwQAIcQCAQClBAAhxQIBAKUEACHPAgAA3wTPAiPQAiAAtQQAIQIAAAAnACAYAADAAgAgCaACEACYBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAhwgIBAJcEACHEAgEApQQAIcUCAQClBAAhzwIAAN8EzwIj0AIgALUEACECAAAAJQAgGAAAwgIAIAIAAAAlACAYAADCAgAgAwAAACcAIB8AALsCACAgAADAAgAgAQAAACcAIAEAAAAlACAIBwAApQUAICUAAKgFACAmAACnBQAgpwEAAKYFACCoAQAAqQUAIMQCAACXBQAgxQIAAJcFACDPAgAAlwUAIAybAgAA1QMAMJwCAADJAgAQnQIAANUDADCgAhAArgMAIbcCAQDAAwAhvwJAALADACHAAkAAsAMAIcICAQDAAwAhxAIBANcDACHFAgEA1wMAIc8CAADWA88CI9ACIADYAwAhAwAAACUAIAEAAMgCADAkAADJAgAgAwAAACUAIAEAACYAMAIAACcAIAEAAAArACABAAAAKwAgAwAAACkAIAEAACoAMAIAACsAIAMAAAApACABAAAqADACAAArACADAAAAKQAgAQAAKgAwAgAAKwAgDQ4AAKQFACC3AgEAAAABvwJAAAAAAcACQAAAAAHBAgEAAAABwgIBAAAAAcMCQAAAAAHEAgEAAAABxQIBAAAAAckCAQAAAAHKAgEAAAABywIBAAAAAc0CAAAAxwICARgAANECACAMtwIBAAAAAb8CQAAAAAHAAkAAAAABwQIBAAAAAcICAQAAAAHDAkAAAAABxAIBAAAAAcUCAQAAAAHJAgEAAAABygIBAAAAAcsCAQAAAAHNAgAAAMcCAgEYAADTAgAwARgAANMCADANDgAAowUAILcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIcECAQCXBAAhwgIBAJcEACHDAkAAmQQAIcQCAQCXBAAhxQIBAJcEACHJAgEAlwQAIcoCAQCXBAAhywIBAJcEACHNAgAA0gTHAiICAAAAKwAgGAAA1gIAIAy3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHBAgEAlwQAIcICAQCXBAAhwwJAAJkEACHEAgEAlwQAIcUCAQCXBAAhyQIBAJcEACHKAgEAlwQAIcsCAQCXBAAhzQIAANIExwIiAgAAACkAIBgAANgCACACAAAAKQAgGAAA2AIAIAMAAAArACAfAADRAgAgIAAA1gIAIAEAAAArACABAAAAKQAgAwcAAKAFACAlAACiBQAgJgAAoQUAIA-bAgAA1AMAMJwCAADfAgAQnQIAANQDADC3AgEAwAMAIb8CQACwAwAhwAJAALADACHBAgEArQMAIcICAQDAAwAhwwJAALADACHEAgEArQMAIcUCAQCtAwAhyQIBAK0DACHKAgEArQMAIcsCAQCtAwAhzQIAAM8DxwIiAwAAACkAIAEAAN4CADAkAADfAgAgAwAAACkAIAEAACoAMAIAACsAIA-bAgAA0gMAMJwCAADlAgAQnQIAANIDADC3AgEAAAABwQIBALoDACHCAgEAygMAIcMCQAC9AwAhxAIBALoDACHFAgEAugMAIccCAADTA8cCIsgCAADTA8cCIskCAQC6AwAhygIBALoDACHLAgEAugMAIcwCQAC9AwAhAQAAAOICACABAAAA4gIAIA-bAgAA0gMAMJwCAADlAgAQnQIAANIDADC3AgEAygMAIcECAQC6AwAhwgIBAMoDACHDAkAAvQMAIcQCAQC6AwAhxQIBALoDACHHAgAA0wPHAiLIAgAA0wPHAiLJAgEAugMAIcoCAQC6AwAhywIBALoDACHMAkAAvQMAIQADAAAA5QIAIAEAAOYCADACAADiAgAgAwAAAOUCACABAADmAgAwAgAA4gIAIAMAAADlAgAgAQAA5gIAMAIAAOICACAMtwIBAAAAAcECAQAAAAHCAgEAAAABwwJAAAAAAcQCAQAAAAHFAgEAAAABxwIAAADHAgLIAgAAAMcCAskCAQAAAAHKAgEAAAABywIBAAAAAcwCQAAAAAEBGAAA6gIAIAy3AgEAAAABwQIBAAAAAcICAQAAAAHDAkAAAAABxAIBAAAAAcUCAQAAAAHHAgAAAMcCAsgCAAAAxwICyQIBAAAAAcoCAQAAAAHLAgEAAAABzAJAAAAAAQEYAADsAgAwARgAAOwCADAMtwIBAJcEACHBAgEAlwQAIcICAQCXBAAhwwJAAJkEACHEAgEAlwQAIcUCAQCXBAAhxwIAANIExwIiyAIAANIExwIiyQIBAJcEACHKAgEAlwQAIcsCAQCXBAAhzAJAAJkEACECAAAA4gIAIBgAAO8CACAMtwIBAJcEACHBAgEAlwQAIcICAQCXBAAhwwJAAJkEACHEAgEAlwQAIcUCAQCXBAAhxwIAANIExwIiyAIAANIExwIiyQIBAJcEACHKAgEAlwQAIcsCAQCXBAAhzAJAAJkEACECAAAA5QIAIBgAAPECACACAAAA5QIAIBgAAPECACADAAAA4gIAIB8AAOoCACAgAADvAgAgAQAAAOICACABAAAA5QIAIAMHAACdBQAgJQAAnwUAICYAAJ4FACAPmwIAAM4DADCcAgAA-AIAEJ0CAADOAwAwtwIBAMADACHBAgEArQMAIcICAQDAAwAhwwJAALADACHEAgEArQMAIcUCAQCtAwAhxwIAAM8DxwIiyAIAAM8DxwIiyQIBAK0DACHKAgEArQMAIcsCAQCtAwAhzAJAALADACEDAAAA5QIAIAEAAPcCADAkAAD4AgAgAwAAAOUCACABAADmAgAwAgAA4gIAIA2bAgAAyQMAMJwCAAD-AgAQnQIAAMkDADC3AgEAAAABuAIBALoDACG5AgEAugMAIboCQAC9AwAhuwICAMsDACG8AkAAvQMAIb0CAgDLAwAhvgJAAMwDACG_AkAAvQMAIcACQAC9AwAhAQAAAPsCACABAAAA-wIAIA2bAgAAyQMAMJwCAAD-AgAQnQIAAMkDADC3AgEAygMAIbgCAQC6AwAhuQIBALoDACG6AkAAvQMAIbsCAgDLAwAhvAJAAL0DACG9AgIAywMAIb4CQADMAwAhvwJAAL0DACHAAkAAvQMAIQG-AgAAlwUAIAMAAAD-AgAgAQAA_wIAMAIAAPsCACADAAAA_gIAIAEAAP8CADACAAD7AgAgAwAAAP4CACABAAD_AgAwAgAA-wIAIAq3AgEAAAABuAIBAAAAAbkCAQAAAAG6AkAAAAABuwICAAAAAbwCQAAAAAG9AgIAAAABvgJAAAAAAb8CQAAAAAHAAkAAAAABARgAAIMDACAKtwIBAAAAAbgCAQAAAAG5AgEAAAABugJAAAAAAbsCAgAAAAG8AkAAAAABvQICAAAAAb4CQAAAAAG_AkAAAAABwAJAAAAAAQEYAACFAwAwARgAAIUDADAKtwIBAJcEACG4AgEAlwQAIbkCAQCXBAAhugJAAJkEACG7AgIAtAQAIbwCQACZBAAhvQICALQEACG-AkAA_wQAIb8CQACZBAAhwAJAAJkEACECAAAA-wIAIBgAAIgDACAKtwIBAJcEACG4AgEAlwQAIbkCAQCXBAAhugJAAJkEACG7AgIAtAQAIbwCQACZBAAhvQICALQEACG-AkAA_wQAIb8CQACZBAAhwAJAAJkEACECAAAA_gIAIBgAAIoDACACAAAA_gIAIBgAAIoDACADAAAA-wIAIB8AAIMDACAgAACIAwAgAQAAAPsCACABAAAA_gIAIAYHAACYBQAgJQAAmwUAICYAAJoFACCnAQAAmQUAIKgBAACcBQAgvgIAAJcFACANmwIAAL8DADCcAgAAkQMAEJ0CAAC_AwAwtwIBAMADACG4AgEArQMAIbkCAQCtAwAhugJAALADACG7AgIAwQMAIbwCQACwAwAhvQICAMEDACG-AkAAwgMAIb8CQACwAwAhwAJAALADACEDAAAA_gIAIAEAAJADADAkAACRAwAgAwAAAP4CACABAAD_AgAwAgAA-wIAIAkGAAC-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_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_AkAAsAMAIcACQACwAwAh2wJAALADACHpAgEArQMAIeoCAQCtAwAhCZsCAADwAwAwnAIAAIEBABCdAgAA8AMAMLcCAQC6AwAhvwJAAL0DACHAAkAAvQMAIdsCQAC9AwAh6QIBALoDACHqAgEAugMAIRCbAgAA8QMAMJwCAAB7ABCdAgAA8QMAMLcCAQCtAwAhvwJAALADACHAAkAAsAMAId4CAQCtAwAh6wIBAK0DACHsAgEArQMAIe0CAQDXAwAh7gIBANcDACHvAgEA1wMAIfACQADCAwAh8QJAAMIDACHyAgEA1wMAIfMCAQDXAwAhC5sCAADyAwAwnAIAAGUAEJ0CAADyAwAwtwIBAK0DACG_AkAAsAMAIcACQACwAwAh2wJAALADACHeAgEArQMAIfQCAQCtAwAh9QIBANcDACH2AgEA1wMAIQ-bAgAA8wMAMJwCAABPABCdAgAA8wMAMJ8CAQCtAwAhtwIBAK0DACG4AgEArQMAIb8CQACwAwAhwAJAALADACHgAgEArQMAIfcCIADYAwAh-AIBANcDACH5AgEA1wMAIfoCIADYAwAh-wJAAMIDACH8AgEA1wMAIRIEAAD2AwAgBQAA9wMAIAYAAPgDACCbAgAA9AMAMJwCAAA8ABCdAgAA9AMAMJ8CAQC6AwAhtwIBALoDACG4AgEAugMAIb8CQAC9AwAhwAJAAL0DACHgAgEAugMAIfcCIADnAwAh-AIBAPUDACH5AgEA9QMAIfoCIADnAwAh-wJAAMwDACH8AgEA9QMAIQujAgEAAAABpAIBAAAABaUCAQAAAAWmAgEAAAABpwIBAAAAAagCAQAAAAGpAgEAAAABqgIBANwDACGxAgEAAAABsgIBAAAAAbMCAQAAAAEDtAIAAAMAILUCAAADACC2AgAAAwAgA7QCAAAHACC1AgAABwAgtgIAAAcAIAO0AgAACwAgtQIAAAsAILYCAAALACAMDgAA-gMAIJsCAAD5AwAwnAIAAC0AEJ0CAAD5AwAwtwIBAMoDACG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAh0QJAAL0DACHSAgEA9QMAIRUKAACCBAAgDQAAgwQAIA8AAIQEACAQAACFBAAgEQAAhgQAIBIAAIcEACCbAgAAgQQAMJwCAAAbABCdAgAAgQQAMJ8CAQC6AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHUAgEAygMAIdUCAgDLAwAh1gIQALsDACHXAiAA5wMAIdgCAQD1AwAh_wIAABsAIIADAAAbACADwgIBAAAAAcMCQAAAAAHEAgEAAAABEA4AAPoDACCbAgAA_AMAMJwCAAApABCdAgAA_AMAMLcCAQDKAwAhvwJAAL0DACHAAkAAvQMAIcECAQC6AwAhwgIBAMoDACHDAkAAvQMAIcQCAQC6AwAhxQIBALoDACHJAgEAugMAIcoCAQC6AwAhywIBALoDACHNAgAA0wPHAiINDgAA-gMAIJsCAAD9AwAwnAIAACUAEJ0CAAD9AwAwoAIQALsDACG3AgEAygMAIb8CQAC9AwAhwAJAAL0DACHCAgEAygMAIcQCAQD1AwAhxQIBAPUDACHPAgAA_gPPAiPQAiAA5wMAIQSjAgAAAM8CA6QCAAAAzwIJpQIAAADPAgmqAgAA3gPPAiMKDgAA-gMAIJsCAAD_AwAwnAIAACEAEJ0CAAD_AwAwtwIBAMoDACG_AkAAvQMAIcICAQDKAwAhxAIBALoDACHFAgEAugMAIc8CAACABM8CIgSjAgAAAM8CAqQCAAAAzwIIpQIAAADPAgiqAgAA4gPPAiITCgAAggQAIA0AAIMEACAPAACEBAAgEAAAhQQAIBEAAIYEACASAACHBAAgmwIAAIEEADCcAgAAGwAQnQIAAIEEADCfAgEAugMAIbcCAQDKAwAhvwJAAL0DACHAAkAAvQMAIdMCAQDKAwAh1AIBAMoDACHVAgIAywMAIdYCEAC7AwAh1wIgAOcDACHYAgEA9QMAIRQIAACKBAAgCQAA-AMAIAsAAIsEACAMAADoAwAgmwIAAIkEADCcAgAAEQAQnQIAAIkEADC3AgEAygMAIb8CQAC9AwAhwAJAAL0DACHhAgEAugMAIeICAQD1AwAh4wIBAPUDACHkAgEA9QMAIeUCAQD1AwAh5gIBALoDACHnAgEAugMAIegCAQD1AwAh_wIAABEAIIADAAARACAMDAAA6AMAIJsCAADmAwAwnAIAAN4BABCdAgAA5gMAMJ8CAQC6AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh0AIgAOcDACHZAgEAugMAIf8CAADeAQAggAMAAN4BACADtAIAACEAILUCAAAhACC2AgAAIQAgA7QCAAAlACC1AgAAJQAgtgIAACUAIAO0AgAAKQAgtQIAACkAILYCAAApACADtAIAAC0AILUCAAAtACC2AgAALQAgDQoAAIIEACCbAgAAiAQAMJwCAAAXABCdAgAAiAQAMLcCAQDKAwAhuAIBALoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHaAgEAugMAIdsCQAC9AwAh3AJAAMwDACHdAkAAzAMAIRIIAACKBAAgCQAA-AMAIAsAAIsEACAMAADoAwAgmwIAAIkEADCcAgAAEQAQnQIAAIkEADC3AgEAygMAIb8CQAC9AwAhwAJAAL0DACHhAgEAugMAIeICAQD1AwAh4wIBAPUDACHkAgEA9QMAIeUCAQD1AwAh5gIBALoDACHnAgEAugMAIegCAQD1AwAhCwYAAL4DACCbAgAAuQMAMJwCAAAPABCdAgAAuQMAMJ4CAQC6AwAhnwIBALoDACGgAhAAuwMAIaECAAC8AwAgogJAAL0DACH_AgAADwAggAMAAA8AIAO0AgAAFwAgtQIAABcAILYCAAAXACAC0wIBAAAAAd4CAQAAAAEJAwAAjwQAIAoAAIIEACCbAgAAjQQAMJwCAAALABCdAgAAjQQAML8CQAC9AwAh0wIBAMoDACHeAgEAugMAIeACAACOBOACIgSjAgAAAOACAqQCAAAA4AIIpQIAAADgAgiqAgAA7QPgAiIUBAAA9gMAIAUAAPcDACAGAAD4AwAgmwIAAPQDADCcAgAAPAAQnQIAAPQDADCfAgEAugMAIbcCAQC6AwAhuAIBALoDACG_AkAAvQMAIcACQAC9AwAh4AIBALoDACH3AiAA5wMAIfgCAQD1AwAh-QIBAPUDACH6AiAA5wMAIfsCQADMAwAh_AIBAPUDACH_AgAAPAAggAMAADwAIBEDAACPBAAgmwIAAJAEADCcAgAABwAQnQIAAJAEADC3AgEAugMAIb8CQAC9AwAhwAJAAL0DACHeAgEAugMAIesCAQC6AwAh7AIBALoDACHtAgEA9QMAIe4CAQD1AwAh7wIBAPUDACHwAkAAzAMAIfECQADMAwAh8gIBAPUDACHzAgEA9QMAIQwDAACPBAAgmwIAAJEEADCcAgAAAwAQnQIAAJEEADC3AgEAugMAIb8CQAC9AwAhwAJAAL0DACHbAkAAvQMAId4CAQC6AwAh9AIBALoDACH1AgEA9QMAIfYCAQD1AwAhAAAAAAABhAMBAAAAAQWEAxAAAAABigMQAAAAAYsDEAAAAAGMAxAAAAABjQMQAAAAAQGEA0AAAAABCx8AAJsEADAgAACgBAAwgQMAAJwEADCCAwAAnQQAMIMDAACeBAAghAMAAJ8EADCFAwAAnwQAMIYDAACfBAAwhwMAAJ8EADCIAwAAoQQAMIkDAACiBAAwDQkAAJIFACALAACTBQAgDAAAlAUAILcCAQAAAAG_AkAAAAABwAJAAAAAAeECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAECAAAAEwAgHwAAkQUAIAMAAAATACAfAACRBQAgIAAApgQAIAEYAADmBgAwEggAAIoEACAJAAD4AwAgCwAAiwQAIAwAAOgDACCbAgAAiQQAMJwCAAARABCdAgAAiQQAMLcCAQAAAAG_AkAAvQMAIcACQAC9AwAh4QIBALoDACHiAgEA9QMAIeMCAQD1AwAh5AIBAPUDACHlAgEA9QMAIeYCAQAAAAHnAgEAugMAIegCAQD1AwAhAgAAABMAIBgAAKYEACACAAAAowQAIBgAAKQEACAOmwIAAKIEADCcAgAAowQAEJ0CAACiBAAwtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh4QIBALoDACHiAgEA9QMAIeMCAQD1AwAh5AIBAPUDACHlAgEA9QMAIeYCAQC6AwAh5wIBALoDACHoAgEA9QMAIQ6bAgAAogQAMJwCAACjBAAQnQIAAKIEADC3AgEAygMAIb8CQAC9AwAhwAJAAL0DACHhAgEAugMAIeICAQD1AwAh4wIBAPUDACHkAgEA9QMAIeUCAQD1AwAh5gIBALoDACHnAgEAugMAIegCAQD1AwAhCrcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIeECAQCXBAAh4gIBAKUEACHjAgEApQQAIeQCAQClBAAh5QIBAKUEACHmAgEAlwQAIecCAQCXBAAhAYQDAQAAAAENCQAApwQAIAsAAKgEACAMAACpBAAgtwIBAJcEACG_AkAAmQQAIcACQACZBAAh4QIBAJcEACHiAgEApQQAIeMCAQClBAAh5AIBAKUEACHlAgEApQQAIeYCAQCXBAAh5wIBAJcEACELHwAAggUAMCAAAIcFADCBAwAAgwUAMIIDAACEBQAwgwMAAIUFACCEAwAAhgUAMIUDAACGBQAwhgMAAIYFADCHAwAAhgUAMIgDAACIBQAwiQMAAIkFADALHwAA9QQAMCAAAPoEADCBAwAA9gQAMIIDAAD3BAAwgwMAAPgEACCEAwAA-QQAMIUDAAD5BAAwhgMAAPkEADCHAwAA-QQAMIgDAAD7BAAwiQMAAPwEADALHwAAqgQAMCAAAK8EADCBAwAAqwQAMIIDAACsBAAwgwMAAK0EACCEAwAArgQAMIUDAACuBAAwhgMAAK4EADCHAwAArgQAMIgDAACwBAAwiQMAALEEADAODQAA8AQAIA8AAPEEACAQAADyBAAgEQAA8wQAIBIAAPQEACCfAgEAAAABtwIBAAAAAb8CQAAAAAHAAkAAAAAB1AIBAAAAAdUCAgAAAAHWAhAAAAAB1wIgAAAAAdgCAQAAAAECAAAAHQAgHwAA7wQAIAMAAAAdACAfAADvBAAgIAAAtgQAIAEYAADlBgAwEwoAAIIEACANAACDBAAgDwAAhAQAIBAAAIUEACARAACGBAAgEgAAhwQAIJsCAACBBAAwnAIAABsAEJ0CAACBBAAwnwIBALoDACG3AgEAAAABvwJAAL0DACHAAkAAvQMAIdMCAQDKAwAh1AIBAMoDACHVAgIAywMAIdYCEAC7AwAh1wIgAOcDACHYAgEA9QMAIQIAAAAdACAYAAC2BAAgAgAAALIEACAYAACzBAAgDZsCAACxBAAwnAIAALIEABCdAgAAsQQAMJ8CAQC6AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHUAgEAygMAIdUCAgDLAwAh1gIQALsDACHXAiAA5wMAIdgCAQD1AwAhDZsCAACxBAAwnAIAALIEABCdAgAAsQQAMJ8CAQC6AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHUAgEAygMAIdUCAgDLAwAh1gIQALsDACHXAiAA5wMAIdgCAQD1AwAhCZ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh1AIBAJcEACHVAgIAtAQAIdYCEACYBAAh1wIgALUEACHYAgEApQQAIQWEAwIAAAABigMCAAAAAYsDAgAAAAGMAwIAAAABjQMCAAAAAQGEAyAAAAABDg0AALcEACAPAAC4BAAgEAAAuQQAIBEAALoEACASAAC7BAAgnwIBAJcEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHUAgEAlwQAIdUCAgC0BAAh1gIQAJgEACHXAiAAtQQAIdgCAQClBAAhBR8AANwGACAgAADjBgAggQMAAN0GACCCAwAA4gYAIIcDAADbAQAgCx8AAOIEADAgAADnBAAwgQMAAOMEADCCAwAA5AQAMIMDAADlBAAghAMAAOYEADCFAwAA5gQAMIYDAADmBAAwhwMAAOYEADCIAwAA6AQAMIkDAADpBAAwCx8AANUEADAgAADaBAAwgQMAANYEADCCAwAA1wQAMIMDAADYBAAghAMAANkEADCFAwAA2QQAMIYDAADZBAAwhwMAANkEADCIAwAA2wQAMIkDAADcBAAwCx8AAMgEADAgAADNBAAwgQMAAMkEADCCAwAAygQAMIMDAADLBAAghAMAAMwEADCFAwAAzAQAMIYDAADMBAAwhwMAAMwEADCIAwAAzgQAMIkDAADPBAAwCx8AALwEADAgAADBBAAwgQMAAL0EADCCAwAAvgQAMIMDAAC_BAAghAMAAMAEADCFAwAAwAQAMIYDAADABAAwhwMAAMAEADCIAwAAwgQAMIkDAADDBAAwB7cCAQAAAAG_AkAAAAABwAJAAAAAAcQCAQAAAAHFAgEAAAAB0QJAAAAAAdICAQAAAAECAAAALwAgHwAAxwQAIAMAAAAvACAfAADHBAAgIAAAxgQAIAEYAADhBgAwDA4AAPoDACCbAgAA-QMAMJwCAAAtABCdAgAA-QMAMLcCAQAAAAG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAh0QJAAL0DACHSAgEA9QMAIQIAAAAvACAYAADGBAAgAgAAAMQEACAYAADFBAAgC5sCAADDBAAwnAIAAMQEABCdAgAAwwQAMLcCAQDKAwAhvwJAAL0DACHAAkAAvQMAIcICAQDKAwAhxAIBAPUDACHFAgEA9QMAIdECQAC9AwAh0gIBAPUDACELmwIAAMMEADCcAgAAxAQAEJ0CAADDBAAwtwIBAMoDACG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAh0QJAAL0DACHSAgEA9QMAIQe3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHEAgEApQQAIcUCAQClBAAh0QJAAJkEACHSAgEApQQAIQe3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHEAgEApQQAIcUCAQClBAAh0QJAAJkEACHSAgEApQQAIQe3AgEAAAABvwJAAAAAAcACQAAAAAHEAgEAAAABxQIBAAAAAdECQAAAAAHSAgEAAAABC7cCAQAAAAG_AkAAAAABwAJAAAAAAcECAQAAAAHDAkAAAAABxAIBAAAAAcUCAQAAAAHJAgEAAAABygIBAAAAAcsCAQAAAAHNAgAAAMcCAgIAAAArACAfAADUBAAgAwAAACsAIB8AANQEACAgAADTBAAgARgAAOAGADARDgAA-gMAIJsCAAD8AwAwnAIAACkAEJ0CAAD8AwAwtwIBAAAAAb8CQAC9AwAhwAJAAL0DACHBAgEAAAABwgIBAMoDACHDAkAAvQMAIcQCAQC6AwAhxQIBALoDACHJAgEAugMAIcoCAQC6AwAhywIBALoDACHNAgAA0wPHAiL9AgAA-wMAIAIAAAArACAYAADTBAAgAgAAANAEACAYAADRBAAgD5sCAADPBAAwnAIAANAEABCdAgAAzwQAMLcCAQDKAwAhvwJAAL0DACHAAkAAvQMAIcECAQC6AwAhwgIBAMoDACHDAkAAvQMAIcQCAQC6AwAhxQIBALoDACHJAgEAugMAIcoCAQC6AwAhywIBALoDACHNAgAA0wPHAiIPmwIAAM8EADCcAgAA0AQAEJ0CAADPBAAwtwIBAMoDACG_AkAAvQMAIcACQAC9AwAhwQIBALoDACHCAgEAygMAIcMCQAC9AwAhxAIBALoDACHFAgEAugMAIckCAQC6AwAhygIBALoDACHLAgEAugMAIc0CAADTA8cCIgu3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHBAgEAlwQAIcMCQACZBAAhxAIBAJcEACHFAgEAlwQAIckCAQCXBAAhygIBAJcEACHLAgEAlwQAIc0CAADSBMcCIgGEAwAAAMcCAgu3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHBAgEAlwQAIcMCQACZBAAhxAIBAJcEACHFAgEAlwQAIckCAQCXBAAhygIBAJcEACHLAgEAlwQAIc0CAADSBMcCIgu3AgEAAAABvwJAAAAAAcACQAAAAAHBAgEAAAABwwJAAAAAAcQCAQAAAAHFAgEAAAAByQIBAAAAAcoCAQAAAAHLAgEAAAABzQIAAADHAgIIoAIQAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAcQCAQAAAAHFAgEAAAABzwIAAADPAgPQAiAAAAABAgAAACcAIB8AAOEEACADAAAAJwAgHwAA4QQAICAAAOAEACABGAAA3wYAMA0OAAD6AwAgmwIAAP0DADCcAgAAJQAQnQIAAP0DADCgAhAAuwMAIbcCAQAAAAG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAhzwIAAP4DzwIj0AIgAOcDACECAAAAJwAgGAAA4AQAIAIAAADdBAAgGAAA3gQAIAybAgAA3AQAMJwCAADdBAAQnQIAANwEADCgAhAAuwMAIbcCAQDKAwAhvwJAAL0DACHAAkAAvQMAIcICAQDKAwAhxAIBAPUDACHFAgEA9QMAIc8CAAD-A88CI9ACIADnAwAhDJsCAADcBAAwnAIAAN0EABCdAgAA3AQAMKACEAC7AwAhtwIBAMoDACG_AkAAvQMAIcACQAC9AwAhwgIBAMoDACHEAgEA9QMAIcUCAQD1AwAhzwIAAP4DzwIj0AIgAOcDACEIoAIQAJgEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHEAgEApQQAIcUCAQClBAAhzwIAAN8EzwIj0AIgALUEACEBhAMAAADPAgMIoAIQAJgEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHEAgEApQQAIcUCAQClBAAhzwIAAN8EzwIj0AIgALUEACEIoAIQAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAcQCAQAAAAHFAgEAAAABzwIAAADPAgPQAiAAAAABBbcCAQAAAAG_AkAAAAABxAIBAAAAAcUCAQAAAAHPAgAAAM8CAgIAAAAjACAfAADuBAAgAwAAACMAIB8AAO4EACAgAADtBAAgARgAAN4GADAKDgAA-gMAIJsCAAD_AwAwnAIAACEAEJ0CAAD_AwAwtwIBAAAAAb8CQAC9AwAhwgIBAMoDACHEAgEAugMAIcUCAQC6AwAhzwIAAIAEzwIiAgAAACMAIBgAAO0EACACAAAA6gQAIBgAAOsEACAJmwIAAOkEADCcAgAA6gQAEJ0CAADpBAAwtwIBAMoDACG_AkAAvQMAIcICAQDKAwAhxAIBALoDACHFAgEAugMAIc8CAACABM8CIgmbAgAA6QQAMJwCAADqBAAQnQIAAOkEADC3AgEAygMAIb8CQAC9AwAhwgIBAMoDACHEAgEAugMAIcUCAQC6AwAhzwIAAIAEzwIiBbcCAQCXBAAhvwJAAJkEACHEAgEAlwQAIcUCAQCXBAAhzwIAAOwEzwIiAYQDAAAAzwICBbcCAQCXBAAhvwJAAJkEACHEAgEAlwQAIcUCAQCXBAAhzwIAAOwEzwIiBbcCAQAAAAG_AkAAAAABxAIBAAAAAcUCAQAAAAHPAgAAAM8CAg4NAADwBAAgDwAA8QQAIBAAAPIEACARAADzBAAgEgAA9AQAIJ8CAQAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHUAgEAAAAB1QICAAAAAdYCEAAAAAHXAiAAAAAB2AIBAAAAAQMfAADcBgAggQMAAN0GACCHAwAA2wEAIAQfAADiBAAwgQMAAOMEADCDAwAA5QQAIIcDAADmBAAwBB8AANUEADCBAwAA1gQAMIMDAADYBAAghwMAANkEADAEHwAAyAQAMIEDAADJBAAwgwMAAMsEACCHAwAAzAQAMAQfAAC8BAAwgQMAAL0EADCDAwAAvwQAIIcDAADABAAwCLcCAQAAAAG4AgEAAAABvwJAAAAAAcACQAAAAAHaAgEAAAAB2wJAAAAAAdwCQAAAAAHdAkAAAAABAgAAABkAIB8AAIEFACADAAAAGQAgHwAAgQUAICAAAIAFACABGAAA2wYAMA0KAACCBAAgmwIAAIgEADCcAgAAFwAQnQIAAIgEADC3AgEAAAABuAIBALoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHaAgEAAAAB2wJAAL0DACHcAkAAzAMAId0CQADMAwAhAgAAABkAIBgAAIAFACACAAAA_QQAIBgAAP4EACAMmwIAAPwEADCcAgAA_QQAEJ0CAAD8BAAwtwIBAMoDACG4AgEAugMAIb8CQAC9AwAhwAJAAL0DACHTAgEAygMAIdoCAQC6AwAh2wJAAL0DACHcAkAAzAMAId0CQADMAwAhDJsCAAD8BAAwnAIAAP0EABCdAgAA_AQAMLcCAQDKAwAhuAIBALoDACG_AkAAvQMAIcACQAC9AwAh0wIBAMoDACHaAgEAugMAIdsCQAC9AwAh3AJAAMwDACHdAkAAzAMAIQi3AgEAlwQAIbgCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdoCAQCXBAAh2wJAAJkEACHcAkAA_wQAId0CQAD_BAAhAYQDQAAAAAEItwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHaAgEAlwQAIdsCQACZBAAh3AJAAP8EACHdAkAA_wQAIQi3AgEAAAABuAIBAAAAAb8CQAAAAAHAAkAAAAAB2gIBAAAAAdsCQAAAAAHcAkAAAAAB3QJAAAAAAQQDAACQBQAgvwJAAAAAAd4CAQAAAAHgAgAAAOACAgIAAAANACAfAACPBQAgAwAAAA0AIB8AAI8FACAgAACNBQAgARgAANoGADAKAwAAjwQAIAoAAIIEACCbAgAAjQQAMJwCAAALABCdAgAAjQQAML8CQAC9AwAh0wIBAMoDACHeAgEAugMAIeACAACOBOACIv4CAACMBAAgAgAAAA0AIBgAAI0FACACAAAAigUAIBgAAIsFACAHmwIAAIkFADCcAgAAigUAEJ0CAACJBQAwvwJAAL0DACHTAgEAygMAId4CAQC6AwAh4AIAAI4E4AIiB5sCAACJBQAwnAIAAIoFABCdAgAAiQUAML8CQAC9AwAh0wIBAMoDACHeAgEAugMAIeACAACOBOACIgO_AkAAmQQAId4CAQCXBAAh4AIAAIwF4AIiAYQDAAAA4AICBAMAAI4FACC_AkAAmQQAId4CAQCXBAAh4AIAAIwF4AIiBR8AANUGACAgAADYBgAggQMAANYGACCCAwAA1wYAIIcDAAABACAEAwAAkAUAIL8CQAAAAAHeAgEAAAAB4AIAAADgAgIDHwAA1QYAIIEDAADWBgAghwMAAAEAIA0JAACSBQAgCwAAkwUAIAwAAJQFACC3AgEAAAABvwJAAAAAAcACQAAAAAHhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAABBB8AAIIFADCBAwAAgwUAMIMDAACFBQAghwMAAIYFADAEHwAA9QQAMIEDAAD2BAAwgwMAAPgEACCHAwAA-QQAMAQfAACqBAAwgQMAAKsEADCDAwAArQQAIIcDAACuBAAwBB8AAJsEADCBAwAAnAQAMIMDAACeBAAghwMAAJ8EADAAAAAAAAAAAAAAAAAABR8AANAGACAgAADTBgAggQMAANEGACCCAwAA0gYAIIcDAAAdACADHwAA0AYAIIEDAADRBgAghwMAAB0AIAAAAAAABR8AAMsGACAgAADOBgAggQMAAMwGACCCAwAAzQYAIIcDAAAdACADHwAAywYAIIEDAADMBgAghwMAAB0AIAAAAAUfAADGBgAgIAAAyQYAIIEDAADHBgAgggMAAMgGACCHAwAAHQAgAx8AAMYGACCBAwAAxwYAIIcDAAAdACAAAAAFHwAAwQYAICAAAMQGACCBAwAAwgYAIIIDAADDBgAghwMAAB0AIAMfAADBBgAggQMAAMIGACCHAwAAHQAgAAAAAAAFHwAAvAYAICAAAL8GACCBAwAAvQYAIIIDAAC-BgAghwMAABMAIAMfAAC8BgAggQMAAL0GACCHAwAAEwAgAAAACx8AAMEFADAgAADFBQAwgQMAAMIFADCCAwAAwwUAMIMDAADEBQAghAMAAK4EADCFAwAArgQAMIYDAACuBAAwhwMAAK4EADCIAwAAxgUAMIkDAACxBAAwDgoAALwFACAPAADxBAAgEAAA8gQAIBEAAPMEACASAAD0BAAgnwIBAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAdMCAQAAAAHVAgIAAAAB1gIQAAAAAdcCIAAAAAHYAgEAAAABAgAAAB0AIB8AAMkFACADAAAAHQAgHwAAyQUAICAAAMgFACABGAAAuwYAMAIAAAAdACAYAADIBQAgAgAAALIEACAYAADHBQAgCZ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHVAgIAtAQAIdYCEACYBAAh1wIgALUEACHYAgEApQQAIQ4KAAC7BQAgDwAAuAQAIBAAALkEACARAAC6BAAgEgAAuwQAIJ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHVAgIAtAQAIdYCEACYBAAh1wIgALUEACHYAgEApQQAIQ4KAAC8BQAgDwAA8QQAIBAAAPIEACARAADzBAAgEgAA9AQAIJ8CAQAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHTAgEAAAAB1QICAAAAAdYCEAAAAAHXAiAAAAAB2AIBAAAAAQQfAADBBQAwgQMAAMIFADCDAwAAxAUAIIcDAACuBAAwAAAAAAUfAAC2BgAgIAAAuQYAIIEDAAC3BgAgggMAALgGACCHAwAAEwAgAx8AALYGACCBAwAAtwYAIIcDAAATACAAAAAFHwAAsQYAICAAALQGACCBAwAAsgYAIIIDAACzBgAghwMAABMAIAMfAACxBgAggQMAALIGACCHAwAAEwAgAAAABx8AAKwGACAgAACvBgAggQMAAK0GACCCAwAArgYAIIUDAAAPACCGAwAADwAghwMAAJQDACADHwAArAYAIIEDAACtBgAghwMAAJQDACAAAAAAAAAFHwAApwYAICAAAKoGACCBAwAAqAYAIIIDAACpBgAghwMAAAEAIAMfAACnBgAggQMAAKgGACCHAwAAAQAgAAAABR8AAKIGACAgAAClBgAggQMAAKMGACCCAwAApAYAIIcDAAABACADHwAAogYAIIEDAACjBgAghwMAAAEAIAAAAAsfAACDBgAwIAAAiAYAMIEDAACEBgAwggMAAIUGADCDAwAAhgYAIIQDAACHBgAwhQMAAIcGADCGAwAAhwYAMIcDAACHBgAwiAMAAIkGADCJAwAAigYAMAsfAAD3BQAwIAAA_AUAMIEDAAD4BQAwggMAAPkFADCDAwAA-gUAIIQDAAD7BQAwhQMAAPsFADCGAwAA-wUAMIcDAAD7BQAwiAMAAP0FADCJAwAA_gUAMAsfAADuBQAwIAAA8gUAMIEDAADvBQAwggMAAPAFADCDAwAA8QUAIIQDAACGBQAwhQMAAIYFADCGAwAAhgUAMIcDAACGBQAwiAMAAPMFADCJAwAAiQUAMAQKAADVBQAgvwJAAAAAAdMCAQAAAAHgAgAAAOACAgIAAAANACAfAAD2BQAgAwAAAA0AIB8AAPYFACAgAAD1BQAgARgAAKEGADACAAAADQAgGAAA9QUAIAIAAACKBQAgGAAA9AUAIAO_AkAAmQQAIdMCAQCXBAAh4AIAAIwF4AIiBAoAANQFACC_AkAAmQQAIdMCAQCXBAAh4AIAAIwF4AIiBAoAANUFACC_AkAAAAAB0wIBAAAAAeACAAAA4AICDLcCAQAAAAG_AkAAAAABwAJAAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAHvAgEAAAAB8AJAAAAAAfECQAAAAAHyAgEAAAAB8wIBAAAAAQIAAAAJACAfAACCBgAgAwAAAAkAIB8AAIIGACAgAACBBgAgARgAAKAGADARAwAAjwQAIJsCAACQBAAwnAIAAAcAEJ0CAACQBAAwtwIBAAAAAb8CQAC9AwAhwAJAAL0DACHeAgEAugMAIesCAQC6AwAh7AIBALoDACHtAgEA9QMAIe4CAQD1AwAh7wIBAPUDACHwAkAAzAMAIfECQADMAwAh8gIBAPUDACHzAgEA9QMAIQIAAAAJACAYAACBBgAgAgAAAP8FACAYAACABgAgEJsCAAD-BQAwnAIAAP8FABCdAgAA_gUAMLcCAQC6AwAhvwJAAL0DACHAAkAAvQMAId4CAQC6AwAh6wIBALoDACHsAgEAugMAIe0CAQD1AwAh7gIBAPUDACHvAgEA9QMAIfACQADMAwAh8QJAAMwDACHyAgEA9QMAIfMCAQD1AwAhEJsCAAD-BQAwnAIAAP8FABCdAgAA_gUAMLcCAQC6AwAhvwJAAL0DACHAAkAAvQMAId4CAQC6AwAh6wIBALoDACHsAgEAugMAIe0CAQD1AwAh7gIBAPUDACHvAgEA9QMAIfACQADMAwAh8QJAAMwDACHyAgEA9QMAIfMCAQD1AwAhDLcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIesCAQCXBAAh7AIBAJcEACHtAgEApQQAIe4CAQClBAAh7wIBAKUEACHwAkAA_wQAIfECQAD_BAAh8gIBAKUEACHzAgEApQQAIQy3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHrAgEAlwQAIewCAQCXBAAh7QIBAKUEACHuAgEApQQAIe8CAQClBAAh8AJAAP8EACHxAkAA_wQAIfICAQClBAAh8wIBAKUEACEMtwIBAAAAAb8CQAAAAAHAAkAAAAAB6wIBAAAAAewCAQAAAAHtAgEAAAAB7gIBAAAAAe8CAQAAAAHwAkAAAAAB8QJAAAAAAfICAQAAAAHzAgEAAAABB7cCAQAAAAG_AkAAAAABwAJAAAAAAdsCQAAAAAH0AgEAAAAB9QIBAAAAAfYCAQAAAAECAAAABQAgHwAAjgYAIAMAAAAFACAfAACOBgAgIAAAjQYAIAEYAACfBgAwDAMAAI8EACCbAgAAkQQAMJwCAAADABCdAgAAkQQAMLcCAQAAAAG_AkAAvQMAIcACQAC9AwAh2wJAAL0DACHeAgEAugMAIfQCAQAAAAH1AgEA9QMAIfYCAQD1AwAhAgAAAAUAIBgAAI0GACACAAAAiwYAIBgAAIwGACALmwIAAIoGADCcAgAAiwYAEJ0CAACKBgAwtwIBALoDACG_AkAAvQMAIcACQAC9AwAh2wJAAL0DACHeAgEAugMAIfQCAQC6AwAh9QIBAPUDACH2AgEA9QMAIQubAgAAigYAMJwCAACLBgAQnQIAAIoGADC3AgEAugMAIb8CQAC9AwAhwAJAAL0DACHbAkAAvQMAId4CAQC6AwAh9AIBALoDACH1AgEA9QMAIfYCAQD1AwAhB7cCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdsCQACZBAAh9AIBAJcEACH1AgEApQQAIfYCAQClBAAhB7cCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdsCQACZBAAh9AIBAJcEACH1AgEApQQAIfYCAQClBAAhB7cCAQAAAAG_AkAAAAABwAJAAAAAAdsCQAAAAAH0AgEAAAAB9QIBAAAAAfYCAQAAAAEEHwAAgwYAMIEDAACEBgAwgwMAAIYGACCHAwAAhwYAMAQfAAD3BQAwgQMAAPgFADCDAwAA-gUAIIcDAAD7BQAwBB8AAO4FADCBAwAA7wUAMIMDAADxBQAghwMAAIYFADAAAAAHCgAAlgYAIA0AAJcGACAPAACYBgAgEAAAmQYAIBEAAJoGACASAACbBgAg2AIAAJcFACAJCAAAnAYAIAkAAJQGACALAACdBgAgDAAAywUAIOICAACXBQAg4wIAAJcFACDkAgAAlwUAIOUCAACXBQAg6AIAAJcFACABDAAAywUAIAAAAAABBgAAlgUAIAAHBAAAkgYAIAUAAJMGACAGAACUBgAg-AIAAJcFACD5AgAAlwUAIPsCAACXBQAg_AIAAJcFACAHtwIBAAAAAb8CQAAAAAHAAkAAAAAB2wJAAAAAAfQCAQAAAAH1AgEAAAAB9gIBAAAAAQy3AgEAAAABvwJAAAAAAcACQAAAAAHrAgEAAAAB7AIBAAAAAe0CAQAAAAHuAgEAAAAB7wIBAAAAAfACQAAAAAHxAkAAAAAB8gIBAAAAAfMCAQAAAAEDvwJAAAAAAdMCAQAAAAHgAgAAAOACAg4FAACQBgAgBgAAkQYAIJ8CAQAAAAG3AgEAAAABuAIBAAAAAb8CQAAAAAHAAkAAAAAB4AIBAAAAAfcCIAAAAAH4AgEAAAAB-QIBAAAAAfoCIAAAAAH7AkAAAAAB_AIBAAAAAQIAAAABACAfAACiBgAgAwAAADwAIB8AAKIGACAgAACmBgAgEAAAADwAIAUAAOwFACAGAADtBQAgGAAApgYAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQ4FAADsBQAgBgAA7QUAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQ4EAACPBgAgBgAAkQYAIJ8CAQAAAAG3AgEAAAABuAIBAAAAAb8CQAAAAAHAAkAAAAAB4AIBAAAAAfcCIAAAAAH4AgEAAAAB-QIBAAAAAfoCIAAAAAH7AkAAAAAB_AIBAAAAAQIAAAABACAfAACnBgAgAwAAADwAIB8AAKcGACAgAACrBgAgEAAAADwAIAQAAOsFACAGAADtBQAgGAAAqwYAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQ4EAADrBQAgBgAA7QUAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQWeAgEAAAABnwIBAAAAAaACEAAAAAGhAoAAAAABogJAAAAAAQIAAACUAwAgHwAArAYAIAMAAAAPACAfAACsBgAgIAAAsAYAIAcAAAAPACAYAACwBgAgngIBAJcEACGfAgEAlwQAIaACEACYBAAhoQKAAAAAAaICQACZBAAhBZ4CAQCXBAAhnwIBAJcEACGgAhAAmAQAIaECgAAAAAGiAkAAmQQAIQ4IAADaBQAgCwAAkwUAIAwAAJQFACC3AgEAAAABvwJAAAAAAcACQAAAAAHhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAQIAAAATACAfAACxBgAgAwAAABEAIB8AALEGACAgAAC1BgAgEAAAABEAIAgAANkFACALAACoBAAgDAAAqQQAIBgAALUGACC3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHhAgEAlwQAIeICAQClBAAh4wIBAKUEACHkAgEApQQAIeUCAQClBAAh5gIBAJcEACHnAgEAlwQAIegCAQClBAAhDggAANkFACALAACoBAAgDAAAqQQAILcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIeECAQCXBAAh4gIBAKUEACHjAgEApQQAIeQCAQClBAAh5QIBAKUEACHmAgEAlwQAIecCAQCXBAAh6AIBAKUEACEOCAAA2gUAIAkAAJIFACAMAACUBQAgtwIBAAAAAb8CQAAAAAHAAkAAAAAB4QIBAAAAAeICAQAAAAHjAgEAAAAB5AIBAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAECAAAAEwAgHwAAtgYAIAMAAAARACAfAAC2BgAgIAAAugYAIBAAAAARACAIAADZBQAgCQAApwQAIAwAAKkEACAYAAC6BgAgtwIBAJcEACG_AkAAmQQAIcACQACZBAAh4QIBAJcEACHiAgEApQQAIeMCAQClBAAh5AIBAKUEACHlAgEApQQAIeYCAQCXBAAh5wIBAJcEACHoAgEApQQAIQ4IAADZBQAgCQAApwQAIAwAAKkEACC3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHhAgEAlwQAIeICAQClBAAh4wIBAKUEACHkAgEApQQAIeUCAQClBAAh5gIBAJcEACHnAgEAlwQAIegCAQClBAAhCZ8CAQAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHTAgEAAAAB1QICAAAAAdYCEAAAAAHXAiAAAAAB2AIBAAAAAQ4IAADaBQAgCQAAkgUAIAsAAJMFACC3AgEAAAABvwJAAAAAAcACQAAAAAHhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAQIAAAATACAfAAC8BgAgAwAAABEAIB8AALwGACAgAADABgAgEAAAABEAIAgAANkFACAJAACnBAAgCwAAqAQAIBgAAMAGACC3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHhAgEAlwQAIeICAQClBAAh4wIBAKUEACHkAgEApQQAIeUCAQClBAAh5gIBAJcEACHnAgEAlwQAIegCAQClBAAhDggAANkFACAJAACnBAAgCwAAqAQAILcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIeECAQCXBAAh4gIBAKUEACHjAgEApQQAIeQCAQClBAAh5QIBAKUEACHmAgEAlwQAIecCAQCXBAAh6AIBAKUEACEPCgAAvAUAIA0AAPAEACAPAADxBAAgEAAA8gQAIBEAAPMEACCfAgEAAAABtwIBAAAAAb8CQAAAAAHAAkAAAAAB0wIBAAAAAdQCAQAAAAHVAgIAAAAB1gIQAAAAAdcCIAAAAAHYAgEAAAABAgAAAB0AIB8AAMEGACADAAAAGwAgHwAAwQYAICAAAMUGACARAAAAGwAgCgAAuwUAIA0AALcEACAPAAC4BAAgEAAAuQQAIBEAALoEACAYAADFBgAgnwIBAJcEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHTAgEAlwQAIdQCAQCXBAAh1QICALQEACHWAhAAmAQAIdcCIAC1BAAh2AIBAKUEACEPCgAAuwUAIA0AALcEACAPAAC4BAAgEAAAuQQAIBEAALoEACCfAgEAlwQAIbcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdMCAQCXBAAh1AIBAJcEACHVAgIAtAQAIdYCEACYBAAh1wIgALUEACHYAgEApQQAIQ8KAAC8BQAgDQAA8AQAIBAAAPIEACARAADzBAAgEgAA9AQAIJ8CAQAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHTAgEAAAAB1AIBAAAAAdUCAgAAAAHWAhAAAAAB1wIgAAAAAdgCAQAAAAECAAAAHQAgHwAAxgYAIAMAAAAbACAfAADGBgAgIAAAygYAIBEAAAAbACAKAAC7BQAgDQAAtwQAIBAAALkEACARAAC6BAAgEgAAuwQAIBgAAMoGACCfAgEAlwQAIbcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdMCAQCXBAAh1AIBAJcEACHVAgIAtAQAIdYCEACYBAAh1wIgALUEACHYAgEApQQAIQ8KAAC7BQAgDQAAtwQAIBAAALkEACARAAC6BAAgEgAAuwQAIJ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHUAgEAlwQAIdUCAgC0BAAh1gIQAJgEACHXAiAAtQQAIdgCAQClBAAhDwoAALwFACANAADwBAAgDwAA8QQAIBEAAPMEACASAAD0BAAgnwIBAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAdMCAQAAAAHUAgEAAAAB1QICAAAAAdYCEAAAAAHXAiAAAAAB2AIBAAAAAQIAAAAdACAfAADLBgAgAwAAABsAIB8AAMsGACAgAADPBgAgEQAAABsAIAoAALsFACANAAC3BAAgDwAAuAQAIBEAALoEACASAAC7BAAgGAAAzwYAIJ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh0wIBAJcEACHUAgEAlwQAIdUCAgC0BAAh1gIQAJgEACHXAiAAtQQAIdgCAQClBAAhDwoAALsFACANAAC3BAAgDwAAuAQAIBEAALoEACASAAC7BAAgnwIBAJcEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHTAgEAlwQAIdQCAQCXBAAh1QICALQEACHWAhAAmAQAIdcCIAC1BAAh2AIBAKUEACEPCgAAvAUAIA0AAPAEACAPAADxBAAgEAAA8gQAIBIAAPQEACCfAgEAAAABtwIBAAAAAb8CQAAAAAHAAkAAAAAB0wIBAAAAAdQCAQAAAAHVAgIAAAAB1gIQAAAAAdcCIAAAAAHYAgEAAAABAgAAAB0AIB8AANAGACADAAAAGwAgHwAA0AYAICAAANQGACARAAAAGwAgCgAAuwUAIA0AALcEACAPAAC4BAAgEAAAuQQAIBIAALsEACAYAADUBgAgnwIBAJcEACG3AgEAlwQAIb8CQACZBAAhwAJAAJkEACHTAgEAlwQAIdQCAQCXBAAh1QICALQEACHWAhAAmAQAIdcCIAC1BAAh2AIBAKUEACEPCgAAuwUAIA0AALcEACAPAAC4BAAgEAAAuQQAIBIAALsEACCfAgEAlwQAIbcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdMCAQCXBAAh1AIBAJcEACHVAgIAtAQAIdYCEACYBAAh1wIgALUEACHYAgEApQQAIQ4EAACPBgAgBQAAkAYAIJ8CAQAAAAG3AgEAAAABuAIBAAAAAb8CQAAAAAHAAkAAAAAB4AIBAAAAAfcCIAAAAAH4AgEAAAAB-QIBAAAAAfoCIAAAAAH7AkAAAAAB_AIBAAAAAQIAAAABACAfAADVBgAgAwAAADwAIB8AANUGACAgAADZBgAgEAAAADwAIAQAAOsFACAFAADsBQAgGAAA2QYAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQ4EAADrBQAgBQAA7AUAIJ8CAQCXBAAhtwIBAJcEACG4AgEAlwQAIb8CQACZBAAhwAJAAJkEACHgAgEAlwQAIfcCIAC1BAAh-AIBAKUEACH5AgEApQQAIfoCIAC1BAAh-wJAAP8EACH8AgEApQQAIQO_AkAAAAAB3gIBAAAAAeACAAAA4AICCLcCAQAAAAG4AgEAAAABvwJAAAAAAcACQAAAAAHaAgEAAAAB2wJAAAAAAdwCQAAAAAHdAkAAAAABBp8CAQAAAAG3AgEAAAABvwJAAAAAAcACQAAAAAHQAiAAAAAB2QIBAAAAAQIAAADbAQAgHwAA3AYAIAW3AgEAAAABvwJAAAAAAcQCAQAAAAHFAgEAAAABzwIAAADPAgIIoAIQAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAcQCAQAAAAHFAgEAAAABzwIAAADPAgPQAiAAAAABC7cCAQAAAAG_AkAAAAABwAJAAAAAAcECAQAAAAHDAkAAAAABxAIBAAAAAcUCAQAAAAHJAgEAAAABygIBAAAAAcsCAQAAAAHNAgAAAMcCAge3AgEAAAABvwJAAAAAAcACQAAAAAHEAgEAAAABxQIBAAAAAdECQAAAAAHSAgEAAAABAwAAAN4BACAfAADcBgAgIAAA5AYAIAgAAADeAQAgGAAA5AYAIJ8CAQCXBAAhtwIBAJcEACG_AkAAmQQAIcACQACZBAAh0AIgALUEACHZAgEAlwQAIQafAgEAlwQAIbcCAQCXBAAhvwJAAJkEACHAAkAAmQQAIdACIAC1BAAh2QIBAJcEACEJnwIBAAAAAbcCAQAAAAG_AkAAAAABwAJAAAAAAdQCAQAAAAHVAgIAAAAB1gIQAAAAAdcCIAAAAAHYAgEAAAABCrcCAQAAAAG_AkAAAAABwAJAAAAAAeECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAEEBAYCBQoDBg4EBwASAQMAAQEDAAECAwABCgAFBQcAEQgQBgkWBAsaCAweCQIGFAUHAAcBBhUAAQoABQcHABAKAAUNAAoPJAwQKA0RLA4SMA8CBwALDB8JAQwgAAEOAAkBDgAJAQ4ACQEOAAkEDzEAEDIAETMAEjQAAwk1AAs2AAw3AAMEOAAFOQAGOgAAAAADBwAXJQAYJgAZAAAAAwcAFyUAGCYAGQEDAAEBAwABAwcAHiUAHyYAIAAAAAMHAB4lAB8mACABAwABAQMAAQMHACUlACYmACcAAAADBwAlJQAmJgAnAAAAAwcALSUALiYALwAAAAMHAC0lAC4mAC8BCKEBBgEIpwEGAwcANCUANSYANgAAAAMHADQlADUmADYCAwABCgAFAgMAAQoABQMHADslADwmAD0AAAADBwA7JQA8JgA9AQoABQEKAAUDBwBCJQBDJgBEAAAAAwcAQiUAQyYARAAAAwcASSUASiYASwAAAAMHAEklAEomAEsCCgAFDQAKAgoABQ0ACgUHAFAlAFMmAFSnAQBRqAEAUgAAAAAABQcAUCUAUyYAVKcBAFGoAQBSAQ4ACQEOAAkDBwBZJQBaJgBbAAAAAwcAWSUAWiYAWwEOAAkBDgAJAwcAYCUAYSYAYgAAAAMHAGAlAGEmAGIBDgAJAQ4ACQUHAGclAGomAGunAQBoqAEAaQAAAAAABQcAZyUAaiYAa6cBAGioAQBpAQ4ACQEOAAkDBwBwJQBxJgByAAAAAwcAcCUAcSYAcgAAAAMHAHglAHkmAHoAAAADBwB4JQB5JgB6AAAABQcAgAElAIMBJgCEAacBAIEBqAEAggEAAAAAAAUHAIABJQCDASYAhAGnAQCBAagBAIIBAAAFBwCJASUAjAEmAI0BpwEAigGoAQCLAQAAAAAABQcAiQElAIwBJgCNAacBAIoBqAEAiwETAgEUOwEVPgEWPwEXQAEZQgEaRBMbRRQcRwEdSRMeShUhSwEiTAEjTRMnUBYoURopUgIqUwIrVAIsVQItVgIuWAIvWhMwWxsxXQIyXxMzYBw0YQI1YgI2YxM3Zh04ZyE5aAM6aQM7agM8awM9bAM-bgM_cBNAcSJBcwNCdRNDdiNEdwNFeANGeRNHfCRIfShJfylKgAEpS4MBKUyEASlNhQEpTocBKU-JARNQigEqUYwBKVKOARNTjwErVJABKVWRASlWkgETV5UBLFiWATBZlwEFWpgBBVuZAQVcmgEFXZsBBV6dAQVfnwETYKABMWGjAQVipQETY6YBMmSoAQVlqQEFZqoBE2etATNorgE3aa8BBGqwAQRrsQEEbLIBBG2zAQRutQEEb7cBE3C4AThxugEEcrwBE3O9ATl0vgEEdb8BBHbAARN3wwE6eMQBPnnFAQh6xgEIe8cBCHzIAQh9yQEIfssBCH_NAROAAc4BP4EB0AEIggHSARODAdMBQIQB1AEIhQHVAQiGAdYBE4cB2QFBiAHaAUWJAdwBCooB3QEKiwHgAQqMAeEBCo0B4gEKjgHkAQqPAeYBE5AB5wFGkQHpAQqSAesBE5MB7AFHlAHtAQqVAe4BCpYB7wETlwHyAUiYAfMBTJkB9AEJmgH1AQmbAfYBCZwB9wEJnQH4AQmeAfoBCZ8B_AEToAH9AU2hAf8BCaIBgQITowGCAk6kAYMCCaUBhAIJpgGFAhOpAYgCT6oBiQJVqwGKAg-sAYsCD60BjAIPrgGNAg-vAY4CD7ABkAIPsQGSAhOyAZMCVrMBlQIPtAGXAhO1AZgCV7YBmQIPtwGaAg-4AZsCE7kBngJYugGfAly7AaACDLwBoQIMvQGiAgy-AaMCDL8BpAIMwAGmAgzBAagCE8IBqQJdwwGrAgzEAa0CE8UBrgJexgGvAgzHAbACDMgBsQITyQG0Al_KAbUCY8sBtgINzAG3Ag3NAbgCDc4BuQINzwG6Ag3QAbwCDdEBvgIT0gG_AmTTAcECDdQBwwIT1QHEAmXWAcUCDdcBxgIN2AHHAhPZAcoCZtoBywJs2wHMAg7cAc0CDt0BzgIO3gHPAg7fAdACDuAB0gIO4QHUAhPiAdUCbeMB1wIO5AHZAhPlAdoCbuYB2wIO5wHcAg7oAd0CE-kB4AJv6gHhAnPrAeMCdOwB5AJ07QHnAnTuAegCdO8B6QJ08AHrAnTxAe0CE_IB7gJ18wHwAnT0AfICE_UB8wJ29gH0AnT3AfUCdPgB9gIT-QH5Anf6AfoCe_sB_AJ8_AH9Anz9AYADfP4BgQN8_wGCA3yAAoQDfIEChgMTggKHA32DAokDfIQCiwMThQKMA36GAo0DfIcCjgN8iAKPAxOJApIDf4oCkwOFAYsClQMGjAKWAwaNApgDBo4CmQMGjwKaAwaQApwDBpECngMTkgKfA4YBkwKhAwaUAqMDE5UCpAOHAZYCpQMGlwKmAwaYAqcDE5kCqgOIAZoCqwOOAQ" } async function decodeBase64AsWasm(wasmBase64: string): Promise { @@ -278,6 +278,16 @@ export interface PrismaClient< */ get court(): Prisma.CourtDelegate; + /** + * `prisma.courtMaintenance`: Exposes CRUD operations for the **CourtMaintenance** model. + * Example usage: + * ```ts + * // Fetch zero or more CourtMaintenances + * const courtMaintenances = await prisma.courtMaintenance.findMany() + * ``` + */ + get courtMaintenance(): Prisma.CourtMaintenanceDelegate; + /** * `prisma.courtAvailability`: Exposes CRUD operations for the **CourtAvailability** model. * Example usage: diff --git a/apps/backend/src/generated/prisma/internal/prismaNamespace.ts b/apps/backend/src/generated/prisma/internal/prismaNamespace.ts index 7eebafc..dc47dc3 100644 --- a/apps/backend/src/generated/prisma/internal/prismaNamespace.ts +++ b/apps/backend/src/generated/prisma/internal/prismaNamespace.ts @@ -393,6 +393,7 @@ export const ModelName = { ComplexInvitation: 'ComplexInvitation', Sport: 'Sport', Court: 'Court', + CourtMaintenance: 'CourtMaintenance', CourtAvailability: 'CourtAvailability', CourtPriceRule: 'CourtPriceRule', CourtBooking: 'CourtBooking', @@ -414,7 +415,7 @@ export type TypeMap + fields: Prisma.CourtMaintenanceFieldRefs + operations: { + findUnique: { + args: Prisma.CourtMaintenanceFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.CourtMaintenanceFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.CourtMaintenanceFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.CourtMaintenanceFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.CourtMaintenanceFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.CourtMaintenanceCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.CourtMaintenanceCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.CourtMaintenanceCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.CourtMaintenanceDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.CourtMaintenanceUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.CourtMaintenanceDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.CourtMaintenanceUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.CourtMaintenanceUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.CourtMaintenanceUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.CourtMaintenanceAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.CourtMaintenanceGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.CourtMaintenanceCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } CourtAvailability: { payload: Prisma.$CourtAvailabilityPayload fields: Prisma.CourtAvailabilityFieldRefs @@ -1574,6 +1649,9 @@ export const UserScalarFieldEnum = { emailVerified: 'emailVerified', image: 'image', phone: 'phone', + banned: 'banned', + bannedAt: 'bannedAt', + banReason: 'banReason', createdAt: 'createdAt', updatedAt: 'updatedAt', role: 'role' @@ -1688,6 +1766,8 @@ export const CourtScalarFieldEnum = { name: 'name', slotDurationMinutes: 'slotDurationMinutes', basePrice: 'basePrice', + isUnderMaintenance: 'isUnderMaintenance', + maintenanceReason: 'maintenanceReason', createdAt: 'createdAt', updatedAt: 'updatedAt' } as const @@ -1695,6 +1775,20 @@ export const CourtScalarFieldEnum = { export type CourtScalarFieldEnum = (typeof CourtScalarFieldEnum)[keyof typeof CourtScalarFieldEnum] +export const CourtMaintenanceScalarFieldEnum = { + id: 'id', + courtId: 'courtId', + startDate: 'startDate', + startTime: 'startTime', + endTime: 'endTime', + reason: 'reason', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +} as const + +export type CourtMaintenanceScalarFieldEnum = (typeof CourtMaintenanceScalarFieldEnum)[keyof typeof CourtMaintenanceScalarFieldEnum] + + export const CourtAvailabilityScalarFieldEnum = { id: 'id', courtId: 'courtId', @@ -2067,6 +2161,7 @@ export type GlobalOmitConfig = { complexInvitation?: Prisma.ComplexInvitationOmit sport?: Prisma.SportOmit court?: Prisma.CourtOmit + courtMaintenance?: Prisma.CourtMaintenanceOmit courtAvailability?: Prisma.CourtAvailabilityOmit courtPriceRule?: Prisma.CourtPriceRuleOmit courtBooking?: Prisma.CourtBookingOmit diff --git a/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts b/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts index 51b012f..3cee369 100644 --- a/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -60,6 +60,7 @@ export const ModelName = { ComplexInvitation: 'ComplexInvitation', Sport: 'Sport', Court: 'Court', + CourtMaintenance: 'CourtMaintenance', CourtAvailability: 'CourtAvailability', CourtPriceRule: 'CourtPriceRule', CourtBooking: 'CourtBooking', @@ -91,6 +92,9 @@ export const UserScalarFieldEnum = { emailVerified: 'emailVerified', image: 'image', phone: 'phone', + banned: 'banned', + bannedAt: 'bannedAt', + banReason: 'banReason', createdAt: 'createdAt', updatedAt: 'updatedAt', role: 'role' @@ -205,6 +209,8 @@ export const CourtScalarFieldEnum = { name: 'name', slotDurationMinutes: 'slotDurationMinutes', basePrice: 'basePrice', + isUnderMaintenance: 'isUnderMaintenance', + maintenanceReason: 'maintenanceReason', createdAt: 'createdAt', updatedAt: 'updatedAt' } as const @@ -212,6 +218,20 @@ export const CourtScalarFieldEnum = { export type CourtScalarFieldEnum = (typeof CourtScalarFieldEnum)[keyof typeof CourtScalarFieldEnum] +export const CourtMaintenanceScalarFieldEnum = { + id: 'id', + courtId: 'courtId', + startDate: 'startDate', + startTime: 'startTime', + endTime: 'endTime', + reason: 'reason', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +} as const + +export type CourtMaintenanceScalarFieldEnum = (typeof CourtMaintenanceScalarFieldEnum)[keyof typeof CourtMaintenanceScalarFieldEnum] + + export const CourtAvailabilityScalarFieldEnum = { id: 'id', courtId: 'courtId', diff --git a/apps/backend/src/generated/prisma/models.ts b/apps/backend/src/generated/prisma/models.ts index 90f253a..72a2f70 100644 --- a/apps/backend/src/generated/prisma/models.ts +++ b/apps/backend/src/generated/prisma/models.ts @@ -17,6 +17,7 @@ export type * from './models/ComplexUser' export type * from './models/ComplexInvitation' export type * from './models/Sport' export type * from './models/Court' +export type * from './models/CourtMaintenance' export type * from './models/CourtAvailability' export type * from './models/CourtPriceRule' export type * from './models/CourtBooking' diff --git a/apps/backend/src/generated/prisma/models/Court.ts b/apps/backend/src/generated/prisma/models/Court.ts index fc388ba..7607fef 100644 --- a/apps/backend/src/generated/prisma/models/Court.ts +++ b/apps/backend/src/generated/prisma/models/Court.ts @@ -43,6 +43,8 @@ export type CourtMinAggregateOutputType = { name: string | null slotDurationMinutes: number | null basePrice: runtime.Decimal | null + isUnderMaintenance: boolean | null + maintenanceReason: string | null createdAt: Date | null updatedAt: Date | null } @@ -54,6 +56,8 @@ export type CourtMaxAggregateOutputType = { name: string | null slotDurationMinutes: number | null basePrice: runtime.Decimal | null + isUnderMaintenance: boolean | null + maintenanceReason: string | null createdAt: Date | null updatedAt: Date | null } @@ -65,6 +69,8 @@ export type CourtCountAggregateOutputType = { name: number slotDurationMinutes: number basePrice: number + isUnderMaintenance: number + maintenanceReason: number createdAt: number updatedAt: number _all: number @@ -88,6 +94,8 @@ export type CourtMinAggregateInputType = { name?: true slotDurationMinutes?: true basePrice?: true + isUnderMaintenance?: true + maintenanceReason?: true createdAt?: true updatedAt?: true } @@ -99,6 +107,8 @@ export type CourtMaxAggregateInputType = { name?: true slotDurationMinutes?: true basePrice?: true + isUnderMaintenance?: true + maintenanceReason?: true createdAt?: true updatedAt?: true } @@ -110,6 +120,8 @@ export type CourtCountAggregateInputType = { name?: true slotDurationMinutes?: true basePrice?: true + isUnderMaintenance?: true + maintenanceReason?: true createdAt?: true updatedAt?: true _all?: true @@ -208,6 +220,8 @@ export type CourtGroupByOutputType = { name: string slotDurationMinutes: number basePrice: runtime.Decimal + isUnderMaintenance: boolean + maintenanceReason: string | null createdAt: Date updatedAt: Date _count: CourtCountAggregateOutputType | null @@ -242,6 +256,8 @@ export type CourtWhereInput = { name?: Prisma.StringFilter<"Court"> | string slotDurationMinutes?: Prisma.IntFilter<"Court"> | number basePrice?: Prisma.DecimalFilter<"Court"> | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFilter<"Court"> | boolean + maintenanceReason?: Prisma.StringNullableFilter<"Court"> | string | null createdAt?: Prisma.DateTimeFilter<"Court"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Court"> | Date | string complex?: Prisma.XOR @@ -249,6 +265,7 @@ export type CourtWhereInput = { availabilities?: Prisma.CourtAvailabilityListRelationFilter priceRules?: Prisma.CourtPriceRuleListRelationFilter bookings?: Prisma.CourtBookingListRelationFilter + maintenances?: Prisma.CourtMaintenanceListRelationFilter } export type CourtOrderByWithRelationInput = { @@ -258,6 +275,8 @@ export type CourtOrderByWithRelationInput = { name?: Prisma.SortOrder slotDurationMinutes?: Prisma.SortOrder basePrice?: Prisma.SortOrder + isUnderMaintenance?: Prisma.SortOrder + maintenanceReason?: Prisma.SortOrderInput | Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder complex?: Prisma.ComplexOrderByWithRelationInput @@ -265,6 +284,7 @@ export type CourtOrderByWithRelationInput = { availabilities?: Prisma.CourtAvailabilityOrderByRelationAggregateInput priceRules?: Prisma.CourtPriceRuleOrderByRelationAggregateInput bookings?: Prisma.CourtBookingOrderByRelationAggregateInput + maintenances?: Prisma.CourtMaintenanceOrderByRelationAggregateInput } export type CourtWhereUniqueInput = Prisma.AtLeast<{ @@ -277,6 +297,8 @@ export type CourtWhereUniqueInput = Prisma.AtLeast<{ name?: Prisma.StringFilter<"Court"> | string slotDurationMinutes?: Prisma.IntFilter<"Court"> | number basePrice?: Prisma.DecimalFilter<"Court"> | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFilter<"Court"> | boolean + maintenanceReason?: Prisma.StringNullableFilter<"Court"> | string | null createdAt?: Prisma.DateTimeFilter<"Court"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Court"> | Date | string complex?: Prisma.XOR @@ -284,6 +306,7 @@ export type CourtWhereUniqueInput = Prisma.AtLeast<{ availabilities?: Prisma.CourtAvailabilityListRelationFilter priceRules?: Prisma.CourtPriceRuleListRelationFilter bookings?: Prisma.CourtBookingListRelationFilter + maintenances?: Prisma.CourtMaintenanceListRelationFilter }, "id"> export type CourtOrderByWithAggregationInput = { @@ -293,6 +316,8 @@ export type CourtOrderByWithAggregationInput = { name?: Prisma.SortOrder slotDurationMinutes?: Prisma.SortOrder basePrice?: Prisma.SortOrder + isUnderMaintenance?: Prisma.SortOrder + maintenanceReason?: Prisma.SortOrderInput | Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder _count?: Prisma.CourtCountOrderByAggregateInput @@ -312,6 +337,8 @@ export type CourtScalarWhereWithAggregatesInput = { name?: Prisma.StringWithAggregatesFilter<"Court"> | string slotDurationMinutes?: Prisma.IntWithAggregatesFilter<"Court"> | number basePrice?: Prisma.DecimalWithAggregatesFilter<"Court"> | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolWithAggregatesFilter<"Court"> | boolean + maintenanceReason?: Prisma.StringNullableWithAggregatesFilter<"Court"> | string | null createdAt?: Prisma.DateTimeWithAggregatesFilter<"Court"> | Date | string updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Court"> | Date | string } @@ -321,6 +348,8 @@ export type CourtCreateInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput @@ -328,6 +357,7 @@ export type CourtCreateInput = { availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput } export type CourtUncheckedCreateInput = { @@ -337,11 +367,14 @@ export type CourtUncheckedCreateInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput } export type CourtUpdateInput = { @@ -349,6 +382,8 @@ export type CourtUpdateInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput @@ -356,6 +391,7 @@ export type CourtUpdateInput = { availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateInput = { @@ -365,11 +401,14 @@ export type CourtUncheckedUpdateInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput } export type CourtCreateManyInput = { @@ -379,6 +418,8 @@ export type CourtCreateManyInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string } @@ -388,6 +429,8 @@ export type CourtUpdateManyMutationInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -399,6 +442,8 @@ export type CourtUncheckedUpdateManyInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -420,6 +465,8 @@ export type CourtCountOrderByAggregateInput = { name?: Prisma.SortOrder slotDurationMinutes?: Prisma.SortOrder basePrice?: Prisma.SortOrder + isUnderMaintenance?: Prisma.SortOrder + maintenanceReason?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } @@ -436,6 +483,8 @@ export type CourtMaxOrderByAggregateInput = { name?: Prisma.SortOrder slotDurationMinutes?: Prisma.SortOrder basePrice?: Prisma.SortOrder + isUnderMaintenance?: Prisma.SortOrder + maintenanceReason?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } @@ -447,6 +496,8 @@ export type CourtMinOrderByAggregateInput = { name?: Prisma.SortOrder slotDurationMinutes?: Prisma.SortOrder basePrice?: Prisma.SortOrder + isUnderMaintenance?: Prisma.SortOrder + maintenanceReason?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder } @@ -561,6 +612,20 @@ export type DecimalFieldUpdateOperationsInput = { divide?: runtime.Decimal | runtime.DecimalJsLike | number | string } +export type CourtCreateNestedOneWithoutMaintenancesInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.CourtCreateOrConnectWithoutMaintenancesInput + connect?: Prisma.CourtWhereUniqueInput +} + +export type CourtUpdateOneRequiredWithoutMaintenancesNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.CourtCreateOrConnectWithoutMaintenancesInput + upsert?: Prisma.CourtUpsertWithoutMaintenancesInput + connect?: Prisma.CourtWhereUniqueInput + update?: Prisma.XOR, Prisma.CourtUncheckedUpdateWithoutMaintenancesInput> +} + export type CourtCreateNestedOneWithoutAvailabilitiesInput = { create?: Prisma.XOR connectOrCreate?: Prisma.CourtCreateOrConnectWithoutAvailabilitiesInput @@ -608,12 +673,15 @@ export type CourtCreateWithoutComplexInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string sport: Prisma.SportCreateNestedOneWithoutCourtsInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput } export type CourtUncheckedCreateWithoutComplexInput = { @@ -622,11 +690,14 @@ export type CourtUncheckedCreateWithoutComplexInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput } export type CourtCreateOrConnectWithoutComplexInput = { @@ -665,6 +736,8 @@ export type CourtScalarWhereInput = { name?: Prisma.StringFilter<"Court"> | string slotDurationMinutes?: Prisma.IntFilter<"Court"> | number basePrice?: Prisma.DecimalFilter<"Court"> | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFilter<"Court"> | boolean + maintenanceReason?: Prisma.StringNullableFilter<"Court"> | string | null createdAt?: Prisma.DateTimeFilter<"Court"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Court"> | Date | string } @@ -674,12 +747,15 @@ export type CourtCreateWithoutSportInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput } export type CourtUncheckedCreateWithoutSportInput = { @@ -688,11 +764,14 @@ export type CourtUncheckedCreateWithoutSportInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput } export type CourtCreateOrConnectWithoutSportInput = { @@ -721,17 +800,100 @@ export type CourtUpdateManyWithWhereWithoutSportInput = { data: Prisma.XOR } +export type CourtCreateWithoutMaintenancesInput = { + id: string + name: string + slotDurationMinutes: number + basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null + createdAt?: Date | string + updatedAt?: Date | string + complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput + sport: Prisma.SportCreateNestedOneWithoutCourtsInput + availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput + priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput + bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput +} + +export type CourtUncheckedCreateWithoutMaintenancesInput = { + id: string + complexId: string + sportId: string + name: string + slotDurationMinutes: number + basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null + createdAt?: Date | string + updatedAt?: Date | string + availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput + priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput + bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput +} + +export type CourtCreateOrConnectWithoutMaintenancesInput = { + where: Prisma.CourtWhereUniqueInput + create: Prisma.XOR +} + +export type CourtUpsertWithoutMaintenancesInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.CourtWhereInput +} + +export type CourtUpdateToOneWithWhereWithoutMaintenancesInput = { + where?: Prisma.CourtWhereInput + data: Prisma.XOR +} + +export type CourtUpdateWithoutMaintenancesInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number + basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput + sport?: Prisma.SportUpdateOneRequiredWithoutCourtsNestedInput + availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput + priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput + bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput +} + +export type CourtUncheckedUpdateWithoutMaintenancesInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + complexId?: Prisma.StringFieldUpdateOperationsInput | string + sportId?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number + basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput + priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput + bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput +} + export type CourtCreateWithoutAvailabilitiesInput = { id: string name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput sport: Prisma.SportCreateNestedOneWithoutCourtsInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput } export type CourtUncheckedCreateWithoutAvailabilitiesInput = { @@ -741,10 +903,13 @@ export type CourtUncheckedCreateWithoutAvailabilitiesInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput } export type CourtCreateOrConnectWithoutAvailabilitiesInput = { @@ -768,12 +933,15 @@ export type CourtUpdateWithoutAvailabilitiesInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput sport?: Prisma.SportUpdateOneRequiredWithoutCourtsNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateWithoutAvailabilitiesInput = { @@ -783,10 +951,13 @@ export type CourtUncheckedUpdateWithoutAvailabilitiesInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput } export type CourtCreateWithoutPriceRulesInput = { @@ -794,12 +965,15 @@ export type CourtCreateWithoutPriceRulesInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput sport: Prisma.SportCreateNestedOneWithoutCourtsInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput } export type CourtUncheckedCreateWithoutPriceRulesInput = { @@ -809,10 +983,13 @@ export type CourtUncheckedCreateWithoutPriceRulesInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput } export type CourtCreateOrConnectWithoutPriceRulesInput = { @@ -836,12 +1013,15 @@ export type CourtUpdateWithoutPriceRulesInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput sport?: Prisma.SportUpdateOneRequiredWithoutCourtsNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateWithoutPriceRulesInput = { @@ -851,10 +1031,13 @@ export type CourtUncheckedUpdateWithoutPriceRulesInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput } export type CourtCreateWithoutBookingsInput = { @@ -862,12 +1045,15 @@ export type CourtCreateWithoutBookingsInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput sport: Prisma.SportCreateNestedOneWithoutCourtsInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput } export type CourtUncheckedCreateWithoutBookingsInput = { @@ -877,10 +1063,13 @@ export type CourtUncheckedCreateWithoutBookingsInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput + maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput } export type CourtCreateOrConnectWithoutBookingsInput = { @@ -904,12 +1093,15 @@ export type CourtUpdateWithoutBookingsInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput sport?: Prisma.SportUpdateOneRequiredWithoutCourtsNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateWithoutBookingsInput = { @@ -919,10 +1111,13 @@ export type CourtUncheckedUpdateWithoutBookingsInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput } export type CourtCreateManyComplexInput = { @@ -931,6 +1126,8 @@ export type CourtCreateManyComplexInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string } @@ -940,12 +1137,15 @@ export type CourtUpdateWithoutComplexInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string sport?: Prisma.SportUpdateOneRequiredWithoutCourtsNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateWithoutComplexInput = { @@ -954,11 +1154,14 @@ export type CourtUncheckedUpdateWithoutComplexInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateManyWithoutComplexInput = { @@ -967,6 +1170,8 @@ export type CourtUncheckedUpdateManyWithoutComplexInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -977,6 +1182,8 @@ export type CourtCreateManySportInput = { name: string slotDurationMinutes: number basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: boolean + maintenanceReason?: string | null createdAt?: Date | string updatedAt?: Date | string } @@ -986,12 +1193,15 @@ export type CourtUpdateWithoutSportInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateWithoutSportInput = { @@ -1000,11 +1210,14 @@ export type CourtUncheckedUpdateWithoutSportInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput + maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput } export type CourtUncheckedUpdateManyWithoutSportInput = { @@ -1013,6 +1226,8 @@ export type CourtUncheckedUpdateManyWithoutSportInput = { name?: Prisma.StringFieldUpdateOperationsInput | string slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean + maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } @@ -1026,12 +1241,14 @@ export type CourtCountOutputType = { availabilities: number priceRules: number bookings: number + maintenances: number } export type CourtCountOutputTypeSelect = { availabilities?: boolean | CourtCountOutputTypeCountAvailabilitiesArgs priceRules?: boolean | CourtCountOutputTypeCountPriceRulesArgs bookings?: boolean | CourtCountOutputTypeCountBookingsArgs + maintenances?: boolean | CourtCountOutputTypeCountMaintenancesArgs } /** @@ -1065,6 +1282,13 @@ export type CourtCountOutputTypeCountBookingsArgs = { + where?: Prisma.CourtMaintenanceWhereInput +} + export type CourtSelect = runtime.Types.Extensions.GetSelect<{ id?: boolean @@ -1073,6 +1297,8 @@ export type CourtSelect @@ -1080,6 +1306,7 @@ export type CourtSelect priceRules?: boolean | Prisma.Court$priceRulesArgs bookings?: boolean | Prisma.Court$bookingsArgs + maintenances?: boolean | Prisma.Court$maintenancesArgs _count?: boolean | Prisma.CourtCountOutputTypeDefaultArgs }, ExtArgs["result"]["court"]> @@ -1090,6 +1317,8 @@ export type CourtSelectCreateManyAndReturn @@ -1103,6 +1332,8 @@ export type CourtSelectUpdateManyAndReturn @@ -1116,17 +1347,20 @@ export type CourtSelectScalar = { name?: boolean slotDurationMinutes?: boolean basePrice?: boolean + isUnderMaintenance?: boolean + maintenanceReason?: boolean createdAt?: boolean updatedAt?: boolean } -export type CourtOmit = runtime.Types.Extensions.GetOmit<"id" | "complexId" | "sportId" | "name" | "slotDurationMinutes" | "basePrice" | "createdAt" | "updatedAt", ExtArgs["result"]["court"]> +export type CourtOmit = runtime.Types.Extensions.GetOmit<"id" | "complexId" | "sportId" | "name" | "slotDurationMinutes" | "basePrice" | "isUnderMaintenance" | "maintenanceReason" | "createdAt" | "updatedAt", ExtArgs["result"]["court"]> export type CourtInclude = { complex?: boolean | Prisma.ComplexDefaultArgs sport?: boolean | Prisma.SportDefaultArgs availabilities?: boolean | Prisma.Court$availabilitiesArgs priceRules?: boolean | Prisma.Court$priceRulesArgs bookings?: boolean | Prisma.Court$bookingsArgs + maintenances?: boolean | Prisma.Court$maintenancesArgs _count?: boolean | Prisma.CourtCountOutputTypeDefaultArgs } export type CourtIncludeCreateManyAndReturn = { @@ -1146,6 +1380,7 @@ export type $CourtPayload[] priceRules: Prisma.$CourtPriceRulePayload[] bookings: Prisma.$CourtBookingPayload[] + maintenances: Prisma.$CourtMaintenancePayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1154,6 +1389,8 @@ export type $CourtPayload @@ -1555,6 +1792,7 @@ export interface Prisma__CourtClient = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> priceRules = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> bookings = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + maintenances = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, 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. @@ -1590,6 +1828,8 @@ export interface CourtFieldRefs { readonly name: Prisma.FieldRef<"Court", 'String'> readonly slotDurationMinutes: Prisma.FieldRef<"Court", 'Int'> readonly basePrice: Prisma.FieldRef<"Court", 'Decimal'> + readonly isUnderMaintenance: Prisma.FieldRef<"Court", 'Boolean'> + readonly maintenanceReason: Prisma.FieldRef<"Court", 'String'> readonly createdAt: Prisma.FieldRef<"Court", 'DateTime'> readonly updatedAt: Prisma.FieldRef<"Court", 'DateTime'> } @@ -2064,6 +2304,30 @@ export type Court$bookingsArgs = { + /** + * Select specific fields to fetch from the CourtMaintenance + */ + select?: Prisma.CourtMaintenanceSelect | null + /** + * Omit specific fields from the CourtMaintenance + */ + omit?: Prisma.CourtMaintenanceOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CourtMaintenanceInclude | null + where?: Prisma.CourtMaintenanceWhereInput + orderBy?: Prisma.CourtMaintenanceOrderByWithRelationInput | Prisma.CourtMaintenanceOrderByWithRelationInput[] + cursor?: Prisma.CourtMaintenanceWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.CourtMaintenanceScalarFieldEnum | Prisma.CourtMaintenanceScalarFieldEnum[] +} + /** * Court without action */ diff --git a/apps/backend/src/generated/prisma/models/User.ts b/apps/backend/src/generated/prisma/models/User.ts index 1787905..d289dff 100644 --- a/apps/backend/src/generated/prisma/models/User.ts +++ b/apps/backend/src/generated/prisma/models/User.ts @@ -31,6 +31,9 @@ export type UserMinAggregateOutputType = { emailVerified: boolean | null image: string | null phone: string | null + banned: boolean | null + bannedAt: Date | null + banReason: string | null createdAt: Date | null updatedAt: Date | null role: string | null @@ -43,6 +46,9 @@ export type UserMaxAggregateOutputType = { emailVerified: boolean | null image: string | null phone: string | null + banned: boolean | null + bannedAt: Date | null + banReason: string | null createdAt: Date | null updatedAt: Date | null role: string | null @@ -55,6 +61,9 @@ export type UserCountAggregateOutputType = { emailVerified: number image: number phone: number + banned: number + bannedAt: number + banReason: number createdAt: number updatedAt: number role: number @@ -69,6 +78,9 @@ export type UserMinAggregateInputType = { emailVerified?: true image?: true phone?: true + banned?: true + bannedAt?: true + banReason?: true createdAt?: true updatedAt?: true role?: true @@ -81,6 +93,9 @@ export type UserMaxAggregateInputType = { emailVerified?: true image?: true phone?: true + banned?: true + bannedAt?: true + banReason?: true createdAt?: true updatedAt?: true role?: true @@ -93,6 +108,9 @@ export type UserCountAggregateInputType = { emailVerified?: true image?: true phone?: true + banned?: true + bannedAt?: true + banReason?: true createdAt?: true updatedAt?: true role?: true @@ -178,6 +196,9 @@ export type UserGroupByOutputType = { emailVerified: boolean image: string | null phone: string | null + banned: boolean + bannedAt: Date | null + banReason: string | null createdAt: Date updatedAt: Date role: string @@ -211,6 +232,9 @@ export type UserWhereInput = { emailVerified?: Prisma.BoolFilter<"User"> | boolean image?: Prisma.StringNullableFilter<"User"> | string | null phone?: Prisma.StringNullableFilter<"User"> | string | null + banned?: Prisma.BoolFilter<"User"> | boolean + bannedAt?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null + banReason?: Prisma.StringNullableFilter<"User"> | string | null createdAt?: Prisma.DateTimeFilter<"User"> | Date | string updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string role?: Prisma.StringFilter<"User"> | string @@ -226,6 +250,9 @@ export type UserOrderByWithRelationInput = { emailVerified?: Prisma.SortOrder image?: Prisma.SortOrderInput | Prisma.SortOrder phone?: Prisma.SortOrderInput | Prisma.SortOrder + banned?: Prisma.SortOrder + bannedAt?: Prisma.SortOrderInput | Prisma.SortOrder + banReason?: Prisma.SortOrderInput | Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder role?: Prisma.SortOrder @@ -244,6 +271,9 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{ emailVerified?: Prisma.BoolFilter<"User"> | boolean image?: Prisma.StringNullableFilter<"User"> | string | null phone?: Prisma.StringNullableFilter<"User"> | string | null + banned?: Prisma.BoolFilter<"User"> | boolean + bannedAt?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null + banReason?: Prisma.StringNullableFilter<"User"> | string | null createdAt?: Prisma.DateTimeFilter<"User"> | Date | string updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string role?: Prisma.StringFilter<"User"> | string @@ -259,6 +289,9 @@ export type UserOrderByWithAggregationInput = { emailVerified?: Prisma.SortOrder image?: Prisma.SortOrderInput | Prisma.SortOrder phone?: Prisma.SortOrderInput | Prisma.SortOrder + banned?: Prisma.SortOrder + bannedAt?: Prisma.SortOrderInput | Prisma.SortOrder + banReason?: Prisma.SortOrderInput | Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder role?: Prisma.SortOrder @@ -277,6 +310,9 @@ export type UserScalarWhereWithAggregatesInput = { emailVerified?: Prisma.BoolWithAggregatesFilter<"User"> | boolean image?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null phone?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null + banned?: Prisma.BoolWithAggregatesFilter<"User"> | boolean + bannedAt?: Prisma.DateTimeNullableWithAggregatesFilter<"User"> | Date | string | null + banReason?: Prisma.StringNullableWithAggregatesFilter<"User"> | string | null createdAt?: Prisma.DateTimeWithAggregatesFilter<"User"> | Date | string updatedAt?: Prisma.DateTimeWithAggregatesFilter<"User"> | Date | string role?: Prisma.StringWithAggregatesFilter<"User"> | string @@ -289,6 +325,9 @@ export type UserCreateInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -304,6 +343,9 @@ export type UserUncheckedCreateInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -319,6 +361,9 @@ export type UserUpdateInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -334,6 +379,9 @@ export type UserUncheckedUpdateInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -349,6 +397,9 @@ export type UserCreateManyInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -361,6 +412,9 @@ export type UserUpdateManyMutationInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -373,6 +427,9 @@ export type UserUncheckedUpdateManyInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -385,6 +442,9 @@ export type UserCountOrderByAggregateInput = { emailVerified?: Prisma.SortOrder image?: Prisma.SortOrder phone?: Prisma.SortOrder + banned?: Prisma.SortOrder + bannedAt?: Prisma.SortOrder + banReason?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder role?: Prisma.SortOrder @@ -397,6 +457,9 @@ export type UserMaxOrderByAggregateInput = { emailVerified?: Prisma.SortOrder image?: Prisma.SortOrder phone?: Prisma.SortOrder + banned?: Prisma.SortOrder + bannedAt?: Prisma.SortOrder + banReason?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder role?: Prisma.SortOrder @@ -409,6 +472,9 @@ export type UserMinOrderByAggregateInput = { emailVerified?: Prisma.SortOrder image?: Prisma.SortOrder phone?: Prisma.SortOrder + banned?: Prisma.SortOrder + bannedAt?: Prisma.SortOrder + banReason?: Prisma.SortOrder createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder role?: Prisma.SortOrder @@ -431,6 +497,10 @@ export type NullableStringFieldUpdateOperationsInput = { set?: string | null } +export type NullableDateTimeFieldUpdateOperationsInput = { + set?: Date | string | null +} + export type DateTimeFieldUpdateOperationsInput = { set?: Date | string } @@ -484,6 +554,9 @@ export type UserCreateWithoutSessionsInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -498,6 +571,9 @@ export type UserUncheckedCreateWithoutSessionsInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -528,6 +604,9 @@ export type UserUpdateWithoutSessionsInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -542,6 +621,9 @@ export type UserUncheckedUpdateWithoutSessionsInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -556,6 +638,9 @@ export type UserCreateWithoutAccountsInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -570,6 +655,9 @@ export type UserUncheckedCreateWithoutAccountsInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -600,6 +688,9 @@ export type UserUpdateWithoutAccountsInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -614,6 +705,9 @@ export type UserUncheckedUpdateWithoutAccountsInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -628,6 +722,9 @@ export type UserCreateWithoutComplexesInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -642,6 +739,9 @@ export type UserUncheckedCreateWithoutComplexesInput = { emailVerified?: boolean image?: string | null phone?: string | null + banned?: boolean + bannedAt?: Date | string | null + banReason?: string | null createdAt?: Date | string updatedAt?: Date | string role?: string @@ -672,6 +772,9 @@ export type UserUpdateWithoutComplexesInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -686,6 +789,9 @@ export type UserUncheckedUpdateWithoutComplexesInput = { emailVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean image?: Prisma.NullableStringFieldUpdateOperationsInput | string | null phone?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + banned?: Prisma.BoolFieldUpdateOperationsInput | boolean + bannedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + banReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string role?: Prisma.StringFieldUpdateOperationsInput | string @@ -749,6 +855,9 @@ export type UserSelect = runtime.Types.Extensions.GetOmit<"id" | "name" | "email" | "emailVerified" | "image" | "phone" | "createdAt" | "updatedAt" | "role", ExtArgs["result"]["user"]> +export type UserOmit = runtime.Types.Extensions.GetOmit<"id" | "name" | "email" | "emailVerified" | "image" | "phone" | "banned" | "bannedAt" | "banReason" | "createdAt" | "updatedAt" | "role", ExtArgs["result"]["user"]> export type UserInclude = { sessions?: boolean | Prisma.User$sessionsArgs accounts?: boolean | Prisma.User$accountsArgs @@ -818,6 +936,9 @@ export type $UserPayload readonly image: Prisma.FieldRef<"User", 'String'> readonly phone: Prisma.FieldRef<"User", 'String'> + readonly banned: Prisma.FieldRef<"User", 'Boolean'> + readonly bannedAt: Prisma.FieldRef<"User", 'DateTime'> + readonly banReason: Prisma.FieldRef<"User", 'String'> readonly createdAt: Prisma.FieldRef<"User", 'DateTime'> readonly updatedAt: Prisma.FieldRef<"User", 'DateTime'> readonly role: Prisma.FieldRef<"User", 'String'> diff --git a/apps/backend/src/lib/auth.ts b/apps/backend/src/lib/auth.ts index f018627..836a074 100644 --- a/apps/backend/src/lib/auth.ts +++ b/apps/backend/src/lib/auth.ts @@ -22,10 +22,26 @@ export const auth = betterAuth({ }, user: { additionalFields: { + role: { + type: 'string', + required: false, + }, phone: { type: 'string', required: false, }, + banned: { + type: 'boolean', + required: false, + }, + bannedAt: { + type: 'string', + required: false, + }, + banReason: { + type: 'string', + required: false, + }, }, }, emailVerification: { diff --git a/apps/backend/src/middlewares/require-auth.middleware.ts b/apps/backend/src/middlewares/require-auth.middleware.ts index 387ff97..561cf54 100644 --- a/apps/backend/src/middlewares/require-auth.middleware.ts +++ b/apps/backend/src/middlewares/require-auth.middleware.ts @@ -11,6 +11,18 @@ export const requireAuth = createMiddleware(async (c, next) => { return c.json({ message: 'Unauthorized' }, 401); } + const user = session.user as { banned?: boolean; banReason?: string | null }; + + if (user.banned) { + return c.json( + { + message: 'Tu cuenta ha sido bloqueada.', + ...(user.banReason ? { reason: user.banReason } : {}), + }, + 403 + ); + } + c.set('user', session.user); c.set('session', session.session); diff --git a/apps/backend/src/modules/admin/admin.routes.ts b/apps/backend/src/modules/admin/admin.routes.ts new file mode 100644 index 0000000..1de3e12 --- /dev/null +++ b/apps/backend/src/modules/admin/admin.routes.ts @@ -0,0 +1,64 @@ +import { validate } from '@/lib/http/validate'; +import { requireAuth } from '@/middlewares/require-auth.middleware'; +import { requireSuperAdmin } from '@/middlewares/require-super-admin.middleware'; +import { blockUserHandler } from '@/modules/admin/handlers/block-user.handler'; +import { createPlanHandler } from '@/modules/admin/handlers/create-plan.handler'; +import { deletePlanHandler } from '@/modules/admin/handlers/delete-plan.handler'; +import { getUserSessionsHandler } from '@/modules/admin/handlers/get-user-sessions.handler'; +import { listComplexesHandler } from '@/modules/admin/handlers/list-complexes.handler'; +import { revokeAllSessionsHandler } from '@/modules/admin/handlers/revoke-all-sessions.handler'; +import { listPlansAdminHandler } from '@/modules/admin/handlers/list-plans-admin.handler'; +import { listUsersHandler } from '@/modules/admin/handlers/list-users.handler'; +import { unblockUserHandler } from '@/modules/admin/handlers/unblock-user.handler'; +import { updatePlanHandler } from '@/modules/admin/handlers/update-plan.handler'; +import type { AppEnv } from '@/types/hono'; +import { + adminBlockUserSchema, + adminCreatePlanSchema, + adminUpdatePlanSchema, +} from '@repo/api-contract'; +import { Hono } from 'hono'; +import { z } from 'zod'; + +export const adminRoutes = new Hono(); + +adminRoutes.use('*', requireAuth, requireSuperAdmin); + +adminRoutes.get('/complexes', listComplexesHandler); + +adminRoutes.get('/plans', listPlansAdminHandler); +adminRoutes.post('/plans', validate.json(adminCreatePlanSchema), createPlanHandler); +adminRoutes.patch( + '/plans/:code', + validate.param(z.object({ code: z.string().min(1).max(10) })), + validate.json(adminUpdatePlanSchema), + updatePlanHandler +); +adminRoutes.delete( + '/plans/:code', + validate.param(z.object({ code: z.string().min(1).max(10) })), + deletePlanHandler +); + +adminRoutes.get('/users', listUsersHandler); +adminRoutes.post( + '/users/:id/block', + validate.param(z.object({ id: z.string().min(1) })), + validate.json(adminBlockUserSchema), + blockUserHandler +); +adminRoutes.post( + '/users/:id/unblock', + validate.param(z.object({ id: z.string().min(1) })), + unblockUserHandler +); +adminRoutes.get( + '/users/:id/sessions', + validate.param(z.object({ id: z.string().min(1) })), + getUserSessionsHandler +); +adminRoutes.post( + '/users/:id/sessions/revoke-all', + validate.param(z.object({ id: z.string().min(1) })), + revokeAllSessionsHandler +); diff --git a/apps/backend/src/modules/admin/handlers/block-user.handler.ts b/apps/backend/src/modules/admin/handlers/block-user.handler.ts new file mode 100644 index 0000000..4a1f730 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/block-user.handler.ts @@ -0,0 +1,20 @@ +import { AdminServiceError, blockUser } from '@/modules/admin/services/admin-users.service'; +import type { AppContext } from '@/types/hono'; +import type { AdminBlockUserInput } from '@repo/api-contract'; + +type BlockUserParams = { id: string }; + +export async function blockUserHandler(c: AppContext) { + const { id } = c.req.valid('param' as never) as BlockUserParams; + const body = c.req.valid('json' as never) as AdminBlockUserInput; + + try { + await blockUser(id, body.banReason); + return c.json({ message: 'Usuario bloqueado correctamente.' }); + } catch (error) { + if (error instanceof AdminServiceError) { + return c.json({ message: error.message }, error.status); + } + throw error; + } +} diff --git a/apps/backend/src/modules/admin/handlers/create-plan.handler.ts b/apps/backend/src/modules/admin/handlers/create-plan.handler.ts new file mode 100644 index 0000000..ff52e11 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/create-plan.handler.ts @@ -0,0 +1,34 @@ +import { db } from '@/lib/prisma'; +import type { AppContext } from '@/types/hono'; +import type { AdminCreatePlanInput } from '@repo/api-contract'; + +export async function createPlanHandler(c: AppContext) { + const body = c.req.valid('json' as never) as AdminCreatePlanInput; + + const existing = await db.plan.findUnique({ + where: { code: body.code }, + }); + + if (existing) { + return c.json({ message: 'Ya existe un plan con ese código.' }, 409); + } + + const plan = await db.plan.create({ + data: { + code: body.code, + name: body.name, + price: body.price, + rules: body.rules, + }, + }); + + return c.json( + { + code: plan.code, + name: plan.name, + price: Number(plan.price), + rules: plan.rules, + }, + 201 + ); +} diff --git a/apps/backend/src/modules/admin/handlers/delete-plan.handler.ts b/apps/backend/src/modules/admin/handlers/delete-plan.handler.ts new file mode 100644 index 0000000..5d03785 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/delete-plan.handler.ts @@ -0,0 +1,31 @@ +import { db } from '@/lib/prisma'; +import type { AppContext } from '@/types/hono'; + +type DeletePlanParams = { code: string }; + +export async function deletePlanHandler(c: AppContext) { + const { code } = c.req.valid('param' as never) as DeletePlanParams; + + const existing = await db.plan.findUnique({ + where: { code }, + include: { + _count: { + select: { complexes: true }, + }, + }, + }); + + if (!existing) { + return c.json({ message: 'Plan no encontrado.' }, 404); + } + + if (existing._count.complexes > 0) { + return c.json({ message: 'No se puede eliminar un plan que tiene complejos asignados.' }, 409); + } + + await db.plan.delete({ + where: { code }, + }); + + return c.json({ message: 'Plan eliminado correctamente.' }); +} diff --git a/apps/backend/src/modules/admin/handlers/get-user-sessions.handler.ts b/apps/backend/src/modules/admin/handlers/get-user-sessions.handler.ts new file mode 100644 index 0000000..d3cb9a2 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/get-user-sessions.handler.ts @@ -0,0 +1,12 @@ +import { getUserSessions } from '@/modules/admin/services/admin-users.service'; +import type { AppContext } from '@/types/hono'; + +type UserSessionsParams = { id: string }; + +export async function getUserSessionsHandler(c: AppContext) { + const { id } = c.req.valid('param' as never) as UserSessionsParams; + + const sessions = await getUserSessions(id); + + return c.json(sessions); +} diff --git a/apps/backend/src/modules/admin/handlers/list-complexes.handler.ts b/apps/backend/src/modules/admin/handlers/list-complexes.handler.ts new file mode 100644 index 0000000..f72d8a7 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/list-complexes.handler.ts @@ -0,0 +1,7 @@ +import { getComplexStatsList } from '@/modules/admin/services/complex-stats.service'; +import type { AppContext } from '@/types/hono'; + +export async function listComplexesHandler(c: AppContext) { + const stats = await getComplexStatsList(); + return c.json(stats); +} diff --git a/apps/backend/src/modules/admin/handlers/list-plans-admin.handler.ts b/apps/backend/src/modules/admin/handlers/list-plans-admin.handler.ts new file mode 100644 index 0000000..74ad372 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/list-plans-admin.handler.ts @@ -0,0 +1,24 @@ +import { db } from '@/lib/prisma'; +import type { AppContext } from '@/types/hono'; + +export async function listPlansAdminHandler(c: AppContext) { + const plans = await db.plan.findMany({ + orderBy: { price: 'asc' }, + include: { + _count: { + select: { complexes: true }, + }, + }, + }); + + return c.json( + plans.map((plan) => ({ + code: plan.code, + name: plan.name, + price: Number(plan.price), + rules: plan.rules, + lastUpdatedAt: plan.lastUpdatedAt.toISOString(), + complexCount: plan._count.complexes, + })) + ); +} diff --git a/apps/backend/src/modules/admin/handlers/list-users.handler.ts b/apps/backend/src/modules/admin/handlers/list-users.handler.ts new file mode 100644 index 0000000..f6a757c --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/list-users.handler.ts @@ -0,0 +1,7 @@ +import { listAdminUsers } from '@/modules/admin/services/admin-users.service'; +import type { AppContext } from '@/types/hono'; + +export async function listUsersHandler(c: AppContext) { + const users = await listAdminUsers(); + return c.json(users); +} diff --git a/apps/backend/src/modules/admin/handlers/revoke-all-sessions.handler.ts b/apps/backend/src/modules/admin/handlers/revoke-all-sessions.handler.ts new file mode 100644 index 0000000..9351954 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/revoke-all-sessions.handler.ts @@ -0,0 +1,12 @@ +import { revokeAllUserSessions } from '@/modules/admin/services/admin-users.service'; +import type { AppContext } from '@/types/hono'; + +type RevokeSessionsParams = { id: string }; + +export async function revokeAllSessionsHandler(c: AppContext) { + const { id } = c.req.valid('param' as never) as RevokeSessionsParams; + + const count = await revokeAllUserSessions(id); + + return c.json({ message: `${count} sesiones cerradas correctamente.` }); +} diff --git a/apps/backend/src/modules/admin/handlers/unblock-user.handler.ts b/apps/backend/src/modules/admin/handlers/unblock-user.handler.ts new file mode 100644 index 0000000..750c18c --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/unblock-user.handler.ts @@ -0,0 +1,12 @@ +import { unblockUser } from '@/modules/admin/services/admin-users.service'; +import type { AppContext } from '@/types/hono'; + +type UnblockUserParams = { id: string }; + +export async function unblockUserHandler(c: AppContext) { + const { id } = c.req.valid('param' as never) as UnblockUserParams; + + await unblockUser(id); + + return c.json({ message: 'Usuario desbloqueado correctamente.' }); +} diff --git a/apps/backend/src/modules/admin/handlers/update-plan.handler.ts b/apps/backend/src/modules/admin/handlers/update-plan.handler.ts new file mode 100644 index 0000000..322ebb6 --- /dev/null +++ b/apps/backend/src/modules/admin/handlers/update-plan.handler.ts @@ -0,0 +1,35 @@ +import { db } from '@/lib/prisma'; +import type { AppContext } from '@/types/hono'; +import type { AdminUpdatePlanInput } from '@repo/api-contract'; + +type UpdatePlanParams = { code: string }; + +export async function updatePlanHandler(c: AppContext) { + const { code } = c.req.valid('param' as never) as UpdatePlanParams; + const body = c.req.valid('json' as never) as AdminUpdatePlanInput; + + const existing = await db.plan.findUnique({ + where: { code }, + }); + + if (!existing) { + return c.json({ message: 'Plan no encontrado.' }, 404); + } + + const plan = await db.plan.update({ + where: { code }, + data: { + ...(body.name !== undefined && { name: body.name }), + ...(body.price !== undefined && { price: body.price }), + ...(body.rules !== undefined && { rules: body.rules }), + lastUpdatedAt: new Date(), + }, + }); + + return c.json({ + code: plan.code, + name: plan.name, + price: Number(plan.price), + rules: plan.rules, + }); +} diff --git a/apps/backend/src/modules/admin/services/admin-users.service.ts b/apps/backend/src/modules/admin/services/admin-users.service.ts new file mode 100644 index 0000000..99ded34 --- /dev/null +++ b/apps/backend/src/modules/admin/services/admin-users.service.ts @@ -0,0 +1,113 @@ +import { db } from '@/lib/prisma'; + +type AdminUser = { + id: string; + name: string; + email: string; + role: string; + banned: boolean; + bannedAt: string | null; + banReason: string | null; + createdAt: string; + complexCount: number; + activeSessions: number; +}; + +export async function listAdminUsers(): Promise { + const users = await db.user.findMany({ + include: { + _count: { + select: { complexes: true, sessions: true }, + }, + }, + orderBy: { createdAt: 'desc' }, + }); + + return users.map((user) => ({ + id: user.id, + name: user.name, + email: user.email, + role: user.role, + banned: user.banned ?? false, + bannedAt: user.bannedAt?.toISOString() ?? null, + banReason: user.banReason ?? null, + createdAt: user.createdAt.toISOString(), + complexCount: user._count.complexes, + activeSessions: user._count.sessions, + })); +} + +type AdminUserSession = { + id: string; + createdAt: string; + expiresAt: string; + ipAddress: string | null; + userAgent: string | null; +}; + +export async function getUserSessions(userId: string): Promise { + const sessions = await db.session.findMany({ + where: { userId }, + orderBy: { createdAt: 'desc' }, + }); + + return sessions.map((s) => ({ + id: s.id, + createdAt: s.createdAt.toISOString(), + expiresAt: s.expiresAt.toISOString(), + ipAddress: s.ipAddress, + userAgent: s.userAgent, + })); +} + +export class AdminServiceError extends Error { + status: 400 | 403 | 404; + constructor(message: string, status: 400 | 403 | 404 = 400) { + super(message); + this.status = status; + this.name = 'AdminServiceError'; + } +} + +export async function blockUser(userId: string, banReason?: string): Promise { + const target = await db.user.findUnique({ + where: { id: userId }, + select: { role: true }, + }); + + if (!target) { + throw new AdminServiceError('Usuario no encontrado.', 404); + } + + if (target.role === 'super_admin') { + throw new AdminServiceError('No se puede bloquear un super_admin.', 403); + } + + await db.user.update({ + where: { id: userId }, + data: { + banned: true, + bannedAt: new Date(), + banReason: banReason ?? null, + }, + }); +} + +export async function unblockUser(userId: string): Promise { + await db.user.update({ + where: { id: userId }, + data: { + banned: false, + bannedAt: null, + banReason: null, + }, + }); +} + +export async function revokeAllUserSessions(userId: string): Promise { + const result = await db.session.deleteMany({ + where: { userId }, + }); + + return result.count; +} diff --git a/apps/backend/src/modules/admin/services/complex-stats.service.ts b/apps/backend/src/modules/admin/services/complex-stats.service.ts new file mode 100644 index 0000000..e5aad11 --- /dev/null +++ b/apps/backend/src/modules/admin/services/complex-stats.service.ts @@ -0,0 +1,80 @@ +import { db } from '@/lib/prisma'; + +type ComplexStats = { + id: string; + complexName: string; + complexSlug: string; + city: string | null; + planCode: string | null; + planName: string | null; + userCount: number; + courtCount: number; + totalBookings: number; + avgBookingsPerDay: number; + bookingsByStatus: { + confirmed: number; + cancelled: number; + completed: number; + noshow: number; + }; + paymentStatus: 'active' | 'no_plan' | 'expired'; +}; + +export async function getComplexStatsList(): Promise { + const complexes = await db.complex.findMany({ + include: { + plan: true, + users: true, + courts: { + include: { + bookings: true, + }, + }, + }, + }); + + return complexes.map((complex) => { + const courtCount = complex.courts.length; + const allBookings = complex.courts.flatMap((c) => c.bookings); + + const bookingsByStatus = { + confirmed: allBookings.filter((b) => b.status === 'CONFIRMED').length, + cancelled: allBookings.filter((b) => b.status === 'CANCELLED').length, + completed: allBookings.filter((b) => b.status === 'COMPLETED').length, + noshow: allBookings.filter((b) => b.status === 'NOSHOW').length, + }; + + const totalBookings = allBookings.length; + + let avgBookingsPerDay = 0; + if (allBookings.length > 0) { + const dates = allBookings.map((b) => b.bookingDate); + const minDate = new Date(Math.min(...dates.map((d) => d.getTime()))); + const daysDiff = Math.max( + 1, + Math.ceil((Date.now() - minDate.getTime()) / (1000 * 60 * 60 * 24)) + ); + avgBookingsPerDay = Math.round((totalBookings / daysDiff) * 100) / 100; + } + + let paymentStatus: 'active' | 'no_plan' | 'expired' = 'no_plan'; + if (complex.plan) { + paymentStatus = 'active'; + } + + return { + id: complex.id, + complexName: complex.complexName, + complexSlug: complex.complexSlug, + city: complex.city, + planCode: complex.planCode, + planName: complex.plan?.name ?? null, + userCount: complex.users.length, + courtCount, + totalBookings, + avgBookingsPerDay, + bookingsByStatus, + paymentStatus, + }; + }); +} diff --git a/apps/backend/src/register-routes.ts b/apps/backend/src/register-routes.ts index 1d7c48d..57d1707 100644 --- a/apps/backend/src/register-routes.ts +++ b/apps/backend/src/register-routes.ts @@ -1,5 +1,6 @@ import path from 'node:path'; import { adminBookingRoutes } from '@/modules/admin-booking/admin-booking.routes'; +import { adminRoutes } from '@/modules/admin/admin.routes'; import { authRoutes } from '@/modules/auth/auth.routes'; import { complexRoutes } from '@/modules/complex/complex.routes'; import { courtRoutes } from '@/modules/court/court.routes'; @@ -17,6 +18,7 @@ import { healthCheckRoutes } from './modules/health-check/health-check.routes'; export function registerRoutes(app: Hono) { app .route('', authRoutes) + .route('/api/admin', adminRoutes) .route('/api/user', userRoutes) .route('/api/plans', planRoutes) .route('/api/password-reset', passwordResetRoutes) diff --git a/apps/frontend/src/components/header.tsx b/apps/frontend/src/components/header.tsx index e3137df..500898c 100644 --- a/apps/frontend/src/components/header.tsx +++ b/apps/frontend/src/components/header.tsx @@ -6,6 +6,7 @@ import { Menu, Moon, Settings, + Shield, Sun, User, X, @@ -241,6 +242,18 @@ export function Header() { )} + {user?.role === 'super_admin' && ( + { + void navigate({ to: '/admin' }); + }} + > + + Admin + + )} + )} + {user?.role === 'super_admin' && ( + + )} + {isAuthenticated && ( + ); + })} + +
+ +
+ + + +
{children}
+ + ); +} diff --git a/apps/frontend/src/features/admin/admin-page.tsx b/apps/frontend/src/features/admin/admin-page.tsx new file mode 100644 index 0000000..48aafa6 --- /dev/null +++ b/apps/frontend/src/features/admin/admin-page.tsx @@ -0,0 +1,130 @@ +import { apiClient } from '@/lib/api-client'; +import { useQuery } from '@tanstack/react-query'; +import { Link, useLocation } from '@tanstack/react-router'; +import { Building2, CalendarDays, Crosshair, Users } from 'lucide-react'; +import { AdminLayout } from './admin-layout'; + +export function AdminPage() { + const location = useLocation(); + + const complexesQuery = useQuery({ + queryKey: ['admin-complexes'], + queryFn: () => apiClient.admin.listComplexes(), + }); + + const usersQuery = useQuery({ + queryKey: ['admin-users'], + queryFn: () => apiClient.admin.listUsers(), + }); + + const stats = { + totalComplexes: complexesQuery.data?.length ?? 0, + totalUsers: usersQuery.data?.length ?? 0, + totalCourts: complexesQuery.data?.reduce((sum, c) => sum + c.courtCount, 0) ?? 0, + totalBookings: + complexesQuery.data?.reduce((sum, c) => sum + Math.round(c.avgBookingsPerDay * 30), 0) ?? 0, + }; + + const cards = [ + { + label: 'Complejos', + value: stats.totalComplexes, + icon: Building2, + color: 'text-blue-600', + bg: 'bg-blue-100 dark:bg-blue-900/30', + }, + { + label: 'Usuarios', + value: stats.totalUsers, + icon: Users, + color: 'text-emerald-600', + bg: 'bg-emerald-100 dark:bg-emerald-900/30', + }, + { + label: 'Canchas', + value: stats.totalCourts, + icon: Crosshair, + color: 'text-purple-600', + bg: 'bg-purple-100 dark:bg-purple-900/30', + }, + { + label: 'Reservas (30d)', + value: stats.totalBookings.toLocaleString(), + icon: CalendarDays, + color: 'text-amber-600', + bg: 'bg-amber-100 dark:bg-amber-900/30', + }, + ]; + + return ( + +
+

Panel de Administración

+

+ Gestioná complejos, planes y usuarios de Playzer. +

+
+ +
+ {cards.map((card) => { + const Icon = card.icon; + + return ( +
+
+
+ +
+ +
+

+ {card.label} +

+

{card.value}

+
+
+
+ ); + })} +
+ +
+

Acceso rápido

+ +
+ + +

Complejos

+

+ {stats.totalComplexes} complejos registrados +

+ + + + +

Planes

+

Administrar suscripciones

+ + + + +

Usuarios

+

{stats.totalUsers} usuarios registrados

+ +
+
+
+ ); +} diff --git a/apps/frontend/src/features/admin/complexes-page.tsx b/apps/frontend/src/features/admin/complexes-page.tsx new file mode 100644 index 0000000..f7e6344 --- /dev/null +++ b/apps/frontend/src/features/admin/complexes-page.tsx @@ -0,0 +1,167 @@ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { apiClient } from '@/lib/api-client'; +import { useQuery } from '@tanstack/react-query'; +import { useLocation } from '@tanstack/react-router'; +import { Building2, ChevronDown, ChevronUp, MapPin, RefreshCw } from 'lucide-react'; +import { useState } from 'react'; +import { AdminLayout } from './admin-layout'; + +function PaymentBadge({ status }: { status: string }) { + if (status === 'active') { + return ( + + Activo + + ); + } + + if (status === 'no_plan') { + return ( + + Sin plan + + ); + } + + return ( + + Expirado + + ); +} + +export function ComplexesPage() { + const location = useLocation(); + const [expandedId, setExpandedId] = useState(null); + + const { data, isLoading, refetch } = useQuery({ + queryKey: ['admin-complexes'], + queryFn: () => apiClient.admin.listComplexes(), + }); + + return ( + +
+
+

Complejos

+

+ {data?.length ?? 0} complejos registrados en Playzer. +

+
+ + +
+ + {isLoading ? ( +
+

Cargando complejos...

+
+ ) : data?.length === 0 ? ( +
+ +

No hay complejos registrados.

+
+ ) : ( +
+ {data?.map((complex) => { + const isExpanded = expandedId === complex.id; + + return ( +
+ + + {isExpanded && ( +
+
+
+

Plan

+

{complex.planName ?? 'Sin plan'}

+
+
+

Canchas

+

{complex.courtCount}

+
+
+

Usuarios

+

{complex.userCount}

+
+
+

Prom. reservas/día

+

{complex.avgBookingsPerDay.toFixed(1)}

+
+
+
+ )} +
+ ); + })} +
+ )} +
+ ); +} diff --git a/apps/frontend/src/features/admin/plans-page.tsx b/apps/frontend/src/features/admin/plans-page.tsx new file mode 100644 index 0000000..fa6b9ef --- /dev/null +++ b/apps/frontend/src/features/admin/plans-page.tsx @@ -0,0 +1,337 @@ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { AdminLayout } from '@/features/admin/admin-layout'; +import { ApiClientError, apiClient } from '@/lib/api-client'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useLocation } from '@tanstack/react-router'; +import { BarChart3, Pencil, Plus, RefreshCw, Trash2 } from 'lucide-react'; +import { useState } from 'react'; + +type Plan = { + code: string; + name: string; + price: number; + rules: unknown; + lastUpdatedAt: string; + complexCount: number; +}; + +function PlanFormDialog({ + mode, + plan, + onClose, +}: { + mode: 'create' | 'edit'; + plan?: Plan; + onClose: () => void; +}) { + const queryClient = useQueryClient(); + const [code, setCode] = useState(plan?.code ?? ''); + const [name, setName] = useState(plan?.name ?? ''); + const [price, setPrice] = useState(String(plan?.price ?? '')); + + const createMutation = useMutation({ + mutationFn: (data: { code: string; name: string; price: number; rules: object }) => + apiClient.admin.createPlan(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-plans'] }); + onClose(); + }, + }); + + const updateMutation = useMutation({ + mutationFn: (data: { name?: string; price?: number }) => + apiClient.admin.updatePlan(plan!.code, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-plans'] }); + onClose(); + }, + }); + + const isPending = createMutation.isPending || updateMutation.isPending; + const error = createMutation.error ?? updateMutation.error; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + if (mode === 'create') { + createMutation.mutate({ + code, + name, + price: Number.parseFloat(price), + rules: {}, + }); + } else { + updateMutation.mutate({ + name, + price: Number.parseFloat(price), + }); + } + }; + + return ( + !open && onClose()}> + + + {mode === 'create' ? 'Crear plan' : 'Editar plan'} + + {mode === 'create' + ? 'Agregá un nuevo plan de suscripción.' + : 'Actualizá los datos del plan.'} + + + +
+ {mode === 'create' && ( +
+ + setCode(e.target.value)} + placeholder="pro" + maxLength={10} + required + /> +
+ )} + +
+ + setName(e.target.value)} + placeholder="Pro" + maxLength={30} + required + /> +
+ +
+ + setPrice(e.target.value)} + placeholder="29.99" + required + /> +
+ + {error && ( +

+ {error instanceof ApiClientError + ? String(error.details ?? error.message) + : error.message} +

+ )} + +
+ + +
+
+
+
+ ); +} + +function DeleteConfirmDialog({ + plan, + onClose, +}: { + plan: Plan; + onClose: () => void; +}) { + const queryClient = useQueryClient(); + const deleteMutation = useMutation({ + mutationFn: () => apiClient.admin.deletePlan(plan.code), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-plans'] }); + onClose(); + }, + }); + + return ( + !open && onClose()}> + + + Eliminar plan + + ¿Estás seguro de eliminar el plan {plan.name}? + {plan.complexCount > 0 && ( + + No se puede eliminar porque tiene {plan.complexCount} complejo + {plan.complexCount > 1 ? 's' : ''} asignado{plan.complexCount > 1 ? 's' : ''}. + + )} + + + + {deleteMutation.error && ( +

+ {deleteMutation.error instanceof ApiClientError + ? String(deleteMutation.error.details ?? deleteMutation.error.message) + : deleteMutation.error.message} +

+ )} + +
+ + +
+
+
+ ); +} + +export function PlansPage() { + const location = useLocation(); + const queryClient = useQueryClient(); + const [createOpen, setCreateOpen] = useState(false); + const [editingPlan, setEditingPlan] = useState(null); + const [deletingPlan, setDeletingPlan] = useState(null); + + const { data, isLoading } = useQuery({ + queryKey: ['admin-plans'], + queryFn: () => apiClient.admin.listPlans(), + }); + + return ( + +
+
+

Planes

+

+ {data?.length ?? 0} planes de suscripción. +

+
+ +
+ + +
+
+ + {createOpen && setCreateOpen(false)} />} + + {editingPlan && ( + setEditingPlan(null)} /> + )} + + {deletingPlan && ( + setDeletingPlan(null)} /> + )} + + {isLoading ? ( +
+

Cargando planes...

+
+ ) : data?.length === 0 ? ( +
+ +

No hay planes creados.

+
+ ) : ( +
+ + + + + + + + + + + + {data?.map((plan) => ( + + + + + + + + ))} + +
+ Código + + Nombre + + Precio + + Complejos + + Acciones +
+ + {plan.code} + + {plan.name} + ${Number(plan.price).toFixed(2)} + + {plan.complexCount} + +
+ + +
+
+
+ )} +
+ ); +} diff --git a/apps/frontend/src/features/admin/users-page.tsx b/apps/frontend/src/features/admin/users-page.tsx new file mode 100644 index 0000000..eb4560c --- /dev/null +++ b/apps/frontend/src/features/admin/users-page.tsx @@ -0,0 +1,437 @@ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { AdminLayout } from '@/features/admin/admin-layout'; +import { ApiClientError, apiClient } from '@/lib/api-client'; +import type { AdminUser, AdminUserSession } from '@repo/api-contract'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useLocation } from '@tanstack/react-router'; +import { + Ban, + CheckCircle2, + Globe, + LogIn, + Monitor, + RefreshCw, + ShieldAlert, + Users, +} from 'lucide-react'; +import { useState } from 'react'; + +function SessionsDialog({ + user, + onClose, +}: { + user: AdminUser; + onClose: () => void; +}) { + const queryClient = useQueryClient(); + const { data, isLoading } = useQuery({ + queryKey: ['admin-user-sessions', user.id], + queryFn: () => apiClient.admin.getUserSessions(user.id), + }); + + const revokeMutation = useMutation({ + mutationFn: () => apiClient.admin.revokeAllSessions(user.id), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-user-sessions', user.id] }); + queryClient.invalidateQueries({ queryKey: ['admin-users'] }); + }, + }); + + return ( + !open && onClose()}> + + + Sesiones de {user.name} + {data?.length ?? 0} sesiones activas + + +
+ {isLoading ? ( +

Cargando sesiones...

+ ) : data?.length === 0 ? ( +

Sin sesiones activas.

+ ) : ( + data?.map((session) => ) + )} +
+ +
+ {revokeMutation.error && ( +

+ {revokeMutation.error instanceof ApiClientError + ? String(revokeMutation.error.details ?? revokeMutation.error.message) + : revokeMutation.error.message} +

+ )} +
+ + {data && data.length > 0 && ( + + )} +
+
+
+
+ ); +} + +function SessionRow({ session }: { session: AdminUserSession }) { + const isExpired = new Date(session.expiresAt) < new Date(); + const userAgent = session.userAgent ?? 'Desconocido'; + const ip = session.ipAddress ?? '—'; + + return ( +
+
+ + {userAgent} + {isExpired ? ( + + Expirada + + ) : ( + + Activa + + )} +
+
+ + + {ip} + + + + {new Date(session.createdAt).toLocaleString()} + +
+
+ ); +} + +function BlockDialog({ + user, + onClose, +}: { + user: AdminUser; + onClose: () => void; +}) { + const queryClient = useQueryClient(); + const [reason, setReason] = useState(''); + + const mutation = useMutation({ + mutationFn: (banReason?: string) => apiClient.admin.blockUser(user.id, { banReason }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-users'] }); + onClose(); + }, + }); + + return ( + !open && onClose()}> + + + Bloquear usuario + + ¿Estás seguro de bloquear a {user.name} ({user.email})? No podrá + iniciar sesión en Playzer. + + + +
+
+ + setReason(e.target.value)} + placeholder="Violación de términos..." + maxLength={500} + /> +
+ + {mutation.error && ( +

+ {mutation.error instanceof ApiClientError + ? String(mutation.error.details ?? mutation.error.message) + : mutation.error.message} +

+ )} + +
+ + +
+
+
+
+ ); +} + +function UnblockDialog({ + user, + onClose, +}: { + user: AdminUser; + onClose: () => void; +}) { + const queryClient = useQueryClient(); + + const mutation = useMutation({ + mutationFn: () => apiClient.admin.unblockUser(user.id), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-users'] }); + onClose(); + }, + }); + + return ( + !open && onClose()}> + + + Desbloquear usuario + + ¿Estás seguro de desbloquear a {user.name}? Podrá volver a iniciar + sesión en Playzer. + + + + {mutation.error && ( +

+ {mutation.error instanceof ApiClientError + ? String(mutation.error.details ?? mutation.error.message) + : mutation.error.message} +

+ )} + +
+ + +
+
+
+ ); +} + +function RoleBadge({ role }: { role: string }) { + if (role === 'super_admin') { + return ( + + + Super Admin + + ); + } + + return ( + + {role} + + ); +} + +export function UsersPage() { + const location = useLocation(); + const queryClient = useQueryClient(); + const [blockingUser, setBlockingUser] = useState(null); + const [unblockingUser, setUnblockingUser] = useState(null); + const [sessionsUser, setSessionsUser] = useState(null); + + const { data, isLoading } = useQuery({ + queryKey: ['admin-users'], + queryFn: () => apiClient.admin.listUsers(), + }); + + return ( + +
+
+

Usuarios

+

+ {data?.length ?? 0} usuarios registrados en Playzer. +

+
+ + +
+ + {blockingUser && setBlockingUser(null)} />} + + {unblockingUser && ( + setUnblockingUser(null)} /> + )} + + {sessionsUser && setSessionsUser(null)} />} + + {isLoading ? ( +
+

Cargando usuarios...

+
+ ) : data?.length === 0 ? ( +
+ +

No hay usuarios registrados.

+
+ ) : ( +
+ + + + + + + + + + + + + + {data?.map((user) => ( + + + + + + + + + + ))} + +
+ Usuario + + Rol + + Complejos + + Sesiones + + Registro + + Estado + + Acción +
+
+

{user.name}

+

{user.email}

+
+
+ + + {user.complexCount} + + + + {new Date(user.createdAt).toLocaleDateString()} + + {user.banned ? ( + + Bloqueado + + ) : ( + + Activo + + )} + +
+ {user.banned ? ( + + ) : ( + + )} +
+
+
+ )} +
+ ); +} diff --git a/apps/frontend/src/lib/api-client.ts b/apps/frontend/src/lib/api-client.ts index bc1f547..7e6f455 100644 --- a/apps/frontend/src/lib/api-client.ts +++ b/apps/frontend/src/lib/api-client.ts @@ -5,24 +5,40 @@ import * as api from './api'; const apiBaseUrl = api.apiBaseUrl; -const plugins = [ - sentinelClient(), - inferAdditionalFields({ - user: { - phone: { - type: 'string', - required: false, - }, - }, - }), -]; +const infraPlugins = import.meta.env.VITE_BETTER_AUTH_INFRA === 'true' ? [sentinelClient()] : []; export const authClient = createAuthClient({ baseURL: apiBaseUrl, fetchOptions: { credentials: 'include', }, - plugins: import.meta.env.VITE_BETTER_AUTH_INFRA === 'true' ? plugins : [], + plugins: [ + ...infraPlugins, + inferAdditionalFields({ + user: { + phone: { + type: 'string', + required: false, + }, + role: { + type: 'string', + required: false, + }, + banned: { + type: 'boolean', + required: false, + }, + bannedAt: { + type: 'string', + required: false, + }, + banReason: { + type: 'string', + required: false, + }, + }, + }), + ], }); export class ApiClientError extends Error { @@ -48,6 +64,7 @@ export const apiClient = { complexes: api.complexes, sports: api.sports, courts: api.courts, + admin: api.admin, publicBookings: { getAvailability: api.getAvailability, create: api.createPublic, diff --git a/apps/frontend/src/lib/api/base.ts b/apps/frontend/src/lib/api/base.ts index 0201e21..7ad78f7 100644 --- a/apps/frontend/src/lib/api/base.ts +++ b/apps/frontend/src/lib/api/base.ts @@ -17,6 +17,7 @@ export class ApiClientError extends Error { export type ErrorHandlers = { onForbidden?: (error: ApiClientError) => void | Promise; + onUnauthorized?: (error: ApiClientError) => void | Promise; onError?: (error: ApiClientError) => void | Promise; }; @@ -28,6 +29,7 @@ export const apiBaseUrl = export function configureApiClient(nextHandlers: ErrorHandlers) { handlers.onForbidden = nextHandlers.onForbidden; + handlers.onUnauthorized = nextHandlers.onUnauthorized; handlers.onError = nextHandlers.onError; } diff --git a/apps/frontend/src/lib/api/http.ts b/apps/frontend/src/lib/api/http.ts index 67a5a11..9a673b8 100644 --- a/apps/frontend/src/lib/api/http.ts +++ b/apps/frontend/src/lib/api/http.ts @@ -69,6 +69,10 @@ http.interceptors.response.use( async (error: AxiosError) => { const normalized = normalizeError(error); + if (normalized.status === 401 && handlers.onUnauthorized) { + await handlers.onUnauthorized(normalized); + } + if (normalized.status === 403 && handlers.onForbidden) { await handlers.onForbidden(normalized); } diff --git a/apps/frontend/src/lib/api/index.ts b/apps/frontend/src/lib/api/index.ts index 5bd919a..c175d7f 100644 --- a/apps/frontend/src/lib/api/index.ts +++ b/apps/frontend/src/lib/api/index.ts @@ -6,6 +6,7 @@ export * as courts from './resources/courts'; export * as user from './resources/user'; export * as sports from './resources/sports'; export * as plans from './resources/plans'; +export * as admin from './resources/admin'; export { cancelPublic, diff --git a/apps/frontend/src/lib/api/resources/admin.ts b/apps/frontend/src/lib/api/resources/admin.ts new file mode 100644 index 0000000..4d7409a --- /dev/null +++ b/apps/frontend/src/lib/api/resources/admin.ts @@ -0,0 +1,88 @@ +import type { + AdminBlockUserInput, + AdminComplexListItem, + AdminCreatePlanInput, + AdminGlobalStats, + AdminUpdatePlanInput, + AdminUser, + AdminUserSession, +} from '@repo/api-contract'; +import { http } from '../http'; + +type AdminPlan = { + code: string; + name: string; + price: number; + rules: unknown; + lastUpdatedAt: string; + complexCount: number; +}; + +export async function listComplexes() { + const response = await http.get('/api/admin/complexes'); + return response.data; +} + +export async function listPlans() { + const response = await http.get('/api/admin/plans'); + return response.data; +} + +export async function createPlan(data: AdminCreatePlanInput) { + const response = await http.post<{ code: string; name: string; price: number }>( + '/api/admin/plans', + JSON.stringify(data), + { headers: { 'Content-Type': 'application/json' } } + ); + return response.data; +} + +export async function updatePlan(code: string, data: AdminUpdatePlanInput) { + const response = await http.patch<{ code: string; name: string; price: number }>( + `/api/admin/plans/${code}`, + JSON.stringify(data), + { headers: { 'Content-Type': 'application/json' } } + ); + return response.data; +} + +export async function deletePlan(code: string) { + const response = await http.delete<{ message: string }>(`/api/admin/plans/${code}`); + return response.data; +} + +export async function listUsers() { + const response = await http.get('/api/admin/users'); + return response.data; +} + +export async function blockUser(userId: string, data?: AdminBlockUserInput) { + const response = await http.post<{ message: string }>( + `/api/admin/users/${userId}/block`, + JSON.stringify(data ?? {}), + { headers: { 'Content-Type': 'application/json' } } + ); + return response.data; +} + +export async function unblockUser(userId: string) { + const response = await http.post<{ message: string }>(`/api/admin/users/${userId}/unblock`); + return response.data; +} + +export async function getGlobalStats() { + const response = await http.get('/api/admin/stats'); + return response.data; +} + +export async function getUserSessions(userId: string) { + const response = await http.get(`/api/admin/users/${userId}/sessions`); + return response.data; +} + +export async function revokeAllSessions(userId: string) { + const response = await http.post<{ message: string }>( + `/api/admin/users/${userId}/sessions/revoke-all` + ); + return response.data; +} diff --git a/apps/frontend/src/main.tsx b/apps/frontend/src/main.tsx index 2d2b641..7914725 100644 --- a/apps/frontend/src/main.tsx +++ b/apps/frontend/src/main.tsx @@ -27,6 +27,14 @@ function AppRouter() { useEffect(() => { configureApiClient({ + onUnauthorized: async () => { + if (!auth.isAuthenticated) { + return; + } + + await auth.signOut(); + await router.navigate({ to: '/login' }); + }, onForbidden: async (error) => { if (error.message?.includes('verificar tu email')) { return; diff --git a/apps/frontend/src/routeTree.gen.ts b/apps/frontend/src/routeTree.gen.ts index 2de1645..2e584de 100644 --- a/apps/frontend/src/routeTree.gen.ts +++ b/apps/frontend/src/routeTree.gen.ts @@ -23,6 +23,11 @@ import { Route as ComplexSlugBookingRouteImport } from './routes/$complexSlug/bo import { Route as AppAuthenticatedRouteRouteImport } from './routes/_app/_authenticated/route' import { Route as AppAuthenticatedIndexRouteImport } from './routes/_app/_authenticated/index' import { Route as ComplexSlugBookingIndexRouteImport } from './routes/$complexSlug/booking/index' +import { Route as AppAuthenticatedAdminRouteRouteImport } from './routes/_app/_authenticated/admin/route' +import { Route as AppAuthenticatedAdminIndexRouteImport } from './routes/_app/_authenticated/admin/index' +import { Route as AppAuthenticatedAdminUsersRouteImport } from './routes/_app/_authenticated/admin/users' +import { Route as AppAuthenticatedAdminPlansRouteImport } from './routes/_app/_authenticated/admin/plans' +import { Route as AppAuthenticatedAdminComplexesRouteImport } from './routes/_app/_authenticated/admin/complexes' import { Route as ComplexSlugBookingConfirmedBookingCodeRouteImport } from './routes/$complexSlug/booking/confirmed/$bookingCode' import { Route as AppAuthenticatedComplexSlugEditRouteImport } from './routes/_app/_authenticated/complex/$slug/edit' @@ -94,6 +99,36 @@ const ComplexSlugBookingIndexRoute = ComplexSlugBookingIndexRouteImport.update({ path: '/', getParentRoute: () => ComplexSlugBookingRoute, } as any) +const AppAuthenticatedAdminRouteRoute = + AppAuthenticatedAdminRouteRouteImport.update({ + id: '/admin', + path: '/admin', + getParentRoute: () => AppAuthenticatedRouteRoute, + } as any) +const AppAuthenticatedAdminIndexRoute = + AppAuthenticatedAdminIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => AppAuthenticatedAdminRouteRoute, + } as any) +const AppAuthenticatedAdminUsersRoute = + AppAuthenticatedAdminUsersRouteImport.update({ + id: '/users', + path: '/users', + getParentRoute: () => AppAuthenticatedAdminRouteRoute, + } as any) +const AppAuthenticatedAdminPlansRoute = + AppAuthenticatedAdminPlansRouteImport.update({ + id: '/plans', + path: '/plans', + getParentRoute: () => AppAuthenticatedAdminRouteRoute, + } as any) +const AppAuthenticatedAdminComplexesRoute = + AppAuthenticatedAdminComplexesRouteImport.update({ + id: '/complexes', + path: '/complexes', + getParentRoute: () => AppAuthenticatedAdminRouteRoute, + } as any) const ComplexSlugBookingConfirmedBookingCodeRoute = ComplexSlugBookingConfirmedBookingCodeRouteImport.update({ id: '/confirmed/$bookingCode', @@ -119,8 +154,13 @@ export interface FileRoutesByFullPath { '/$complexSlug/booking': typeof ComplexSlugBookingRouteWithChildren '/profile': typeof AppProfileRoute '/onboard/setup': typeof OnboardSetupRoute + '/admin': typeof AppAuthenticatedAdminRouteRouteWithChildren '/$complexSlug/booking/': typeof ComplexSlugBookingIndexRoute '/$complexSlug/booking/confirmed/$bookingCode': typeof ComplexSlugBookingConfirmedBookingCodeRoute + '/admin/complexes': typeof AppAuthenticatedAdminComplexesRoute + '/admin/plans': typeof AppAuthenticatedAdminPlansRoute + '/admin/users': typeof AppAuthenticatedAdminUsersRoute + '/admin/': typeof AppAuthenticatedAdminIndexRoute '/complex/$slug/edit': typeof AppAuthenticatedComplexSlugEditRoute } export interface FileRoutesByTo { @@ -136,6 +176,10 @@ export interface FileRoutesByTo { '/onboard/setup': typeof OnboardSetupRoute '/$complexSlug/booking': typeof ComplexSlugBookingIndexRoute '/$complexSlug/booking/confirmed/$bookingCode': typeof ComplexSlugBookingConfirmedBookingCodeRoute + '/admin/complexes': typeof AppAuthenticatedAdminComplexesRoute + '/admin/plans': typeof AppAuthenticatedAdminPlansRoute + '/admin/users': typeof AppAuthenticatedAdminUsersRoute + '/admin': typeof AppAuthenticatedAdminIndexRoute '/complex/$slug/edit': typeof AppAuthenticatedComplexSlugEditRoute } export interface FileRoutesById { @@ -152,9 +196,14 @@ export interface FileRoutesById { '/$complexSlug/booking': typeof ComplexSlugBookingRouteWithChildren '/_app/profile': typeof AppProfileRoute '/onboard/setup': typeof OnboardSetupRoute + '/_app/_authenticated/admin': typeof AppAuthenticatedAdminRouteRouteWithChildren '/$complexSlug/booking/': typeof ComplexSlugBookingIndexRoute '/_app/_authenticated/': typeof AppAuthenticatedIndexRoute '/$complexSlug/booking/confirmed/$bookingCode': typeof ComplexSlugBookingConfirmedBookingCodeRoute + '/_app/_authenticated/admin/complexes': typeof AppAuthenticatedAdminComplexesRoute + '/_app/_authenticated/admin/plans': typeof AppAuthenticatedAdminPlansRoute + '/_app/_authenticated/admin/users': typeof AppAuthenticatedAdminUsersRoute + '/_app/_authenticated/admin/': typeof AppAuthenticatedAdminIndexRoute '/_app/_authenticated/complex/$slug/edit': typeof AppAuthenticatedComplexSlugEditRoute } export interface FileRouteTypes { @@ -171,8 +220,13 @@ export interface FileRouteTypes { | '/$complexSlug/booking' | '/profile' | '/onboard/setup' + | '/admin' | '/$complexSlug/booking/' | '/$complexSlug/booking/confirmed/$bookingCode' + | '/admin/complexes' + | '/admin/plans' + | '/admin/users' + | '/admin/' | '/complex/$slug/edit' fileRoutesByTo: FileRoutesByTo to: @@ -188,6 +242,10 @@ export interface FileRouteTypes { | '/onboard/setup' | '/$complexSlug/booking' | '/$complexSlug/booking/confirmed/$bookingCode' + | '/admin/complexes' + | '/admin/plans' + | '/admin/users' + | '/admin' | '/complex/$slug/edit' id: | '__root__' @@ -203,9 +261,14 @@ export interface FileRouteTypes { | '/$complexSlug/booking' | '/_app/profile' | '/onboard/setup' + | '/_app/_authenticated/admin' | '/$complexSlug/booking/' | '/_app/_authenticated/' | '/$complexSlug/booking/confirmed/$bookingCode' + | '/_app/_authenticated/admin/complexes' + | '/_app/_authenticated/admin/plans' + | '/_app/_authenticated/admin/users' + | '/_app/_authenticated/admin/' | '/_app/_authenticated/complex/$slug/edit' fileRoutesById: FileRoutesById } @@ -321,6 +384,41 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ComplexSlugBookingIndexRouteImport parentRoute: typeof ComplexSlugBookingRoute } + '/_app/_authenticated/admin': { + id: '/_app/_authenticated/admin' + path: '/admin' + fullPath: '/admin' + preLoaderRoute: typeof AppAuthenticatedAdminRouteRouteImport + parentRoute: typeof AppAuthenticatedRouteRoute + } + '/_app/_authenticated/admin/': { + id: '/_app/_authenticated/admin/' + path: '/' + fullPath: '/admin/' + preLoaderRoute: typeof AppAuthenticatedAdminIndexRouteImport + parentRoute: typeof AppAuthenticatedAdminRouteRoute + } + '/_app/_authenticated/admin/users': { + id: '/_app/_authenticated/admin/users' + path: '/users' + fullPath: '/admin/users' + preLoaderRoute: typeof AppAuthenticatedAdminUsersRouteImport + parentRoute: typeof AppAuthenticatedAdminRouteRoute + } + '/_app/_authenticated/admin/plans': { + id: '/_app/_authenticated/admin/plans' + path: '/plans' + fullPath: '/admin/plans' + preLoaderRoute: typeof AppAuthenticatedAdminPlansRouteImport + parentRoute: typeof AppAuthenticatedAdminRouteRoute + } + '/_app/_authenticated/admin/complexes': { + id: '/_app/_authenticated/admin/complexes' + path: '/complexes' + fullPath: '/admin/complexes' + preLoaderRoute: typeof AppAuthenticatedAdminComplexesRouteImport + parentRoute: typeof AppAuthenticatedAdminRouteRoute + } '/$complexSlug/booking/confirmed/$bookingCode': { id: '/$complexSlug/booking/confirmed/$bookingCode' path: '/confirmed/$bookingCode' @@ -338,12 +436,34 @@ declare module '@tanstack/react-router' { } } +interface AppAuthenticatedAdminRouteRouteChildren { + AppAuthenticatedAdminComplexesRoute: typeof AppAuthenticatedAdminComplexesRoute + AppAuthenticatedAdminPlansRoute: typeof AppAuthenticatedAdminPlansRoute + AppAuthenticatedAdminUsersRoute: typeof AppAuthenticatedAdminUsersRoute + AppAuthenticatedAdminIndexRoute: typeof AppAuthenticatedAdminIndexRoute +} + +const AppAuthenticatedAdminRouteRouteChildren: AppAuthenticatedAdminRouteRouteChildren = + { + AppAuthenticatedAdminComplexesRoute: AppAuthenticatedAdminComplexesRoute, + AppAuthenticatedAdminPlansRoute: AppAuthenticatedAdminPlansRoute, + AppAuthenticatedAdminUsersRoute: AppAuthenticatedAdminUsersRoute, + AppAuthenticatedAdminIndexRoute: AppAuthenticatedAdminIndexRoute, + } + +const AppAuthenticatedAdminRouteRouteWithChildren = + AppAuthenticatedAdminRouteRoute._addFileChildren( + AppAuthenticatedAdminRouteRouteChildren, + ) + interface AppAuthenticatedRouteRouteChildren { + AppAuthenticatedAdminRouteRoute: typeof AppAuthenticatedAdminRouteRouteWithChildren AppAuthenticatedIndexRoute: typeof AppAuthenticatedIndexRoute AppAuthenticatedComplexSlugEditRoute: typeof AppAuthenticatedComplexSlugEditRoute } const AppAuthenticatedRouteRouteChildren: AppAuthenticatedRouteRouteChildren = { + AppAuthenticatedAdminRouteRoute: AppAuthenticatedAdminRouteRouteWithChildren, AppAuthenticatedIndexRoute: AppAuthenticatedIndexRoute, AppAuthenticatedComplexSlugEditRoute: AppAuthenticatedComplexSlugEditRoute, } diff --git a/apps/frontend/src/routes/_app/_authenticated/admin/complexes.tsx b/apps/frontend/src/routes/_app/_authenticated/admin/complexes.tsx new file mode 100644 index 0000000..2f3fc97 --- /dev/null +++ b/apps/frontend/src/routes/_app/_authenticated/admin/complexes.tsx @@ -0,0 +1,6 @@ +import { ComplexesPage } from '@/features/admin/complexes-page'; +import { createFileRoute } from '@tanstack/react-router'; + +export const Route = createFileRoute('/_app/_authenticated/admin/complexes')({ + component: ComplexesPage, +}); diff --git a/apps/frontend/src/routes/_app/_authenticated/admin/index.tsx b/apps/frontend/src/routes/_app/_authenticated/admin/index.tsx new file mode 100644 index 0000000..c5b8c18 --- /dev/null +++ b/apps/frontend/src/routes/_app/_authenticated/admin/index.tsx @@ -0,0 +1,6 @@ +import { AdminPage } from '@/features/admin/admin-page'; +import { createFileRoute } from '@tanstack/react-router'; + +export const Route = createFileRoute('/_app/_authenticated/admin/')({ + component: AdminPage, +}); diff --git a/apps/frontend/src/routes/_app/_authenticated/admin/plans.tsx b/apps/frontend/src/routes/_app/_authenticated/admin/plans.tsx new file mode 100644 index 0000000..809b136 --- /dev/null +++ b/apps/frontend/src/routes/_app/_authenticated/admin/plans.tsx @@ -0,0 +1,6 @@ +import { PlansPage } from '@/features/admin/plans-page'; +import { createFileRoute } from '@tanstack/react-router'; + +export const Route = createFileRoute('/_app/_authenticated/admin/plans')({ + component: PlansPage, +}); diff --git a/apps/frontend/src/routes/_app/_authenticated/admin/route.tsx b/apps/frontend/src/routes/_app/_authenticated/admin/route.tsx new file mode 100644 index 0000000..33f19e6 --- /dev/null +++ b/apps/frontend/src/routes/_app/_authenticated/admin/route.tsx @@ -0,0 +1,16 @@ +import { createFileRoute, redirect } from '@tanstack/react-router'; + +export const Route = createFileRoute('/_app/_authenticated/admin')({ + beforeLoad: ({ context, location }) => { + if (!context.auth.isAuthenticated) { + throw redirect({ + to: '/login', + search: { redirect: location.href }, + }); + } + + if (context.auth.user?.role !== 'super_admin') { + throw redirect({ to: '/' }); + } + }, +}); diff --git a/apps/frontend/src/routes/_app/_authenticated/admin/users.tsx b/apps/frontend/src/routes/_app/_authenticated/admin/users.tsx new file mode 100644 index 0000000..76c025c --- /dev/null +++ b/apps/frontend/src/routes/_app/_authenticated/admin/users.tsx @@ -0,0 +1,6 @@ +import { UsersPage } from '@/features/admin/users-page'; +import { createFileRoute } from '@tanstack/react-router'; + +export const Route = createFileRoute('/_app/_authenticated/admin/users')({ + component: UsersPage, +}); diff --git a/packages/api-contract/src/admin.ts b/packages/api-contract/src/admin.ts new file mode 100644 index 0000000..2b52fc8 --- /dev/null +++ b/packages/api-contract/src/admin.ts @@ -0,0 +1,92 @@ +import { z } from 'zod' + +export const adminPaymentStatusSchema = z.enum(['active', 'no_plan', 'expired']) + +export const adminComplexListItemSchema = z.object({ + id: z.string(), + complexName: z.string(), + complexSlug: z.string(), + city: z.string().nullable(), + planCode: z.string().nullable(), + planName: z.string().nullable(), + userCount: z.number().int().nonnegative(), + courtCount: z.number().int().nonnegative(), + avgBookingsPerDay: z.number().nonnegative(), + paymentStatus: adminPaymentStatusSchema, +}) + +export const adminComplexStatsSchema = z.object({ + id: z.string(), + complexName: z.string(), + complexSlug: z.string(), + city: z.string().nullable(), + adminEmail: z.string(), + planCode: z.string().nullable(), + planName: z.string().nullable(), + userCount: z.number().int().nonnegative(), + courtCount: z.number().int().nonnegative(), + totalBookings: z.number().int().nonnegative(), + avgBookingsPerDay: z.number().nonnegative(), + bookingsByStatus: z.object({ + confirmed: z.number().int().nonnegative(), + cancelled: z.number().int().nonnegative(), + completed: z.number().int().nonnegative(), + noshow: z.number().int().nonnegative(), + }), + paymentStatus: adminPaymentStatusSchema, +}) + +export const adminCreatePlanSchema = z.object({ + code: z.string().trim().min(1).max(10), + name: z.string().trim().min(1).max(30), + price: z.number().nonnegative(), + rules: z.any(), +}) + +export const adminUpdatePlanSchema = z.object({ + name: z.string().trim().min(1).max(30).optional(), + price: z.number().nonnegative().optional(), + rules: z.any().optional(), +}) + +export const adminUserSchema = z.object({ + id: z.string(), + name: z.string(), + email: z.string(), + role: z.string(), + banned: z.boolean(), + bannedAt: z.string().datetime().nullable(), + banReason: z.string().nullable(), + createdAt: z.string().datetime(), + complexCount: z.number().int().nonnegative(), + activeSessions: z.number().int().nonnegative(), +}) + +export const adminBlockUserSchema = z.object({ + banReason: z.string().max(500).optional(), +}) + +export const adminGlobalStatsSchema = z.object({ + totalComplexes: z.number().int().nonnegative(), + totalUsers: z.number().int().nonnegative(), + totalCourts: z.number().int().nonnegative(), + totalBookings: z.number().int().nonnegative(), +}) + +export const adminUserSessionSchema = z.object({ + id: z.string(), + createdAt: z.string().datetime(), + expiresAt: z.string().datetime(), + ipAddress: z.string().nullable(), + userAgent: z.string().nullable(), +}) + +export type AdminComplexListItem = z.infer +export type AdminComplexStats = z.infer +export type AdminCreatePlanInput = z.infer +export type AdminUpdatePlanInput = z.infer +export type AdminUser = z.infer +export type AdminBlockUserInput = z.infer +export type AdminGlobalStats = z.infer +export type AdminPaymentStatus = z.infer +export type AdminUserSession = z.infer diff --git a/packages/api-contract/src/index.ts b/packages/api-contract/src/index.ts index b6443de..264766b 100644 --- a/packages/api-contract/src/index.ts +++ b/packages/api-contract/src/index.ts @@ -129,3 +129,25 @@ export type { PasswordResetVerifyResponse, PasswordResetResendResponse, } from './user' +export { + adminComplexListItemSchema, + adminComplexStatsSchema, + adminCreatePlanSchema, + adminUpdatePlanSchema, + adminUserSchema, + adminBlockUserSchema, + adminGlobalStatsSchema, + adminPaymentStatusSchema, + adminUserSessionSchema, +} from './admin' +export type { + AdminComplexListItem, + AdminComplexStats, + AdminCreatePlanInput, + AdminUpdatePlanInput, + AdminUser, + AdminBlockUserInput, + AdminGlobalStats, + AdminPaymentStatus, + AdminUserSession, +} from './admin'