From e06bc1209718a333c5dd9d72a77c6dcf073795b9 Mon Sep 17 00:00:00 2001 From: Jose Selesan Date: Mon, 29 Jun 2026 15:55:20 -0300 Subject: [PATCH] feat(billing): implement billing module with Stripe and Mercado Pago integration - Add Stripe and Mercado Pago providers for handling subscriptions. - Create billing repository and access services for managing billing records. - Implement webhook handlers for processing events from Stripe and Mercado Pago. - Add routes for checkout, canceling subscriptions, and retrieving billing status. - Introduce billing status management with appropriate state transitions. - Create tests for billing functionalities including webhook idempotency and provider resolution. - Document the billing module architecture, environment variables, and API endpoints. --- apps/backend/.env.example | 20 ++ apps/backend/package.json | 2 + apps/backend/prisma/billing.prisma | 52 ++++ apps/backend/prisma/complex.prisma | 1 + .../migration.sql | 56 ++++ apps/backend/src/generated/prisma/browser.ts | 10 + apps/backend/src/generated/prisma/client.ts | 10 + .../src/generated/prisma/commonInputTypes.ts | 211 +++++++++++++ apps/backend/src/generated/prisma/enums.ts | 20 ++ .../src/generated/prisma/internal/class.ts | 28 +- .../prisma/internal/prismaNamespace.ts | 254 +++++++++++++++- .../prisma/internal/prismaNamespaceBrowser.ts | 46 +++ apps/backend/src/generated/prisma/models.ts | 2 + .../src/generated/prisma/models/Complex.ts | 162 +++++++++- ...create-admin-recurring-booking.business.ts | 2 +- .../src/modules/billing/billing.routes.ts | 24 ++ .../cancel-subscription.business.ts | 47 +++ .../cancel-subscription.handler.ts | 17 ++ .../create-checkout.business.ts | 80 +++++ .../create-checkout.handler.ts | 19 ++ .../get-billing-status.business.ts | 26 ++ .../get-billing-status.handler.ts | 17 ++ .../mercadopago-webhook.business.ts | 133 ++++++++ .../mercadopago-webhook.handler.ts | 15 + .../stripe-webhook/stripe-webhook.business.ts | 128 ++++++++ .../stripe-webhook/stripe-webhook.handler.ts | 10 + .../providers/billing-provider.interface.ts | 34 +++ .../billing/providers/mercadopago.provider.ts | 164 ++++++++++ .../billing/providers/stripe.provider.ts | 165 ++++++++++ .../services/billing-access.service.ts | 38 +++ .../services/billing-repository.service.ts | 150 ++++++++++ .../services/provider-resolver.service.ts | 33 ++ .../modules/public-booking/shared/helpers.ts | 4 +- apps/backend/src/register-routes.ts | 2 + .../billing/duplicate-subscription.test.ts | 66 ++++ .../test/billing/event-mapping.test.ts | 31 ++ apps/backend/test/billing/helpers.ts | 22 ++ apps/backend/test/billing/idempotency.test.ts | 83 +++++ .../test/billing/provider-resolver.test.ts | 36 +++ .../test/billing/status-transitions.test.ts | 20 ++ apps/backend/test/support/prisma.mock.ts | 2 + bun.lock | 10 +- docs/billing.md | 283 ++++++++++++++++++ packages/api-contract/src/billing.ts | 34 +++ packages/api-contract/src/index.ts | 14 + 45 files changed, 2553 insertions(+), 30 deletions(-) create mode 100644 apps/backend/prisma/billing.prisma create mode 100644 apps/backend/prisma/migrations/20260626183242_add_billing_models/migration.sql create mode 100644 apps/backend/src/modules/billing/billing.routes.ts create mode 100644 apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.business.ts create mode 100644 apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.handler.ts create mode 100644 apps/backend/src/modules/billing/features/create-checkout/create-checkout.business.ts create mode 100644 apps/backend/src/modules/billing/features/create-checkout/create-checkout.handler.ts create mode 100644 apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.business.ts create mode 100644 apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.handler.ts create mode 100644 apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.business.ts create mode 100644 apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.handler.ts create mode 100644 apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.business.ts create mode 100644 apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.handler.ts create mode 100644 apps/backend/src/modules/billing/providers/billing-provider.interface.ts create mode 100644 apps/backend/src/modules/billing/providers/mercadopago.provider.ts create mode 100644 apps/backend/src/modules/billing/providers/stripe.provider.ts create mode 100644 apps/backend/src/modules/billing/services/billing-access.service.ts create mode 100644 apps/backend/src/modules/billing/services/billing-repository.service.ts create mode 100644 apps/backend/src/modules/billing/services/provider-resolver.service.ts create mode 100644 apps/backend/test/billing/duplicate-subscription.test.ts create mode 100644 apps/backend/test/billing/event-mapping.test.ts create mode 100644 apps/backend/test/billing/helpers.ts create mode 100644 apps/backend/test/billing/idempotency.test.ts create mode 100644 apps/backend/test/billing/provider-resolver.test.ts create mode 100644 apps/backend/test/billing/status-transitions.test.ts create mode 100644 docs/billing.md create mode 100644 packages/api-contract/src/billing.ts diff --git a/apps/backend/.env.example b/apps/backend/.env.example index 1dceb75..3a5a39a 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -16,3 +16,23 @@ SMTP_FROM=Playzer # Google OAuth GOOGLE_CLIENT_ID=your-google-client-id GOOGLE_CLIENT_SECRET=your-google-client-secret + +# Billing / Subscriptions +BILLING_ENV=sandbox +FRONTEND_BASE_URL=http://localhost:5173 + +# Stripe +STRIPE_SECRET_KEY=sk_test_your-stripe-secret-key +STRIPE_WEBHOOK_SECRET=whsec_your-webhook-secret +# Price IDs por plan y moneda (ajustar según tus products/prices en Stripe) +STRIPE_PRICE_ID_USD_BASIC=price_basic_usd +STRIPE_PRICE_ID_USD_ADVANCED=price_advanced_usd +STRIPE_PRICE_ID_USD_ENTERPRISE=price_enterprise_usd + +# Mercado Pago (Argentina) +MERCADOPAGO_ACCESS_TOKEN=TEST-your-access-token +MERCADOPAGO_WEBHOOK_SECRET=your-webhook-secret +# Plan IDs por plan (ajustar según tus planes de suscripción en MP) +MERCADOPAGO_PLAN_ID_ARS_BASIC=2c938084... +MERCADOPAGO_PLAN_ID_ARS_ADVANCED=2c938084... +MERCADOPAGO_PLAN_ID_ARS_ENTERPRISE=2c938084... diff --git a/apps/backend/package.json b/apps/backend/package.json index 4905b44..7c8d99c 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -24,12 +24,14 @@ "dotenv": "^17.4.1", "hono": "4.12.10", "mailtrap": "^4.5.1", + "mercadopago": "^3.1.0", "nodemailer": "^8.0.5", "pg": "^8.20.0", "pino": "10.3.1", "pino-pretty": "13.1.3", "pino-std-serializers": "7.1.0", "prisma": "^7", + "stripe": "^22.2.2", "uuid": "^13.0.0" }, "devDependencies": { diff --git a/apps/backend/prisma/billing.prisma b/apps/backend/prisma/billing.prisma new file mode 100644 index 0000000..fba7a0d --- /dev/null +++ b/apps/backend/prisma/billing.prisma @@ -0,0 +1,52 @@ +enum BillingProvider { + STRIPE + MERCADOPAGO + PAYPAL +} + +enum BillingStatus { + TRIAL + ACTIVE + PAST_DUE + CANCELED + SUSPENDED +} + +model ComplexBilling { + complexId String @id @map("complex_id") @db.Uuid + status BillingStatus @default(TRIAL) + planCode String @map("plan_code") @db.VarChar(10) + currency String @db.VarChar(3) + provider BillingProvider? + providerCustomerId String? @map("provider_customer_id") + providerSubscriptionId String? @map("provider_subscription_id") + providerPreapprovalId String? @map("provider_preapproval_id") + currentPeriodStart DateTime? @map("current_period_start") + currentPeriodEnd DateTime? @map("current_period_end") + trialEndsAt DateTime? @map("trial_ends_at") + canceledAt DateTime? @map("canceled_at") + suspendedAt DateTime? @map("suspended_at") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade) + events BillingEvent[] + + @@map("complex_billings") +} + +model BillingEvent { + id String @id @db.Uuid + complexId String @map("complex_id") @db.Uuid + eventType String @map("event_type") @db.VarChar(100) + provider BillingProvider + providerEventId String? @unique @map("provider_event_id") + providerData Json? @map("provider_data") + previousStatus BillingStatus? @map("previous_status") + newStatus BillingStatus? @map("new_status") + processedAt DateTime @default(now()) @map("processed_at") + billing ComplexBilling @relation(fields: [complexId], references: [complexId]) + + @@index([provider, providerEventId]) + @@index([complexId]) + @@map("billing_events") +} diff --git a/apps/backend/prisma/complex.prisma b/apps/backend/prisma/complex.prisma index ba454b3..9c689a3 100644 --- a/apps/backend/prisma/complex.prisma +++ b/apps/backend/prisma/complex.prisma @@ -15,6 +15,7 @@ model Complex { invitations ComplexInvitation[] courts Court[] recurringGroups RecurringBookingGroup[] + billing ComplexBilling? @@index([planCode]) @@index([complexSlug]) diff --git a/apps/backend/prisma/migrations/20260626183242_add_billing_models/migration.sql b/apps/backend/prisma/migrations/20260626183242_add_billing_models/migration.sql new file mode 100644 index 0000000..518422f --- /dev/null +++ b/apps/backend/prisma/migrations/20260626183242_add_billing_models/migration.sql @@ -0,0 +1,56 @@ +-- CreateEnum +CREATE TYPE "BillingProvider" AS ENUM ('STRIPE', 'MERCADOPAGO', 'PAYPAL'); + +-- CreateEnum +CREATE TYPE "BillingStatus" AS ENUM ('TRIAL', 'ACTIVE', 'PAST_DUE', 'CANCELED', 'SUSPENDED'); + +-- CreateTable +CREATE TABLE "complex_billings" ( + "complex_id" UUID NOT NULL, + "status" "BillingStatus" NOT NULL DEFAULT 'TRIAL', + "plan_code" VARCHAR(10) NOT NULL, + "currency" VARCHAR(3) NOT NULL, + "provider" "BillingProvider", + "provider_customer_id" TEXT, + "provider_subscription_id" TEXT, + "provider_preapproval_id" TEXT, + "current_period_start" TIMESTAMP(3), + "current_period_end" TIMESTAMP(3), + "trial_ends_at" TIMESTAMP(3), + "canceled_at" TIMESTAMP(3), + "suspended_at" TIMESTAMP(3), + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "complex_billings_pkey" PRIMARY KEY ("complex_id") +); + +-- CreateTable +CREATE TABLE "billing_events" ( + "id" UUID NOT NULL, + "complex_id" UUID NOT NULL, + "event_type" VARCHAR(100) NOT NULL, + "provider" "BillingProvider" NOT NULL, + "provider_event_id" TEXT, + "provider_data" JSONB, + "previous_status" "BillingStatus", + "new_status" "BillingStatus", + "processed_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "billing_events_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "billing_events_provider_event_id_key" ON "billing_events"("provider_event_id"); + +-- CreateIndex +CREATE INDEX "billing_events_provider_provider_event_id_idx" ON "billing_events"("provider", "provider_event_id"); + +-- CreateIndex +CREATE INDEX "billing_events_complex_id_idx" ON "billing_events"("complex_id"); + +-- AddForeignKey +ALTER TABLE "complex_billings" ADD CONSTRAINT "complex_billings_complex_id_fkey" FOREIGN KEY ("complex_id") REFERENCES "complexes"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "billing_events" ADD CONSTRAINT "billing_events_complex_id_fkey" FOREIGN KEY ("complex_id") REFERENCES "complex_billings"("complex_id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/backend/src/generated/prisma/browser.ts b/apps/backend/src/generated/prisma/browser.ts index e5ac584..7adcd5c 100644 --- a/apps/backend/src/generated/prisma/browser.ts +++ b/apps/backend/src/generated/prisma/browser.ts @@ -37,6 +37,16 @@ export type Account = Prisma.AccountModel * */ export type Verification = Prisma.VerificationModel +/** + * Model ComplexBilling + * + */ +export type ComplexBilling = Prisma.ComplexBillingModel +/** + * Model BillingEvent + * + */ +export type BillingEvent = Prisma.BillingEventModel /** * Model Complex * diff --git a/apps/backend/src/generated/prisma/client.ts b/apps/backend/src/generated/prisma/client.ts index 52733da..179b2a0 100644 --- a/apps/backend/src/generated/prisma/client.ts +++ b/apps/backend/src/generated/prisma/client.ts @@ -61,6 +61,16 @@ export type Account = Prisma.AccountModel * */ export type Verification = Prisma.VerificationModel +/** + * Model ComplexBilling + * + */ +export type ComplexBilling = Prisma.ComplexBillingModel +/** + * Model BillingEvent + * + */ +export type BillingEvent = Prisma.BillingEventModel /** * Model Complex * diff --git a/apps/backend/src/generated/prisma/commonInputTypes.ts b/apps/backend/src/generated/prisma/commonInputTypes.ts index 6289eb5..6820865 100644 --- a/apps/backend/src/generated/prisma/commonInputTypes.ts +++ b/apps/backend/src/generated/prisma/commonInputTypes.ts @@ -187,6 +187,20 @@ export type UuidFilter<$PrismaModel = never> = { not?: Prisma.NestedUuidFilter<$PrismaModel> | string } +export type EnumBillingStatusFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingStatusFilter<$PrismaModel> | $Enums.BillingStatus +} + +export type EnumBillingProviderNullableFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingProviderNullableFilter<$PrismaModel> | $Enums.BillingProvider | null +} + export type UuidWithAggregatesFilter<$PrismaModel = never> = { equals?: string | Prisma.StringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> @@ -202,6 +216,111 @@ export type UuidWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedStringFilter<$PrismaModel> } +export type EnumBillingStatusWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingStatusWithAggregatesFilter<$PrismaModel> | $Enums.BillingStatus + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingStatusFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingStatusFilter<$PrismaModel> +} + +export type EnumBillingProviderNullableWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingProviderNullableWithAggregatesFilter<$PrismaModel> | $Enums.BillingProvider | null + _count?: Prisma.NestedIntNullableFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingProviderNullableFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingProviderNullableFilter<$PrismaModel> +} + +export type EnumBillingProviderFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingProviderFilter<$PrismaModel> | $Enums.BillingProvider +} + +export type JsonNullableFilter<$PrismaModel = never> = +| Prisma.PatchUndefined< + Prisma.Either>, Exclude>, 'path'>>, + Required> + > +| Prisma.OptionalFlat>, 'path'>> + +export type JsonNullableFilterBase<$PrismaModel = never> = { + equals?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter + path?: string[] + mode?: Prisma.QueryMode | Prisma.EnumQueryModeFieldRefInput<$PrismaModel> + string_contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + string_starts_with?: string | Prisma.StringFieldRefInput<$PrismaModel> + string_ends_with?: string | Prisma.StringFieldRefInput<$PrismaModel> + array_starts_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + array_ends_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + array_contains?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + lt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + lte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + gt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + gte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + not?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter +} + +export type EnumBillingStatusNullableFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingStatusNullableFilter<$PrismaModel> | $Enums.BillingStatus | null +} + +export type EnumBillingProviderWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingProviderWithAggregatesFilter<$PrismaModel> | $Enums.BillingProvider + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingProviderFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingProviderFilter<$PrismaModel> +} + +export type JsonNullableWithAggregatesFilter<$PrismaModel = never> = +| Prisma.PatchUndefined< + Prisma.Either>, Exclude>, 'path'>>, + Required> + > +| Prisma.OptionalFlat>, 'path'>> + +export type JsonNullableWithAggregatesFilterBase<$PrismaModel = never> = { + equals?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter + path?: string[] + mode?: Prisma.QueryMode | Prisma.EnumQueryModeFieldRefInput<$PrismaModel> + string_contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + string_starts_with?: string | Prisma.StringFieldRefInput<$PrismaModel> + string_ends_with?: string | Prisma.StringFieldRefInput<$PrismaModel> + array_starts_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + array_ends_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + array_contains?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + lt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + lte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + gt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + gte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + not?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter + _count?: Prisma.NestedIntNullableFilter<$PrismaModel> + _min?: Prisma.NestedJsonNullableFilter<$PrismaModel> + _max?: Prisma.NestedJsonNullableFilter<$PrismaModel> +} + +export type EnumBillingStatusNullableWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingStatusNullableWithAggregatesFilter<$PrismaModel> | $Enums.BillingStatus | null + _count?: Prisma.NestedIntNullableFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingStatusNullableFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingStatusNullableFilter<$PrismaModel> +} + export type EnumComplexUserRoleFilter<$PrismaModel = never> = { equals?: $Enums.ComplexUserRole | Prisma.EnumComplexUserRoleFieldRefInput<$PrismaModel> in?: $Enums.ComplexUserRole[] | Prisma.ListEnumComplexUserRoleFieldRefInput<$PrismaModel> @@ -604,6 +723,20 @@ export type NestedUuidFilter<$PrismaModel = never> = { not?: Prisma.NestedUuidFilter<$PrismaModel> | string } +export type NestedEnumBillingStatusFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingStatusFilter<$PrismaModel> | $Enums.BillingStatus +} + +export type NestedEnumBillingProviderNullableFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingProviderNullableFilter<$PrismaModel> | $Enums.BillingProvider | null +} + export type NestedUuidWithAggregatesFilter<$PrismaModel = never> = { equals?: string | Prisma.StringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> @@ -618,6 +751,84 @@ export type NestedUuidWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedStringFilter<$PrismaModel> } +export type NestedEnumBillingStatusWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingStatusWithAggregatesFilter<$PrismaModel> | $Enums.BillingStatus + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingStatusFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingStatusFilter<$PrismaModel> +} + +export type NestedEnumBillingProviderNullableWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingProviderNullableWithAggregatesFilter<$PrismaModel> | $Enums.BillingProvider | null + _count?: Prisma.NestedIntNullableFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingProviderNullableFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingProviderNullableFilter<$PrismaModel> +} + +export type NestedEnumBillingProviderFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingProviderFilter<$PrismaModel> | $Enums.BillingProvider +} + +export type NestedEnumBillingStatusNullableFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingStatusNullableFilter<$PrismaModel> | $Enums.BillingStatus | null +} + +export type NestedEnumBillingProviderWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingProvider | Prisma.EnumBillingProviderFieldRefInput<$PrismaModel> + in?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + notIn?: $Enums.BillingProvider[] | Prisma.ListEnumBillingProviderFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumBillingProviderWithAggregatesFilter<$PrismaModel> | $Enums.BillingProvider + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingProviderFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingProviderFilter<$PrismaModel> +} + +export type NestedJsonNullableFilter<$PrismaModel = never> = +| Prisma.PatchUndefined< + Prisma.Either>, Exclude>, 'path'>>, + Required> + > +| Prisma.OptionalFlat>, 'path'>> + +export type NestedJsonNullableFilterBase<$PrismaModel = never> = { + equals?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter + path?: string[] + mode?: Prisma.QueryMode | Prisma.EnumQueryModeFieldRefInput<$PrismaModel> + string_contains?: string | Prisma.StringFieldRefInput<$PrismaModel> + string_starts_with?: string | Prisma.StringFieldRefInput<$PrismaModel> + string_ends_with?: string | Prisma.StringFieldRefInput<$PrismaModel> + array_starts_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + array_ends_with?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + array_contains?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | null + lt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + lte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + gt?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + gte?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> + not?: runtime.InputJsonValue | Prisma.JsonFieldRefInput<$PrismaModel> | Prisma.JsonNullValueFilter +} + +export type NestedEnumBillingStatusNullableWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.BillingStatus | Prisma.EnumBillingStatusFieldRefInput<$PrismaModel> | null + in?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + notIn?: $Enums.BillingStatus[] | Prisma.ListEnumBillingStatusFieldRefInput<$PrismaModel> | null + not?: Prisma.NestedEnumBillingStatusNullableWithAggregatesFilter<$PrismaModel> | $Enums.BillingStatus | null + _count?: Prisma.NestedIntNullableFilter<$PrismaModel> + _min?: Prisma.NestedEnumBillingStatusNullableFilter<$PrismaModel> + _max?: Prisma.NestedEnumBillingStatusNullableFilter<$PrismaModel> +} + export type NestedEnumComplexUserRoleFilter<$PrismaModel = never> = { equals?: $Enums.ComplexUserRole | Prisma.EnumComplexUserRoleFieldRefInput<$PrismaModel> in?: $Enums.ComplexUserRole[] | Prisma.ListEnumComplexUserRoleFieldRefInput<$PrismaModel> diff --git a/apps/backend/src/generated/prisma/enums.ts b/apps/backend/src/generated/prisma/enums.ts index 2045cb1..08513f7 100644 --- a/apps/backend/src/generated/prisma/enums.ts +++ b/apps/backend/src/generated/prisma/enums.ts @@ -9,6 +9,26 @@ * 🟢 You can import this file directly. */ +export const BillingProvider = { + STRIPE: 'STRIPE', + MERCADOPAGO: 'MERCADOPAGO', + PAYPAL: 'PAYPAL' +} as const + +export type BillingProvider = (typeof BillingProvider)[keyof typeof BillingProvider] + + +export const BillingStatus = { + TRIAL: 'TRIAL', + ACTIVE: 'ACTIVE', + PAST_DUE: 'PAST_DUE', + CANCELED: 'CANCELED', + SUSPENDED: 'SUSPENDED' +} as const + +export type BillingStatus = (typeof BillingStatus)[keyof typeof BillingStatus] + + export const ComplexUserRole = { ADMIN: 'ADMIN', EMPLOYEE: 'EMPLOYEE' diff --git a/apps/backend/src/generated/prisma/internal/class.ts b/apps/backend/src/generated/prisma/internal/class.ts index 30fac00..59633bb 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 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 country String?\n city String?\n countryCode String?\n latitude Float?\n longitude Float?\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 recurringGroups RecurringBookingGroup[]\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\nenum RecurringBookingGroupStatus {\n ACTIVE\n CANCELLED\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 recurringGroups RecurringBookingGroup[]\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 recurringGroupId String? @map(\"recurring_group_id\") @db.Uuid\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 recurringGroup RecurringBookingGroup? @relation(fields: [recurringGroupId], references: [id])\n\n @@unique([courtId, bookingDate, startTime])\n @@index([courtId, bookingDate])\n @@index([bookingDate])\n @@index([recurringGroupId])\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 previousCourtId String? @map(\"previous_court_id\") @db.Uuid\n previousStartTime String? @map(\"previous_start_time\") @db.VarChar(5)\n previousEndTime String? @map(\"previous_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 changedAt DateTime @default(now()) @map(\"changed_at\")\n\n @@index([courtId, newStatus])\n @@map(\"court_booking_logs\")\n}\n\nmodel RecurringBookingGroup {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n dayOfWeek DayOfWeek @map(\"day_of_week\")\n startDate DateTime @map(\"start_date\") @db.Date\n endDate DateTime? @map(\"end_date\") @db.Date\n status RecurringBookingGroupStatus @default(ACTIVE)\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 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 complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n bookings CourtBooking[]\n\n @@index([complexId])\n @@index([courtId])\n @@index([status])\n @@map(\"recurring_booking_groups\")\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 country String?\n city String?\n countryCode String?\n latitude Float?\n longitude Float?\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\nenum BillingProvider {\n STRIPE\n MERCADOPAGO\n PAYPAL\n}\n\nenum BillingStatus {\n TRIAL\n ACTIVE\n PAST_DUE\n CANCELED\n SUSPENDED\n}\n\nmodel ComplexBilling {\n complexId String @id @map(\"complex_id\") @db.Uuid\n status BillingStatus @default(TRIAL)\n planCode String @map(\"plan_code\") @db.VarChar(10)\n currency String @db.VarChar(3)\n provider BillingProvider?\n providerCustomerId String? @map(\"provider_customer_id\")\n providerSubscriptionId String? @map(\"provider_subscription_id\")\n providerPreapprovalId String? @map(\"provider_preapproval_id\")\n currentPeriodStart DateTime? @map(\"current_period_start\")\n currentPeriodEnd DateTime? @map(\"current_period_end\")\n trialEndsAt DateTime? @map(\"trial_ends_at\")\n canceledAt DateTime? @map(\"canceled_at\")\n suspendedAt DateTime? @map(\"suspended_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 events BillingEvent[]\n\n @@map(\"complex_billings\")\n}\n\nmodel BillingEvent {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n eventType String @map(\"event_type\") @db.VarChar(100)\n provider BillingProvider\n providerEventId String? @unique @map(\"provider_event_id\")\n providerData Json? @map(\"provider_data\")\n previousStatus BillingStatus? @map(\"previous_status\")\n newStatus BillingStatus? @map(\"new_status\")\n processedAt DateTime @default(now()) @map(\"processed_at\")\n billing ComplexBilling @relation(fields: [complexId], references: [complexId])\n\n @@index([provider, providerEventId])\n @@index([complexId])\n @@map(\"billing_events\")\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 recurringGroups RecurringBookingGroup[]\n billing ComplexBilling?\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\nenum RecurringBookingGroupStatus {\n ACTIVE\n CANCELLED\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 recurringGroups RecurringBookingGroup[]\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 recurringGroupId String? @map(\"recurring_group_id\") @db.Uuid\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 recurringGroup RecurringBookingGroup? @relation(fields: [recurringGroupId], references: [id])\n\n @@unique([courtId, bookingDate, startTime])\n @@index([courtId, bookingDate])\n @@index([bookingDate])\n @@index([recurringGroupId])\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 previousCourtId String? @map(\"previous_court_id\") @db.Uuid\n previousStartTime String? @map(\"previous_start_time\") @db.VarChar(5)\n previousEndTime String? @map(\"previous_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 changedAt DateTime @default(now()) @map(\"changed_at\")\n\n @@index([courtId, newStatus])\n @@map(\"court_booking_logs\")\n}\n\nmodel RecurringBookingGroup {\n id String @id @db.Uuid\n complexId String @map(\"complex_id\") @db.Uuid\n courtId String @map(\"court_id\") @db.Uuid\n startTime String @map(\"start_time\") @db.VarChar(5)\n endTime String @map(\"end_time\") @db.VarChar(5)\n dayOfWeek DayOfWeek @map(\"day_of_week\")\n startDate DateTime @map(\"start_date\") @db.Date\n endDate DateTime? @map(\"end_date\") @db.Date\n status RecurringBookingGroupStatus @default(ACTIVE)\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 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 complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)\n bookings CourtBooking[]\n\n @@index([complexId])\n @@index([courtId])\n @@index([status])\n @@map(\"recurring_booking_groups\")\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\":\"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\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"countryCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"latitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"longitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"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\"},{\"name\":\"recurringGroups\",\"kind\":\"object\",\"type\":\"RecurringBookingGroup\",\"relationName\":\"ComplexToRecurringBookingGroup\"}],\"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\"},{\"name\":\"recurringGroups\",\"kind\":\"object\",\"type\":\"RecurringBookingGroup\",\"relationName\":\"CourtToRecurringBookingGroup\"}],\"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\":\"recurringGroupId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"recurring_group_id\"},{\"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\"},{\"name\":\"recurringGroup\",\"kind\":\"object\",\"type\":\"RecurringBookingGroup\",\"relationName\":\"CourtBookingToRecurringBookingGroup\"}],\"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\":\"previousCourtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"previous_court_id\"},{\"name\":\"previousStartTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"previous_start_time\"},{\"name\":\"previousEndTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"previous_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\":\"changedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"changed_at\"}],\"dbName\":\"court_booking_logs\"},\"RecurringBookingGroup\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"dayOfWeek\",\"kind\":\"enum\",\"type\":\"DayOfWeek\",\"dbName\":\"day_of_week\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"start_date\"},{\"name\":\"endDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"end_date\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"RecurringBookingGroupStatus\"},{\"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\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToRecurringBookingGroup\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToRecurringBookingGroup\"},{\"name\":\"bookings\",\"kind\":\"object\",\"type\":\"CourtBooking\",\"relationName\":\"CourtBookingToRecurringBookingGroup\"}],\"dbName\":\"recurring_booking_groups\"},\"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\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"countryCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"latitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"longitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"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\"},\"ComplexBilling\":{\"fields\":[{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"BillingStatus\"},{\"name\":\"planCode\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"plan_code\"},{\"name\":\"currency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"provider\",\"kind\":\"enum\",\"type\":\"BillingProvider\"},{\"name\":\"providerCustomerId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"provider_customer_id\"},{\"name\":\"providerSubscriptionId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"provider_subscription_id\"},{\"name\":\"providerPreapprovalId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"provider_preapproval_id\"},{\"name\":\"currentPeriodStart\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"current_period_start\"},{\"name\":\"currentPeriodEnd\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"current_period_end\"},{\"name\":\"trialEndsAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"trial_ends_at\"},{\"name\":\"canceledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"canceled_at\"},{\"name\":\"suspendedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"suspended_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\":\"ComplexToComplexBilling\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"BillingEvent\",\"relationName\":\"BillingEventToComplexBilling\"}],\"dbName\":\"complex_billings\"},\"BillingEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"eventType\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"event_type\"},{\"name\":\"provider\",\"kind\":\"enum\",\"type\":\"BillingProvider\"},{\"name\":\"providerEventId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"provider_event_id\"},{\"name\":\"providerData\",\"kind\":\"scalar\",\"type\":\"Json\",\"dbName\":\"provider_data\"},{\"name\":\"previousStatus\",\"kind\":\"enum\",\"type\":\"BillingStatus\",\"dbName\":\"previous_status\"},{\"name\":\"newStatus\",\"kind\":\"enum\",\"type\":\"BillingStatus\",\"dbName\":\"new_status\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"processed_at\"},{\"name\":\"billing\",\"kind\":\"object\",\"type\":\"ComplexBilling\",\"relationName\":\"BillingEventToComplexBilling\"}],\"dbName\":\"billing_events\"},\"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\"},{\"name\":\"recurringGroups\",\"kind\":\"object\",\"type\":\"RecurringBookingGroup\",\"relationName\":\"ComplexToRecurringBookingGroup\"},{\"name\":\"billing\",\"kind\":\"object\",\"type\":\"ComplexBilling\",\"relationName\":\"ComplexToComplexBilling\"}],\"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\"},{\"name\":\"recurringGroups\",\"kind\":\"object\",\"type\":\"RecurringBookingGroup\",\"relationName\":\"CourtToRecurringBookingGroup\"}],\"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\":\"recurringGroupId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"recurring_group_id\"},{\"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\"},{\"name\":\"recurringGroup\",\"kind\":\"object\",\"type\":\"RecurringBookingGroup\",\"relationName\":\"CourtBookingToRecurringBookingGroup\"}],\"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\":\"previousCourtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"previous_court_id\"},{\"name\":\"previousStartTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"previous_start_time\"},{\"name\":\"previousEndTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"previous_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\":\"changedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"changed_at\"}],\"dbName\":\"court_booking_logs\"},\"RecurringBookingGroup\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"complexId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"complex_id\"},{\"name\":\"courtId\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"court_id\"},{\"name\":\"startTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"start_time\"},{\"name\":\"endTime\",\"kind\":\"scalar\",\"type\":\"String\",\"dbName\":\"end_time\"},{\"name\":\"dayOfWeek\",\"kind\":\"enum\",\"type\":\"DayOfWeek\",\"dbName\":\"day_of_week\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"start_date\"},{\"name\":\"endDate\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"end_date\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"RecurringBookingGroupStatus\"},{\"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\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"created_at\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\",\"dbName\":\"updated_at\"},{\"name\":\"court\",\"kind\":\"object\",\"type\":\"Court\",\"relationName\":\"CourtToRecurringBookingGroup\"},{\"name\":\"complex\",\"kind\":\"object\",\"type\":\"Complex\",\"relationName\":\"ComplexToRecurringBookingGroup\"},{\"name\":\"bookings\",\"kind\":\"object\",\"type\":\"CourtBooking\",\"relationName\":\"CourtBookingToRecurringBookingGroup\"}],\"dbName\":\"recurring_booking_groups\"},\"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\",\"recurringGroup\",\"maintenances\",\"recurringGroups\",\"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\",\"_avg\",\"_sum\",\"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\",\"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\",\"RecurringBookingGroup.findUnique\",\"RecurringBookingGroup.findUniqueOrThrow\",\"RecurringBookingGroup.findFirst\",\"RecurringBookingGroup.findFirstOrThrow\",\"RecurringBookingGroup.findMany\",\"RecurringBookingGroup.createOne\",\"RecurringBookingGroup.createMany\",\"RecurringBookingGroup.createManyAndReturn\",\"RecurringBookingGroup.updateOne\",\"RecurringBookingGroup.updateMany\",\"RecurringBookingGroup.updateManyAndReturn\",\"RecurringBookingGroup.upsertOne\",\"RecurringBookingGroup.deleteOne\",\"RecurringBookingGroup.deleteMany\",\"RecurringBookingGroup.groupBy\",\"RecurringBookingGroup.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\",\"complexId\",\"courtId\",\"startTime\",\"endTime\",\"DayOfWeek\",\"dayOfWeek\",\"startDate\",\"endDate\",\"RecurringBookingGroupStatus\",\"status\",\"customerName\",\"customerPhone\",\"customerEmail\",\"bookingCode\",\"bookingDate\",\"CourtBookingStatus\",\"previousStatus\",\"newStatus\",\"previousCourtId\",\"previousStartTime\",\"previousEndTime\",\"changedAt\",\"recurringGroupId\",\"isActive\",\"reason\",\"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\",\"countryCode\",\"latitude\",\"longitude\",\"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: "3QeZAZACEgQAAKMEACAFAACkBAAgBgAApQQAIK0CAACiBAAwrgIAAEYAEK8CAACiBAAwsQIBANwDACHJAgEAAAABygIBAAAAAdECQADfAwAh0gJAAN8DACH4AgEA3AMAIZIDIACSBAAhkwMBAIMEACGUAwEAgwQAIZUDIACSBAAhlgNAAO4DACGXAwEAgwQAIQEAAAABACARAwAAwAQAIK0CAADCBAAwrgIAAAMAEK8CAADCBAAwyQIBANwDACHRAkAA3wMAIdICQADfAwAh8wJAAN8DACH2AgEA3AMAIfsCAQCDBAAh_QIBAIMEACGMAwEA3AMAIY0DAQCDBAAhjgMBAIMEACGPAwEAgwQAIZADCADDBAAhkQMIAMMEACEIAwAAgwcAIPsCAAD2BQAg_QIAAPYFACCNAwAA9gUAII4DAAD2BQAgjwMAAPYFACCQAwAA9gUAIJEDAAD2BQAgEQMAAMAEACCtAgAAwgQAMK4CAAADABCvAgAAwgQAMMkCAQAAAAHRAkAA3wMAIdICQADfAwAh8wJAAN8DACH2AgEA3AMAIfsCAQCDBAAh_QIBAIMEACGMAwEAAAABjQMBAIMEACGOAwEAgwQAIY8DAQCDBAAhkAMIAMMEACGRAwgAwwQAIQMAAAADACABAAAEADACAAAFACARAwAAwAQAIK0CAADBBAAwrgIAAAcAEK8CAADBBAAwyQIBANwDACHRAkAA3wMAIdICQADfAwAh9gIBANwDACGDAwEA3AMAIYQDAQDcAwAhhQMBAIMEACGGAwEAgwQAIYcDAQCDBAAhiANAAO4DACGJA0AA7gMAIYoDAQCDBAAhiwMBAIMEACEIAwAAgwcAIIUDAAD2BQAghgMAAPYFACCHAwAA9gUAIIgDAAD2BQAgiQMAAPYFACCKAwAA9gUAIIsDAAD2BQAgEQMAAMAEACCtAgAAwQQAMK4CAAAHABCvAgAAwQQAMMkCAQAAAAHRAkAA3wMAIdICQADfAwAh9gIBANwDACGDAwEA3AMAIYQDAQDcAwAhhQMBAIMEACGGAwEAgwQAIYcDAQCDBAAhiANAAO4DACGJA0AA7gMAIYoDAQCDBAAhiwMBAIMEACEDAAAABwAgAQAACAAwAgAACQAgCQMAAMAEACAKAACqBAAgrQIAAL4EADCuAgAACwAQrwIAAL4EADDRAkAA3wMAIdMCAQDsAwAh9gIBANwDACH4AgAAvwT4AiICAwAAgwcAIAoAAPkGACAKAwAAwAQAIAoAAKoEACCtAgAAvgQAMK4CAAALABCvAgAAvgQAMNECQADfAwAh0wIBAOwDACH2AgEA3AMAIfgCAAC_BPgCIpkDAAC9BAAgAwAAAAsAIAEAAAwAMAIAAA0AIAkGAADgAwAgrQIAANsDADCuAgAADwAQrwIAANsDADCwAgEA3AMAIbECAQDcAwAhsgIQAN0DACGzAgAA3gMAILQCQADfAwAhAQAAAA8AIBMIAAC7BAAgCQAApQQAIAsAALwEACAMAACTBAAgFAAAuAQAIK0CAAC6BAAwrgIAABEAEK8CAAC6BAAwyQIBAOwDACHRAkAA3wMAIdICQADfAwAh-QIBANwDACH6AgEAgwQAIfsCAQCDBAAh_AIBAIMEACH9AgEAgwQAIf4CAQDcAwAh_wIBANwDACGAAwEAgwQAIQoIAACBBwAgCQAA9wYAIAsAAIIHACAMAACrBgAgFAAAgAcAIPoCAAD2BQAg-wIAAPYFACD8AgAA9gUAIP0CAAD2BQAggAMAAPYFACATCAAAuwQAIAkAAKUEACALAAC8BAAgDAAAkwQAIBQAALgEACCtAgAAugQAMK4CAAARABCvAgAAugQAMMkCAQAAAAHRAkAA3wMAIdICQADfAwAh-QIBANwDACH6AgEAgwQAIfsCAQCDBAAh_AIBAIMEACH9AgEAgwQAIf4CAQAAAAH_AgEA3AMAIYADAQCDBAAhAwAAABEAIAEAABIAMAIAABMAIAEAAAARACADAAAACwAgAQAADAAwAgAADQAgDQoAAKoEACCtAgAAuQQAMK4CAAAXABCvAgAAuQQAMMkCAQDsAwAhygIBANwDACHRAkAA3wMAIdICQADfAwAh0wIBAOwDACHyAgEA3AMAIfMCQADfAwAh9AJAAO4DACH1AkAA7gMAIQMKAAD5BgAg9AIAAPYFACD1AgAA9gUAIA0KAACqBAAgrQIAALkEADCuAgAAFwAQrwIAALkEADDJAgEAAAABygIBANwDACHRAkAA3wMAIdICQADfAwAh0wIBAOwDACHyAgEAAAAB8wJAAN8DACH0AkAA7gMAIfUCQADuAwAhAwAAABcAIAEAABgAMAIAABkAIBQKAACqBAAgDQAAtAQAIA8AALUEACAQAAC2BAAgEQAAqwQAIBMAALcEACAUAAC4BAAgrQIAALMEADCuAgAAGwAQrwIAALMEADCxAgEA3AMAIckCAQDsAwAh0QJAAN8DACHSAkAA3wMAIdMCAQDsAwAh7AIBAOwDACHtAgIA7QMAIe4CEADdAwAh7wIgAJIEACHwAgEAgwQAIQgKAAD5BgAgDQAA_AYAIA8AAP0GACAQAAD-BgAgEQAA-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-wIBAPoDACH9AgEA-gMAIYwDAQDPAwAhjQMBAPoDACGOAwEA-gMAIY8DAQD6AwAhkAMIAJ4EACGRAwgAngQAIQMAAAADACABAABuADAmAABvACADAAAAAwAgAQAABAAwAgAABQAgAQAAAAkAIAEAAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACAOAwAAwgYAIMkCAQAAAAHRAkAAAAAB0gJAAAAAAfYCAQAAAAGDAwEAAAABhAMBAAAAAYUDAQAAAAGGAwEAAAABhwMBAAAAAYgDQAAAAAGJA0AAAAABigMBAAAAAYsDAQAAAAEBGgAAdwAgDckCAQAAAAHRAkAAAAAB0gJAAAAAAfYCAQAAAAGDAwEAAAABhAMBAAAAAYUDAQAAAAGGAwEAAAABhwMBAAAAAYgDQAAAAAGJA0AAAAABigMBAAAAAYsDAQAAAAEBGgAAeQAwARoAAHkAMA4DAADBBgAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh9gIBAMkEACGDAwEAyQQAIYQDAQDJBAAhhQMBANcEACGGAwEA1wQAIYcDAQDXBAAhiANAAOgEACGJA0AA6AQAIYoDAQDXBAAhiwMBANcEACECAAAACQAgGgAAfAAgDckCAQDJBAAh0QJAAMsEACHSAkAAywQAIfYCAQDJBAAhgwMBAMkEACGEAwEAyQQAIYUDAQDXBAAhhgMBANcEACGHAwEA1wQAIYgDQADoBAAhiQNAAOgEACGKAwEA1wQAIYsDAQDXBAAhAgAAAAcAIBoAAH4AIAIAAAAHACAaAAB-ACADAAAACQAgIQAAdwAgIgAAfAAgAQAAAAkAIAEAAAAHACAKBwAAvgYAICcAAMAGACAoAAC_BgAghQMAAPYFACCGAwAA9gUAIIcDAAD2BQAgiAMAAPYFACCJAwAA9gUAIIoDAAD2BQAgiwMAAPYFACAQrQIAAJwEADCuAgAAhQEAEK8CAACcBAAwyQIBAM8DACHRAkAA0gMAIdICQADSAwAh9gIBAM8DACGDAwEAzwMAIYQDAQDPAwAhhQMBAPoDACGGAwEA-gMAIYcDAQD6AwAhiANAAOQDACGJA0AA5AMAIYoDAQD6AwAhiwMBAPoDACEDAAAABwAgAQAAhAEAMCYAAIUBACADAAAABwAgAQAACAAwAgAACQAgCa0CAACbBAAwrgIAAIsBABCvAgAAmwQAMMkCAQAAAAHRAkAA3wMAIdICQADfAwAh8wJAAN8DACGBAwEA3AMAIYIDAQDcAwAhAQAAAIgBACABAAAAiAEAIAmtAgAAmwQAMK4CAACLAQAQrwIAAJsEADDJAgEA3AMAIdECQADfAwAh0gJAAN8DACHzAkAA3wMAIYEDAQDcAwAhggMBANwDACEAAwAAAIsBACABAACMAQAwAgAAiAEAIAMAAACLAQAgAQAAjAEAMAIAAIgBACADAAAAiwEAIAEAAIwBADACAACIAQAgBskCAQAAAAHRAkAAAAAB0gJAAAAAAfMCQAAAAAGBAwEAAAABggMBAAAAAQEaAACQAQAgBskCAQAAAAHRAkAAAAAB0gJAAAAAAfMCQAAAAAGBAwEAAAABggMBAAAAAQEaAACSAQAwARoAAJIBADAGyQIBAMkEACHRAkAAywQAIdICQADLBAAh8wJAAMsEACGBAwEAyQQAIYIDAQDJBAAhAgAAAIgBACAaAACVAQAgBskCAQDJBAAh0QJAAMsEACHSAkAAywQAIfMCQADLBAAhgQMBAMkEACGCAwEAyQQAIQIAAACLAQAgGgAAlwEAIAIAAACLAQAgGgAAlwEAIAMAAACIAQAgIQAAkAEAICIAAJUBACABAAAAiAEAIAEAAACLAQAgAwcAALsGACAnAAC9BgAgKAAAvAYAIAmtAgAAmgQAMK4CAACeAQAQrwIAAJoEADDJAgEAzwMAIdECQADSAwAh0gJAANIDACHzAkAA0gMAIYEDAQDPAwAhggMBAM8DACEDAAAAiwEAIAEAAJ0BADAmAACeAQAgAwAAAIsBACABAACMAQAwAgAAiAEAIAEAAAATACABAAAAEwAgAwAAABEAIAEAABIAMAIAABMAIAMAAAARACABAAASADACAAATACADAAAAEQAgAQAAEgAwAgAAEwAgEAgAALoGACAJAADwBQAgCwAA8QUAIAwAAPIFACAUAADzBQAgyQIBAAAAAdECQAAAAAHSAkAAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADAQAAAAEBGgAApgEAIAvJAgEAAAAB0QJAAAAAAdICQAAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgAMBAAAAAQEaAACoAQAwARoAAKgBADABAAAADwAgEAgAALkGACAJAADZBAAgCwAA2gQAIAwAANsEACAUAADcBAAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh-QIBAMkEACH6AgEA1wQAIfsCAQDXBAAh_AIBANcEACH9AgEA1wQAIf4CAQDJBAAh_wIBAMkEACGAAwEA1wQAIQIAAAATACAaAACsAQAgC8kCAQDJBAAh0QJAAMsEACHSAkAAywQAIfkCAQDJBAAh-gIBANcEACH7AgEA1wQAIfwCAQDXBAAh_QIBANcEACH-AgEAyQQAIf8CAQDJBAAhgAMBANcEACECAAAAEQAgGgAArgEAIAIAAAARACAaAACuAQAgAQAAAA8AIAMAAAATACAhAACmAQAgIgAArAEAIAEAAAATACABAAAAEQAgCAcAALYGACAnAAC4BgAgKAAAtwYAIPoCAAD2BQAg-wIAAPYFACD8AgAA9gUAIP0CAAD2BQAggAMAAPYFACAOrQIAAJkEADCuAgAAtgEAEK8CAACZBAAwyQIBAOIDACHRAkAA0gMAIdICQADSAwAh-QIBAM8DACH6AgEA-gMAIfsCAQD6AwAh_AIBAPoDACH9AgEA-gMAIf4CAQDPAwAh_wIBAM8DACGAAwEA-gMAIQMAAAARACABAAC1AQAwJgAAtgEAIAMAAAARACABAAASADACAAATACABAAAADQAgAQAAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAYDAADuBQAgCgAAtQYAINECQAAAAAHTAgEAAAAB9gIBAAAAAfgCAAAA-AICARoAAL4BACAE0QJAAAAAAdMCAQAAAAH2AgEAAAAB-AIAAAD4AgIBGgAAwAEAMAEaAADAAQAwBgMAAOwFACAKAAC0BgAg0QJAAMsEACHTAgEAyQQAIfYCAQDJBAAh-AIAAOoF-AIiAgAAAA0AIBoAAMMBACAE0QJAAMsEACHTAgEAyQQAIfYCAQDJBAAh-AIAAOoF-AIiAgAAAAsAIBoAAMUBACACAAAACwAgGgAAxQEAIAMAAAANACAhAAC-AQAgIgAAwwEAIAEAAAANACABAAAACwAgAwcAALEGACAnAACzBgAgKAAAsgYAIAetAgAAlQQAMK4CAADMAQAQrwIAAJUEADDRAkAA0gMAIdMCAQDiAwAh9gIBAM8DACH4AgAAlgT4AiIDAAAACwAgAQAAywEAMCYAAMwBACADAAAACwAgAQAADAAwAgAADQAgAQAAABkAIAEAAAAZACADAAAAFwAgAQAAGAAwAgAAGQAgAwAAABcAIAEAABgAMAIAABkAIAMAAAAXACABAAAYADACAAAZACAKCgAAsAYAIMkCAQAAAAHKAgEAAAAB0QJAAAAAAdICQAAAAAHTAgEAAAAB8gIBAAAAAfMCQAAAAAH0AkAAAAAB9QJAAAAAAQEaAADUAQAgCckCAQAAAAHKAgEAAAAB0QJAAAAAAdICQAAAAAHTAgEAAAAB8gIBAAAAAfMCQAAAAAH0AkAAAAAB9QJAAAAAAQEaAADWAQAwARoAANYBADAKCgAArwYAIMkCAQDJBAAhygIBAMkEACHRAkAAywQAIdICQADLBAAh0wIBAMkEACHyAgEAyQQAIfMCQADLBAAh9AJAAOgEACH1AkAA6AQAIQIAAAAZACAaAADZAQAgCckCAQDJBAAhygIBAMkEACHRAkAAywQAIdICQADLBAAh0wIBAMkEACHyAgEAyQQAIfMCQADLBAAh9AJAAOgEACH1AkAA6AQAIQIAAAAXACAaAADbAQAgAgAAABcAIBoAANsBACADAAAAGQAgIQAA1AEAICIAANkBACABAAAAGQAgAQAAABcAIAUHAACsBgAgJwAArgYAICgAAK0GACD0AgAA9gUAIPUCAAD2BQAgDK0CAACUBAAwrgIAAOIBABCvAgAAlAQAMMkCAQDiAwAhygIBAM8DACHRAkAA0gMAIdICQADSAwAh0wIBAOIDACHyAgEAzwMAIfMCQADSAwAh9AJAAOQDACH1AkAA5AMAIQMAAAAXACABAADhAQAwJgAA4gEAIAMAAAAXACABAAAYADACAAAZACAKDAAAkwQAIK0CAACRBAAwrgIAAOgBABCvAgAAkQQAMLECAQAAAAHJAgEAAAAB0QJAAN8DACHSAkAA3wMAIeoCIACSBAAh8QIBAAAAAQEAAADlAQAgAQAAAOUBACAKDAAAkwQAIK0CAACRBAAwrgIAAOgBABCvAgAAkQQAMLECAQDcAwAhyQIBAOwDACHRAkAA3wMAIdICQADfAwAh6gIgAJIEACHxAgEA3AMAIQEMAACrBgAgAwAAAOgBACABAADpAQAwAgAA5QEAIAMAAADoAQAgAQAA6QEAMAIAAOUBACADAAAA6AEAIAEAAOkBADACAADlAQAgBwwAAKoGACCxAgEAAAAByQIBAAAAAdECQAAAAAHSAkAAAAAB6gIgAAAAAfECAQAAAAEBGgAA7QEAIAaxAgEAAAAByQIBAAAAAdECQAAAAAHSAkAAAAAB6gIgAAAAAfECAQAAAAEBGgAA7wEAMAEaAADvAQAwBwwAAKAGACCxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIeoCIACKBQAh8QIBAMkEACECAAAA5QEAIBoAAPIBACAGsQIBAMkEACHJAgEAyQQAIdECQADLBAAh0gJAAMsEACHqAiAAigUAIfECAQDJBAAhAgAAAOgBACAaAAD0AQAgAgAAAOgBACAaAAD0AQAgAwAAAOUBACAhAADtAQAgIgAA8gEAIAEAAADlAQAgAQAAAOgBACADBwAAnQYAICcAAJ8GACAoAACeBgAgCa0CAACQBAAwrgIAAPsBABCvAgAAkAQAMLECAQDPAwAhyQIBAOIDACHRAkAA0gMAIdICQADSAwAh6gIgAIgEACHxAgEAzwMAIQMAAADoAQAgAQAA-gEAMCYAAPsBACADAAAA6AEAIAEAAOkBADACAADlAQAgAQAAAB0AIAEAAAAdACADAAAAGwAgAQAAHAAwAgAAHQAgAwAAABsAIAEAABwAMAIAAB0AIAMAAAAbACABAAAcADACAAAdACARCgAAnAYAIA0AAM4FACAPAADPBQAgEAAA0AUAIBEAANEFACATAADSBQAgFAAA0wUAILECAQAAAAHJAgEAAAAB0QJAAAAAAdICQAAAAAHTAgEAAAAB7AIBAAAAAe0CAgAAAAHuAhAAAAAB7wIgAAAAAfACAQAAAAEBGgAAgwIAIAqxAgEAAAAByQIBAAAAAdECQAAAAAHSAkAAAAAB0wIBAAAAAewCAQAAAAHtAgIAAAAB7gIQAAAAAe8CIAAAAAHwAgEAAAABARoAAIUCADABGgAAhQIAMBEKAACbBgAgDQAAjAUAIA8AAI0FACAQAACOBQAgEQAAjwUAIBMAAJAFACAUAACRBQAgsQIBAMkEACHJAgEAyQQAIdECQADLBAAh0gJAAMsEACHTAgEAyQQAIewCAQDJBAAh7QICAIkFACHuAhAAygQAIe8CIACKBQAh8AIBANcEACECAAAAHQAgGgAAiAIAIAqxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIdMCAQDJBAAh7AIBAMkEACHtAgIAiQUAIe4CEADKBAAh7wIgAIoFACHwAgEA1wQAIQIAAAAbACAaAACKAgAgAgAAABsAIBoAAIoCACADAAAAHQAgIQAAgwIAICIAAIgCACABAAAAHQAgAQAAABsAIAYHAACWBgAgJwAAmQYAICgAAJgGACA5AACXBgAgOgAAmgYAIPACAAD2BQAgDa0CAACPBAAwrgIAAJECABCvAgAAjwQAMLECAQDPAwAhyQIBAOIDACHRAkAA0gMAIdICQADSAwAh0wIBAOIDACHsAgEA4gMAIe0CAgDjAwAh7gIQANADACHvAiAAiAQAIfACAQD6AwAhAwAAABsAIAEAAJACADAmAACRAgAgAwAAABsAIAEAABwAMAIAAB0AIAEAAAAzACABAAAAMwAgAwAAADEAIAEAADIAMAIAADMAIAMAAAAxACABAAAyADACAAAzACADAAAAMQAgAQAAMgAwAgAAMwAgCQ4AAJUGACDJAgEAAAAB0QJAAAAAAdICQAAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHZAkAAAAAB6wIBAAAAAQEaAACZAgAgCMkCAQAAAAHRAkAAAAAB0gJAAAAAAdQCAQAAAAHVAgEAAAAB1gIBAAAAAdkCQAAAAAHrAgEAAAABARoAAJsCADABGgAAmwIAMAkOAACUBgAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh1AIBAMkEACHVAgEA1wQAIdYCAQDXBAAh2QJAAMsEACHrAgEA1wQAIQIAAAAzACAaAACeAgAgCMkCAQDJBAAh0QJAAMsEACHSAkAAywQAIdQCAQDJBAAh1QIBANcEACHWAgEA1wQAIdkCQADLBAAh6wIBANcEACECAAAAMQAgGgAAoAIAIAIAAAAxACAaAACgAgAgAwAAADMAICEAAJkCACAiAACeAgAgAQAAADMAIAEAAAAxACAGBwAAkQYAICcAAJMGACAoAACSBgAg1QIAAPYFACDWAgAA9gUAIOsCAAD2BQAgC60CAACOBAAwrgIAAKcCABCvAgAAjgQAMMkCAQDiAwAh0QJAANIDACHSAkAA0gMAIdQCAQDiAwAh1QIBAPoDACHWAgEA-gMAIdkCQADSAwAh6wIBAPoDACEDAAAAMQAgAQAApgIAMCYAAKcCACADAAAAMQAgAQAAMgAwAgAAMwAgAQAAACMAIAEAAAAjACADAAAAIQAgAQAAIgAwAgAAIwAgAwAAACEAIAEAACIAMAIAACMAIAMAAAAhACABAAAiADACAAAjACAHDgAAkAYAIMkCAQAAAAHRAkAAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB2AIAAADYAgIBGgAArwIAIAbJAgEAAAAB0QJAAAAAAdQCAQAAAAHVAgEAAAAB1gIBAAAAAdgCAAAA2AICARoAALECADABGgAAsQIAMAcOAACPBgAgyQIBAMkEACHRAkAAywQAIdQCAQDJBAAh1QIBAMkEACHWAgEAyQQAIdgCAADnBNgCIgIAAAAjACAaAAC0AgAgBskCAQDJBAAh0QJAAMsEACHUAgEAyQQAIdUCAQDJBAAh1gIBAMkEACHYAgAA5wTYAiICAAAAIQAgGgAAtgIAIAIAAAAhACAaAAC2AgAgAwAAACMAICEAAK8CACAiAAC0AgAgAQAAACMAIAEAAAAhACADBwAAjAYAICcAAI4GACAoAACNBgAgCa0CAACNBAAwrgIAAL0CABCvAgAAjQQAMMkCAQDiAwAh0QJAANIDACHUAgEA4gMAIdUCAQDPAwAh1gIBAM8DACHYAgAA8QPYAiIDAAAAIQAgAQAAvAIAMCYAAL0CACADAAAAIQAgAQAAIgAwAgAAIwAgAQAAACcAIAEAAAAnACADAAAAJQAgAQAAJgAwAgAAJwAgAwAAACUAIAEAACYAMAIAACcAIAMAAAAlACABAAAmADACAAAnACAKDgAAiwYAILICEAAAAAHJAgEAAAAB0QJAAAAAAdICQAAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHYAgAAANgCA-oCIAAAAAEBGgAAxQIAIAmyAhAAAAAByQIBAAAAAdECQAAAAAHSAkAAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB2AIAAADYAgPqAiAAAAABARoAAMcCADABGgAAxwIAMAoOAACKBgAgsgIQAMoEACHJAgEAyQQAIdECQADLBAAh0gJAAMsEACHUAgEAyQQAIdUCAQDXBAAh1gIBANcEACHYAgAAvgXYAiPqAiAAigUAIQIAAAAnACAaAADKAgAgCbICEADKBAAhyQIBAMkEACHRAkAAywQAIdICQADLBAAh1AIBAMkEACHVAgEA1wQAIdYCAQDXBAAh2AIAAL4F2AIj6gIgAIoFACECAAAAJQAgGgAAzAIAIAIAAAAlACAaAADMAgAgAwAAACcAICEAAMUCACAiAADKAgAgAQAAACcAIAEAAAAlACAIBwAAhQYAICcAAIgGACAoAACHBgAgOQAAhgYAIDoAAIkGACDVAgAA9gUAINYCAAD2BQAg2AIAAPYFACAMrQIAAIYEADCuAgAA0wIAEK8CAACGBAAwsgIQANADACHJAgEA4gMAIdECQADSAwAh0gJAANIDACHUAgEA4gMAIdUCAQD6AwAh1gIBAPoDACHYAgAAhwTYAiPqAiAAiAQAIQMAAAAlACABAADSAgAwJgAA0wIAIAMAAAAlACABAAAmADACAAAnACABAAAAKwAgAQAAACsAIAMAAAApACABAAAqADACAAArACADAAAAKQAgAQAAKgAwAgAAKwAgAwAAACkAIAEAACoAMAIAACsAIA8OAAD7BAAgEgAAswUAIMkCAQAAAAHRAkAAAAAB0gJAAAAAAdQCAQAAAAHVAgEAAAAB1gIBAAAAAdwCAAAA4wIC3QIBAAAAAd4CAQAAAAHfAgEAAAAB4AIBAAAAAeECQAAAAAHpAgEAAAABARoAANsCACANyQIBAAAAAdECQAAAAAHSAkAAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB3AIAAADjAgLdAgEAAAAB3gIBAAAAAd8CAQAAAAHgAgEAAAAB4QJAAAAAAekCAQAAAAEBGgAA3QIAMAEaAADdAgAwAQAAAC0AIA8OAAD5BAAgEgAAsQUAIMkCAQDJBAAh0QJAAMsEACHSAkAAywQAIdQCAQDJBAAh1QIBAMkEACHWAgEAyQQAIdwCAAD3BOMCIt0CAQDJBAAh3gIBAMkEACHfAgEAyQQAIeACAQDJBAAh4QJAAMsEACHpAgEA1wQAIQIAAAArACAaAADhAgAgDckCAQDJBAAh0QJAAMsEACHSAkAAywQAIdQCAQDJBAAh1QIBAMkEACHWAgEAyQQAIdwCAAD3BOMCIt0CAQDJBAAh3gIBAMkEACHfAgEAyQQAIeACAQDJBAAh4QJAAMsEACHpAgEA1wQAIQIAAAApACAaAADjAgAgAgAAACkAIBoAAOMCACABAAAALQAgAwAAACsAICEAANsCACAiAADhAgAgAQAAACsAIAEAAAApACAEBwAAggYAICcAAIQGACAoAACDBgAg6QIAAPYFACAQrQIAAIUEADCuAgAA6wIAEK8CAACFBAAwyQIBAOIDACHRAkAA0gMAIdICQADSAwAh1AIBAOIDACHVAgEAzwMAIdYCAQDPAwAh3AIAAPgD4wIi3QIBAM8DACHeAgEAzwMAId8CAQDPAwAh4AIBAM8DACHhAkAA0gMAIekCAQD5AwAhAwAAACkAIAEAAOoCADAmAADrAgAgAwAAACkAIAEAACoAMAIAACsAIBKtAgAAgAQAMK4CAADxAgAQrwIAAIAEADDJAgEAAAAB1AIBAOwDACHVAgEA3AMAIdYCAQDcAwAh3QIBANwDACHeAgEA3AMAId8CAQDcAwAh4AIBANwDACHhAkAA3wMAIeMCAACBBOMCIuQCAACBBOMCIuUCAQCCBAAh5gIBAIMEACHnAgEAgwQAIegCQADfAwAhAQAAAO4CACABAAAA7gIAIBKtAgAAgAQAMK4CAADxAgAQrwIAAIAEADDJAgEA7AMAIdQCAQDsAwAh1QIBANwDACHWAgEA3AMAId0CAQDcAwAh3gIBANwDACHfAgEA3AMAIeACAQDcAwAh4QJAAN8DACHjAgAAgQTjAiLkAgAAgQTjAiLlAgEAggQAIeYCAQCDBAAh5wIBAIMEACHoAkAA3wMAIQPlAgAA9gUAIOYCAAD2BQAg5wIAAPYFACADAAAA8QIAIAEAAPICADACAADuAgAgAwAAAPECACABAADyAgAwAgAA7gIAIAMAAADxAgAgAQAA8gIAMAIAAO4CACAPyQIBAAAAAdQCAQAAAAHVAgEAAAAB1gIBAAAAAd0CAQAAAAHeAgEAAAAB3wIBAAAAAeACAQAAAAHhAkAAAAAB4wIAAADjAgLkAgAAAOMCAuUCAQAAAAHmAgEAAAAB5wIBAAAAAegCQAAAAAEBGgAA9gIAIA_JAgEAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB3QIBAAAAAd4CAQAAAAHfAgEAAAAB4AIBAAAAAeECQAAAAAHjAgAAAOMCAuQCAAAA4wIC5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AJAAAAAAQEaAAD4AgAwARoAAPgCADAPyQIBAMkEACHUAgEAyQQAIdUCAQDJBAAh1gIBAMkEACHdAgEAyQQAId4CAQDJBAAh3wIBAMkEACHgAgEAyQQAIeECQADLBAAh4wIAAPcE4wIi5AIAAPcE4wIi5QIBANcEACHmAgEA1wQAIecCAQDXBAAh6AJAAMsEACECAAAA7gIAIBoAAPsCACAPyQIBAMkEACHUAgEAyQQAIdUCAQDJBAAh1gIBAMkEACHdAgEAyQQAId4CAQDJBAAh3wIBAMkEACHgAgEAyQQAIeECQADLBAAh4wIAAPcE4wIi5AIAAPcE4wIi5QIBANcEACHmAgEA1wQAIecCAQDXBAAh6AJAAMsEACECAAAA8QIAIBoAAP0CACACAAAA8QIAIBoAAP0CACADAAAA7gIAICEAAPYCACAiAAD7AgAgAQAAAO4CACABAAAA8QIAIAYHAAD_BQAgJwAAgQYAICgAAIAGACDlAgAA9gUAIOYCAAD2BQAg5wIAAPYFACASrQIAAPcDADCuAgAAhAMAEK8CAAD3AwAwyQIBAOIDACHUAgEA4gMAIdUCAQDPAwAh1gIBAM8DACHdAgEAzwMAId4CAQDPAwAh3wIBAM8DACHgAgEAzwMAIeECQADSAwAh4wIAAPgD4wIi5AIAAPgD4wIi5QIBAPkDACHmAgEA-gMAIecCAQD6AwAh6AJAANIDACEDAAAA8QIAIAEAAIMDADAmAACEAwAgAwAAAPECACABAADyAgAwAgAA7gIAIAEAAAA2ACABAAAANgAgAwAAAC0AIAEAADUAMAIAADYAIAMAAAAtACABAAA1ADACAAA2ACADAAAALQAgAQAANQAwAgAANgAgEQoAAJwFACAOAAD9BAAgEQAA_gQAIMkCAQAAAAHRAkAAAAAB0gJAAAAAAdMCAQAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHYAgAAANgCAtkCQAAAAAHaAkAAAAAB3AIAAADcAgLdAgEAAAAB3gIBAAAAAd8CAQAAAAEBGgAAjAMAIA7JAgEAAAAB0QJAAAAAAdICQAAAAAHTAgEAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB2AIAAADYAgLZAkAAAAAB2gJAAAAAAdwCAAAA3AIC3QIBAAAAAd4CAQAAAAHfAgEAAAABARoAAI4DADABGgAAjgMAMBEKAACaBQAgDgAA6wQAIBEAAOwEACDJAgEAyQQAIdECQADLBAAh0gJAAMsEACHTAgEAyQQAIdQCAQDJBAAh1QIBAMkEACHWAgEAyQQAIdgCAADnBNgCItkCQADLBAAh2gJAAOgEACHcAgAA6QTcAiLdAgEAyQQAId4CAQDJBAAh3wIBAMkEACECAAAANgAgGgAAkQMAIA7JAgEAyQQAIdECQADLBAAh0gJAAMsEACHTAgEAyQQAIdQCAQDJBAAh1QIBAMkEACHWAgEAyQQAIdgCAADnBNgCItkCQADLBAAh2gJAAOgEACHcAgAA6QTcAiLdAgEAyQQAId4CAQDJBAAh3wIBAMkEACECAAAALQAgGgAAkwMAIAIAAAAtACAaAACTAwAgAwAAADYAICEAAIwDACAiAACRAwAgAQAAADYAIAEAAAAtACAEBwAA_AUAICcAAP4FACAoAAD9BQAg2gIAAPYFACARrQIAAPADADCuAgAAmgMAEK8CAADwAwAwyQIBAOIDACHRAkAA0gMAIdICQADSAwAh0wIBAOIDACHUAgEA4gMAIdUCAQDPAwAh1gIBAM8DACHYAgAA8QPYAiLZAkAA0gMAIdoCQADkAwAh3AIAAPID3AIi3QIBAM8DACHeAgEAzwMAId8CAQDPAwAhAwAAAC0AIAEAAJkDADAmAACaAwAgAwAAAC0AIAEAADUAMAIAADYAIA2tAgAA6wMAMK4CAACgAwAQrwIAAOsDADDJAgEAAAABygIBANwDACHLAgEA3AMAIcwCQADfAwAhzQICAO0DACHOAkAA3wMAIc8CAgDtAwAh0AJAAO4DACHRAkAA3wMAIdICQADfAwAhAQAAAJ0DACABAAAAnQMAIA2tAgAA6wMAMK4CAACgAwAQrwIAAOsDADDJAgEA7AMAIcoCAQDcAwAhywIBANwDACHMAkAA3wMAIc0CAgDtAwAhzgJAAN8DACHPAgIA7QMAIdACQADuAwAh0QJAAN8DACHSAkAA3wMAIQHQAgAA9gUAIAMAAACgAwAgAQAAoQMAMAIAAJ0DACADAAAAoAMAIAEAAKEDADACAACdAwAgAwAAAKADACABAAChAwAwAgAAnQMAIArJAgEAAAABygIBAAAAAcsCAQAAAAHMAkAAAAABzQICAAAAAc4CQAAAAAHPAgIAAAAB0AJAAAAAAdECQAAAAAHSAkAAAAABARoAAKUDACAKyQIBAAAAAcoCAQAAAAHLAgEAAAABzAJAAAAAAc0CAgAAAAHOAkAAAAABzwICAAAAAdACQAAAAAHRAkAAAAAB0gJAAAAAAQEaAACnAwAwARoAAKcDADAKyQIBAMkEACHKAgEAyQQAIcsCAQDJBAAhzAJAAMsEACHNAgIAiQUAIc4CQADLBAAhzwICAIkFACHQAkAA6AQAIdECQADLBAAh0gJAAMsEACECAAAAnQMAIBoAAKoDACAKyQIBAMkEACHKAgEAyQQAIcsCAQDJBAAhzAJAAMsEACHNAgIAiQUAIc4CQADLBAAhzwICAIkFACHQAkAA6AQAIdECQADLBAAh0gJAAMsEACECAAAAoAMAIBoAAKwDACACAAAAoAMAIBoAAKwDACADAAAAnQMAICEAAKUDACAiAACqAwAgAQAAAJ0DACABAAAAoAMAIAYHAAD3BQAgJwAA-gUAICgAAPkFACA5AAD4BQAgOgAA-wUAINACAAD2BQAgDa0CAADhAwAwrgIAALMDABCvAgAA4QMAMMkCAQDiAwAhygIBAM8DACHLAgEAzwMAIcwCQADSAwAhzQICAOMDACHOAkAA0gMAIc8CAgDjAwAh0AJAAOQDACHRAkAA0gMAIdICQADSAwAhAwAAAKADACABAACyAwAwJgAAswMAIAMAAACgAwAgAQAAoQMAMAIAAJ0DACAJBgAA4AMAIK0CAADbAwAwrgIAAA8AEK8CAADbAwAwsAIBAAAAAbECAQDcAwAhsgIQAN0DACGzAgAA3gMAILQCQADfAwAhAQAAALYDACABAAAAtgMAIAEGAAD1BQAgAwAAAA8AIAEAALkDADACAAC2AwAgAwAAAA8AIAEAALkDADACAAC2AwAgAwAAAA8AIAEAALkDADACAAC2AwAgBgYAAPQFACCwAgEAAAABsQIBAAAAAbICEAAAAAGzAoAAAAABtAJAAAAAAQEaAAC9AwAgBbACAQAAAAGxAgEAAAABsgIQAAAAAbMCgAAAAAG0AkAAAAABARoAAL8DADABGgAAvwMAMAYGAADMBAAgsAIBAMkEACGxAgEAyQQAIbICEADKBAAhswKAAAAAAbQCQADLBAAhAgAAALYDACAaAADCAwAgBbACAQDJBAAhsQIBAMkEACGyAhAAygQAIbMCgAAAAAG0AkAAywQAIQIAAAAPACAaAADEAwAgAgAAAA8AIBoAAMQDACADAAAAtgMAICEAAL0DACAiAADCAwAgAQAAALYDACABAAAADwAgBQcAAMQEACAnAADHBAAgKAAAxgQAIDkAAMUEACA6AADIBAAgCK0CAADOAwAwrgIAAMsDABCvAgAAzgMAMLACAQDPAwAhsQIBAM8DACGyAhAA0AMAIbMCAADRAwAgtAJAANIDACEDAAAADwAgAQAAygMAMCYAAMsDACADAAAADwAgAQAAuQMAMAIAALYDACAIrQIAAM4DADCuAgAAywMAEK8CAADOAwAwsAIBAM8DACGxAgEAzwMAIbICEADQAwAhswIAANEDACC0AkAA0gMAIQ4HAADUAwAgJwAA2gMAICgAANoDACC1AgEAAAABtgIBAAAABLcCAQAAAAS4AgEAAAABuQIBAAAAAboCAQAAAAG7AgEAAAABvAIBANkDACHDAgEAAAABxAIBAAAAAcUCAQAAAAENBwAA1AMAICcAANgDACAoAADYAwAgOQAA2AMAIDoAANgDACC1AhAAAAABtgIQAAAABLcCEAAAAAS4AhAAAAABuQIQAAAAAboCEAAAAAG7AhAAAAABvAIQANcDACEPBwAA1AMAICcAANYDACAoAADWAwAgtQKAAAAAAbgCgAAAAAG5AoAAAAABugKAAAAAAbsCgAAAAAG8AoAAAAABvQIBAAAAAb4CAQAAAAG_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-MCIuQCAAD4A-MCIuUCAQD5AwAh5gIBAPoDACHnAgEA-gMAIegCQADSAwAhBwcAANQDACAnAAD_AwAgKAAA_wMAILUCAAAA4wICtgIAAADjAgi3AgAAAOMCCLwCAAD-A-MCIgsHAADmAwAgJwAA_AMAICgAAPwDACC1AgEAAAABtgIBAAAABbcCAQAAAAW4AgEAAAABuQIBAAAAAboCAQAAAAG7AgEAAAABvAIBAP0DACEOBwAA5gMAICcAAPwDACAoAAD8AwAgtQIBAAAAAbYCAQAAAAW3AgEAAAAFuAIBAAAAAbkCAQAAAAG6AgEAAAABuwIBAAAAAbwCAQD7AwAhwwIBAAAAAcQCAQAAAAHFAgEAAAABDgcAAOYDACAnAAD8AwAgKAAA_AMAILUCAQAAAAG2AgEAAAAFtwIBAAAABbgCAQAAAAG5AgEAAAABugIBAAAAAbsCAQAAAAG8AgEA-wMAIcMCAQAAAAHEAgEAAAABxQIBAAAAAQu1AgEAAAABtgIBAAAABbcCAQAAAAW4AgEAAAABuQIBAAAAAboCAQAAAAG7AgEAAAABvAIBAPwDACHDAgEAAAABxAIBAAAAAcUCAQAAAAELBwAA5gMAICcAAPwDACAoAAD8AwAgtQIBAAAAAbYCAQAAAAW3AgEAAAAFuAIBAAAAAbkCAQAAAAG6AgEAAAABuwIBAAAAAbwCAQD9AwAhBwcAANQDACAnAAD_AwAgKAAA_wMAILUCAAAA4wICtgIAAADjAgi3AgAAAOMCCLwCAAD-A-MCIgS1AgAAAOMCArYCAAAA4wIItwIAAADjAgi8AgAA_wPjAiISrQIAAIAEADCuAgAA8QIAEK8CAACABAAwyQIBAOwDACHUAgEA7AMAIdUCAQDcAwAh1gIBANwDACHdAgEA3AMAId4CAQDcAwAh3wIBANwDACHgAgEA3AMAIeECQADfAwAh4wIAAIEE4wIi5AIAAIEE4wIi5QIBAIIEACHmAgEAgwQAIecCAQCDBAAh6AJAAN8DACEEtQIAAADjAgK2AgAAAOMCCLcCAAAA4wIIvAIAAP8D4wIiCLUCAQAAAAG2AgEAAAAFtwIBAAAABbgCAQAAAAG5AgEAAAABugIBAAAAAbsCAQAAAAG8AgEAhAQAIQu1AgEAAAABtgIBAAAABbcCAQAAAAW4AgEAAAABuQIBAAAAAboCAQAAAAG7AgEAAAABvAIBAPwDACHDAgEAAAABxAIBAAAAAcUCAQAAAAEItQIBAAAAAbYCAQAAAAW3AgEAAAAFuAIBAAAAAbkCAQAAAAG6AgEAAAABuwIBAAAAAbwCAQCEBAAhEK0CAACFBAAwrgIAAOsCABCvAgAAhQQAMMkCAQDiAwAh0QJAANIDACHSAkAA0gMAIdQCAQDiAwAh1QIBAM8DACHWAgEAzwMAIdwCAAD4A-MCIt0CAQDPAwAh3gIBAM8DACHfAgEAzwMAIeACAQDPAwAh4QJAANIDACHpAgEA-QMAIQytAgAAhgQAMK4CAADTAgAQrwIAAIYEADCyAhAA0AMAIckCAQDiAwAh0QJAANIDACHSAkAA0gMAIdQCAQDiAwAh1QIBAPoDACHWAgEA-gMAIdgCAACHBNgCI-oCIACIBAAhBwcAAOYDACAnAACMBAAgKAAAjAQAILUCAAAA2AIDtgIAAADYAgm3AgAAANgCCbwCAACLBNgCIwUHAADUAwAgJwAAigQAICgAAIoEACC1AiAAAAABvAIgAIkEACEFBwAA1AMAICcAAIoEACAoAACKBAAgtQIgAAAAAbwCIACJBAAhArUCIAAAAAG8AiAAigQAIQcHAADmAwAgJwAAjAQAICgAAIwEACC1AgAAANgCA7YCAAAA2AIJtwIAAADYAgm8AgAAiwTYAiMEtQIAAADYAgO2AgAAANgCCbcCAAAA2AIJvAIAAIwE2AIjCa0CAACNBAAwrgIAAL0CABCvAgAAjQQAMMkCAQDiAwAh0QJAANIDACHUAgEA4gMAIdUCAQDPAwAh1gIBAM8DACHYAgAA8QPYAiILrQIAAI4EADCuAgAApwIAEK8CAACOBAAwyQIBAOIDACHRAkAA0gMAIdICQADSAwAh1AIBAOIDACHVAgEA-gMAIdYCAQD6AwAh2QJAANIDACHrAgEA-gMAIQ2tAgAAjwQAMK4CAACRAgAQrwIAAI8EADCxAgEAzwMAIckCAQDiAwAh0QJAANIDACHSAkAA0gMAIdMCAQDiAwAh7AIBAOIDACHtAgIA4wMAIe4CEADQAwAh7wIgAIgEACHwAgEA-gMAIQmtAgAAkAQAMK4CAAD7AQAQrwIAAJAEADCxAgEAzwMAIckCAQDiAwAh0QJAANIDACHSAkAA0gMAIeoCIACIBAAh8QIBAM8DACEKDAAAkwQAIK0CAACRBAAwrgIAAOgBABCvAgAAkQQAMLECAQDcAwAhyQIBAOwDACHRAkAA3wMAIdICQADfAwAh6gIgAJIEACHxAgEA3AMAIQK1AiAAAAABvAIgAIoEACEDxgIAABsAIMcCAAAbACDIAgAAGwAgDK0CAACUBAAwrgIAAOIBABCvAgAAlAQAMMkCAQDiAwAhygIBAM8DACHRAkAA0gMAIdICQADSAwAh0wIBAOIDACHyAgEAzwMAIfMCQADSAwAh9AJAAOQDACH1AkAA5AMAIQetAgAAlQQAMK4CAADMAQAQrwIAAJUEADDRAkAA0gMAIdMCAQDiAwAh9gIBAM8DACH4AgAAlgT4AiIHBwAA1AMAICcAAJgEACAoAACYBAAgtQIAAAD4AgK2AgAAAPgCCLcCAAAA-AIIvAIAAJcE-AIiBwcAANQDACAnAACYBAAgKAAAmAQAILUCAAAA-AICtgIAAAD4Agi3AgAAAPgCCLwCAACXBPgCIgS1AgAAAPgCArYCAAAA-AIItwIAAAD4Agi8AgAAmAT4AiIOrQIAAJkEADCuAgAAtgEAEK8CAACZBAAwyQIBAOIDACHRAkAA0gMAIdICQADSAwAh-QIBAM8DACH6AgEA-gMAIfsCAQD6AwAh_AIBAPoDACH9AgEA-gMAIf4CAQDPAwAh_wIBAM8DACGAAwEA-gMAIQmtAgAAmgQAMK4CAACeAQAQrwIAAJoEADDJAgEAzwMAIdECQADSAwAh0gJAANIDACHzAkAA0gMAIYEDAQDPAwAhggMBAM8DACEJrQIAAJsEADCuAgAAiwEAEK8CAACbBAAwyQIBANwDACHRAkAA3wMAIdICQADfAwAh8wJAAN8DACGBAwEA3AMAIYIDAQDcAwAhEK0CAACcBAAwrgIAAIUBABCvAgAAnAQAMMkCAQDPAwAh0QJAANIDACHSAkAA0gMAIfYCAQDPAwAhgwMBAM8DACGEAwEAzwMAIYUDAQD6AwAhhgMBAPoDACGHAwEA-gMAIYgDQADkAwAhiQNAAOQDACGKAwEA-gMAIYsDAQD6AwAhEK0CAACdBAAwrgIAAG8AEK8CAACdBAAwyQIBAM8DACHRAkAA0gMAIdICQADSAwAh8wJAANIDACH2AgEAzwMAIfsCAQD6AwAh_QIBAPoDACGMAwEAzwMAIY0DAQD6AwAhjgMBAPoDACGPAwEA-gMAIZADCACeBAAhkQMIAJ4EACENBwAA5gMAICcAAKAEACAoAACgBAAgOQAAoAQAIDoAAKAEACC1AggAAAABtgIIAAAABbcCCAAAAAW4AggAAAABuQIIAAAAAboCCAAAAAG7AggAAAABvAIIAJ8EACENBwAA5gMAICcAAKAEACAoAACgBAAgOQAAoAQAIDoAAKAEACC1AggAAAABtgIIAAAABbcCCAAAAAW4AggAAAABuQIIAAAAAboCCAAAAAG7AggAAAABvAIIAJ8EACEItQIIAAAAAbYCCAAAAAW3AggAAAAFuAIIAAAAAbkCCAAAAAG6AggAAAABuwIIAAAAAbwCCACgBAAhD60CAAChBAAwrgIAAFkAEK8CAAChBAAwsQIBAM8DACHJAgEAzwMAIcoCAQDPAwAh0QJAANIDACHSAkAA0gMAIfgCAQDPAwAhkgMgAIgEACGTAwEA-gMAIZQDAQD6AwAhlQMgAIgEACGWA0AA5AMAIZcDAQD6AwAhEgQAAKMEACAFAACkBAAgBgAApQQAIK0CAACiBAAwrgIAAEYAEK8CAACiBAAwsQIBANwDACHJAgEA3AMAIcoCAQDcAwAh0QJAAN8DACHSAkAA3wMAIfgCAQDcAwAhkgMgAJIEACGTAwEAgwQAIZQDAQCDBAAhlQMgAJIEACGWA0AA7gMAIZcDAQCDBAAhA8YCAAADACDHAgAAAwAgyAIAAAMAIAPGAgAABwAgxwIAAAcAIMgCAAAHACADxgIAAAsAIMcCAAALACDIAgAACwAgFAoAAKoEACAOAACpBAAgEQAAqwQAIK0CAACmBAAwrgIAAC0AEK8CAACmBAAwyQIBAOwDACHRAkAA3wMAIdICQADfAwAh0wIBAOwDACHUAgEA7AMAIdUCAQDcAwAh1gIBANwDACHYAgAApwTYAiLZAkAA3wMAIdoCQADuAwAh3AIAAKgE3AIi3QIBANwDACHeAgEA3AMAId8CAQDcAwAhBLUCAAAA2AICtgIAAADYAgi3AgAAANgCCLwCAAD2A9gCIgS1AgAAANwCArYCAAAA3AIItwIAAADcAgi8AgAA9APcAiIWCgAAqgQAIA0AALQEACAPAAC1BAAgEAAAtgQAIBEAAKsEACATAAC3BAAgFAAAuAQAIK0CAACzBAAwrgIAABsAEK8CAACzBAAwsQIBANwDACHJAgEA7AMAIdECQADfAwAh0gJAAN8DACHTAgEA7AMAIewCAQDsAwAh7QICAO0DACHuAhAA3QMAIe8CIACSBAAh8AIBAIMEACGaAwAAGwAgmwMAABsAIBUIAAC7BAAgCQAApQQAIAsAALwEACAMAACTBAAgFAAAuAQAIK0CAAC6BAAwrgIAABEAEK8CAAC6BAAwyQIBAOwDACHRAkAA3wMAIdICQADfAwAh-QIBANwDACH6AgEAgwQAIfsCAQCDBAAh_AIBAIMEACH9AgEAgwQAIf4CAQDcAwAh_wIBANwDACGAAwEAgwQAIZoDAAARACCbAwAAEQAgA8YCAAApACDHAgAAKQAgyAIAACkAIAwOAACpBAAgrQIAAKwEADCuAgAAMQAQrwIAAKwEADDJAgEA7AMAIdECQADfAwAh0gJAAN8DACHUAgEA7AMAIdUCAQCDBAAh1gIBAIMEACHZAkAA3wMAIesCAQCDBAAhA9QCAQAAAAHVAgEAAAAB4QJAAAAAARIOAACpBAAgEgAArwQAIK0CAACuBAAwrgIAACkAEK8CAACuBAAwyQIBAOwDACHRAkAA3wMAIdICQADfAwAh1AIBAOwDACHVAgEA3AMAIdYCAQDcAwAh3AIAAIEE4wIi3QIBANwDACHeAgEA3AMAId8CAQDcAwAh4AIBANwDACHhAkAA3wMAIekCAQCCBAAhFgoAAKoEACAOAACpBAAgEQAAqwQAIK0CAACmBAAwrgIAAC0AEK8CAACmBAAwyQIBAOwDACHRAkAA3wMAIdICQADfAwAh0wIBAOwDACHUAgEA7AMAIdUCAQDcAwAh1gIBANwDACHYAgAApwTYAiLZAkAA3wMAIdoCQADuAwAh3AIAAKgE3AIi3QIBANwDACHeAgEA3AMAId8CAQDcAwAhmgMAAC0AIJsDAAAtACANDgAAqQQAIK0CAACwBAAwrgIAACUAEK8CAACwBAAwsgIQAN0DACHJAgEA7AMAIdECQADfAwAh0gJAAN8DACHUAgEA7AMAIdUCAQCDBAAh1gIBAIMEACHYAgAAsQTYAiPqAiAAkgQAIQS1AgAAANgCA7YCAAAA2AIJtwIAAADYAgm8AgAAjATYAiMKDgAAqQQAIK0CAACyBAAwrgIAACEAEK8CAACyBAAwyQIBAOwDACHRAkAA3wMAIdQCAQDsAwAh1QIBANwDACHWAgEA3AMAIdgCAACnBNgCIhQKAACqBAAgDQAAtAQAIA8AALUEACAQAAC2BAAgEQAAqwQAIBMAALcEACAUAAC4BAAgrQIAALMEADCuAgAAGwAQrwIAALMEADCxAgEA3AMAIckCAQDsAwAh0QJAAN8DACHSAkAA3wMAIdMCAQDsAwAh7AIBAOwDACHtAgIA7QMAIe4CEADdAwAh7wIgAJIEACHwAgEAgwQAIQwMAACTBAAgrQIAAJEEADCuAgAA6AEAEK8CAACRBAAwsQIBANwDACHJAgEA7AMAIdECQADfAwAh0gJAAN8DACHqAiAAkgQAIfECAQDcAwAhmgMAAOgBACCbAwAA6AEAIAPGAgAAIQAgxwIAACEAIMgCAAAhACADxgIAACUAIMcCAAAlACDIAgAAJQAgA8YCAAAxACDHAgAAMQAgyAIAADEAIAPGAgAALQAgxwIAAC0AIMgCAAAtACANCgAAqgQAIK0CAAC5BAAwrgIAABcAEK8CAAC5BAAwyQIBAOwDACHKAgEA3AMAIdECQADfAwAh0gJAAN8DACHTAgEA7AMAIfICAQDcAwAh8wJAAN8DACH0AkAA7gMAIfUCQADuAwAhEwgAALsEACAJAAClBAAgCwAAvAQAIAwAAJMEACAUAAC4BAAgrQIAALoEADCuAgAAEQAQrwIAALoEADDJAgEA7AMAIdECQADfAwAh0gJAAN8DACH5AgEA3AMAIfoCAQCDBAAh-wIBAIMEACH8AgEAgwQAIf0CAQCDBAAh_gIBANwDACH_AgEA3AMAIYADAQCDBAAhCwYAAOADACCtAgAA2wMAMK4CAAAPABCvAgAA2wMAMLACAQDcAwAhsQIBANwDACGyAhAA3QMAIbMCAADeAwAgtAJAAN8DACGaAwAADwAgmwMAAA8AIAPGAgAAFwAgxwIAABcAIMgCAAAXACAC0wIBAAAAAfYCAQAAAAEJAwAAwAQAIAoAAKoEACCtAgAAvgQAMK4CAAALABCvAgAAvgQAMNECQADfAwAh0wIBAOwDACH2AgEA3AMAIfgCAAC_BPgCIgS1AgAAAPgCArYCAAAA-AIItwIAAAD4Agi8AgAAmAT4AiIUBAAAowQAIAUAAKQEACAGAAClBAAgrQIAAKIEADCuAgAARgAQrwIAAKIEADCxAgEA3AMAIckCAQDcAwAhygIBANwDACHRAkAA3wMAIdICQADfAwAh-AIBANwDACGSAyAAkgQAIZMDAQCDBAAhlAMBAIMEACGVAyAAkgQAIZYDQADuAwAhlwMBAIMEACGaAwAARgAgmwMAAEYAIBEDAADABAAgrQIAAMEEADCuAgAABwAQrwIAAMEEADDJAgEA3AMAIdECQADfAwAh0gJAAN8DACH2AgEA3AMAIYMDAQDcAwAhhAMBANwDACGFAwEAgwQAIYYDAQCDBAAhhwMBAIMEACGIA0AA7gMAIYkDQADuAwAhigMBAIMEACGLAwEAgwQAIREDAADABAAgrQIAAMIEADCuAgAAAwAQrwIAAMIEADDJAgEA3AMAIdECQADfAwAh0gJAAN8DACHzAkAA3wMAIfYCAQDcAwAh-wIBAIMEACH9AgEAgwQAIYwDAQDcAwAhjQMBAIMEACGOAwEAgwQAIY8DAQCDBAAhkAMIAMMEACGRAwgAwwQAIQi1AggAAAABtgIIAAAABbcCCAAAAAW4AggAAAABuQIIAAAAAboCCAAAAAG7AggAAAABvAIIAKAEACEAAAAAAAGfAwEAAAABBZ8DEAAAAAGlAxAAAAABpgMQAAAAAacDEAAAAAGoAxAAAAABAZ8DQAAAAAELIQAAzQQAMCIAANIEADCcAwAAzgQAMJ0DAADPBAAwngMAANAEACCfAwAA0QQAMKADAADRBAAwoQMAANEEADCiAwAA0QQAMKMDAADTBAAwpAMAANQEADAOCQAA8AUAIAsAAPEFACAMAADyBQAgFAAA8wUAIMkCAQAAAAHRAkAAAAAB0gJAAAAAAfkCAQAAAAH6AgEAAAAB-wIBAAAAAfwCAQAAAAH9AgEAAAAB_gIBAAAAAf8CAQAAAAECAAAAEwAgIQAA7wUAIAMAAAATACAhAADvBQAgIgAA2AQAIAEaAADdBwAwEwgAALsEACAJAAClBAAgCwAAvAQAIAwAAJMEACAUAAC4BAAgrQIAALoEADCuAgAAEQAQrwIAALoEADDJAgEAAAAB0QJAAN8DACHSAkAA3wMAIfkCAQDcAwAh-gIBAIMEACH7AgEAgwQAIfwCAQCDBAAh_QIBAIMEACH-AgEAAAAB_wIBANwDACGAAwEAgwQAIQIAAAATACAaAADYBAAgAgAAANUEACAaAADWBAAgDq0CAADUBAAwrgIAANUEABCvAgAA1AQAMMkCAQDsAwAh0QJAAN8DACHSAkAA3wMAIfkCAQDcAwAh-gIBAIMEACH7AgEAgwQAIfwCAQCDBAAh_QIBAIMEACH-AgEA3AMAIf8CAQDcAwAhgAMBAIMEACEOrQIAANQEADCuAgAA1QQAEK8CAADUBAAwyQIBAOwDACHRAkAA3wMAIdICQADfAwAh-QIBANwDACH6AgEAgwQAIfsCAQCDBAAh_AIBAIMEACH9AgEAgwQAIf4CAQDcAwAh_wIBANwDACGAAwEAgwQAIQrJAgEAyQQAIdECQADLBAAh0gJAAMsEACH5AgEAyQQAIfoCAQDXBAAh-wIBANcEACH8AgEA1wQAIf0CAQDXBAAh_gIBAMkEACH_AgEAyQQAIQGfAwEAAAABDgkAANkEACALAADaBAAgDAAA2wQAIBQAANwEACDJAgEAyQQAIdECQADLBAAh0gJAAMsEACH5AgEAyQQAIfoCAQDXBAAh-wIBANcEACH8AgEA1wQAIf0CAQDXBAAh_gIBAMkEACH_AgEAyQQAIQshAADgBQAwIgAA5QUAMJwDAADhBQAwnQMAAOIFADCeAwAA4wUAIJ8DAADkBQAwoAMAAOQFADChAwAA5AUAMKIDAADkBQAwowMAAOYFADCkAwAA5wUAMAshAADUBQAwIgAA2QUAMJwDAADVBQAwnQMAANYFADCeAwAA1wUAIJ8DAADYBQAwoAMAANgFADChAwAA2AUAMKIDAADYBQAwowMAANoFADCkAwAA2wUAMAshAAD_BAAwIgAAhAUAMJwDAACABQAwnQMAAIEFADCeAwAAggUAIJ8DAACDBQAwoAMAAIMFADChAwAAgwUAMKIDAACDBQAwowMAAIUFADCkAwAAhgUAMAshAADdBAAwIgAA4gQAMJwDAADeBAAwnQMAAN8EADCeAwAA4AQAIJ8DAADhBAAwoAMAAOEEADChAwAA4QQAMKIDAADhBAAwowMAAOMEADCkAwAA5AQAMA8OAAD9BAAgEQAA_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_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_BQAgARoAAL8HADANDgAAqQQAIK0CAACwBAAwrgIAACUAEK8CAACwBAAwsgIQAN0DACHJAgEAAAAB0QJAAN8DACHSAkAA3wMAIdQCAQDsAwAh1QIBAIMEACHWAgEAgwQAIdgCAACxBNgCI-oCIACSBAAhAgAAACcAIBoAAL8FACACAAAAvAUAIBoAAL0FACAMrQIAALsFADCuAgAAvAUAEK8CAAC7BQAwsgIQAN0DACHJAgEA7AMAIdECQADfAwAh0gJAAN8DACHUAgEA7AMAIdUCAQCDBAAh1gIBAIMEACHYAgAAsQTYAiPqAiAAkgQAIQytAgAAuwUAMK4CAAC8BQAQrwIAALsFADCyAhAA3QMAIckCAQDsAwAh0QJAAN8DACHSAkAA3wMAIdQCAQDsAwAh1QIBAIMEACHWAgEAgwQAIdgCAACxBNgCI-oCIACSBAAhCLICEADKBAAhyQIBAMkEACHRAkAAywQAIdICQADLBAAh1QIBANcEACHWAgEA1wQAIdgCAAC-BdgCI-oCIACKBQAhAZ8DAAAA2AIDCLICEADKBAAhyQIBAMkEACHRAkAAywQAIdICQADLBAAh1QIBANcEACHWAgEA1wQAIdgCAAC-BdgCI-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-BAAwrgIAAAsAEK8CAAC-BAAw0QJAAN8DACHTAgEA7AMAIfYCAQDcAwAh-AIAAL8E-AIimQMAAL0EACACAAAADQAgGgAA6wUAIAIAAADoBQAgGgAA6QUAIAetAgAA5wUAMK4CAADoBQAQrwIAAOcFADDRAkAA3wMAIdMCAQDsAwAh9gIBANwDACH4AgAAvwT4AiIHrQIAAOcFADCuAgAA6AUAEK8CAADnBQAw0QJAAN8DACHTAgEA7AMAIfYCAQDcAwAh-AIAAL8E-AIiA9ECQADLBAAh9gIBAMkEACH4AgAA6gX4AiIBnwMAAAD4AgIEAwAA7AUAINECQADLBAAh9gIBAMkEACH4AgAA6gX4AiIFIQAAtQcAICIAALgHACCcAwAAtgcAIJ0DAAC3BwAgogMAAAEAIAQDAADuBQAg0QJAAAAAAfYCAQAAAAH4AgAAAPgCAgMhAAC1BwAgnAMAALYHACCiAwAAAQAgDgkAAPAFACALAADxBQAgDAAA8gUAIBQAAPMFACDJAgEAAAAB0QJAAAAAAdICQAAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABBCEAAOAFADCcAwAA4QUAMJ4DAADjBQAgogMAAOQFADAEIQAA1AUAMJwDAADVBQAwngMAANcFACCiAwAA2AUAMAQhAAD_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-AIAAOoF-AIiBAoAALQGACDRAkAAywQAIdMCAQDJBAAh-AIAAOoF-AIiBAoAALUGACDRAkAAAAAB0wIBAAAAAfgCAAAA-AICDMkCAQAAAAHRAkAAAAAB0gJAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAYYDAQAAAAGHAwEAAAABiANAAAAAAYkDQAAAAAGKAwEAAAABiwMBAAAAAQIAAAAJACAhAADlBgAgAwAAAAkAICEAAOUGACAiAADkBgAgARoAAIUHADARAwAAwAQAIK0CAADBBAAwrgIAAAcAEK8CAADBBAAwyQIBAAAAAdECQADfAwAh0gJAAN8DACH2AgEA3AMAIYMDAQDcAwAhhAMBANwDACGFAwEAgwQAIYYDAQCDBAAhhwMBAIMEACGIA0AA7gMAIYkDQADuAwAhigMBAIMEACGLAwEAgwQAIQIAAAAJACAaAADkBgAgAgAAAOIGACAaAADjBgAgEK0CAADhBgAwrgIAAOIGABCvAgAA4QYAMMkCAQDcAwAh0QJAAN8DACHSAkAA3wMAIfYCAQDcAwAhgwMBANwDACGEAwEA3AMAIYUDAQCDBAAhhgMBAIMEACGHAwEAgwQAIYgDQADuAwAhiQNAAO4DACGKAwEAgwQAIYsDAQCDBAAhEK0CAADhBgAwrgIAAOIGABCvAgAA4QYAMMkCAQDcAwAh0QJAAN8DACHSAkAA3wMAIfYCAQDcAwAhgwMBANwDACGEAwEA3AMAIYUDAQCDBAAhhgMBAIMEACGHAwEAgwQAIYgDQADuAwAhiQNAAO4DACGKAwEAgwQAIYsDAQCDBAAhDMkCAQDJBAAh0QJAAMsEACHSAkAAywQAIYMDAQDJBAAhhAMBAMkEACGFAwEA1wQAIYYDAQDXBAAhhwMBANcEACGIA0AA6AQAIYkDQADoBAAhigMBANcEACGLAwEA1wQAIQzJAgEAyQQAIdECQADLBAAh0gJAAMsEACGDAwEAyQQAIYQDAQDJBAAhhQMBANcEACGGAwEA1wQAIYcDAQDXBAAhiANAAOgEACGJA0AA6AQAIYoDAQDXBAAhiwMBANcEACEMyQIBAAAAAdECQAAAAAHSAkAAAAABgwMBAAAAAYQDAQAAAAGFAwEAAAABhgMBAAAAAYcDAQAAAAGIA0AAAAABiQNAAAAAAYoDAQAAAAGLAwEAAAABDMkCAQAAAAHRAkAAAAAB0gJAAAAAAfMCQAAAAAH7AgEAAAAB_QIBAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAY8DAQAAAAGQAwgAAAABkQMIAAAAAQIAAAAFACAhAADxBgAgAwAAAAUAICEAAPEGACAiAADwBgAgARoAAIQHADARAwAAwAQAIK0CAADCBAAwrgIAAAMAEK8CAADCBAAwyQIBAAAAAdECQADfAwAh0gJAAN8DACHzAkAA3wMAIfYCAQDcAwAh-wIBAIMEACH9AgEAgwQAIYwDAQAAAAGNAwEAgwQAIY4DAQCDBAAhjwMBAIMEACGQAwgAwwQAIZEDCADDBAAhAgAAAAUAIBoAAPAGACACAAAA7gYAIBoAAO8GACAQrQIAAO0GADCuAgAA7gYAEK8CAADtBgAwyQIBANwDACHRAkAA3wMAIdICQADfAwAh8wJAAN8DACH2AgEA3AMAIfsCAQCDBAAh_QIBAIMEACGMAwEA3AMAIY0DAQCDBAAhjgMBAIMEACGPAwEAgwQAIZADCADDBAAhkQMIAMMEACEQrQIAAO0GADCuAgAA7gYAEK8CAADtBgAwyQIBANwDACHRAkAA3wMAIdICQADfAwAh8wJAAN8DACH2AgEA3AMAIfsCAQCDBAAh_QIBAIMEACGMAwEA3AMAIY0DAQCDBAAhjgMBAIMEACGPAwEAgwQAIZADCADDBAAhkQMIAMMEACEMyQIBAMkEACHRAkAAywQAIdICQADLBAAh8wJAAMsEACH7AgEA1wQAIf0CAQDXBAAhjAMBAMkEACGNAwEA1wQAIY4DAQDXBAAhjwMBANcEACGQAwgAyAYAIZEDCADIBgAhDMkCAQDJBAAh0QJAAMsEACHSAkAAywQAIfMCQADLBAAh-wIBANcEACH9AgEA1wQAIYwDAQDJBAAhjQMBANcEACGOAwEA1wQAIY8DAQDXBAAhkAMIAMgGACGRAwgAyAYAIQzJAgEAAAAB0QJAAAAAAdICQAAAAAHzAkAAAAAB-wIBAAAAAf0CAQAAAAGMAwEAAAABjQMBAAAAAY4DAQAAAAGPAwEAAAABkAMIAAAAAZEDCAAAAAEEIQAA5gYAMJwDAADnBgAwngMAAOkGACCiAwAA6gYAMAQhAADaBgAwnAMAANsGADCeAwAA3QYAIKIDAADeBgAwBCEAANEGADCcAwAA0gYAMJ4DAADUBgAgogMAAOQFADAAAAAICgAA-QYAIA0AAPwGACAPAAD9BgAgEAAA_gYAIBEAAPoGACATAAD_BgAgFAAAgAcAIPACAAD2BQAgCggAAIEHACAJAAD3BgAgCwAAggcAIAwAAKsGACAUAACABwAg-gIAAPYFACD7AgAA9gUAIPwCAAD2BQAg_QIAAPYFACCAAwAA9gUAIAAECgAA-QYAIA4AAPgGACARAAD6BgAg2gIAAPYFACABDAAAqwYAIAAAAAABBgAA9QUAIAAHBAAA9QYAIAUAAPYGACAGAAD3BgAgkwMAAPYFACCUAwAA9gUAIJYDAAD2BQAglwMAAPYFACAMyQIBAAAAAdECQAAAAAHSAkAAAAAB8wJAAAAAAfsCAQAAAAH9AgEAAAABjAMBAAAAAY0DAQAAAAGOAwEAAAABjwMBAAAAAZADCAAAAAGRAwgAAAABDMkCAQAAAAHRAkAAAAAB0gJAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAYYDAQAAAAGHAwEAAAABiANAAAAAAYkDQAAAAAGKAwEAAAABiwMBAAAAAQPRAkAAAAAB0wIBAAAAAfgCAAAA-AICDgUAAPMGACAGAAD0BgAgsQIBAAAAAckCAQAAAAHKAgEAAAAB0QJAAAAAAdICQAAAAAH4AgEAAAABkgMgAAAAAZMDAQAAAAGUAwEAAAABlQMgAAAAAZYDQAAAAAGXAwEAAAABAgAAAAEAICEAAIcHACADAAAARgAgIQAAhwcAICIAAIsHACAQAAAARgAgBQAAzwYAIAYAANAGACAaAACLBwAgsQIBAMkEACHJAgEAyQQAIcoCAQDJBAAh0QJAAMsEACHSAkAAywQAIfgCAQDJBAAhkgMgAIoFACGTAwEA1wQAIZQDAQDXBAAhlQMgAIoFACGWA0AA6AQAIZcDAQDXBAAhDgUAAM8GACAGAADQBgAgsQIBAMkEACHJAgEAyQQAIcoCAQDJBAAh0QJAAMsEACHSAkAAywQAIfgCAQDJBAAhkgMgAIoFACGTAwEA1wQAIZQDAQDXBAAhlQMgAIoFACGWA0AA6AQAIZcDAQDXBAAhDgQAAPIGACAGAAD0BgAgsQIBAAAAAckCAQAAAAHKAgEAAAAB0QJAAAAAAdICQAAAAAH4AgEAAAABkgMgAAAAAZMDAQAAAAGUAwEAAAABlQMgAAAAAZYDQAAAAAGXAwEAAAABAgAAAAEAICEAAIwHACADAAAARgAgIQAAjAcAICIAAJAHACAQAAAARgAgBAAAzgYAIAYAANAGACAaAACQBwAgsQIBAMkEACHJAgEAyQQAIcoCAQDJBAAh0QJAAMsEACHSAkAAywQAIfgCAQDJBAAhkgMgAIoFACGTAwEA1wQAIZQDAQDXBAAhlQMgAIoFACGWA0AA6AQAIZcDAQDXBAAhDgQAAM4GACAGAADQBgAgsQIBAMkEACHJAgEAyQQAIcoCAQDJBAAh0QJAAMsEACHSAkAAywQAIfgCAQDJBAAhkgMgAIoFACGTAwEA1wQAIZQDAQDXBAAhlQMgAIoFACGWA0AA6AQAIZcDAQDXBAAhBbACAQAAAAGxAgEAAAABsgIQAAAAAbMCgAAAAAG0AkAAAAABAgAAALYDACAhAACRBwAgAwAAAA8AICEAAJEHACAiAACVBwAgBwAAAA8AIBoAAJUHACCwAgEAyQQAIbECAQDJBAAhsgIQAMoEACGzAoAAAAABtAJAAMsEACEFsAIBAMkEACGxAgEAyQQAIbICEADKBAAhswKAAAAAAbQCQADLBAAhDwgAALoGACALAADxBQAgDAAA8gUAIBQAAPMFACDJAgEAAAAB0QJAAAAAAdICQAAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgAMBAAAAAQIAAAATACAhAACWBwAgAwAAABEAICEAAJYHACAiAACaBwAgEQAAABEAIAgAALkGACALAADaBAAgDAAA2wQAIBQAANwEACAaAACaBwAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh-QIBAMkEACH6AgEA1wQAIfsCAQDXBAAh_AIBANcEACH9AgEA1wQAIf4CAQDJBAAh_wIBAMkEACGAAwEA1wQAIQ8IAAC5BgAgCwAA2gQAIAwAANsEACAUAADcBAAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh-QIBAMkEACH6AgEA1wQAIfsCAQDXBAAh_AIBANcEACH9AgEA1wQAIf4CAQDJBAAh_wIBAMkEACGAAwEA1wQAIQ8IAAC6BgAgCQAA8AUAIAwAAPIFACAUAADzBQAgyQIBAAAAAdECQAAAAAHSAkAAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADAQAAAAECAAAAEwAgIQAAmwcAIAMAAAARACAhAACbBwAgIgAAnwcAIBEAAAARACAIAAC5BgAgCQAA2QQAIAwAANsEACAUAADcBAAgGgAAnwcAIMkCAQDJBAAh0QJAAMsEACHSAkAAywQAIfkCAQDJBAAh-gIBANcEACH7AgEA1wQAIfwCAQDXBAAh_QIBANcEACH-AgEAyQQAIf8CAQDJBAAhgAMBANcEACEPCAAAuQYAIAkAANkEACAMAADbBAAgFAAA3AQAIMkCAQDJBAAh0QJAAMsEACHSAkAAywQAIfkCAQDJBAAh-gIBANcEACH7AgEA1wQAIfwCAQDXBAAh_QIBANcEACH-AgEAyQQAIf8CAQDJBAAhgAMBANcEACEJsQIBAAAAAckCAQAAAAHRAkAAAAAB0gJAAAAAAdMCAQAAAAHtAgIAAAAB7gIQAAAAAe8CIAAAAAHwAgEAAAABDwgAALoGACAJAADwBQAgCwAA8QUAIBQAAPMFACDJAgEAAAAB0QJAAAAAAdICQAAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgAMBAAAAAQIAAAATACAhAAChBwAgAwAAABEAICEAAKEHACAiAAClBwAgEQAAABEAIAgAALkGACAJAADZBAAgCwAA2gQAIBQAANwEACAaAAClBwAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh-QIBAMkEACH6AgEA1wQAIfsCAQDXBAAh_AIBANcEACH9AgEA1wQAIf4CAQDJBAAh_wIBAMkEACGAAwEA1wQAIQ8IAAC5BgAgCQAA2QQAIAsAANoEACAUAADcBAAgyQIBAMkEACHRAkAAywQAIdICQADLBAAh-QIBAMkEACH6AgEA1wQAIfsCAQDXBAAh_AIBANcEACH9AgEA1wQAIf4CAQDJBAAh_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-wIBAAAAAfwCAQAAAAH9AgEAAAAB_gIBAAAAAf8CAQAAAAGAAwEAAAABAgAAABMAICEAAMcHACADAAAAEQAgIQAAxwcAICIAAMsHACARAAAAEQAgCAAAuQYAIAkAANkEACALAADaBAAgDAAA2wQAIBoAAMsHACDJAgEAyQQAIdECQADLBAAh0gJAAMsEACH5AgEAyQQAIfoCAQDXBAAh-wIBANcEACH8AgEA1wQAIf0CAQDXBAAh_gIBAMkEACH_AgEAyQQAIYADAQDXBAAhDwgAALkGACAJAADZBAAgCwAA2gQAIAwAANsEACDJAgEAyQQAIdECQADLBAAh0gJAAMsEACH5AgEAyQQAIfoCAQDXBAAh-wIBANcEACH8AgEA1wQAIf0CAQDXBAAh_gIBAMkEACH_AgEAyQQAIYADAQDXBAAhDckCAQAAAAHRAkAAAAAB0gJAAAAAAdMCAQAAAAHVAgEAAAAB1gIBAAAAAdgCAAAA2AIC2QJAAAAAAdoCQAAAAAHcAgAAANwCAt0CAQAAAAHeAgEAAAAB3wIBAAAAAQMAAADoAQAgIQAAvAcAICIAAM8HACAIAAAA6AEAIBoAAM8HACCxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIeoCIACKBQAh8QIBAMkEACEGsQIBAMkEACHJAgEAyQQAIdECQADLBAAh0gJAAMsEACHqAiAAigUAIfECAQDJBAAhCbECAQAAAAHJAgEAAAAB0QJAAAAAAdICQAAAAAHsAgEAAAAB7QICAAAAAe4CEAAAAAHvAiAAAAAB8AIBAAAAARAKAACcBgAgDQAAzgUAIA8AAM8FACAQAADQBQAgEQAA0QUAIBMAANIFACCxAgEAAAAByQIBAAAAAdECQAAAAAHSAkAAAAAB0wIBAAAAAewCAQAAAAHtAgIAAAAB7gIQAAAAAe8CIAAAAAHwAgEAAAABAgAAAB0AICEAANEHACAQCgAAnAYAIA0AAM4FACAPAADPBQAgEAAA0AUAIBMAANIFACAUAADTBQAgsQIBAAAAAckCAQAAAAHRAkAAAAAB0gJAAAAAAdMCAQAAAAHsAgEAAAAB7QICAAAAAe4CEAAAAAHvAiAAAAAB8AIBAAAAAQIAAAAdACAhAADTBwAgAwAAABsAICEAANMHACAiAADXBwAgEgAAABsAIAoAAJsGACANAACMBQAgDwAAjQUAIBAAAI4FACATAACQBQAgFAAAkQUAIBoAANcHACCxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIdMCAQDJBAAh7AIBAMkEACHtAgIAiQUAIe4CEADKBAAh7wIgAIoFACHwAgEA1wQAIRAKAACbBgAgDQAAjAUAIA8AAI0FACAQAACOBQAgEwAAkAUAIBQAAJEFACCxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIdMCAQDJBAAh7AIBAMkEACHtAgIAiQUAIe4CEADKBAAh7wIgAIoFACHwAgEA1wQAIQzJAgEAAAAB0QJAAAAAAdICQAAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHcAgAAAOMCAt0CAQAAAAHeAgEAAAAB3wIBAAAAAeACAQAAAAHhAkAAAAABAwAAABsAICEAANEHACAiAADbBwAgEgAAABsAIAoAAJsGACANAACMBQAgDwAAjQUAIBAAAI4FACARAACPBQAgEwAAkAUAIBoAANsHACCxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIdMCAQDJBAAh7AIBAMkEACHtAgIAiQUAIe4CEADKBAAh7wIgAIoFACHwAgEA1wQAIRAKAACbBgAgDQAAjAUAIA8AAI0FACAQAACOBQAgEQAAjwUAIBMAAJAFACCxAgEAyQQAIckCAQDJBAAh0QJAAMsEACHSAkAAywQAIdMCAQDJBAAh7AIBAMkEACHtAgIAiQUAIe4CEADKBAAh7wIgAIoFACHwAgEA1wQAIQ3JAgEAAAAB0QJAAAAAAdICQAAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHYAgAAANgCAtkCQAAAAAHaAkAAAAAB3AIAAADcAgLdAgEAAAAB3gIBAAAAAd8CAQAAAAEKyQIBAAAAAdECQAAAAAHSAkAAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAQQEBgIFCgMGDgQHABQBAwABAQMAAQIDAAEKAAUGBwATCBAGCRYECxoIDB4JFD0PAgYUBQcABwEGFQABCgAFCAcAEgoABQ0ACg8kDBAoDREsDhM0ERQ3DwIHAAsMHwkBDCAAAQ4ACQEOAAkCDgAJEi4PBAcAEAoABQ4ACREvDgERMAABDgAJBQ84ABA5ABE6ABM7ABQ8AAQJPgALPwAMQAAUQQADBEIABUMABkQAAAAAAwcAGScAGigAGwAAAAMHABknABooABsBAwABAQMAAQUHACAnACMoACQ5ACE6ACIAAAAAAAUHACAnACMoACQ5ACE6ACIBAwABAQMAAQMHACknACooACsAAAADBwApJwAqKAArAAAAAwcAMScAMigAMwAAAAMHADEnADIoADMBCKsBBgEIsQEGAwcAOCcAOSgAOgAAAAMHADgnADkoADoCAwABCgAFAgMAAQoABQMHAD8nAEAoAEEAAAADBwA_JwBAKABBAQoABQEKAAUDBwBGJwBHKABIAAAAAwcARicARygASAAAAwcATScATigATwAAAAMHAE0nAE4oAE8CCgAFDQAKAgoABQ0ACgUHAFQnAFcoAFg5AFU6AFYAAAAAAAUHAFQnAFcoAFg5AFU6AFYBDgAJAQ4ACQMHAF0nAF4oAF8AAAADBwBdJwBeKABfAQ4ACQEOAAkDBwBkJwBlKABmAAAAAwcAZCcAZSgAZgEOAAkBDgAJBQcAaycAbigAbzkAbDoAbQAAAAAABQcAaycAbigAbzkAbDoAbQIOAAkS4AIPAg4ACRLmAg8DBwB0JwB1KAB2AAAAAwcAdCcAdSgAdgAAAAMHAHwnAH0oAH4AAAADBwB8JwB9KAB-AgoABQ4ACQIKAAUOAAkDBwCDAScAhAEoAIUBAAAAAwcAgwEnAIQBKACFAQAAAAUHAIsBJwCOASgAjwE5AIwBOgCNAQAAAAAABQcAiwEnAI4BKACPATkAjAE6AI0BAAAFBwCUAScAlwEoAJgBOQCVAToAlgEAAAAAAAUHAJQBJwCXASgAmAE5AJUBOgCWARUCARZFARdIARhJARlKARtMARxOFR1PFh5RAR9TFSBUFyNVASRWASVXFSlaGCpbHCtcAixdAi1eAi5fAi9gAjBiAjFkFTJlHTNnAjRpFTVqHjZrAjdsAjhtFTtwHzxxJT1yAz5zAz90A0B1A0F2A0J4A0N6FUR7JkV9A0Z_FUeAASdIgQEDSYIBA0qDARVLhgEoTIcBLE2JAS1OigEtT40BLVCOAS1RjwEtUpEBLVOTARVUlAEuVZYBLVaYARVXmQEvWJoBLVmbAS1anAEVW58BMFygATRdoQEFXqIBBV-jAQVgpAEFYaUBBWKnAQVjqQEVZKoBNWWtAQVmrwEVZ7ABNmiyAQVpswEFarQBFWu3ATdsuAE7bbkBBG66AQRvuwEEcLwBBHG9AQRyvwEEc8EBFXTCATx1xAEEdsYBFXfHAT14yAEEeckBBHrKARV7zQE-fM4BQn3PAQh-0AEIf9EBCIAB0gEIgQHTAQiCAdUBCIMB1wEVhAHYAUOFAdoBCIYB3AEVhwHdAUSIAd4BCIkB3wEIigHgARWLAeMBRYwB5AFJjQHmAQqOAecBCo8B6gEKkAHrAQqRAewBCpIB7gEKkwHwARWUAfEBSpUB8wEKlgH1ARWXAfYBS5gB9wEKmQH4AQqaAfkBFZsB_AFMnAH9AVCdAf4BCZ4B_wEJnwGAAgmgAYECCaEBggIJogGEAgmjAYYCFaQBhwJRpQGJAgmmAYsCFacBjAJSqAGNAgmpAY4CCaoBjwIVqwGSAlOsAZMCWa0BlAIRrgGVAhGvAZYCEbABlwIRsQGYAhGyAZoCEbMBnAIVtAGdAlq1AZ8CEbYBoQIVtwGiAlu4AaMCEbkBpAIRugGlAhW7AagCXLwBqQJgvQGqAgy-AasCDL8BrAIMwAGtAgzBAa4CDMIBsAIMwwGyAhXEAbMCYcUBtQIMxgG3AhXHAbgCYsgBuQIMyQG6AgzKAbsCFcsBvgJjzAG_AmfNAcACDc4BwQINzwHCAg3QAcMCDdEBxAIN0gHGAg3TAcgCFdQByQJo1QHLAg3WAc0CFdcBzgJp2AHPAg3ZAdACDdoB0QIV2wHUAmrcAdUCcN0B1gIO3gHXAg7fAdgCDuAB2QIO4QHaAg7iAdwCDuMB3gIV5AHfAnHlAeICDuYB5AIV5wHlAnLoAecCDukB6AIO6gHpAhXrAewCc-wB7QJ37QHvAnjuAfACeO8B8wJ48AH0AnjxAfUCePIB9wJ48wH5AhX0AfoCefUB_AJ49gH-AhX3Af8CevgBgAN4-QGBA3j6AYIDFfsBhQN7_AGGA3_9AYcDD_4BiAMP_wGJAw-AAooDD4ECiwMPggKNAw-DAo8DFYQCkAOAAYUCkgMPhgKUAxWHApUDgQGIApYDD4kClwMPigKYAxWLApsDggGMApwDhgGNAp4DhwGOAp8DhwGPAqIDhwGQAqMDhwGRAqQDhwGSAqYDhwGTAqgDFZQCqQOIAZUCqwOHAZYCrQMVlwKuA4kBmAKvA4cBmQKwA4cBmgKxAxWbArQDigGcArUDkAGdArcDBp4CuAMGnwK6AwagArsDBqECvAMGogK-AwajAsADFaQCwQORAaUCwwMGpgLFAxWnAsYDkgGoAscDBqkCyAMGqgLJAxWrAswDkwGsAs0DmQE" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"sessions\",\"accounts\",\"complexes\",\"_count\",\"plan\",\"users\",\"complex\",\"invitations\",\"courts\",\"sport\",\"court\",\"availabilities\",\"priceRules\",\"bookings\",\"recurringGroup\",\"maintenances\",\"recurringGroups\",\"billing\",\"events\",\"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\",\"_avg\",\"_sum\",\"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\",\"ComplexBilling.findUnique\",\"ComplexBilling.findUniqueOrThrow\",\"ComplexBilling.findFirst\",\"ComplexBilling.findFirstOrThrow\",\"ComplexBilling.findMany\",\"ComplexBilling.createOne\",\"ComplexBilling.createMany\",\"ComplexBilling.createManyAndReturn\",\"ComplexBilling.updateOne\",\"ComplexBilling.updateMany\",\"ComplexBilling.updateManyAndReturn\",\"ComplexBilling.upsertOne\",\"ComplexBilling.deleteOne\",\"ComplexBilling.deleteMany\",\"ComplexBilling.groupBy\",\"ComplexBilling.aggregate\",\"BillingEvent.findUnique\",\"BillingEvent.findUniqueOrThrow\",\"BillingEvent.findFirst\",\"BillingEvent.findFirstOrThrow\",\"BillingEvent.findMany\",\"BillingEvent.createOne\",\"BillingEvent.createMany\",\"BillingEvent.createManyAndReturn\",\"BillingEvent.updateOne\",\"BillingEvent.updateMany\",\"BillingEvent.updateManyAndReturn\",\"BillingEvent.upsertOne\",\"BillingEvent.deleteOne\",\"BillingEvent.deleteMany\",\"BillingEvent.groupBy\",\"BillingEvent.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\",\"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\",\"RecurringBookingGroup.findUnique\",\"RecurringBookingGroup.findUniqueOrThrow\",\"RecurringBookingGroup.findFirst\",\"RecurringBookingGroup.findFirstOrThrow\",\"RecurringBookingGroup.findMany\",\"RecurringBookingGroup.createOne\",\"RecurringBookingGroup.createMany\",\"RecurringBookingGroup.createManyAndReturn\",\"RecurringBookingGroup.updateOne\",\"RecurringBookingGroup.updateMany\",\"RecurringBookingGroup.updateManyAndReturn\",\"RecurringBookingGroup.upsertOne\",\"RecurringBookingGroup.deleteOne\",\"RecurringBookingGroup.deleteMany\",\"RecurringBookingGroup.groupBy\",\"RecurringBookingGroup.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\",\"complexId\",\"courtId\",\"startTime\",\"endTime\",\"DayOfWeek\",\"dayOfWeek\",\"startDate\",\"endDate\",\"RecurringBookingGroupStatus\",\"status\",\"customerName\",\"customerPhone\",\"customerEmail\",\"bookingCode\",\"bookingDate\",\"CourtBookingStatus\",\"previousStatus\",\"newStatus\",\"previousCourtId\",\"previousStartTime\",\"previousEndTime\",\"changedAt\",\"recurringGroupId\",\"isActive\",\"reason\",\"sportId\",\"slotDurationMinutes\",\"basePrice\",\"isUnderMaintenance\",\"maintenanceReason\",\"slug\",\"tokenHash\",\"expiresAt\",\"acceptedAt\",\"revokedAt\",\"userId\",\"ComplexUserRole\",\"role\",\"complexName\",\"physicalAddress\",\"city\",\"state\",\"country\",\"complexSlug\",\"adminEmail\",\"planCode\",\"eventType\",\"BillingProvider\",\"provider\",\"providerEventId\",\"providerData\",\"BillingStatus\",\"processedAt\",\"currency\",\"providerCustomerId\",\"providerSubscriptionId\",\"providerPreapprovalId\",\"currentPeriodStart\",\"currentPeriodEnd\",\"trialEndsAt\",\"canceledAt\",\"suspendedAt\",\"identifier\",\"value\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"idToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"password\",\"token\",\"ipAddress\",\"userAgent\",\"countryCode\",\"latitude\",\"longitude\",\"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: "3AiqAbACEgQAAO0EACAFAADuBAAgBgAA7wQAIM8CAADsBAAw0AIAAE0AENECAADsBAAw0wIBAJEEACHrAgEAAAAB7AIBAAAAAfMCQACUBAAh9AJAAJQEACGaAwEAkQQAIcQDIADHBAAhxQMBALgEACHGAwEAuAQAIccDIADHBAAhyANAAKMEACHJAwEAuAQAIQEAAAABACARAwAAjwUAIM8CAACRBQAw0AIAAAMAENECAACRBQAw6wIBAJEEACHzAkAAlAQAIfQCQACUBAAhlQNAAJQEACGYAwEAkQQAIZ0DAQC4BAAhnwMBALgEACG-AwEAkQQAIb8DAQC4BAAhwAMBALgEACHBAwEAuAQAIcIDCACSBQAhwwMIAJIFACEIAwAA9wcAIJ0DAADeBgAgnwMAAN4GACC_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-gIAAPYE-gIiAQ4AAO0HACAKDgAA-AQAIM8CAACABQAw0AIAACEAENECAACABQAw6wIBAAAAAfMCQACUBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh-gIAAPYE-gIiAwAAACEAIAEAACIAMAIAACMAIA0OAAD4BAAgzwIAAP4EADDQAgAAJQAQ0QIAAP4EADDUAhAAkgQAIesCAQChBAAh8wJAAJQEACH0AkAAlAQAIfYCAQChBAAh9wIBALgEACH4AgEAuAQAIfoCAAD_BPoCI4wDIADHBAAhBA4AAO0HACD3AgAA3gYAIPgCAADeBgAg-gIAAN4GACANDgAA-AQAIM8CAAD-BAAw0AIAACUAENECAAD-BAAw1AIQAJIEACHrAgEAAAAB8wJAAJQEACH0AkAAlAQAIfYCAQChBAAh9wIBALgEACH4AgEAuAQAIfoCAAD_BPoCI4wDIADHBAAhAwAAACUAIAEAACYAMAIAACcAIBIOAAD4BAAgEgAA_QQAIM8CAAD8BAAw0AIAACkAENECAAD8BAAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh_gIAALYEhQMi_wIBAJEEACGAAwEAkQQAIYEDAQCRBAAhggMBAJEEACGDA0AAlAQAIYsDAQC3BAAhAw4AAO0HACASAADvBwAgiwMAAN4GACATDgAA-AQAIBIAAP0EACDPAgAA_AQAMNACAAApABDRAgAA_AQAMOsCAQAAAAHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh_gIAALYEhQMi_wIBAJEEACGAAwEAkQQAIYEDAQCRBAAhggMBAAAAAYMDQACUBAAhiwMBALcEACHKAwAA-wQAIAMAAAApACABAAAqADACAAArACAUCgAA4gQAIA4AAPgEACARAAD5BAAgzwIAAPUEADDQAgAALQAQ0QIAAPUEADDrAgEAoQQAIfMCQACUBAAh9AJAAJQEACH1AgEAoQQAIfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIfoCAAD2BPoCIvsCQACUBAAh_AJAAKMEACH-AgAA9wT-AiL_AgEAkQQAIYADAQCRBAAhgQMBAJEEACEBAAAALQAgAwAAACkAIAEAACoAMAIAACsAIAEAAAApACAMDgAA-AQAIM8CAAD6BAAw0AIAADEAENECAAD6BAAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-wJAAJQEACGNAwEAuAQAIQQOAADtBwAg9wIAAN4GACD4AgAA3gYAII0DAADeBgAgDA4AAPgEACDPAgAA-gQAMNACAAAxABDRAgAA-gQAMOsCAQAAAAHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-wJAAJQEACGNAwEAuAQAIQMAAAAxACABAAAyADACAAAzACAECgAArQcAIA4AAO0HACARAADuBwAg_AIAAN4GACAUCgAA4gQAIA4AAPgEACARAAD5BAAgzwIAAPUEADDQAgAALQAQ0QIAAPUEADDrAgEAAAAB8wJAAJQEACH0AkAAlAQAIfUCAQChBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh-gIAAPYE-gIi-wJAAJQEACH8AkAAowQAIf4CAAD3BP4CIv8CAQCRBAAhgAMBAJEEACGBAwEAkQQAIQMAAAAtACABAAA1ADACAAA2ACABAAAAIQAgAQAAACUAIAEAAAApACABAAAAMQAgAQAAAC0AIAMAAAAtACABAAA1ADACAAA2ACAUCgAA4gQAIBYAAOMEACDPAgAA3wQAMNACAAA-ABDRAgAA3wQAMPMCQACUBAAh9AJAAJQEACH1AgEAoQQAIf4CAADgBKkDIqIDAQCRBAAhpQMAAOEEpQMjqgMBAJEEACGrAwEAuAQAIawDAQC4BAAhrQMBALgEACGuA0AAowQAIa8DQACjBAAhsANAAKMEACGxA0AAowQAIbIDQACjBAAhAQAAAD4AIA0VAAD0BAAgzwIAAPAEADDQAgAAQAAQ0QIAAPAEADDrAgEAoQQAIfUCAQChBAAhhQMAAPMEqQMjhgMAAPMEqQMjowMBAJEEACGlAwAA8QSlAyKmAwEAuAQAIacDAADyBAAgqQNAAJQEACEFFQAA7AcAIIUDAADeBgAghgMAAN4GACCmAwAA3gYAIKcDAADeBgAgDRUAAPQEACDPAgAA8AQAMNACAABAABDRAgAA8AQAMOsCAQAAAAH1AgEAoQQAIYUDAADzBKkDI4YDAADzBKkDI6MDAQCRBAAhpQMAAPEEpQMipgMBAAAAAacDAADyBAAgqQNAAJQEACEDAAAAQAAgAQAAQQAwAgAAQgAgAQAAAEAAIAEAAAALACABAAAAFwAgAQAAABsAIAEAAAAtACABAAAAAwAgAQAAAAcAIAEAAAALACABAAAAAQAgEgQAAO0EACAFAADuBAAgBgAA7wQAIM8CAADsBAAw0AIAAE0AENECAADsBAAw0wIBAJEEACHrAgEAkQQAIewCAQCRBAAh8wJAAJQEACH0AkAAlAQAIZoDAQCRBAAhxAMgAMcEACHFAwEAuAQAIcYDAQC4BAAhxwMgAMcEACHIA0AAowQAIckDAQC4BAAhBwQAAOkHACAFAADqBwAgBgAA6wcAIMUDAADeBgAgxgMAAN4GACDIAwAA3gYAIMkDAADeBgAgAwAAAE0AIAEAAE4AMAIAAAEAIAMAAABNACABAABOADACAAABACADAAAATQAgAQAATgAwAgAAAQAgDwQAAOYHACAFAADnBwAgBgAA6AcAINMCAQAAAAHrAgEAAAAB7AIBAAAAAfMCQAAAAAH0AkAAAAABmgMBAAAAAcQDIAAAAAHFAwEAAAABxgMBAAAAAccDIAAAAAHIA0AAAAAByQMBAAAAAQEcAABSACAM0wIBAAAAAesCAQAAAAHsAgEAAAAB8wJAAAAAAfQCQAAAAAGaAwEAAAABxAMgAAAAAcUDAQAAAAHGAwEAAAABxwMgAAAAAcgDQAAAAAHJAwEAAAABARwAAFQAMAEcAABUADAPBAAAwgcAIAUAAMMHACAGAADEBwAg0wIBAJgFACHrAgEAmAUAIewCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZoDAQCYBQAhxAMgAPEFACHFAwEApgUAIcYDAQCmBQAhxwMgAPEFACHIA0AAtAUAIckDAQCmBQAhAgAAAAEAIBwAAFcAIAzTAgEAmAUAIesCAQCYBQAh7AIBAJgFACHzAkAAmgUAIfQCQACaBQAhmgMBAJgFACHEAyAA8QUAIcUDAQCmBQAhxgMBAKYFACHHAyAA8QUAIcgDQAC0BQAhyQMBAKYFACECAAAATQAgHAAAWQAgAgAAAE0AIBwAAFkAIAMAAAABACAjAABSACAkAABXACABAAAAAQAgAQAAAE0AIAcHAAC_BwAgKQAAwQcAICoAAMAHACDFAwAA3gYAIMYDAADeBgAgyAMAAN4GACDJAwAA3gYAIA_PAgAA6wQAMNACAABgABDRAgAA6wQAMNMCAQCEBAAh6wIBAIQEACHsAgEAhAQAIfMCQACHBAAh9AJAAIcEACGaAwEAhAQAIcQDIAC9BAAhxQMBAK8EACHGAwEArwQAIccDIAC9BAAhyANAAJkEACHJAwEArwQAIQMAAABNACABAABfADAoAABgACADAAAATQAgAQAATgAwAgAAAQAgAQAAAAUAIAEAAAAFACADAAAAAwAgAQAABAAwAgAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACAOAwAAvgcAIOsCAQAAAAHzAkAAAAAB9AJAAAAAAZUDQAAAAAGYAwEAAAABnQMBAAAAAZ8DAQAAAAG-AwEAAAABvwMBAAAAAcADAQAAAAHBAwEAAAABwgMIAAAAAcMDCAAAAAEBHAAAaAAgDesCAQAAAAHzAkAAAAAB9AJAAAAAAZUDQAAAAAGYAwEAAAABnQMBAAAAAZ8DAQAAAAG-AwEAAAABvwMBAAAAAcADAQAAAAHBAwEAAAABwgMIAAAAAcMDCAAAAAEBHAAAagAwARwAAGoAMA4DAAC9BwAg6wIBAJgFACHzAkAAmgUAIfQCQACaBQAhlQNAAJoFACGYAwEAmAUAIZ0DAQCmBQAhnwMBAKYFACG-AwEAmAUAIb8DAQCmBQAhwAMBAKYFACHBAwEApgUAIcIDCAC8BwAhwwMIALwHACECAAAABQAgHAAAbQAgDesCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZUDQACaBQAhmAMBAJgFACGdAwEApgUAIZ8DAQCmBQAhvgMBAJgFACG_AwEApgUAIcADAQCmBQAhwQMBAKYFACHCAwgAvAcAIcMDCAC8BwAhAgAAAAMAIBwAAG8AIAIAAAADACAcAABvACADAAAABQAgIwAAaAAgJAAAbQAgAQAAAAUAIAEAAAADACAMBwAAtwcAICkAALoHACAqAAC5BwAgOwAAuAcAIDwAALsHACCdAwAA3gYAIJ8DAADeBgAgvwMAAN4GACDAAwAA3gYAIMEDAADeBgAgwgMAAN4GACDDAwAA3gYAIBDPAgAA5wQAMNACAAB2ABDRAgAA5wQAMOsCAQCEBAAh8wJAAIcEACH0AkAAhwQAIZUDQACHBAAhmAMBAIQEACGdAwEArwQAIZ8DAQCvBAAhvgMBAIQEACG_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-ACABAACrAQAwAgAAqAEAIAMAAAA-ACABAACrAQAwAgAAqAEAIAMAAAA-ACABAACrAQAwAgAAqAEAIBEKAACsBwAgFgAAxAUAIPMCQAAAAAH0AkAAAAAB9QIBAAAAAf4CAAAAqQMCogMBAAAAAaUDAAAApQMDqgMBAAAAAasDAQAAAAGsAwEAAAABrQMBAAAAAa4DQAAAAAGvA0AAAAABsANAAAAAAbEDQAAAAAGyA0AAAAABARwAAK8BACAP8wJAAAAAAfQCQAAAAAH1AgEAAAAB_gIAAACpAwKiAwEAAAABpQMAAAClAwOqAwEAAAABqwMBAAAAAawDAQAAAAGtAwEAAAABrgNAAAAAAa8DQAAAAAGwA0AAAAABsQNAAAAAAbIDQAAAAAEBHAAAsQEAMAEcAACxAQAwEQoAAKsHACAWAAC1BQAg8wJAAJoFACH0AkAAmgUAIfUCAQCYBQAh_gIAALIFqQMiogMBAJgFACGlAwAAswWlAyOqAwEAmAUAIasDAQCmBQAhrAMBAKYFACGtAwEApgUAIa4DQAC0BQAhrwNAALQFACGwA0AAtAUAIbEDQAC0BQAhsgNAALQFACECAAAAqAEAIBwAALQBACAP8wJAAJoFACH0AkAAmgUAIfUCAQCYBQAh_gIAALIFqQMiogMBAJgFACGlAwAAswWlAyOqAwEAmAUAIasDAQCmBQAhrAMBAKYFACGtAwEApgUAIa4DQAC0BQAhrwNAALQFACGwA0AAtAUAIbEDQAC0BQAhsgNAALQFACECAAAAPgAgHAAAtgEAIAIAAAA-ACAcAAC2AQAgAwAAAKgBACAjAACvAQAgJAAAtAEAIAEAAACoAQAgAQAAAD4AIAwHAACoBwAgKQAAqgcAICoAAKkHACClAwAA3gYAIKsDAADeBgAgrAMAAN4GACCtAwAA3gYAIK4DAADeBgAgrwMAAN4GACCwAwAA3gYAILEDAADeBgAgsgMAAN4GACASzwIAANgEADDQAgAAvQEAENECAADYBAAw8wJAAIcEACH0AkAAhwQAIfUCAQCXBAAh_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_AgAgAwAAAB0AICMAALgCACAkAAC9AgAgAQAAAB0AIAEAAAAbACAGBwAA_gYAICkAAIEHACAqAACABwAgOwAA_wYAIDwAAIIHACCSAwAA3gYAIA3PAgAAxAQAMNACAADGAgAQ0QIAAMQEADDTAgEAhAQAIesCAQCXBAAh8wJAAIcEACH0AkAAhwQAIfUCAQCXBAAhjgMBAJcEACGPAwIAmAQAIZADEACFBAAhkQMgAL0EACGSAwEArwQAIQMAAAAbACABAADFAgAwKAAAxgIAIAMAAAAbACABAAAcADACAAAdACABAAAAMwAgAQAAADMAIAMAAAAxACABAAAyADACAAAzACADAAAAMQAgAQAAMgAwAgAAMwAgAwAAADEAIAEAADIAMAIAADMAIAkOAAD9BgAg6wIBAAAAAfMCQAAAAAH0AkAAAAAB9gIBAAAAAfcCAQAAAAH4AgEAAAAB-wJAAAAAAY0DAQAAAAEBHAAAzgIAIAjrAgEAAAAB8wJAAAAAAfQCQAAAAAH2AgEAAAAB9wIBAAAAAfgCAQAAAAH7AkAAAAABjQMBAAAAAQEcAADQAgAwARwAANACADAJDgAA_AYAIOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfYCAQCYBQAh9wIBAKYFACH4AgEApgUAIfsCQACaBQAhjQMBAKYFACECAAAAMwAgHAAA0wIAIAjrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH2AgEAmAUAIfcCAQCmBQAh-AIBAKYFACH7AkAAmgUAIY0DAQCmBQAhAgAAADEAIBwAANUCACACAAAAMQAgHAAA1QIAIAMAAAAzACAjAADOAgAgJAAA0wIAIAEAAAAzACABAAAAMQAgBgcAAPkGACApAAD7BgAgKgAA-gYAIPcCAADeBgAg-AIAAN4GACCNAwAA3gYAIAvPAgAAwwQAMNACAADcAgAQ0QIAAMMEADDrAgEAlwQAIfMCQACHBAAh9AJAAIcEACH2AgEAlwQAIfcCAQCvBAAh-AIBAK8EACH7AkAAhwQAIY0DAQCvBAAhAwAAADEAIAEAANsCADAoAADcAgAgAwAAADEAIAEAADIAMAIAADMAIAEAAAAjACABAAAAIwAgAwAAACEAIAEAACIAMAIAACMAIAMAAAAhACABAAAiADACAAAjACADAAAAIQAgAQAAIgAwAgAAIwAgBw4AAPgGACDrAgEAAAAB8wJAAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAfoCAAAA-gICARwAAOQCACAG6wIBAAAAAfMCQAAAAAH2AgEAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCAgEcAADmAgAwARwAAOYCADAHDgAA9wYAIOsCAQCYBQAh8wJAAJoFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH6AgAAzwX6AiICAAAAIwAgHAAA6QIAIAbrAgEAmAUAIfMCQACaBQAh9gIBAJgFACH3AgEAmAUAIfgCAQCYBQAh-gIAAM8F-gIiAgAAACEAIBwAAOsCACACAAAAIQAgHAAA6wIAIAMAAAAjACAjAADkAgAgJAAA6QIAIAEAAAAjACABAAAAIQAgAwcAAPQGACApAAD2BgAgKgAA9QYAIAnPAgAAwgQAMNACAADyAgAQ0QIAAMIEADDrAgEAlwQAIfMCQACHBAAh9gIBAJcEACH3AgEAhAQAIfgCAQCEBAAh-gIAAKYE-gIiAwAAACEAIAEAAPECADAoAADyAgAgAwAAACEAIAEAACIAMAIAACMAIAEAAAAnACABAAAAJwAgAwAAACUAIAEAACYAMAIAACcAIAMAAAAlACABAAAmADACAAAnACADAAAAJQAgAQAAJgAwAgAAJwAgCg4AAPMGACDUAhAAAAAB6wIBAAAAAfMCQAAAAAH0AkAAAAAB9gIBAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgOMAyAAAAABARwAAPoCACAJ1AIQAAAAAesCAQAAAAHzAkAAAAAB9AJAAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAfoCAAAA-gIDjAMgAAAAAQEcAAD8AgAwARwAAPwCADAKDgAA8gYAINQCEACZBQAh6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9gIBAJgFACH3AgEApgUAIfgCAQCmBQAh-gIAAKUG-gIjjAMgAPEFACECAAAAJwAgHAAA_wIAIAnUAhAAmQUAIesCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfYCAQCYBQAh9wIBAKYFACH4AgEApgUAIfoCAAClBvoCI4wDIADxBQAhAgAAACUAIBwAAIEDACACAAAAJQAgHAAAgQMAIAMAAAAnACAjAAD6AgAgJAAA_wIAIAEAAAAnACABAAAAJQAgCAcAAO0GACApAADwBgAgKgAA7wYAIDsAAO4GACA8AADxBgAg9wIAAN4GACD4AgAA3gYAIPoCAADeBgAgDM8CAAC7BAAw0AIAAIgDABDRAgAAuwQAMNQCEACFBAAh6wIBAJcEACHzAkAAhwQAIfQCQACHBAAh9gIBAJcEACH3AgEArwQAIfgCAQCvBAAh-gIAALwE-gIjjAMgAL0EACEDAAAAJQAgAQAAhwMAMCgAAIgDACADAAAAJQAgAQAAJgAwAgAAJwAgAQAAACsAIAEAAAArACADAAAAKQAgAQAAKgAwAgAAKwAgAwAAACkAIAEAACoAMAIAACsAIAMAAAApACABAAAqADACAAArACAPDgAA4gUAIBIAAJoGACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH2AgEAAAAB9wIBAAAAAfgCAQAAAAH-AgAAAIUDAv8CAQAAAAGAAwEAAAABgQMBAAAAAYIDAQAAAAGDA0AAAAABiwMBAAAAAQEcAACQAwAgDesCAQAAAAHzAkAAAAAB9AJAAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAf4CAAAAhQMC_wIBAAAAAYADAQAAAAGBAwEAAAABggMBAAAAAYMDQAAAAAGLAwEAAAABARwAAJIDADABHAAAkgMAMAEAAAAtACAPDgAA4AUAIBIAAJgGACDrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH-AgAA3gWFAyL_AgEAmAUAIYADAQCYBQAhgQMBAJgFACGCAwEAmAUAIYMDQACaBQAhiwMBAKYFACECAAAAKwAgHAAAlgMAIA3rAgEAmAUAIfMCQACaBQAh9AJAAJoFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH-AgAA3gWFAyL_AgEAmAUAIYADAQCYBQAhgQMBAJgFACGCAwEAmAUAIYMDQACaBQAhiwMBAKYFACECAAAAKQAgHAAAmAMAIAIAAAApACAcAACYAwAgAQAAAC0AIAMAAAArACAjAACQAwAgJAAAlgMAIAEAAAArACABAAAAKQAgBAcAAOoGACApAADsBgAgKgAA6wYAIIsDAADeBgAgEM8CAAC6BAAw0AIAAKADABDRAgAAugQAMOsCAQCXBAAh8wJAAIcEACH0AkAAhwQAIfYCAQCXBAAh9wIBAIQEACH4AgEAhAQAIf4CAACtBIUDIv8CAQCEBAAhgAMBAIQEACGBAwEAhAQAIYIDAQCEBAAhgwNAAIcEACGLAwEArgQAIQMAAAApACABAACfAwAwKAAAoAMAIAMAAAApACABAAAqADACAAArACASzwIAALUEADDQAgAApgMAENECAAC1BAAw6wIBAAAAAfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIf8CAQCRBAAhgAMBAJEEACGBAwEAkQQAIYIDAQCRBAAhgwNAAJQEACGFAwAAtgSFAyKGAwAAtgSFAyKHAwEAtwQAIYgDAQC4BAAhiQMBALgEACGKA0AAlAQAIQEAAACjAwAgAQAAAKMDACASzwIAALUEADDQAgAApgMAENECAAC1BAAw6wIBAKEEACH2AgEAoQQAIfcCAQCRBAAh-AIBAJEEACH_AgEAkQQAIYADAQCRBAAhgQMBAJEEACGCAwEAkQQAIYMDQACUBAAhhQMAALYEhQMihgMAALYEhQMihwMBALcEACGIAwEAuAQAIYkDAQC4BAAhigNAAJQEACEDhwMAAN4GACCIAwAA3gYAIIkDAADeBgAgAwAAAKYDACABAACnAwAwAgAAowMAIAMAAACmAwAgAQAApwMAMAIAAKMDACADAAAApgMAIAEAAKcDADACAACjAwAgD-sCAQAAAAH2AgEAAAAB9wIBAAAAAfgCAQAAAAH_AgEAAAABgAMBAAAAAYEDAQAAAAGCAwEAAAABgwNAAAAAAYUDAAAAhQMChgMAAACFAwKHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABARwAAKsDACAP6wIBAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAf8CAQAAAAGAAwEAAAABgQMBAAAAAYIDAQAAAAGDA0AAAAABhQMAAACFAwKGAwAAAIUDAocDAQAAAAGIAwEAAAABiQMBAAAAAYoDQAAAAAEBHAAArQMAMAEcAACtAwAwD-sCAQCYBQAh9gIBAJgFACH3AgEAmAUAIfgCAQCYBQAh_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhggMBAJgFACGDA0AAmgUAIYUDAADeBYUDIoYDAADeBYUDIocDAQCmBQAhiAMBAKYFACGJAwEApgUAIYoDQACaBQAhAgAAAKMDACAcAACwAwAgD-sCAQCYBQAh9gIBAJgFACH3AgEAmAUAIfgCAQCYBQAh_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhggMBAJgFACGDA0AAmgUAIYUDAADeBYUDIoYDAADeBYUDIocDAQCmBQAhiAMBAKYFACGJAwEApgUAIYoDQACaBQAhAgAAAKYDACAcAACyAwAgAgAAAKYDACAcAACyAwAgAwAAAKMDACAjAACrAwAgJAAAsAMAIAEAAACjAwAgAQAAAKYDACAGBwAA5wYAICkAAOkGACAqAADoBgAghwMAAN4GACCIAwAA3gYAIIkDAADeBgAgEs8CAACsBAAw0AIAALkDABDRAgAArAQAMOsCAQCXBAAh9gIBAJcEACH3AgEAhAQAIfgCAQCEBAAh_wIBAIQEACGAAwEAhAQAIYEDAQCEBAAhggMBAIQEACGDA0AAhwQAIYUDAACtBIUDIoYDAACtBIUDIocDAQCuBAAhiAMBAK8EACGJAwEArwQAIYoDQACHBAAhAwAAAKYDACABAAC4AwAwKAAAuQMAIAMAAACmAwAgAQAApwMAMAIAAKMDACABAAAANgAgAQAAADYAIAMAAAAtACABAAA1ADACAAA2ACADAAAALQAgAQAANQAwAgAANgAgAwAAAC0AIAEAADUAMAIAADYAIBEKAACDBgAgDgAA5AUAIBEAAOUFACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH1AgEAAAAB9gIBAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgL7AkAAAAAB_AJAAAAAAf4CAAAA_gIC_wIBAAAAAYADAQAAAAGBAwEAAAABARwAAMEDACAO6wIBAAAAAfMCQAAAAAH0AkAAAAAB9QIBAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAfoCAAAA-gIC-wJAAAAAAfwCQAAAAAH-AgAAAP4CAv8CAQAAAAGAAwEAAAABgQMBAAAAAQEcAADDAwAwARwAAMMDADARCgAAgQYAIA4AANIFACARAADTBQAg6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH6AgAAzwX6AiL7AkAAmgUAIfwCQAC0BQAh_gIAANAF_gIi_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhAgAAADYAIBwAAMYDACAO6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH6AgAAzwX6AiL7AkAAmgUAIfwCQAC0BQAh_gIAANAF_gIi_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhAgAAAC0AIBwAAMgDACACAAAALQAgHAAAyAMAIAMAAAA2ACAjAADBAwAgJAAAxgMAIAEAAAA2ACABAAAALQAgBAcAAOQGACApAADmBgAgKgAA5QYAIPwCAADeBgAgEc8CAAClBAAw0AIAAM8DABDRAgAApQQAMOsCAQCXBAAh8wJAAIcEACH0AkAAhwQAIfUCAQCXBAAh9gIBAJcEACH3AgEAhAQAIfgCAQCEBAAh-gIAAKYE-gIi-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-gIAAKYE-gIi-wJAAIcEACH8AkAAmQQAIf4CAACnBP4CIv8CAQCEBAAhgAMBAIQEACGBAwEAhAQAIQcHAACJBAAgKQAAqwQAICoAAKsEACDXAgAAAPoCAtgCAAAA-gII2QIAAAD6AgjeAgAAqgT6AiIHBwAAiQQAICkAAKkEACAqAACpBAAg1wIAAAD-AgLYAgAAAP4CCNkCAAAA_gII3gIAAKgE_gIiBwcAAIkEACApAACpBAAgKgAAqQQAINcCAAAA_gIC2AIAAAD-AgjZAgAAAP4CCN4CAACoBP4CIgTXAgAAAP4CAtgCAAAA_gII2QIAAAD-AgjeAgAAqQT-AiIHBwAAiQQAICkAAKsEACAqAACrBAAg1wIAAAD6AgLYAgAAAPoCCNkCAAAA-gII3gIAAKoE-gIiBNcCAAAA-gIC2AIAAAD6AgjZAgAAAPoCCN4CAACrBPoCIhLPAgAArAQAMNACAAC5AwAQ0QIAAKwEADDrAgEAlwQAIfYCAQCXBAAh9wIBAIQEACH4AgEAhAQAIf8CAQCEBAAhgAMBAIQEACGBAwEAhAQAIYIDAQCEBAAhgwNAAIcEACGFAwAArQSFAyKGAwAArQSFAyKHAwEArgQAIYgDAQCvBAAhiQMBAK8EACGKA0AAhwQAIQcHAACJBAAgKQAAtAQAICoAALQEACDXAgAAAIUDAtgCAAAAhQMI2QIAAACFAwjeAgAAswSFAyILBwAAmwQAICkAALEEACAqAACxBAAg1wIBAAAAAdgCAQAAAAXZAgEAAAAF2gIBAAAAAdsCAQAAAAHcAgEAAAAB3QIBAAAAAd4CAQCyBAAhDgcAAJsEACApAACxBAAgKgAAsQQAINcCAQAAAAHYAgEAAAAF2QIBAAAABdoCAQAAAAHbAgEAAAAB3AIBAAAAAd0CAQAAAAHeAgEAsAQAIeUCAQAAAAHmAgEAAAAB5wIBAAAAAQ4HAACbBAAgKQAAsQQAICoAALEEACDXAgEAAAAB2AIBAAAABdkCAQAAAAXaAgEAAAAB2wIBAAAAAdwCAQAAAAHdAgEAAAAB3gIBALAEACHlAgEAAAAB5gIBAAAAAecCAQAAAAEL1wIBAAAAAdgCAQAAAAXZAgEAAAAF2gIBAAAAAdsCAQAAAAHcAgEAAAAB3QIBAAAAAd4CAQCxBAAh5QIBAAAAAeYCAQAAAAHnAgEAAAABCwcAAJsEACApAACxBAAgKgAAsQQAINcCAQAAAAHYAgEAAAAF2QIBAAAABdoCAQAAAAHbAgEAAAAB3AIBAAAAAd0CAQAAAAHeAgEAsgQAIQcHAACJBAAgKQAAtAQAICoAALQEACDXAgAAAIUDAtgCAAAAhQMI2QIAAACFAwjeAgAAswSFAyIE1wIAAACFAwLYAgAAAIUDCNkCAAAAhQMI3gIAALQEhQMiEs8CAAC1BAAw0AIAAKYDABDRAgAAtQQAMOsCAQChBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh_wIBAJEEACGAAwEAkQQAIYEDAQCRBAAhggMBAJEEACGDA0AAlAQAIYUDAAC2BIUDIoYDAAC2BIUDIocDAQC3BAAhiAMBALgEACGJAwEAuAQAIYoDQACUBAAhBNcCAAAAhQMC2AIAAACFAwjZAgAAAIUDCN4CAAC0BIUDIgjXAgEAAAAB2AIBAAAABdkCAQAAAAXaAgEAAAAB2wIBAAAAAdwCAQAAAAHdAgEAAAAB3gIBALkEACEL1wIBAAAAAdgCAQAAAAXZAgEAAAAF2gIBAAAAAdsCAQAAAAHcAgEAAAAB3QIBAAAAAd4CAQCxBAAh5QIBAAAAAeYCAQAAAAHnAgEAAAABCNcCAQAAAAHYAgEAAAAF2QIBAAAABdoCAQAAAAHbAgEAAAAB3AIBAAAAAd0CAQAAAAHeAgEAuQQAIRDPAgAAugQAMNACAACgAwAQ0QIAALoEADDrAgEAlwQAIfMCQACHBAAh9AJAAIcEACH2AgEAlwQAIfcCAQCEBAAh-AIBAIQEACH-AgAArQSFAyL_AgEAhAQAIYADAQCEBAAhgQMBAIQEACGCAwEAhAQAIYMDQACHBAAhiwMBAK4EACEMzwIAALsEADDQAgAAiAMAENECAAC7BAAw1AIQAIUEACHrAgEAlwQAIfMCQACHBAAh9AJAAIcEACH2AgEAlwQAIfcCAQCvBAAh-AIBAK8EACH6AgAAvAT6AiOMAyAAvQQAIQcHAACbBAAgKQAAwQQAICoAAMEEACDXAgAAAPoCA9gCAAAA-gIJ2QIAAAD6AgneAgAAwAT6AiMFBwAAiQQAICkAAL8EACAqAAC_BAAg1wIgAAAAAd4CIAC-BAAhBQcAAIkEACApAAC_BAAgKgAAvwQAINcCIAAAAAHeAiAAvgQAIQLXAiAAAAAB3gIgAL8EACEHBwAAmwQAICkAAMEEACAqAADBBAAg1wIAAAD6AgPYAgAAAPoCCdkCAAAA-gIJ3gIAAMAE-gIjBNcCAAAA-gID2AIAAAD6AgnZAgAAAPoCCd4CAADBBPoCIwnPAgAAwgQAMNACAADyAgAQ0QIAAMIEADDrAgEAlwQAIfMCQACHBAAh9gIBAJcEACH3AgEAhAQAIfgCAQCEBAAh-gIAAKYE-gIiC88CAADDBAAw0AIAANwCABDRAgAAwwQAMOsCAQCXBAAh8wJAAIcEACH0AkAAhwQAIfYCAQCXBAAh9wIBAK8EACH4AgEArwQAIfsCQACHBAAhjQMBAK8EACENzwIAAMQEADDQAgAAxgIAENECAADEBAAw0wIBAIQEACHrAgEAlwQAIfMCQACHBAAh9AJAAIcEACH1AgEAlwQAIY4DAQCXBAAhjwMCAJgEACGQAxAAhQQAIZEDIAC9BAAhkgMBAK8EACEJzwIAAMUEADDQAgAAsAIAENECAADFBAAw0wIBAIQEACHrAgEAlwQAIfMCQACHBAAh9AJAAIcEACGMAyAAvQQAIZMDAQCEBAAhCgwAAMgEACDPAgAAxgQAMNACAACdAgAQ0QIAAMYEADDTAgEAkQQAIesCAQChBAAh8wJAAJQEACH0AkAAlAQAIYwDIADHBAAhkwMBAJEEACEC1wIgAAAAAd4CIAC_BAAhA-gCAAAbACDpAgAAGwAg6gIAABsAIAzPAgAAyQQAMNACAACXAgAQ0QIAAMkEADDrAgEAlwQAIewCAQCEBAAh8wJAAIcEACH0AkAAhwQAIfUCAQCXBAAhlAMBAIQEACGVA0AAhwQAIZYDQACZBAAhlwNAAJkEACEHzwIAAMoEADDQAgAAgQIAENECAADKBAAw8wJAAIcEACH1AgEAlwQAIZgDAQCEBAAhmgMAAMsEmgMiBwcAAIkEACApAADNBAAgKgAAzQQAINcCAAAAmgMC2AIAAACaAwjZAgAAAJoDCN4CAADMBJoDIgcHAACJBAAgKQAAzQQAICoAAM0EACDXAgAAAJoDAtgCAAAAmgMI2QIAAACaAwjeAgAAzASaAyIE1wIAAACaAwLYAgAAAJoDCNkCAAAAmgMI3gIAAM0EmgMiDs8CAADOBAAw0AIAAOsBABDRAgAAzgQAMOsCAQCXBAAh8wJAAIcEACH0AkAAhwQAIZsDAQCEBAAhnAMBAK8EACGdAwEArwQAIZ4DAQCvBAAhnwMBAK8EACGgAwEAhAQAIaEDAQCEBAAhogMBAK8EACEMzwIAAM8EADDQAgAA0wEAENECAADPBAAw6wIBAJcEACH1AgEAlwQAIYUDAADSBKkDI4YDAADSBKkDI6MDAQCEBAAhpQMAANAEpQMipgMBAK8EACGnAwAA0QQAIKkDQACHBAAhBwcAAIkEACApAADXBAAgKgAA1wQAINcCAAAApQMC2AIAAAClAwjZAgAAAKUDCN4CAADWBKUDIg8HAACbBAAgKQAA1QQAICoAANUEACDXAoAAAAAB2gKAAAAAAdsCgAAAAAHcAoAAAAAB3QKAAAAAAd4CgAAAAAHfAgEAAAAB4AIBAAAAAeECAQAAAAHiAoAAAAAB4wKAAAAAAeQCgAAAAAEHBwAAmwQAICkAANQEACAqAADUBAAg1wIAAACpAwPYAgAAAKkDCdkCAAAAqQMJ3gIAANMEqQMjBwcAAJsEACApAADUBAAgKgAA1AQAINcCAAAAqQMD2AIAAACpAwnZAgAAAKkDCd4CAADTBKkDIwTXAgAAAKkDA9gCAAAAqQMJ2QIAAACpAwneAgAA1ASpAyMM1wKAAAAAAdoCgAAAAAHbAoAAAAAB3AKAAAAAAd0CgAAAAAHeAoAAAAAB3wIBAAAAAeACAQAAAAHhAgEAAAAB4gKAAAAAAeMCgAAAAAHkAoAAAAABBwcAAIkEACApAADXBAAgKgAA1wQAINcCAAAApQMC2AIAAAClAwjZAgAAAKUDCN4CAADWBKUDIgTXAgAAAKUDAtgCAAAApQMI2QIAAAClAwjeAgAA1wSlAyISzwIAANgEADDQAgAAvQEAENECAADYBAAw8wJAAIcEACH0AkAAhwQAIfUCAQCXBAAh_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-ACDNAwAAPgAgFAoAAOIEACAOAAD4BAAgEQAA-QQAIM8CAAD1BAAw0AIAAC0AENECAAD1BAAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9QIBAKEEACH2AgEAoQQAIfcCAQCRBAAh-AIBAJEEACH6AgAA9gT6AiL7AkAAlAQAIfwCQACjBAAh_gIAAPcE_gIi_wIBAJEEACGAAwEAkQQAIYEDAQCRBAAhBNcCAAAA-gIC2AIAAAD6AgjZAgAAAPoCCN4CAACrBPoCIgTXAgAAAP4CAtgCAAAA_gII2QIAAAD-AgjeAgAAqQT-AiIWCgAA4gQAIA0AAIIFACAPAACDBQAgEAAAhAUAIBEAAPkEACATAACFBQAgFAAAhgUAIM8CAACBBQAw0AIAABsAENECAACBBQAw0wIBAJEEACHrAgEAoQQAIfMCQACUBAAh9AJAAJQEACH1AgEAoQQAIY4DAQChBAAhjwMCAKIEACGQAxAAkgQAIZEDIADHBAAhkgMBALgEACHMAwAAGwAgzQMAABsAIAPoAgAAKQAg6QIAACkAIOoCAAApACAMDgAA-AQAIM8CAAD6BAAw0AIAADEAENECAAD6BAAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-wJAAJQEACGNAwEAuAQAIQP2AgEAAAAB9wIBAAAAAYMDQAAAAAESDgAA-AQAIBIAAP0EACDPAgAA_AQAMNACAAApABDRAgAA_AQAMOsCAQChBAAh8wJAAJQEACH0AkAAlAQAIfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIf4CAAC2BIUDIv8CAQCRBAAhgAMBAJEEACGBAwEAkQQAIYIDAQCRBAAhgwNAAJQEACGLAwEAtwQAIRYKAADiBAAgDgAA-AQAIBEAAPkEACDPAgAA9QQAMNACAAAtABDRAgAA9QQAMOsCAQChBAAh8wJAAJQEACH0AkAAlAQAIfUCAQChBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh-gIAAPYE-gIi-wJAAJQEACH8AkAAowQAIf4CAAD3BP4CIv8CAQCRBAAhgAMBAJEEACGBAwEAkQQAIcwDAAAtACDNAwAALQAgDQ4AAPgEACDPAgAA_gQAMNACAAAlABDRAgAA_gQAMNQCEACSBAAh6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-gIAAP8E-gIjjAMgAMcEACEE1wIAAAD6AgPYAgAAAPoCCdkCAAAA-gIJ3gIAAMEE-gIjCg4AAPgEACDPAgAAgAUAMNACAAAhABDRAgAAgAUAMOsCAQChBAAh8wJAAJQEACH2AgEAoQQAIfcCAQCRBAAh-AIBAJEEACH6AgAA9gT6AiIUCgAA4gQAIA0AAIIFACAPAACDBQAgEAAAhAUAIBEAAPkEACATAACFBQAgFAAAhgUAIM8CAACBBQAw0AIAABsAENECAACBBQAw0wIBAJEEACHrAgEAoQQAIfMCQACUBAAh9AJAAJQEACH1AgEAoQQAIY4DAQChBAAhjwMCAKIEACGQAxAAkgQAIZEDIADHBAAhkgMBALgEACEMDAAAyAQAIM8CAADGBAAw0AIAAJ0CABDRAgAAxgQAMNMCAQCRBAAh6wIBAKEEACHzAkAAlAQAIfQCQACUBAAhjAMgAMcEACGTAwEAkQQAIcwDAACdAgAgzQMAAJ0CACAD6AIAACEAIOkCAAAhACDqAgAAIQAgA-gCAAAlACDpAgAAJQAg6gIAACUAIAPoAgAAMQAg6QIAADEAIOoCAAAxACAD6AIAAC0AIOkCAAAtACDqAgAALQAgDQoAAOIEACDPAgAAhwUAMNACAAAXABDRAgAAhwUAMOsCAQChBAAh7AIBAJEEACHzAkAAlAQAIfQCQACUBAAh9QIBAKEEACGUAwEAkQQAIZUDQACUBAAhlgNAAKMEACGXA0AAowQAIRQIAACJBQAgCQAA7wQAIAsAAIoFACAMAADIBAAgFAAAhgUAIBUAAIsFACDPAgAAiAUAMNACAAARABDRAgAAiAUAMOsCAQChBAAh8wJAAJQEACH0AkAAlAQAIZsDAQCRBAAhnAMBALgEACGdAwEAuAQAIZ4DAQC4BAAhnwMBALgEACGgAwEAkQQAIaEDAQCRBAAhogMBALgEACELBgAAlQQAIM8CAACQBAAw0AIAAA8AENECAACQBAAw0gIBAJEEACHTAgEAkQQAIdQCEACSBAAh1QIAAJMEACDWAkAAlAQAIcwDAAAPACDNAwAADwAgA-gCAAAXACDpAgAAFwAg6gIAABcAIBYKAADiBAAgFgAA4wQAIM8CAADfBAAw0AIAAD4AENECAADfBAAw8wJAAJQEACH0AkAAlAQAIfUCAQChBAAh_gIAAOAEqQMiogMBAJEEACGlAwAA4QSlAyOqAwEAkQQAIasDAQC4BAAhrAMBALgEACGtAwEAuAQAIa4DQACjBAAhrwNAAKMEACGwA0AAowQAIbEDQACjBAAhsgNAAKMEACHMAwAAPgAgzQMAAD4AIAL1AgEAAAABmAMBAAAAAQkDAACPBQAgCgAA4gQAIM8CAACNBQAw0AIAAAsAENECAACNBQAw8wJAAJQEACH1AgEAoQQAIZgDAQCRBAAhmgMAAI4FmgMiBNcCAAAAmgMC2AIAAACaAwjZAgAAAJoDCN4CAADNBJoDIhQEAADtBAAgBQAA7gQAIAYAAO8EACDPAgAA7AQAMNACAABNABDRAgAA7AQAMNMCAQCRBAAh6wIBAJEEACHsAgEAkQQAIfMCQACUBAAh9AJAAJQEACGaAwEAkQQAIcQDIADHBAAhxQMBALgEACHGAwEAuAQAIccDIADHBAAhyANAAKMEACHJAwEAuAQAIcwDAABNACDNAwAATQAgEQMAAI8FACDPAgAAkAUAMNACAAAHABDRAgAAkAUAMOsCAQCRBAAh8wJAAJQEACH0AkAAlAQAIZgDAQCRBAAhtQMBAJEEACG2AwEAkQQAIbcDAQC4BAAhuAMBALgEACG5AwEAuAQAIboDQACjBAAhuwNAAKMEACG8AwEAuAQAIb0DAQC4BAAhEQMAAI8FACDPAgAAkQUAMNACAAADABDRAgAAkQUAMOsCAQCRBAAh8wJAAJQEACH0AkAAlAQAIZUDQACUBAAhmAMBAJEEACGdAwEAuAQAIZ8DAQC4BAAhvgMBAJEEACG_AwEAuAQAIcADAQC4BAAhwQMBALgEACHCAwgAkgUAIcMDCACSBQAhCNcCCAAAAAHYAggAAAAF2QIIAAAABdoCCAAAAAHbAggAAAAB3AIIAAAAAd0CCAAAAAHeAggA6gQAIQAAAAAAAdEDAQAAAAEF0QMQAAAAAdcDEAAAAAHYAxAAAAAB2QMQAAAAAdoDEAAAAAEB0QNAAAAAAQsjAACcBQAwJAAAoQUAMM4DAACdBQAwzwMAAJ4FADDQAwAAnwUAINEDAACgBQAw0gMAAKAFADDTAwAAoAUAMNQDAACgBQAw1QMAAKIFADDWAwAAowUAMA8JAADXBgAgCwAA2AYAIAwAANkGACAUAADaBgAgFQAA2wYAIOsCAQAAAAHzAkAAAAAB9AJAAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DAQAAAAGfAwEAAAABoAMBAAAAAaEDAQAAAAECAAAAEwAgIwAA1gYAIAMAAAATACAjAADWBgAgJAAApwUAIAEcAADcCAAwFAgAAIkFACAJAADvBAAgCwAAigUAIAwAAMgEACAUAACGBQAgFQAAiwUAIM8CAACIBQAw0AIAABEAENECAACIBQAw6wIBAAAAAfMCQACUBAAh9AJAAJQEACGbAwEAkQQAIZwDAQC4BAAhnQMBALgEACGeAwEAuAQAIZ8DAQC4BAAhoAMBAAAAAaEDAQCRBAAhogMBALgEACECAAAAEwAgHAAApwUAIAIAAACkBQAgHAAApQUAIA7PAgAAowUAMNACAACkBQAQ0QIAAKMFADDrAgEAoQQAIfMCQACUBAAh9AJAAJQEACGbAwEAkQQAIZwDAQC4BAAhnQMBALgEACGeAwEAuAQAIZ8DAQC4BAAhoAMBAJEEACGhAwEAkQQAIaIDAQC4BAAhDs8CAACjBQAw0AIAAKQFABDRAgAAowUAMOsCAQChBAAh8wJAAJQEACH0AkAAlAQAIZsDAQCRBAAhnAMBALgEACGdAwEAuAQAIZ4DAQC4BAAhnwMBALgEACGgAwEAkQQAIaEDAQCRBAAhogMBALgEACEK6wIBAJgFACHzAkAAmgUAIfQCQACaBQAhmwMBAJgFACGcAwEApgUAIZ0DAQCmBQAhngMBAKYFACGfAwEApgUAIaADAQCYBQAhoQMBAJgFACEB0QMBAAAAAQ8JAACoBQAgCwAAqQUAIAwAAKoFACAUAACrBQAgFQAArAUAIOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZsDAQCYBQAhnAMBAKYFACGdAwEApgUAIZ4DAQCmBQAhnwMBAKYFACGgAwEAmAUAIaEDAQCYBQAhCyMAAMcGADAkAADMBgAwzgMAAMgGADDPAwAAyQYAMNADAADKBgAg0QMAAMsGADDSAwAAywYAMNMDAADLBgAw1AMAAMsGADDVAwAAzQYAMNYDAADOBgAwCyMAALsGADAkAADABgAwzgMAALwGADDPAwAAvQYAMNADAAC-BgAg0QMAAL8GADDSAwAAvwYAMNMDAAC_BgAw1AMAAL8GADDVAwAAwQYAMNYDAADCBgAwCyMAAOYFADAkAADrBQAwzgMAAOcFADDPAwAA6AUAMNADAADpBQAg0QMAAOoFADDSAwAA6gUAMNMDAADqBQAw1AMAAOoFADDVAwAA7AUAMNYDAADtBQAwCyMAAMUFADAkAADKBQAwzgMAAMYFADDPAwAAxwUAMNADAADIBQAg0QMAAMkFADDSAwAAyQUAMNMDAADJBQAw1AMAAMkFADDVAwAAywUAMNYDAADMBQAwByMAAK0FACAkAACwBQAgzgMAAK4FACDPAwAArwUAINIDAAA-ACDTAwAAPgAg1AMAAKgBACAPFgAAxAUAIPMCQAAAAAH0AkAAAAAB_gIAAACpAwKiAwEAAAABpQMAAAClAwOqAwEAAAABqwMBAAAAAawDAQAAAAGtAwEAAAABrgNAAAAAAa8DQAAAAAGwA0AAAAABsQNAAAAAAbIDQAAAAAECAAAAqAEAICMAAK0FACADAAAAPgAgIwAArQUAICQAALEFACARAAAAPgAgFgAAtQUAIBwAALEFACDzAkAAmgUAIfQCQACaBQAh_gIAALIFqQMiogMBAJgFACGlAwAAswWlAyOqAwEAmAUAIasDAQCmBQAhrAMBAKYFACGtAwEApgUAIa4DQAC0BQAhrwNAALQFACGwA0AAtAUAIbEDQAC0BQAhsgNAALQFACEPFgAAtQUAIPMCQACaBQAh9AJAAJoFACH-AgAAsgWpAyKiAwEAmAUAIaUDAACzBaUDI6oDAQCYBQAhqwMBAKYFACGsAwEApgUAIa0DAQCmBQAhrgNAALQFACGvA0AAtAUAIbADQAC0BQAhsQNAALQFACGyA0AAtAUAIQHRAwAAAKkDAgHRAwAAAKUDAwHRA0AAAAABCyMAALYFADAkAAC7BQAwzgMAALcFADDPAwAAuAUAMNADAAC5BQAg0QMAALoFADDSAwAAugUAMNMDAAC6BQAw1AMAALoFADDVAwAAvAUAMNYDAAC9BQAwCOsCAQAAAAGFAwAAAKkDA4YDAAAAqQMDowMBAAAAAaUDAAAApQMCpgMBAAAAAacDgAAAAAGpA0AAAAABAgAAAEIAICMAAMMFACADAAAAQgAgIwAAwwUAICQAAMIFACABHAAA2wgAMA0VAAD0BAAgzwIAAPAEADDQAgAAQAAQ0QIAAPAEADDrAgEAAAAB9QIBAKEEACGFAwAA8wSpAyOGAwAA8wSpAyOjAwEAkQQAIaUDAADxBKUDIqYDAQAAAAGnAwAA8gQAIKkDQACUBAAhAgAAAEIAIBwAAMIFACACAAAAvgUAIBwAAL8FACAMzwIAAL0FADDQAgAAvgUAENECAAC9BQAw6wIBAKEEACH1AgEAoQQAIYUDAADzBKkDI4YDAADzBKkDI6MDAQCRBAAhpQMAAPEEpQMipgMBALgEACGnAwAA8gQAIKkDQACUBAAhDM8CAAC9BQAw0AIAAL4FABDRAgAAvQUAMOsCAQChBAAh9QIBAKEEACGFAwAA8wSpAyOGAwAA8wSpAyOjAwEAkQQAIaUDAADxBKUDIqYDAQC4BAAhpwMAAPIEACCpA0AAlAQAIQjrAgEAmAUAIYUDAADBBakDI4YDAADBBakDI6MDAQCYBQAhpQMAAMAFpQMipgMBAKYFACGnA4AAAAABqQNAAJoFACEB0QMAAAClAwIB0QMAAACpAwMI6wIBAJgFACGFAwAAwQWpAyOGAwAAwQWpAyOjAwEAmAUAIaUDAADABaUDIqYDAQCmBQAhpwOAAAAAAakDQACaBQAhCOsCAQAAAAGFAwAAAKkDA4YDAAAAqQMDowMBAAAAAaUDAAAApQMCpgMBAAAAAacDgAAAAAGpA0AAAAABBCMAALYFADDOAwAAtwUAMNADAAC5BQAg1AMAALoFADAPDgAA5AUAIBEAAOUFACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH2AgEAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCAvsCQAAAAAH8AkAAAAAB_gIAAAD-AgL_AgEAAAABgAMBAAAAAYEDAQAAAAECAAAANgAgIwAA4wUAIAMAAAA2ACAjAADjBQAgJAAA0QUAIAEcAADaCAAwFAoAAOIEACAOAAD4BAAgEQAA-QQAIM8CAAD1BAAw0AIAAC0AENECAAD1BAAw6wIBAAAAAfMCQACUBAAh9AJAAJQEACH1AgEAoQQAIfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIfoCAAD2BPoCIvsCQACUBAAh_AJAAKMEACH-AgAA9wT-AiL_AgEAkQQAIYADAQCRBAAhgQMBAJEEACECAAAANgAgHAAA0QUAIAIAAADNBQAgHAAAzgUAIBHPAgAAzAUAMNACAADNBQAQ0QIAAMwFADDrAgEAoQQAIfMCQACUBAAh9AJAAJQEACH1AgEAoQQAIfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIfoCAAD2BPoCIvsCQACUBAAh_AJAAKMEACH-AgAA9wT-AiL_AgEAkQQAIYADAQCRBAAhgQMBAJEEACERzwIAAMwFADDQAgAAzQUAENECAADMBQAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9QIBAKEEACH2AgEAoQQAIfcCAQCRBAAh-AIBAJEEACH6AgAA9gT6AiL7AkAAlAQAIfwCQACjBAAh_gIAAPcE_gIi_wIBAJEEACGAAwEAkQQAIYEDAQCRBAAhDesCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfYCAQCYBQAh9wIBAJgFACH4AgEAmAUAIfoCAADPBfoCIvsCQACaBQAh_AJAALQFACH-AgAA0AX-AiL_AgEAmAUAIYADAQCYBQAhgQMBAJgFACEB0QMAAAD6AgIB0QMAAAD-AgIPDgAA0gUAIBEAANMFACDrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH6AgAAzwX6AiL7AkAAmgUAIfwCQAC0BQAh_gIAANAF_gIi_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhBSMAAM8IACAkAADYCAAgzgMAANAIACDPAwAA1wgAINQDAAAdACALIwAA1AUAMCQAANkFADDOAwAA1QUAMM8DAADWBQAw0AMAANcFACDRAwAA2AUAMNIDAADYBQAw0wMAANgFADDUAwAA2AUAMNUDAADaBQAw1gMAANsFADANDgAA4gUAIOsCAQAAAAHzAkAAAAAB9AJAAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAf4CAAAAhQMC_wIBAAAAAYADAQAAAAGBAwEAAAABggMBAAAAAYMDQAAAAAECAAAAKwAgIwAA4QUAIAMAAAArACAjAADhBQAgJAAA3wUAIAEcAADWCAAwEw4AAPgEACASAAD9BAAgzwIAAPwEADDQAgAAKQAQ0QIAAPwEADDrAgEAAAAB8wJAAJQEACH0AkAAlAQAIfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIf4CAAC2BIUDIv8CAQCRBAAhgAMBAJEEACGBAwEAkQQAIYIDAQAAAAGDA0AAlAQAIYsDAQC3BAAhygMAAPsEACACAAAAKwAgHAAA3wUAIAIAAADcBQAgHAAA3QUAIBDPAgAA2wUAMNACAADcBQAQ0QIAANsFADDrAgEAoQQAIfMCQACUBAAh9AJAAJQEACH2AgEAoQQAIfcCAQCRBAAh-AIBAJEEACH-AgAAtgSFAyL_AgEAkQQAIYADAQCRBAAhgQMBAJEEACGCAwEAkQQAIYMDQACUBAAhiwMBALcEACEQzwIAANsFADDQAgAA3AUAENECAADbBQAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh_gIAALYEhQMi_wIBAJEEACGAAwEAkQQAIYEDAQCRBAAhggMBAJEEACGDA0AAlAQAIYsDAQC3BAAhDOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfYCAQCYBQAh9wIBAJgFACH4AgEAmAUAIf4CAADeBYUDIv8CAQCYBQAhgAMBAJgFACGBAwEAmAUAIYIDAQCYBQAhgwNAAJoFACEB0QMAAACFAwINDgAA4AUAIOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfYCAQCYBQAh9wIBAJgFACH4AgEAmAUAIf4CAADeBYUDIv8CAQCYBQAhgAMBAJgFACGBAwEAmAUAIYIDAQCYBQAhgwNAAJoFACEFIwAA0QgAICQAANQIACDOAwAA0ggAIM8DAADTCAAg1AMAAB0AIA0OAADiBQAg6wIBAAAAAfMCQAAAAAH0AkAAAAAB9gIBAAAAAfcCAQAAAAH4AgEAAAAB_gIAAACFAwL_AgEAAAABgAMBAAAAAYEDAQAAAAGCAwEAAAABgwNAAAAAAQMjAADRCAAgzgMAANIIACDUAwAAHQAgDw4AAOQFACARAADlBQAg6wIBAAAAAfMCQAAAAAH0AkAAAAAB9gIBAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgL7AkAAAAAB_AJAAAAAAf4CAAAA_gIC_wIBAAAAAYADAQAAAAGBAwEAAAABAyMAAM8IACDOAwAA0AgAINQDAAAdACAEIwAA1AUAMM4DAADVBQAw0AMAANcFACDUAwAA2AUAMA8NAAC1BgAgDwAAtgYAIBAAALcGACARAAC4BgAgEwAAuQYAIBQAALoGACDTAgEAAAAB6wIBAAAAAfMCQAAAAAH0AkAAAAABjgMBAAAAAY8DAgAAAAGQAxAAAAABkQMgAAAAAZIDAQAAAAECAAAAHQAgIwAAtAYAIAMAAAAdACAjAAC0BgAgJAAA8gUAIAEcAADOCAAwFAoAAOIEACANAACCBQAgDwAAgwUAIBAAAIQFACARAAD5BAAgEwAAhQUAIBQAAIYFACDPAgAAgQUAMNACAAAbABDRAgAAgQUAMNMCAQCRBAAh6wIBAAAAAfMCQACUBAAh9AJAAJQEACH1AgEAoQQAIY4DAQChBAAhjwMCAKIEACGQAxAAkgQAIZEDIADHBAAhkgMBALgEACECAAAAHQAgHAAA8gUAIAIAAADuBQAgHAAA7wUAIA3PAgAA7QUAMNACAADuBQAQ0QIAAO0FADDTAgEAkQQAIesCAQChBAAh8wJAAJQEACH0AkAAlAQAIfUCAQChBAAhjgMBAKEEACGPAwIAogQAIZADEACSBAAhkQMgAMcEACGSAwEAuAQAIQ3PAgAA7QUAMNACAADuBQAQ0QIAAO0FADDTAgEAkQQAIesCAQChBAAh8wJAAJQEACH0AkAAlAQAIfUCAQChBAAhjgMBAKEEACGPAwIAogQAIZADEACSBAAhkQMgAMcEACGSAwEAuAQAIQnTAgEAmAUAIesCAQCYBQAh8wJAAJoFACH0AkAAmgUAIY4DAQCYBQAhjwMCAPAFACGQAxAAmQUAIZEDIADxBQAhkgMBAKYFACEF0QMCAAAAAdcDAgAAAAHYAwIAAAAB2QMCAAAAAdoDAgAAAAEB0QMgAAAAAQ8NAADzBQAgDwAA9AUAIBAAAPUFACARAAD2BQAgEwAA9wUAIBQAAPgFACDTAgEAmAUAIesCAQCYBQAh8wJAAJoFACH0AkAAmgUAIY4DAQCYBQAhjwMCAPAFACGQAxAAmQUAIZEDIADxBQAhkgMBAKYFACEFIwAAuggAICQAAMwIACDOAwAAuwgAIM8DAADLCAAg1AMAAJoCACALIwAAqAYAMCQAAK0GADDOAwAAqQYAMM8DAACqBgAw0AMAAKsGACDRAwAArAYAMNIDAACsBgAw0wMAAKwGADDUAwAArAYAMNUDAACuBgAw1gMAAK8GADALIwAAmwYAMCQAAKAGADDOAwAAnAYAMM8DAACdBgAw0AMAAJ4GACDRAwAAnwYAMNIDAACfBgAw0wMAAJ8GADDUAwAAnwYAMNUDAAChBgAw1gMAAKIGADALIwAAkAYAMCQAAJQGADDOAwAAkQYAMM8DAACSBgAw0AMAAJMGACDRAwAA2AUAMNIDAADYBQAw0wMAANgFADDUAwAA2AUAMNUDAACVBgAw1gMAANsFADALIwAAhAYAMCQAAIkGADDOAwAAhQYAMM8DAACGBgAw0AMAAIcGACDRAwAAiAYAMNIDAACIBgAw0wMAAIgGADDUAwAAiAYAMNUDAACKBgAw1gMAAIsGADALIwAA-QUAMCQAAP0FADDOAwAA-gUAMM8DAAD7BQAw0AMAAPwFACDRAwAAyQUAMNIDAADJBQAw0wMAAMkFADDUAwAAyQUAMNUDAAD-BQAw1gMAAMwFADAPCgAAgwYAIBEAAOUFACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH1AgEAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCAvsCQAAAAAH8AkAAAAAB_gIAAAD-AgL_AgEAAAABgAMBAAAAAYEDAQAAAAECAAAANgAgIwAAggYAIAMAAAA2ACAjAACCBgAgJAAAgAYAIAEcAADKCAAwAgAAADYAIBwAAIAGACACAAAAzQUAIBwAAP8FACAN6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACH3AgEAmAUAIfgCAQCYBQAh-gIAAM8F-gIi-wJAAJoFACH8AkAAtAUAIf4CAADQBf4CIv8CAQCYBQAhgAMBAJgFACGBAwEAmAUAIQ8KAACBBgAgEQAA0wUAIOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfUCAQCYBQAh9wIBAJgFACH4AgEAmAUAIfoCAADPBfoCIvsCQACaBQAh_AJAALQFACH-AgAA0AX-AiL_AgEAmAUAIYADAQCYBQAhgQMBAJgFACEFIwAAxQgAICQAAMgIACDOAwAAxggAIM8DAADHCAAg1AMAABMAIA8KAACDBgAgEQAA5QUAIOsCAQAAAAHzAkAAAAAB9AJAAAAAAfUCAQAAAAH3AgEAAAAB-AIBAAAAAfoCAAAA-gIC-wJAAAAAAfwCQAAAAAH-AgAAAP4CAv8CAQAAAAGAAwEAAAABgQMBAAAAAQMjAADFCAAgzgMAAMYIACDUAwAAEwAgB-sCAQAAAAHzAkAAAAAB9AJAAAAAAfcCAQAAAAH4AgEAAAAB-wJAAAAAAY0DAQAAAAECAAAAMwAgIwAAjwYAIAMAAAAzACAjAACPBgAgJAAAjgYAIAEcAADECAAwDA4AAPgEACDPAgAA-gQAMNACAAAxABDRAgAA-gQAMOsCAQAAAAHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-wJAAJQEACGNAwEAuAQAIQIAAAAzACAcAACOBgAgAgAAAIwGACAcAACNBgAgC88CAACLBgAw0AIAAIwGABDRAgAAiwYAMOsCAQChBAAh8wJAAJQEACH0AkAAlAQAIfYCAQChBAAh9wIBALgEACH4AgEAuAQAIfsCQACUBAAhjQMBALgEACELzwIAAIsGADDQAgAAjAYAENECAACLBgAw6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-wJAAJQEACGNAwEAuAQAIQfrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH3AgEApgUAIfgCAQCmBQAh-wJAAJoFACGNAwEApgUAIQfrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH3AgEApgUAIfgCAQCmBQAh-wJAAJoFACGNAwEApgUAIQfrAgEAAAAB8wJAAAAAAfQCQAAAAAH3AgEAAAAB-AIBAAAAAfsCQAAAAAGNAwEAAAABDRIAAJoGACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH3AgEAAAAB-AIBAAAAAf4CAAAAhQMC_wIBAAAAAYADAQAAAAGBAwEAAAABggMBAAAAAYMDQAAAAAGLAwEAAAABAgAAACsAICMAAJkGACADAAAAKwAgIwAAmQYAICQAAJcGACABHAAAwwgAMAIAAAArACAcAACXBgAgAgAAANwFACAcAACWBgAgDOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfcCAQCYBQAh-AIBAJgFACH-AgAA3gWFAyL_AgEAmAUAIYADAQCYBQAhgQMBAJgFACGCAwEAmAUAIYMDQACaBQAhiwMBAKYFACENEgAAmAYAIOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIfcCAQCYBQAh-AIBAJgFACH-AgAA3gWFAyL_AgEAmAUAIYADAQCYBQAhgQMBAJgFACGCAwEAmAUAIYMDQACaBQAhiwMBAKYFACEHIwAAvggAICQAAMEIACDOAwAAvwgAIM8DAADACAAg0gMAAC0AINMDAAAtACDUAwAANgAgDRIAAJoGACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH3AgEAAAAB-AIBAAAAAf4CAAAAhQMC_wIBAAAAAYADAQAAAAGBAwEAAAABggMBAAAAAYMDQAAAAAGLAwEAAAABAyMAAL4IACDOAwAAvwgAINQDAAA2ACAI1AIQAAAAAesCAQAAAAHzAkAAAAAB9AJAAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgOMAyAAAAABAgAAACcAICMAAKcGACADAAAAJwAgIwAApwYAICQAAKYGACABHAAAvQgAMA0OAAD4BAAgzwIAAP4EADDQAgAAJQAQ0QIAAP4EADDUAhAAkgQAIesCAQAAAAHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-gIAAP8E-gIjjAMgAMcEACECAAAAJwAgHAAApgYAIAIAAACjBgAgHAAApAYAIAzPAgAAogYAMNACAACjBgAQ0QIAAKIGADDUAhAAkgQAIesCAQChBAAh8wJAAJQEACH0AkAAlAQAIfYCAQChBAAh9wIBALgEACH4AgEAuAQAIfoCAAD_BPoCI4wDIADHBAAhDM8CAACiBgAw0AIAAKMGABDRAgAAogYAMNQCEACSBAAh6wIBAKEEACHzAkAAlAQAIfQCQACUBAAh9gIBAKEEACH3AgEAuAQAIfgCAQC4BAAh-gIAAP8E-gIjjAMgAMcEACEI1AIQAJkFACHrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH3AgEApgUAIfgCAQCmBQAh-gIAAKUG-gIjjAMgAPEFACEB0QMAAAD6AgMI1AIQAJkFACHrAgEAmAUAIfMCQACaBQAh9AJAAJoFACH3AgEApgUAIfgCAQCmBQAh-gIAAKUG-gIjjAMgAPEFACEI1AIQAAAAAesCAQAAAAHzAkAAAAAB9AJAAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgOMAyAAAAABBesCAQAAAAHzAkAAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCAgIAAAAjACAjAACzBgAgAwAAACMAICMAALMGACAkAACyBgAgARwAALwIADAKDgAA-AQAIM8CAACABQAw0AIAACEAENECAACABQAw6wIBAAAAAfMCQACUBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh-gIAAPYE-gIiAgAAACMAIBwAALIGACACAAAAsAYAIBwAALEGACAJzwIAAK8GADDQAgAAsAYAENECAACvBgAw6wIBAKEEACHzAkAAlAQAIfYCAQChBAAh9wIBAJEEACH4AgEAkQQAIfoCAAD2BPoCIgnPAgAArwYAMNACAACwBgAQ0QIAAK8GADDrAgEAoQQAIfMCQACUBAAh9gIBAKEEACH3AgEAkQQAIfgCAQCRBAAh-gIAAPYE-gIiBesCAQCYBQAh8wJAAJoFACH3AgEAmAUAIfgCAQCYBQAh-gIAAM8F-gIiBesCAQCYBQAh8wJAAJoFACH3AgEAmAUAIfgCAQCYBQAh-gIAAM8F-gIiBesCAQAAAAHzAkAAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCAg8NAAC1BgAgDwAAtgYAIBAAALcGACARAAC4BgAgEwAAuQYAIBQAALoGACDTAgEAAAAB6wIBAAAAAfMCQAAAAAH0AkAAAAABjgMBAAAAAY8DAgAAAAGQAxAAAAABkQMgAAAAAZIDAQAAAAEDIwAAuggAIM4DAAC7CAAg1AMAAJoCACAEIwAAqAYAMM4DAACpBgAw0AMAAKsGACDUAwAArAYAMAQjAACbBgAwzgMAAJwGADDQAwAAngYAINQDAACfBgAwBCMAAJAGADDOAwAAkQYAMNADAACTBgAg1AMAANgFADAEIwAAhAYAMM4DAACFBgAw0AMAAIcGACDUAwAAiAYAMAQjAAD5BQAwzgMAAPoFADDQAwAA_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_gcAIM4DAAD8BwAgzwMAAP0HACDUAwAAAQAgAyMAAPsHACDOAwAA_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_AwEAuAQAIcADAQC4BAAhwQMBALgEACHCAwgAkgUAIcMDCACSBQAhEM8CAADhBwAw0AIAAOIHABDRAgAA4QcAMOsCAQCRBAAh8wJAAJQEACH0AkAAlAQAIZUDQACUBAAhmAMBAJEEACGdAwEAuAQAIZ8DAQC4BAAhvgMBAJEEACG_AwEAuAQAIcADAQC4BAAhwQMBALgEACHCAwgAkgUAIcMDCACSBQAhDOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZUDQACaBQAhnQMBAKYFACGfAwEApgUAIb4DAQCYBQAhvwMBAKYFACHAAwEApgUAIcEDAQCmBQAhwgMIALwHACHDAwgAvAcAIQzrAgEAmAUAIfMCQACaBQAh9AJAAJoFACGVA0AAmgUAIZ0DAQCmBQAhnwMBAKYFACG-AwEAmAUAIb8DAQCmBQAhwAMBAKYFACHBAwEApgUAIcIDCAC8BwAhwwMIALwHACEM6wIBAAAAAfMCQAAAAAH0AkAAAAABlQNAAAAAAZ0DAQAAAAGfAwEAAAABvgMBAAAAAb8DAQAAAAHAAwEAAAABwQMBAAAAAcIDCAAAAAHDAwgAAAABBCMAANoHADDOAwAA2wcAMNADAADdBwAg1AMAAN4HADAEIwAAzgcAMM4DAADPBwAw0AMAANEHACDUAwAA0gcAMAQjAADFBwAwzgMAAMYHADDQAwAAyAcAINQDAADLBgAwAAAACwoAAK0HACAWAACuBwAgpQMAAN4GACCrAwAA3gYAIKwDAADeBgAgrQMAAN4GACCuAwAA3gYAIK8DAADeBgAgsAMAAN4GACCxAwAA3gYAILIDAADeBgAgCAoAAK0HACANAADwBwAgDwAA8QcAIBAAAPIHACARAADuBwAgEwAA8wcAIBQAAPQHACCSAwAA3gYAIAAECgAArQcAIA4AAO0HACARAADuBwAg_AIAAN4GACABDAAAkwcAIAAAAAABBgAA3QYAIAAHBAAA6QcAIAUAAOoHACAGAADrBwAgxQMAAN4GACDGAwAA3gYAIMgDAADeBgAgyQMAAN4GACAM6wIBAAAAAfMCQAAAAAH0AkAAAAABlQNAAAAAAZ0DAQAAAAGfAwEAAAABvgMBAAAAAb8DAQAAAAHAAwEAAAABwQMBAAAAAcIDCAAAAAHDAwgAAAABDOsCAQAAAAHzAkAAAAAB9AJAAAAAAbUDAQAAAAG2AwEAAAABtwMBAAAAAbgDAQAAAAG5AwEAAAABugNAAAAAAbsDQAAAAAG8AwEAAAABvQMBAAAAAQPzAkAAAAAB9QIBAAAAAZoDAAAAmgMCDgUAAOcHACAGAADoBwAg0wIBAAAAAesCAQAAAAHsAgEAAAAB8wJAAAAAAfQCQAAAAAGaAwEAAAABxAMgAAAAAcUDAQAAAAHGAwEAAAABxwMgAAAAAcgDQAAAAAHJAwEAAAABAgAAAAEAICMAAPsHACADAAAATQAgIwAA-wcAICQAAP8HACAQAAAATQAgBQAAwwcAIAYAAMQHACAcAAD_BwAg0wIBAJgFACHrAgEAmAUAIewCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZoDAQCYBQAhxAMgAPEFACHFAwEApgUAIcYDAQCmBQAhxwMgAPEFACHIA0AAtAUAIckDAQCmBQAhDgUAAMMHACAGAADEBwAg0wIBAJgFACHrAgEAmAUAIewCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZoDAQCYBQAhxAMgAPEFACHFAwEApgUAIcYDAQCmBQAhxwMgAPEFACHIA0AAtAUAIckDAQCmBQAhDgQAAOYHACAGAADoBwAg0wIBAAAAAesCAQAAAAHsAgEAAAAB8wJAAAAAAfQCQAAAAAGaAwEAAAABxAMgAAAAAcUDAQAAAAHGAwEAAAABxwMgAAAAAcgDQAAAAAHJAwEAAAABAgAAAAEAICMAAIAIACADAAAATQAgIwAAgAgAICQAAIQIACAQAAAATQAgBAAAwgcAIAYAAMQHACAcAACECAAg0wIBAJgFACHrAgEAmAUAIewCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZoDAQCYBQAhxAMgAPEFACHFAwEApgUAIcYDAQCmBQAhxwMgAPEFACHIA0AAtAUAIckDAQCmBQAhDgQAAMIHACAGAADEBwAg0wIBAJgFACHrAgEAmAUAIewCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZoDAQCYBQAhxAMgAPEFACHFAwEApgUAIcYDAQCmBQAhxwMgAPEFACHIA0AAtAUAIckDAQCmBQAhEAgAAKIHACAJAADXBgAgCwAA2AYAIAwAANkGACAUAADaBgAg6wIBAAAAAfMCQAAAAAH0AkAAAAABmwMBAAAAAZwDAQAAAAGdAwEAAAABngMBAAAAAZ8DAQAAAAGgAwEAAAABoQMBAAAAAaIDAQAAAAECAAAAEwAgIwAAhQgAIAMAAAARACAjAACFCAAgJAAAiQgAIBIAAAARACAIAAChBwAgCQAAqAUAIAsAAKkFACAMAACqBQAgFAAAqwUAIBwAAIkIACDrAgEAmAUAIfMCQACaBQAh9AJAAJoFACGbAwEAmAUAIZwDAQCmBQAhnQMBAKYFACGeAwEApgUAIZ8DAQCmBQAhoAMBAJgFACGhAwEAmAUAIaIDAQCmBQAhEAgAAKEHACAJAACoBQAgCwAAqQUAIAwAAKoFACAUAACrBQAg6wIBAJgFACHzAkAAmgUAIfQCQACaBQAhmwMBAJgFACGcAwEApgUAIZ0DAQCmBQAhngMBAKYFACGfAwEApgUAIaADAQCYBQAhoQMBAJgFACGiAwEApgUAIRAKAACsBwAg8wJAAAAAAfQCQAAAAAH1AgEAAAAB_gIAAACpAwKiAwEAAAABpQMAAAClAwOqAwEAAAABqwMBAAAAAawDAQAAAAGtAwEAAAABrgNAAAAAAa8DQAAAAAGwA0AAAAABsQNAAAAAAbIDQAAAAAECAAAAqAEAICMAAIoIACADAAAAPgAgIwAAiggAICQAAI4IACASAAAAPgAgCgAAqwcAIBwAAI4IACDzAkAAmgUAIfQCQACaBQAh9QIBAJgFACH-AgAAsgWpAyKiAwEAmAUAIaUDAACzBaUDI6oDAQCYBQAhqwMBAKYFACGsAwEApgUAIa0DAQCmBQAhrgNAALQFACGvA0AAtAUAIbADQAC0BQAhsQNAALQFACGyA0AAtAUAIRAKAACrBwAg8wJAAJoFACH0AkAAmgUAIfUCAQCYBQAh_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_MCQAAAAAGYAwEAAAABmgMAAACaAwII6wIBAAAAAewCAQAAAAHzAkAAAAAB9AJAAAAAAZQDAQAAAAGVA0AAAAABlgNAAAAAAZcDQAAAAAEG0wIBAAAAAesCAQAAAAHzAkAAAAAB9AJAAAAAAYwDIAAAAAGTAwEAAAABAgAAAJoCACAjAAC6CAAgBesCAQAAAAHzAkAAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCAgjUAhAAAAAB6wIBAAAAAfMCQAAAAAH0AkAAAAAB9wIBAAAAAfgCAQAAAAH6AgAAAPoCA4wDIAAAAAEQCgAAgwYAIA4AAOQFACDrAgEAAAAB8wJAAAAAAfQCQAAAAAH1AgEAAAAB9gIBAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgL7AkAAAAAB_AJAAAAAAf4CAAAA_gIC_wIBAAAAAYADAQAAAAGBAwEAAAABAgAAADYAICMAAL4IACADAAAALQAgIwAAvggAICQAAMIIACASAAAALQAgCgAAgQYAIA4AANIFACAcAADCCAAg6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH6AgAAzwX6AiL7AkAAmgUAIfwCQAC0BQAh_gIAANAF_gIi_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhEAoAAIEGACAOAADSBQAg6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACH2AgEAmAUAIfcCAQCYBQAh-AIBAJgFACH6AgAAzwX6AiL7AkAAmgUAIfwCQAC0BQAh_gIAANAF_gIi_wIBAJgFACGAAwEAmAUAIYEDAQCYBQAhDOsCAQAAAAHzAkAAAAAB9AJAAAAAAfcCAQAAAAH4AgEAAAAB_gIAAACFAwL_AgEAAAABgAMBAAAAAYEDAQAAAAGCAwEAAAABgwNAAAAAAYsDAQAAAAEH6wIBAAAAAfMCQAAAAAH0AkAAAAAB9wIBAAAAAfgCAQAAAAH7AkAAAAABjQMBAAAAARAIAACiBwAgCQAA1wYAIAsAANgGACAMAADZBgAgFQAA2wYAIOsCAQAAAAHzAkAAAAAB9AJAAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DAQAAAAGfAwEAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABAgAAABMAICMAAMUIACADAAAAEQAgIwAAxQgAICQAAMkIACASAAAAEQAgCAAAoQcAIAkAAKgFACALAACpBQAgDAAAqgUAIBUAAKwFACAcAADJCAAg6wIBAJgFACHzAkAAmgUAIfQCQACaBQAhmwMBAJgFACGcAwEApgUAIZ0DAQCmBQAhngMBAKYFACGfAwEApgUAIaADAQCYBQAhoQMBAJgFACGiAwEApgUAIRAIAAChBwAgCQAAqAUAIAsAAKkFACAMAACqBQAgFQAArAUAIOsCAQCYBQAh8wJAAJoFACH0AkAAmgUAIZsDAQCYBQAhnAMBAKYFACGdAwEApgUAIZ4DAQCmBQAhnwMBAKYFACGgAwEAmAUAIaEDAQCYBQAhogMBAKYFACEN6wIBAAAAAfMCQAAAAAH0AkAAAAAB9QIBAAAAAfcCAQAAAAH4AgEAAAAB-gIAAAD6AgL7AkAAAAAB_AJAAAAAAf4CAAAA_gIC_wIBAAAAAYADAQAAAAGBAwEAAAABAwAAAJ0CACAjAAC6CAAgJAAAzQgAIAgAAACdAgAgHAAAzQgAINMCAQCYBQAh6wIBAJgFACHzAkAAmgUAIfQCQACaBQAhjAMgAPEFACGTAwEAmAUAIQbTAgEAmAUAIesCAQCYBQAh8wJAAJoFACH0AkAAmgUAIYwDIADxBQAhkwMBAJgFACEJ0wIBAAAAAesCAQAAAAHzAkAAAAAB9AJAAAAAAY4DAQAAAAGPAwIAAAABkAMQAAAAAZEDIAAAAAGSAwEAAAABEAoAAIQHACANAAC1BgAgDwAAtgYAIBAAALcGACARAAC4BgAgEwAAuQYAINMCAQAAAAHrAgEAAAAB8wJAAAAAAfQCQAAAAAH1AgEAAAABjgMBAAAAAY8DAgAAAAGQAxAAAAABkQMgAAAAAZIDAQAAAAECAAAAHQAgIwAAzwgAIBAKAACEBwAgDQAAtQYAIA8AALYGACAQAAC3BgAgEwAAuQYAIBQAALoGACDTAgEAAAAB6wIBAAAAAfMCQAAAAAH0AkAAAAAB9QIBAAAAAY4DAQAAAAGPAwIAAAABkAMQAAAAAZEDIAAAAAGSAwEAAAABAgAAAB0AICMAANEIACADAAAAGwAgIwAA0QgAICQAANUIACASAAAAGwAgCgAAgwcAIA0AAPMFACAPAAD0BQAgEAAA9QUAIBMAAPcFACAUAAD4BQAgHAAA1QgAINMCAQCYBQAh6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACGOAwEAmAUAIY8DAgDwBQAhkAMQAJkFACGRAyAA8QUAIZIDAQCmBQAhEAoAAIMHACANAADzBQAgDwAA9AUAIBAAAPUFACATAAD3BQAgFAAA-AUAINMCAQCYBQAh6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACGOAwEAmAUAIY8DAgDwBQAhkAMQAJkFACGRAyAA8QUAIZIDAQCmBQAhDOsCAQAAAAHzAkAAAAAB9AJAAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAf4CAAAAhQMC_wIBAAAAAYADAQAAAAGBAwEAAAABggMBAAAAAYMDQAAAAAEDAAAAGwAgIwAAzwgAICQAANkIACASAAAAGwAgCgAAgwcAIA0AAPMFACAPAAD0BQAgEAAA9QUAIBEAAPYFACATAAD3BQAgHAAA2QgAINMCAQCYBQAh6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACGOAwEAmAUAIY8DAgDwBQAhkAMQAJkFACGRAyAA8QUAIZIDAQCmBQAhEAoAAIMHACANAADzBQAgDwAA9AUAIBAAAPUFACARAAD2BQAgEwAA9wUAINMCAQCYBQAh6wIBAJgFACHzAkAAmgUAIfQCQACaBQAh9QIBAJgFACGOAwEAmAUAIY8DAgDwBQAhkAMQAJkFACGRAyAA8QUAIZIDAQCmBQAhDesCAQAAAAHzAkAAAAAB9AJAAAAAAfYCAQAAAAH3AgEAAAAB-AIBAAAAAfoCAAAA-gIC-wJAAAAAAfwCQAAAAAH-AgAAAP4CAv8CAQAAAAGAAwEAAAABgQMBAAAAAQjrAgEAAAABhQMAAACpAwOGAwAAAKkDA6MDAQAAAAGlAwAAAKUDAqYDAQAAAAGnA4AAAAABqQNAAAAAAQrrAgEAAAAB8wJAAAAAAfQCQAAAAAGbAwEAAAABnAMBAAAAAZ0DAQAAAAGeAwEAAAABnwMBAAAAAaADAQAAAAGhAwEAAAABBAQGAgUKAwYOBAcAFwEDAAEBAwABAgMAAQoABQcHABYIEAYJFgQLGggMHgkUPQ8VPxMCBhQFBwAHAQYVAAEKAAUIBwASCgAFDQAKDyQMECgNESwOEzQRFDcPAgcACwwfCQEMIAABDgAJAQ4ACQIOAAkSLg8EBwAQCgAFDgAJES8OAREwAAEOAAkFDzgAEDkAEToAEzsAFDwAAwcAFQoABRZDFAEVABMBFkQABAlFAAtGAAxHABRIAAMESQAFSgAGSwAAAAADBwAcKQAdKgAeAAAAAwcAHCkAHSoAHgEDAAEBAwABBQcAIykAJioAJzsAJDwAJQAAAAAABQcAIykAJioAJzsAJDwAJQEDAAEBAwABAwcALCkALSoALgAAAAMHACwpAC0qAC4AAAADBwA0KQA1KgA2AAAAAwcANCkANSoANgEKAAUBCgAFAwcAOykAPCoAPQAAAAMHADspADwqAD0BFQATARUAEwMHAEIpAEMqAEQAAAADBwBCKQBDKgBEAQjgAQYBCOYBBgMHAEkpAEoqAEsAAAADBwBJKQBKKgBLAgMAAQoABQIDAAEKAAUDBwBQKQBRKgBSAAAAAwcAUCkAUSoAUgEKAAUBCgAFAwcAVykAWCoAWQAAAAMHAFcpAFgqAFkAAAMHAF4pAF8qAGAAAAADBwBeKQBfKgBgAgoABQ0ACgIKAAUNAAoFBwBlKQBoKgBpOwBmPABnAAAAAAAFBwBlKQBoKgBpOwBmPABnAQ4ACQEOAAkDBwBuKQBvKgBwAAAAAwcAbikAbyoAcAEOAAkBDgAJAwcAdSkAdioAdwAAAAMHAHUpAHYqAHcBDgAJAQ4ACQUHAHwpAH8qAIABOwB9PAB-AAAAAAAFBwB8KQB_KgCAATsAfTwAfgIOAAkSlQMPAg4ACRKbAw8DBwCFASkAhgEqAIcBAAAAAwcAhQEpAIYBKgCHAQAAAAMHAI0BKQCOASoAjwEAAAADBwCNASkAjgEqAI8BAgoABQ4ACQIKAAUOAAkDBwCUASkAlQEqAJYBAAAAAwcAlAEpAJUBKgCWAQAAAAUHAJwBKQCfASoAoAE7AJ0BPACeAQAAAAAABQcAnAEpAJ8BKgCgATsAnQE8AJ4BAAAFBwClASkAqAEqAKkBOwCmATwApwEAAAAAAAUHAKUBKQCoASoAqQE7AKYBPACnARcCARhMARlPARpQARtRAR1TAR5VGB9WGSBYASFaGCJbGiVcASZdASdeGCthGyxiHy1jAi5kAi9lAjBmAjFnAjJpAjNrGDRsIDVuAjZwGDdxIThyAjlzAjp0GD13Ij54KD95A0B6A0F7A0J8A0N9A0R_A0WBARhGggEpR4QBA0iGARhJhwEqSogBA0uJAQNMigEYTY0BK06OAS9PkAEwUJEBMFGUATBSlQEwU5YBMFSYATBVmgEYVpsBMVedATBYnwEYWaABMlqhATBbogEwXKMBGF2mATNepwE3X6kBE2CqARNhrAETYq0BE2OuARNksAETZbIBGGazAThntQETaLcBGGm4ATlquQETa7oBE2y7ARhtvgE6br8BPm_AARRwwQEUccIBFHLDARRzxAEUdMYBFHXIARh2yQE_d8sBFHjNARh5zgFAes8BFHvQARR80QEYfdQBQX7VAUV_1gEFgAHXAQWBAdgBBYIB2QEFgwHaAQWEAdwBBYUB3gEYhgHfAUaHAeIBBYgB5AEYiQHlAUeKAecBBYsB6AEFjAHpARiNAewBSI4B7QFMjwHuAQSQAe8BBJEB8AEEkgHxAQSTAfIBBJQB9AEElQH2ARiWAfcBTZcB-QEEmAH7ARiZAfwBTpoB_QEEmwH-AQScAf8BGJ0BggJPngGDAlOfAYQCCKABhQIIoQGGAgiiAYcCCKMBiAIIpAGKAgilAYwCGKYBjQJUpwGPAgioAZECGKkBkgJVqgGTAgirAZQCCKwBlQIYrQGYAlauAZkCWq8BmwIKsAGcAgqxAZ8CCrIBoAIKswGhAgq0AaMCCrUBpQIYtgGmAlu3AagCCrgBqgIYuQGrAly6AawCCrsBrQIKvAGuAhi9AbECXb4BsgJhvwGzAgnAAbQCCcEBtQIJwgG2AgnDAbcCCcQBuQIJxQG7AhjGAbwCYscBvgIJyAHAAhjJAcECY8oBwgIJywHDAgnMAcQCGM0BxwJkzgHIAmrPAckCEdABygIR0QHLAhHSAcwCEdMBzQIR1AHPAhHVAdECGNYB0gJr1wHUAhHYAdYCGNkB1wJs2gHYAhHbAdkCEdwB2gIY3QHdAm3eAd4Ccd8B3wIM4AHgAgzhAeECDOIB4gIM4wHjAgzkAeUCDOUB5wIY5gHoAnLnAeoCDOgB7AIY6QHtAnPqAe4CDOsB7wIM7AHwAhjtAfMCdO4B9AJ47wH1Ag3wAfYCDfEB9wIN8gH4Ag3zAfkCDfQB-wIN9QH9Ahj2Af4CefcBgAMN-AGCAxj5AYMDevoBhAMN-wGFAw38AYYDGP0BiQN7_gGKA4EB_wGLAw6AAowDDoECjQMOggKOAw6DAo8DDoQCkQMOhQKTAxiGApQDggGHApcDDogCmQMYiQKaA4MBigKcAw6LAp0DDowCngMYjQKhA4QBjgKiA4gBjwKkA4kBkAKlA4kBkQKoA4kBkgKpA4kBkwKqA4kBlAKsA4kBlQKuAxiWAq8DigGXArEDiQGYArMDGJkCtAOLAZoCtQOJAZsCtgOJAZwCtwMYnQK6A4wBngK7A5ABnwK8Aw-gAr0DD6ECvgMPogK_Aw-jAsADD6QCwgMPpQLEAximAsUDkQGnAscDD6gCyQMYqQLKA5IBqgLLAw-rAswDD6wCzQMYrQLQA5MBrgLRA5cBrwLTA5gBsALUA5gBsQLXA5gBsgLYA5gBswLZA5gBtALbA5gBtQLdAxi2At4DmQG3AuADmAG4AuIDGLkC4wOaAboC5AOYAbsC5QOYAbwC5gMYvQLpA5sBvgLqA6EBvwLsAwbAAu0DBsEC7wMGwgLwAwbDAvEDBsQC8wMGxQL1AxjGAvYDogHHAvgDBsgC-gMYyQL7A6MBygL8AwbLAv0DBswC_gMYzQKBBKQBzgKCBKoB" } async function decodeBase64AsWasm(wasmBase64: string): Promise { @@ -228,6 +228,26 @@ export interface PrismaClient< */ get verification(): Prisma.VerificationDelegate; + /** + * `prisma.complexBilling`: Exposes CRUD operations for the **ComplexBilling** model. + * Example usage: + * ```ts + * // Fetch zero or more ComplexBillings + * const complexBillings = await prisma.complexBilling.findMany() + * ``` + */ + get complexBilling(): Prisma.ComplexBillingDelegate; + + /** + * `prisma.billingEvent`: Exposes CRUD operations for the **BillingEvent** model. + * Example usage: + * ```ts + * // Fetch zero or more BillingEvents + * const billingEvents = await prisma.billingEvent.findMany() + * ``` + */ + get billingEvent(): Prisma.BillingEventDelegate; + /** * `prisma.complex`: Exposes CRUD operations for the **Complex** model. * Example usage: diff --git a/apps/backend/src/generated/prisma/internal/prismaNamespace.ts b/apps/backend/src/generated/prisma/internal/prismaNamespace.ts index e2ee12e..9effa11 100644 --- a/apps/backend/src/generated/prisma/internal/prismaNamespace.ts +++ b/apps/backend/src/generated/prisma/internal/prismaNamespace.ts @@ -388,6 +388,8 @@ export const ModelName = { Session: 'Session', Account: 'Account', Verification: 'Verification', + ComplexBilling: 'ComplexBilling', + BillingEvent: 'BillingEvent', Complex: 'Complex', ComplexUser: 'ComplexUser', ComplexInvitation: 'ComplexInvitation', @@ -416,7 +418,7 @@ export type TypeMap + fields: Prisma.ComplexBillingFieldRefs + operations: { + findUnique: { + args: Prisma.ComplexBillingFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.ComplexBillingFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.ComplexBillingFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.ComplexBillingFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.ComplexBillingFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.ComplexBillingCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.ComplexBillingCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.ComplexBillingCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.ComplexBillingDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.ComplexBillingUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.ComplexBillingDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.ComplexBillingUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.ComplexBillingUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.ComplexBillingUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.ComplexBillingAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.ComplexBillingGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.ComplexBillingCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } + BillingEvent: { + payload: Prisma.$BillingEventPayload + fields: Prisma.BillingEventFieldRefs + operations: { + findUnique: { + args: Prisma.BillingEventFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.BillingEventFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.BillingEventFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.BillingEventFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.BillingEventFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.BillingEventCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.BillingEventCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.BillingEventCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.BillingEventDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.BillingEventUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.BillingEventDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.BillingEventUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.BillingEventUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.BillingEventUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.BillingEventAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.BillingEventGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.BillingEventCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } Complex: { payload: Prisma.$ComplexPayload fields: Prisma.ComplexFieldRefs @@ -1785,6 +1935,42 @@ export const VerificationScalarFieldEnum = { export type VerificationScalarFieldEnum = (typeof VerificationScalarFieldEnum)[keyof typeof VerificationScalarFieldEnum] +export const ComplexBillingScalarFieldEnum = { + complexId: 'complexId', + status: 'status', + planCode: 'planCode', + currency: 'currency', + provider: 'provider', + providerCustomerId: 'providerCustomerId', + providerSubscriptionId: 'providerSubscriptionId', + providerPreapprovalId: 'providerPreapprovalId', + currentPeriodStart: 'currentPeriodStart', + currentPeriodEnd: 'currentPeriodEnd', + trialEndsAt: 'trialEndsAt', + canceledAt: 'canceledAt', + suspendedAt: 'suspendedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +} as const + +export type ComplexBillingScalarFieldEnum = (typeof ComplexBillingScalarFieldEnum)[keyof typeof ComplexBillingScalarFieldEnum] + + +export const BillingEventScalarFieldEnum = { + id: 'id', + complexId: 'complexId', + eventType: 'eventType', + provider: 'provider', + providerEventId: 'providerEventId', + providerData: 'providerData', + previousStatus: 'previousStatus', + newStatus: 'newStatus', + processedAt: 'processedAt' +} as const + +export type BillingEventScalarFieldEnum = (typeof BillingEventScalarFieldEnum)[keyof typeof BillingEventScalarFieldEnum] + + export const ComplexScalarFieldEnum = { id: 'id', complexName: 'complexName', @@ -1991,6 +2177,14 @@ export const SortOrder = { export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder] +export const NullableJsonNullValueInput = { + DbNull: DbNull, + JsonNull: JsonNull +} as const + +export type NullableJsonNullValueInput = (typeof NullableJsonNullValueInput)[keyof typeof NullableJsonNullValueInput] + + export const JsonNullValueInput = { JsonNull: JsonNull } as const @@ -2078,6 +2272,48 @@ export type ListFloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaMode +/** + * Reference to a field of type 'BillingStatus' + */ +export type EnumBillingStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'BillingStatus'> + + + +/** + * Reference to a field of type 'BillingStatus[]' + */ +export type ListEnumBillingStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'BillingStatus[]'> + + + +/** + * Reference to a field of type 'BillingProvider' + */ +export type EnumBillingProviderFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'BillingProvider'> + + + +/** + * Reference to a field of type 'BillingProvider[]' + */ +export type ListEnumBillingProviderFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'BillingProvider[]'> + + + +/** + * Reference to a field of type 'Json' + */ +export type JsonFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Json'> + + + +/** + * Reference to a field of type 'QueryMode' + */ +export type EnumQueryModeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'QueryMode'> + + + /** * Reference to a field of type 'ComplexUserRole' */ @@ -2161,20 +2397,6 @@ export type EnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel> = FieldRe export type ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'RecurringBookingGroupStatus[]'> - -/** - * Reference to a field of type 'Json' - */ -export type JsonFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Json'> - - - -/** - * Reference to a field of type 'QueryMode' - */ -export type EnumQueryModeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'QueryMode'> - - /** * Batch Payload for updateMany & deleteMany & createMany */ @@ -2274,6 +2496,8 @@ export type GlobalOmitConfig = { session?: Prisma.SessionOmit account?: Prisma.AccountOmit verification?: Prisma.VerificationOmit + complexBilling?: Prisma.ComplexBillingOmit + billingEvent?: Prisma.BillingEventOmit complex?: Prisma.ComplexOmit complexUser?: Prisma.ComplexUserOmit complexInvitation?: Prisma.ComplexInvitationOmit diff --git a/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts b/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts index 4b52b60..a9ff484 100644 --- a/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/apps/backend/src/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -55,6 +55,8 @@ export const ModelName = { Session: 'Session', Account: 'Account', Verification: 'Verification', + ComplexBilling: 'ComplexBilling', + BillingEvent: 'BillingEvent', Complex: 'Complex', ComplexUser: 'ComplexUser', ComplexInvitation: 'ComplexInvitation', @@ -154,6 +156,42 @@ export const VerificationScalarFieldEnum = { export type VerificationScalarFieldEnum = (typeof VerificationScalarFieldEnum)[keyof typeof VerificationScalarFieldEnum] +export const ComplexBillingScalarFieldEnum = { + complexId: 'complexId', + status: 'status', + planCode: 'planCode', + currency: 'currency', + provider: 'provider', + providerCustomerId: 'providerCustomerId', + providerSubscriptionId: 'providerSubscriptionId', + providerPreapprovalId: 'providerPreapprovalId', + currentPeriodStart: 'currentPeriodStart', + currentPeriodEnd: 'currentPeriodEnd', + trialEndsAt: 'trialEndsAt', + canceledAt: 'canceledAt', + suspendedAt: 'suspendedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +} as const + +export type ComplexBillingScalarFieldEnum = (typeof ComplexBillingScalarFieldEnum)[keyof typeof ComplexBillingScalarFieldEnum] + + +export const BillingEventScalarFieldEnum = { + id: 'id', + complexId: 'complexId', + eventType: 'eventType', + provider: 'provider', + providerEventId: 'providerEventId', + providerData: 'providerData', + previousStatus: 'previousStatus', + newStatus: 'newStatus', + processedAt: 'processedAt' +} as const + +export type BillingEventScalarFieldEnum = (typeof BillingEventScalarFieldEnum)[keyof typeof BillingEventScalarFieldEnum] + + export const ComplexScalarFieldEnum = { id: 'id', complexName: 'complexName', @@ -360,6 +398,14 @@ export const SortOrder = { export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder] +export const NullableJsonNullValueInput = { + DbNull: DbNull, + JsonNull: JsonNull +} as const + +export type NullableJsonNullValueInput = (typeof NullableJsonNullValueInput)[keyof typeof NullableJsonNullValueInput] + + export const JsonNullValueInput = { JsonNull: JsonNull } as const diff --git a/apps/backend/src/generated/prisma/models.ts b/apps/backend/src/generated/prisma/models.ts index f499e73..9f7820d 100644 --- a/apps/backend/src/generated/prisma/models.ts +++ b/apps/backend/src/generated/prisma/models.ts @@ -12,6 +12,8 @@ export type * from './models/User' export type * from './models/Session' export type * from './models/Account' export type * from './models/Verification' +export type * from './models/ComplexBilling' +export type * from './models/BillingEvent' export type * from './models/Complex' export type * from './models/ComplexUser' export type * from './models/ComplexInvitation' diff --git a/apps/backend/src/generated/prisma/models/Complex.ts b/apps/backend/src/generated/prisma/models/Complex.ts index 2aa0058..7ff25e2 100644 --- a/apps/backend/src/generated/prisma/models/Complex.ts +++ b/apps/backend/src/generated/prisma/models/Complex.ts @@ -235,6 +235,7 @@ export type ComplexWhereInput = { invitations?: Prisma.ComplexInvitationListRelationFilter courts?: Prisma.CourtListRelationFilter recurringGroups?: Prisma.RecurringBookingGroupListRelationFilter + billing?: Prisma.XOR | null } export type ComplexOrderByWithRelationInput = { @@ -254,6 +255,7 @@ export type ComplexOrderByWithRelationInput = { invitations?: Prisma.ComplexInvitationOrderByRelationAggregateInput courts?: Prisma.CourtOrderByRelationAggregateInput recurringGroups?: Prisma.RecurringBookingGroupOrderByRelationAggregateInput + billing?: Prisma.ComplexBillingOrderByWithRelationInput } export type ComplexWhereUniqueInput = Prisma.AtLeast<{ @@ -276,6 +278,7 @@ export type ComplexWhereUniqueInput = Prisma.AtLeast<{ invitations?: Prisma.ComplexInvitationListRelationFilter courts?: Prisma.CourtListRelationFilter recurringGroups?: Prisma.RecurringBookingGroupListRelationFilter + billing?: Prisma.XOR | null }, "id" | "complexSlug"> export type ComplexOrderByWithAggregationInput = { @@ -328,6 +331,7 @@ export type ComplexCreateInput = { invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingCreateNestedOneWithoutComplexInput } export type ComplexUncheckedCreateInput = { @@ -346,6 +350,7 @@ export type ComplexUncheckedCreateInput = { invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingUncheckedCreateNestedOneWithoutComplexInput } export type ComplexUpdateInput = { @@ -364,6 +369,7 @@ export type ComplexUpdateInput = { invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateInput = { @@ -382,6 +388,7 @@ export type ComplexUncheckedUpdateInput = { invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUncheckedUpdateOneWithoutComplexNestedInput } export type ComplexCreateManyInput = { @@ -425,6 +432,11 @@ export type ComplexUncheckedUpdateManyInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string } +export type ComplexScalarRelationFilter = { + is?: Prisma.ComplexWhereInput + isNot?: Prisma.ComplexWhereInput +} + export type ComplexCountOrderByAggregateInput = { id?: Prisma.SortOrder complexName?: Prisma.SortOrder @@ -467,11 +479,6 @@ export type ComplexMinOrderByAggregateInput = { updatedAt?: Prisma.SortOrder } -export type ComplexScalarRelationFilter = { - is?: Prisma.ComplexWhereInput - isNot?: Prisma.ComplexWhereInput -} - export type ComplexListRelationFilter = { every?: Prisma.ComplexWhereInput some?: Prisma.ComplexWhereInput @@ -482,6 +489,20 @@ export type ComplexOrderByRelationAggregateInput = { _count?: Prisma.SortOrder } +export type ComplexCreateNestedOneWithoutBillingInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutBillingInput + connect?: Prisma.ComplexWhereUniqueInput +} + +export type ComplexUpdateOneRequiredWithoutBillingNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutBillingInput + upsert?: Prisma.ComplexUpsertWithoutBillingInput + connect?: Prisma.ComplexWhereUniqueInput + update?: Prisma.XOR, Prisma.ComplexUncheckedUpdateWithoutBillingInput> +} + export type ComplexCreateNestedOneWithoutUsersInput = { create?: Prisma.XOR connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutUsersInput @@ -580,6 +601,94 @@ export type ComplexUncheckedUpdateManyWithoutPlanNestedInput = { deleteMany?: Prisma.ComplexScalarWhereInput | Prisma.ComplexScalarWhereInput[] } +export type ComplexCreateWithoutBillingInput = { + id: string + complexName: string + physicalAddress?: string | null + city?: string | null + state?: string | null + country?: string | null + complexSlug: string + adminEmail: string + createdAt?: Date | string + updatedAt?: Date | string + plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput + users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput + invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput + courts?: Prisma.CourtCreateNestedManyWithoutComplexInput + recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput +} + +export type ComplexUncheckedCreateWithoutBillingInput = { + id: string + complexName: string + physicalAddress?: string | null + city?: string | null + state?: string | null + country?: string | null + complexSlug: string + adminEmail: string + planCode?: string | null + createdAt?: Date | string + updatedAt?: Date | string + users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput + invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput + courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput + recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput +} + +export type ComplexCreateOrConnectWithoutBillingInput = { + where: Prisma.ComplexWhereUniqueInput + create: Prisma.XOR +} + +export type ComplexUpsertWithoutBillingInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.ComplexWhereInput +} + +export type ComplexUpdateToOneWithWhereWithoutBillingInput = { + where?: Prisma.ComplexWhereInput + data: Prisma.XOR +} + +export type ComplexUpdateWithoutBillingInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + complexName?: Prisma.StringFieldUpdateOperationsInput | string + physicalAddress?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + city?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + state?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + country?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + complexSlug?: Prisma.StringFieldUpdateOperationsInput | string + adminEmail?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput + users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput + invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput + courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput + recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput +} + +export type ComplexUncheckedUpdateWithoutBillingInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + complexName?: Prisma.StringFieldUpdateOperationsInput | string + physicalAddress?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + city?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + state?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + country?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + complexSlug?: Prisma.StringFieldUpdateOperationsInput | string + adminEmail?: Prisma.StringFieldUpdateOperationsInput | string + planCode?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput + invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput + courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput + recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput +} + export type ComplexCreateWithoutUsersInput = { id: string complexName: string @@ -595,6 +704,7 @@ export type ComplexCreateWithoutUsersInput = { invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingCreateNestedOneWithoutComplexInput } export type ComplexUncheckedCreateWithoutUsersInput = { @@ -612,6 +722,7 @@ export type ComplexUncheckedCreateWithoutUsersInput = { invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingUncheckedCreateNestedOneWithoutComplexInput } export type ComplexCreateOrConnectWithoutUsersInput = { @@ -645,6 +756,7 @@ export type ComplexUpdateWithoutUsersInput = { invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateWithoutUsersInput = { @@ -662,6 +774,7 @@ export type ComplexUncheckedUpdateWithoutUsersInput = { invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUncheckedUpdateOneWithoutComplexNestedInput } export type ComplexCreateWithoutInvitationsInput = { @@ -679,6 +792,7 @@ export type ComplexCreateWithoutInvitationsInput = { users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingCreateNestedOneWithoutComplexInput } export type ComplexUncheckedCreateWithoutInvitationsInput = { @@ -696,6 +810,7 @@ export type ComplexUncheckedCreateWithoutInvitationsInput = { users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingUncheckedCreateNestedOneWithoutComplexInput } export type ComplexCreateOrConnectWithoutInvitationsInput = { @@ -729,6 +844,7 @@ export type ComplexUpdateWithoutInvitationsInput = { users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateWithoutInvitationsInput = { @@ -746,6 +862,7 @@ export type ComplexUncheckedUpdateWithoutInvitationsInput = { users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUncheckedUpdateOneWithoutComplexNestedInput } export type ComplexCreateWithoutCourtsInput = { @@ -763,6 +880,7 @@ export type ComplexCreateWithoutCourtsInput = { users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingCreateNestedOneWithoutComplexInput } export type ComplexUncheckedCreateWithoutCourtsInput = { @@ -780,6 +898,7 @@ export type ComplexUncheckedCreateWithoutCourtsInput = { users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingUncheckedCreateNestedOneWithoutComplexInput } export type ComplexCreateOrConnectWithoutCourtsInput = { @@ -813,6 +932,7 @@ export type ComplexUpdateWithoutCourtsInput = { users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateWithoutCourtsInput = { @@ -830,6 +950,7 @@ export type ComplexUncheckedUpdateWithoutCourtsInput = { users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUncheckedUpdateOneWithoutComplexNestedInput } export type ComplexCreateWithoutRecurringGroupsInput = { @@ -847,6 +968,7 @@ export type ComplexCreateWithoutRecurringGroupsInput = { users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingCreateNestedOneWithoutComplexInput } export type ComplexUncheckedCreateWithoutRecurringGroupsInput = { @@ -864,6 +986,7 @@ export type ComplexUncheckedCreateWithoutRecurringGroupsInput = { users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingUncheckedCreateNestedOneWithoutComplexInput } export type ComplexCreateOrConnectWithoutRecurringGroupsInput = { @@ -897,6 +1020,7 @@ export type ComplexUpdateWithoutRecurringGroupsInput = { users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateWithoutRecurringGroupsInput = { @@ -914,6 +1038,7 @@ export type ComplexUncheckedUpdateWithoutRecurringGroupsInput = { users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUncheckedUpdateOneWithoutComplexNestedInput } export type ComplexCreateWithoutPlanInput = { @@ -931,6 +1056,7 @@ export type ComplexCreateWithoutPlanInput = { invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingCreateNestedOneWithoutComplexInput } export type ComplexUncheckedCreateWithoutPlanInput = { @@ -948,6 +1074,7 @@ export type ComplexUncheckedCreateWithoutPlanInput = { invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput + billing?: Prisma.ComplexBillingUncheckedCreateNestedOneWithoutComplexInput } export type ComplexCreateOrConnectWithoutPlanInput = { @@ -1021,6 +1148,7 @@ export type ComplexUpdateWithoutPlanInput = { invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateWithoutPlanInput = { @@ -1038,6 +1166,7 @@ export type ComplexUncheckedUpdateWithoutPlanInput = { invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput + billing?: Prisma.ComplexBillingUncheckedUpdateOneWithoutComplexNestedInput } export type ComplexUncheckedUpdateManyWithoutPlanInput = { @@ -1128,6 +1257,7 @@ export type ComplexSelect courts?: boolean | Prisma.Complex$courtsArgs recurringGroups?: boolean | Prisma.Complex$recurringGroupsArgs + billing?: boolean | Prisma.Complex$billingArgs _count?: boolean | Prisma.ComplexCountOutputTypeDefaultArgs }, ExtArgs["result"]["complex"]> @@ -1182,6 +1312,7 @@ export type ComplexInclude courts?: boolean | Prisma.Complex$courtsArgs recurringGroups?: boolean | Prisma.Complex$recurringGroupsArgs + billing?: boolean | Prisma.Complex$billingArgs _count?: boolean | Prisma.ComplexCountOutputTypeDefaultArgs } export type ComplexIncludeCreateManyAndReturn = { @@ -1199,6 +1330,7 @@ export type $ComplexPayload[] courts: Prisma.$CourtPayload[] recurringGroups: Prisma.$RecurringBookingGroupPayload[] + billing: Prisma.$ComplexBillingPayload | null } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1611,6 +1743,7 @@ export interface Prisma__ComplexClient = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> courts = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> recurringGroups = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + billing = {}>(args?: Prisma.Subset>): Prisma.Prisma__ComplexBillingClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -2166,6 +2299,25 @@ export type Complex$recurringGroupsArgs = { + /** + * Select specific fields to fetch from the ComplexBilling + */ + select?: Prisma.ComplexBillingSelect | null + /** + * Omit specific fields from the ComplexBilling + */ + omit?: Prisma.ComplexBillingOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ComplexBillingInclude | null + where?: Prisma.ComplexBillingWhereInput +} + /** * Complex without action */ diff --git a/apps/backend/src/modules/admin-booking/features/create-admin-recurring-booking/create-admin-recurring-booking.business.ts b/apps/backend/src/modules/admin-booking/features/create-admin-recurring-booking/create-admin-recurring-booking.business.ts index b484ad8..dacf719 100644 --- a/apps/backend/src/modules/admin-booking/features/create-admin-recurring-booking/create-admin-recurring-booking.business.ts +++ b/apps/backend/src/modules/admin-booking/features/create-admin-recurring-booking/create-admin-recurring-booking.business.ts @@ -249,7 +249,7 @@ export async function createAdminRecurringBooking( customerPhone: input.customerPhone.trim(), customerEmail: input.customerEmail?.trim() ?? '', status: 'CONFIRMED', - recurringGroupId: groupId, + recurringGroupId: groupId, }, include: { court: { diff --git a/apps/backend/src/modules/billing/billing.routes.ts b/apps/backend/src/modules/billing/billing.routes.ts new file mode 100644 index 0000000..f690cb8 --- /dev/null +++ b/apps/backend/src/modules/billing/billing.routes.ts @@ -0,0 +1,24 @@ +import { validate } from '@/lib/http/validate'; +import { requireAuth } from '@/middlewares/require-auth.middleware'; +import { cancelSubscriptionHandler } from '@/modules/billing/features/cancel-subscription/cancel-subscription.handler'; +import { createCheckoutHandler } from '@/modules/billing/features/create-checkout/create-checkout.handler'; +import { getBillingStatusHandler } from '@/modules/billing/features/get-billing-status/get-billing-status.handler'; +import { mercadopagoWebhookHandler } from '@/modules/billing/features/mercadopago-webhook/mercadopago-webhook.handler'; +import { stripeWebhookHandler } from '@/modules/billing/features/stripe-webhook/stripe-webhook.handler'; +import type { AppEnv } from '@/types/hono'; +import { createCheckoutSchema } from '@repo/api-contract'; +import { Hono } from 'hono'; + +export const billingRoutes = new Hono(); + +billingRoutes.post( + '/checkout', + requireAuth, + validate.json(createCheckoutSchema), + createCheckoutHandler +); +billingRoutes.post('/cancel', requireAuth, cancelSubscriptionHandler); +billingRoutes.get('/status', requireAuth, getBillingStatusHandler); + +billingRoutes.post('/webhooks/stripe', stripeWebhookHandler); +billingRoutes.post('/webhooks/mercadopago', mercadopagoWebhookHandler); diff --git a/apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.business.ts b/apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.business.ts new file mode 100644 index 0000000..b8bcb86 --- /dev/null +++ b/apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.business.ts @@ -0,0 +1,47 @@ +import { Errors } from '@/lib/errors'; +import { db } from '@/lib/prisma'; +import { type Result, err, ok } from '@/lib/result'; +import { getBilling } from '@/modules/billing/services/billing-repository.service'; +import { getProviderForComplex } from '@/modules/billing/services/provider-resolver.service'; + +export async function cancelSubscription( + user: { id: string }, + complexId: string +): Promise> { + const userAccess = await db.complexUser.findUnique({ + where: { complexId_userId: { complexId, userId: user.id } }, + select: { role: true }, + }); + + if (!userAccess || userAccess.role !== 'ADMIN') { + return err(Errors.forbidden('Only admins can cancel the subscription')); + } + + const billingResult = await getBilling(complexId); + if (!billingResult.ok) return err(billingResult.error); + const billing = billingResult.value; + + if (billing.status === 'CANCELED' || billing.status === 'SUSPENDED') { + return err(Errors.conflict('La suscripción ya está cancelada o suspendida')); + } + + const providerResult = await getProviderForComplex(complexId); + if (!providerResult.ok) return err(providerResult.error); + const { provider } = providerResult.value; + + const subId = billing.providerSubscriptionId; + if (subId) { + const cancelResult = await provider.cancelSubscription(subId); + if (!cancelResult.ok) return err(cancelResult.error); + } + + await db.complexBilling.update({ + where: { complexId }, + data: { + status: 'CANCELED', + canceledAt: new Date(), + }, + }); + + return ok({ status: 'CANCELED' }); +} diff --git a/apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.handler.ts b/apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.handler.ts new file mode 100644 index 0000000..c7efb80 --- /dev/null +++ b/apps/backend/src/modules/billing/features/cancel-subscription/cancel-subscription.handler.ts @@ -0,0 +1,17 @@ +import { handleResult } from '@/lib/http/handle-result'; +import type { AppContext } from '@/types/hono'; +import { getCookie } from 'hono/cookie'; +import { cancelSubscription } from './cancel-subscription.business'; + +const SELECTED_COMPLEX_COOKIE = 'selected-complex-id'; + +export async function cancelSubscriptionHandler(c: AppContext) { + const user = c.get('user'); + const complexId = getCookie(c, SELECTED_COMPLEX_COOKIE); + + if (!complexId) { + return c.json({ message: 'No complex selected' }, 400); + } + + return handleResult(c, await cancelSubscription(user, complexId)); +} diff --git a/apps/backend/src/modules/billing/features/create-checkout/create-checkout.business.ts b/apps/backend/src/modules/billing/features/create-checkout/create-checkout.business.ts new file mode 100644 index 0000000..97ff628 --- /dev/null +++ b/apps/backend/src/modules/billing/features/create-checkout/create-checkout.business.ts @@ -0,0 +1,80 @@ +import { Errors } from '@/lib/errors'; +import { db } from '@/lib/prisma'; +import { type Result, err, ok } from '@/lib/result'; +import { hasActiveSubscription } from '@/modules/billing/services/billing-repository.service'; +import { getProviderForComplex } from '@/modules/billing/services/provider-resolver.service'; +import type { CheckoutResponse, CreateCheckoutInput } from '@repo/api-contract'; +import { v7 as uuidv7 } from 'uuid'; + +export async function createCheckout( + user: { id: string; email: string }, + complexId: string, + input: CreateCheckoutInput +): Promise> { + const complex = await db.complex.findUnique({ + where: { id: complexId }, + select: { id: true, country: true }, + }); + + if (!complex) { + return err(Errors.notFound('Complex not found')); + } + + const userAccess = await db.complexUser.findUnique({ + where: { complexId_userId: { complexId, userId: user.id } }, + }); + + if (!userAccess) { + return err(Errors.forbidden('You do not have access to this complex')); + } + + const activeResult = await hasActiveSubscription(complexId); + if (!activeResult.ok) return err(activeResult.error); + if (activeResult.value) { + return err(Errors.conflict('Ya existe una suscripción activa para este complejo')); + } + + const providerResult = await getProviderForComplex(complexId); + if (!providerResult.ok) return err(providerResult.error); + const { provider, country } = providerResult.value; + + const currency = country === 'AR' ? 'ARS' : 'USD'; + + const baseUrl = Bun.env.FRONTEND_BASE_URL || Bun.env.APP_BASE_URL || 'http://localhost:5173'; + const successUrl = `${baseUrl}/billing/success`; + const cancelUrl = `${baseUrl}/billing/cancel`; + + const checkoutResult = await provider.createCheckout({ + planCode: input.planCode, + complexId, + customerEmail: user.email, + successUrl, + cancelUrl, + }); + + if (!checkoutResult.ok) return err(checkoutResult.error); + + await db.complexBilling.upsert({ + where: { complexId }, + create: { + complexId, + planCode: input.planCode, + currency, + status: 'TRIAL', + provider: country === 'AR' ? 'MERCADOPAGO' : 'STRIPE', + providerSubscriptionId: checkoutResult.value.providerSubscriptionId, + }, + update: { + planCode: input.planCode, + currency, + status: 'TRIAL', + provider: country === 'AR' ? 'MERCADOPAGO' : 'STRIPE', + providerSubscriptionId: checkoutResult.value.providerSubscriptionId, + }, + }); + + return ok({ + checkoutUrl: checkoutResult.value.checkoutUrl, + subscriptionId: checkoutResult.value.providerSubscriptionId, + }); +} diff --git a/apps/backend/src/modules/billing/features/create-checkout/create-checkout.handler.ts b/apps/backend/src/modules/billing/features/create-checkout/create-checkout.handler.ts new file mode 100644 index 0000000..ead3031 --- /dev/null +++ b/apps/backend/src/modules/billing/features/create-checkout/create-checkout.handler.ts @@ -0,0 +1,19 @@ +import { handleResult } from '@/lib/http/handle-result'; +import type { AppContext } from '@/types/hono'; +import type { CreateCheckoutInput } from '@repo/api-contract'; +import { getCookie } from 'hono/cookie'; +import { createCheckout } from './create-checkout.business'; + +const SELECTED_COMPLEX_COOKIE = 'selected-complex-id'; + +export async function createCheckoutHandler(c: AppContext) { + const user = c.get('user'); + const complexId = getCookie(c, SELECTED_COMPLEX_COOKIE); + const payload = c.req.valid('json' as never) as CreateCheckoutInput; + + if (!complexId) { + return c.json({ message: 'No complex selected' }, 400); + } + + return handleResult(c, await createCheckout(user, complexId, payload), 201); +} diff --git a/apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.business.ts b/apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.business.ts new file mode 100644 index 0000000..3d9836b --- /dev/null +++ b/apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.business.ts @@ -0,0 +1,26 @@ +import { Errors } from '@/lib/errors'; +import { type Result, err, ok } from '@/lib/result'; +import { getBilling } from '@/modules/billing/services/billing-repository.service'; +import type { BillingStatusResponse } from '@repo/api-contract'; + +export async function getBillingStatus( + _user: { id: string }, + complexId: string +): Promise> { + const billingResult = await getBilling(complexId); + if (!billingResult.ok) return err(billingResult.error); + const billing = billingResult.value; + + return ok({ + complexId: billing.complexId, + status: billing.status, + planCode: billing.planCode, + currency: billing.currency, + provider: billing.provider, + currentPeriodEnd: billing.currentPeriodEnd?.toISOString() ?? null, + currentPeriodStart: billing.currentPeriodStart?.toISOString() ?? null, + trialEndsAt: billing.trialEndsAt?.toISOString() ?? null, + canceledAt: billing.canceledAt?.toISOString() ?? null, + suspendedAt: billing.suspendedAt?.toISOString() ?? null, + }); +} diff --git a/apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.handler.ts b/apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.handler.ts new file mode 100644 index 0000000..112fefc --- /dev/null +++ b/apps/backend/src/modules/billing/features/get-billing-status/get-billing-status.handler.ts @@ -0,0 +1,17 @@ +import { handleResult } from '@/lib/http/handle-result'; +import type { AppContext } from '@/types/hono'; +import { getCookie } from 'hono/cookie'; +import { getBillingStatus } from './get-billing-status.business'; + +const SELECTED_COMPLEX_COOKIE = 'selected-complex-id'; + +export async function getBillingStatusHandler(c: AppContext) { + const user = c.get('user'); + const complexId = getCookie(c, SELECTED_COMPLEX_COOKIE); + + if (!complexId) { + return c.json({ message: 'No complex selected' }, 400); + } + + return handleResult(c, await getBillingStatus(user, complexId)); +} diff --git a/apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.business.ts b/apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.business.ts new file mode 100644 index 0000000..9d0493b --- /dev/null +++ b/apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.business.ts @@ -0,0 +1,133 @@ +import { Errors } from '@/lib/errors'; +import { logger } from '@/lib/logger'; +import { db } from '@/lib/prisma'; +import { type Result, err, ok } from '@/lib/result'; +import type { WebhookEvent } from '@/modules/billing/providers/billing-provider.interface'; +import { mercadopagoBillingProvider } from '@/modules/billing/providers/mercadopago.provider'; +import { + findEventByProviderId, + recordBillingEvent, + updateBillingStatus, +} from '@/modules/billing/services/billing-repository.service'; +import type { BillingStatusEnum } from '@/modules/billing/services/billing-repository.service'; + +const MP_PROVIDER = 'MERCADOPAGO'; + +function mapWebhookTypeToStatus(event: WebhookEvent): BillingStatusEnum | null { + switch (event.type) { + case 'activated': + return 'ACTIVE'; + case 'updated': + return 'ACTIVE'; + case 'payment_failed': + return 'PAST_DUE'; + case 'cancelled': + return 'CANCELED'; + default: + return null; + } +} + +async function getBillingByPreapprovalId(preapprovalId: string) { + return db.complexBilling.findFirst({ + where: { providerPreapprovalId: preapprovalId }, + }) as Promise<{ complexId: string; status: BillingStatusEnum } | null>; +} + +async function getBillingByExternalRef(externalRef: string) { + return db.complexBilling.findUnique({ + where: { complexId: externalRef }, + }) as Promise<{ complexId: string; status: BillingStatusEnum } | null>; +} + +export async function processMercadoPagoWebhook( + body: Record, + signature: string | undefined, + requestId: string | undefined +): Promise> { + const parsedResult = await mercadopagoBillingProvider.parseWebhook(body, signature, requestId); + + if (!parsedResult.ok) { + if (parsedResult.error.type === 'validation') { + return err(parsedResult.error); + } + logger.error({ error: parsedResult.error }, 'MP webhook parse failed'); + return ok({ received: true }); + } + + const event = parsedResult.value; + + const existingResult = await findEventByProviderId(event.providerEventId); + if (!existingResult.ok) return err(existingResult.error); + if (existingResult.value) { + logger.info( + { providerEventId: event.providerEventId }, + 'MP webhook: already processed, skipping' + ); + return ok({ received: true }); + } + + const newStatus = mapWebhookTypeToStatus(event); + + try { + const billing = + (await getBillingByPreapprovalId(event.providerSubscriptionId)) ?? + (await getBillingByExternalRef(event.providerSubscriptionId)); + + if (!billing) { + logger.info( + { providerSubscriptionId: event.providerSubscriptionId, eventType: event.type }, + 'MP webhook: no billing record found' + ); + await recordBillingEvent({ + complexId: 'unknown', + eventType: `unlinked:${event.type}`, + provider: MP_PROVIDER, + providerEventId: event.providerEventId, + providerData: event.data ?? null, + previousStatus: null, + newStatus: null, + }); + return ok({ received: true }); + } + + const previousStatus = billing.status; + + if (newStatus) { + await updateBillingStatus(billing.complexId, newStatus, { + provider: MP_PROVIDER, + providerPreapprovalId: event.providerSubscriptionId, + ...(event.type === 'activated' || event.type === 'updated' + ? { + currentPeriodStart: new Date(), + currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), + } + : {}), + }); + } + + await recordBillingEvent({ + complexId: billing.complexId, + eventType: event.type, + provider: MP_PROVIDER, + providerEventId: event.providerEventId, + providerData: event.data ?? null, + previousStatus, + newStatus, + }); + + return ok({ received: true }); + } catch (error) { + logger.error({ error, providerEventId: event.providerEventId }, 'MP webhook processing failed'); + await recordBillingEvent({ + complexId: 'unknown', + eventType: `error:${event.type}`, + provider: MP_PROVIDER, + providerEventId: event.providerEventId, + providerData: { error: String(error) }, + previousStatus: null, + newStatus: null, + }).catch((e) => logger.error({ error: e }, 'Failed to record error event')); + return ok({ received: true }); + } +} diff --git a/apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.handler.ts b/apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.handler.ts new file mode 100644 index 0000000..80d6166 --- /dev/null +++ b/apps/backend/src/modules/billing/features/mercadopago-webhook/mercadopago-webhook.handler.ts @@ -0,0 +1,15 @@ +import { handleResult } from '@/lib/http/handle-result'; +import type { AppContext } from '@/types/hono'; +import { processMercadoPagoWebhook } from './mercadopago-webhook.business'; + +export async function mercadopagoWebhookHandler(c: AppContext) { + const body = await c.req.json(); + const signature = c.req.header('x-signature'); + const requestId = c.req.header('x-request-id'); + + return handleResult( + c, + await processMercadoPagoWebhook(body, signature ?? undefined, requestId ?? undefined), + 200 + ); +} diff --git a/apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.business.ts b/apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.business.ts new file mode 100644 index 0000000..68be17f --- /dev/null +++ b/apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.business.ts @@ -0,0 +1,128 @@ +import { Errors } from '@/lib/errors'; +import { logger } from '@/lib/logger'; +import { db } from '@/lib/prisma'; +import { type Result, err, ok } from '@/lib/result'; +import type { WebhookEvent } from '@/modules/billing/providers/billing-provider.interface'; +import { stripeBillingProvider } from '@/modules/billing/providers/stripe.provider'; +import { + findEventByProviderId, + recordBillingEvent, + updateBillingStatus, +} from '@/modules/billing/services/billing-repository.service'; +import type { BillingStatusEnum } from '@/modules/billing/services/billing-repository.service'; + +const STRIPE_PROVIDER = 'STRIPE'; + +function mapWebhookTypeToStatus(event: WebhookEvent): BillingStatusEnum | null { + switch (event.type) { + case 'activated': + return 'ACTIVE'; + case 'updated': + return 'ACTIVE'; + case 'payment_failed': + return 'PAST_DUE'; + case 'cancelled': + return 'CANCELED'; + default: + return null; + } +} + +async function getBillingBySubscription(providerSubscriptionId: string) { + return db.complexBilling.findFirst({ + where: { providerSubscriptionId }, + }) as Promise<{ complexId: string; status: BillingStatusEnum } | null>; +} + +export async function processStripeWebhook( + rawBody: string, + signature: string | undefined +): Promise> { + const parsedResult = await stripeBillingProvider.parseWebhook(rawBody, signature); + + if (!parsedResult.ok) { + if (parsedResult.error.type === 'validation') { + return err(parsedResult.error); + } + logger.error({ error: parsedResult.error }, 'Stripe webhook parse failed'); + return ok({ received: true }); + } + + const event = parsedResult.value; + + const existingResult = await findEventByProviderId(event.providerEventId); + if (!existingResult.ok) return err(existingResult.error); + if (existingResult.value) { + logger.info( + { providerEventId: event.providerEventId }, + 'Stripe webhook: already processed, skipping' + ); + return ok({ received: true }); + } + + const newStatus = mapWebhookTypeToStatus(event); + + try { + const billing = await getBillingBySubscription(event.providerSubscriptionId); + + if (!billing) { + logger.info( + { providerSubscriptionId: event.providerSubscriptionId, eventType: event.type }, + 'Stripe webhook: no billing record found for subscription' + ); + await recordBillingEvent({ + complexId: 'unknown', + eventType: `unlinked:${event.type}`, + provider: STRIPE_PROVIDER, + providerEventId: event.providerEventId, + providerData: event.data ?? null, + previousStatus: null, + newStatus: null, + }); + return ok({ received: true }); + } + + const previousStatus = billing.status; + + if (newStatus) { + await updateBillingStatus(billing.complexId, newStatus, { + provider: STRIPE_PROVIDER, + providerCustomerId: event.providerCustomerId, + providerSubscriptionId: event.providerSubscriptionId, + ...(event.type === 'activated' || event.type === 'updated' + ? { + currentPeriodStart: new Date(), + currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), + } + : {}), + }); + } + + await recordBillingEvent({ + complexId: billing.complexId, + eventType: event.type, + provider: STRIPE_PROVIDER, + providerEventId: event.providerEventId, + providerData: event.data ?? null, + previousStatus, + newStatus, + }); + + return ok({ received: true }); + } catch (error) { + logger.error( + { error, providerEventId: event.providerEventId }, + 'Stripe webhook processing failed' + ); + await recordBillingEvent({ + complexId: 'unknown', + eventType: `error:${event.type}`, + provider: STRIPE_PROVIDER, + providerEventId: event.providerEventId, + providerData: { error: String(error) }, + previousStatus: null, + newStatus: null, + }).catch((e) => logger.error({ error: e }, 'Failed to record error event')); + return ok({ received: true }); + } +} diff --git a/apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.handler.ts b/apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.handler.ts new file mode 100644 index 0000000..91d49f4 --- /dev/null +++ b/apps/backend/src/modules/billing/features/stripe-webhook/stripe-webhook.handler.ts @@ -0,0 +1,10 @@ +import { handleResult } from '@/lib/http/handle-result'; +import type { AppContext } from '@/types/hono'; +import { processStripeWebhook } from './stripe-webhook.business'; + +export async function stripeWebhookHandler(c: AppContext) { + const body = await c.req.raw.text(); + const signature = c.req.header('stripe-signature'); + + return handleResult(c, await processStripeWebhook(body, signature ?? undefined), 200); +} diff --git a/apps/backend/src/modules/billing/providers/billing-provider.interface.ts b/apps/backend/src/modules/billing/providers/billing-provider.interface.ts new file mode 100644 index 0000000..adb0027 --- /dev/null +++ b/apps/backend/src/modules/billing/providers/billing-provider.interface.ts @@ -0,0 +1,34 @@ +import type { Result } from '@/lib/result'; + +export type WebhookEventType = 'activated' | 'updated' | 'cancelled' | 'payment_failed'; + +export type WebhookEvent = { + providerEventId: string; + type: WebhookEventType; + providerSubscriptionId: string; + providerCustomerId?: string; + data?: Record; +}; + +export type CheckoutParams = { + planCode: string; + complexId: string; + customerEmail: string; + successUrl: string; + cancelUrl: string; +}; + +export type CheckoutResult = { + checkoutUrl: string; + providerSubscriptionId: string; +}; + +export interface BillingProvider { + createCheckout(params: CheckoutParams): Promise>; + cancelSubscription(providerSubscriptionId: string): Promise>; + parseWebhook( + payload: unknown, + signature?: string, + requestId?: string + ): Promise>; +} diff --git a/apps/backend/src/modules/billing/providers/mercadopago.provider.ts b/apps/backend/src/modules/billing/providers/mercadopago.provider.ts new file mode 100644 index 0000000..2f0c4c7 --- /dev/null +++ b/apps/backend/src/modules/billing/providers/mercadopago.provider.ts @@ -0,0 +1,164 @@ +import { Errors } from '@/lib/errors'; +import { logger } from '@/lib/logger'; +import type { Result } from '@/lib/result'; +import { err, ok } from '@/lib/result'; +import MercadoPagoConfig, { PreApproval } from 'mercadopago'; +import { WebhookSignatureValidator } from 'mercadopago'; +import type { + BillingProvider, + CheckoutParams, + CheckoutResult, + WebhookEvent, +} from './billing-provider.interface'; + +function getMpConfig(): MercadoPagoConfig { + const accessToken = Bun.env.MERCADOPAGO_ACCESS_TOKEN; + if (!accessToken) { + throw new Error('Missing MERCADOPAGO_ACCESS_TOKEN env var'); + } + return new MercadoPagoConfig({ accessToken }); +} + +let _mpConfig: MercadoPagoConfig | null = null; +let _preApproval: PreApproval | null = null; +function preapproval(): PreApproval { + if (!_preApproval) { + _mpConfig = getMpConfig(); + _preApproval = new PreApproval(_mpConfig); + } + return _preApproval; +} + +function getMpPlanId(planCode: string, currency: string): string { + const key = `MERCADOPAGO_PLAN_ID_${currency}_${planCode}` as const; + const planId = Bun.env[key]; + if (!planId) { + throw new Error(`Missing env var ${key} for Mercado Pago plan ID`); + } + return planId; +} + +function isSandbox(): boolean { + return Bun.env.BILLING_ENV !== 'production'; +} + +export const mercadopagoBillingProvider: BillingProvider = { + async createCheckout(params: CheckoutParams): Promise> { + try { + const { planCode, complexId, customerEmail, successUrl } = params; + + const currency = 'ARS'; + const planId = getMpPlanId(planCode, currency); + + const response = await preapproval().create({ + body: { + preapproval_plan_id: planId, + reason: `Suscripción ${planCode} - Playzer`, + payer_email: customerEmail, + external_reference: complexId, + back_url: successUrl, + status: isSandbox() ? 'pending' : undefined, + auto_recurring: undefined, + }, + }); + + if (!response.id || !response.init_point) { + return err(Errors.unexpected('Mercado Pago did not return a preapproval ID or init_point')); + } + + return ok({ + checkoutUrl: response.init_point, + providerSubscriptionId: response.id, + }); + } catch (error) { + logger.error( + { error, params: { planCode: params.planCode } }, + 'MercadoPago createCheckout failed' + ); + return err(Errors.unexpected('Failed to create Mercado Pago preapproval')); + } + }, + + async cancelSubscription(providerSubscriptionId: string): Promise> { + try { + await preapproval().update({ + id: providerSubscriptionId, + body: { status: 'cancelled' }, + }); + return ok(undefined); + } catch (error) { + logger.error({ error, providerSubscriptionId }, 'MercadoPago cancelSubscription failed'); + return err(Errors.unexpected('Failed to cancel Mercado Pago preapproval')); + } + }, + + async parseWebhook( + payload: unknown, + signature?: string, + requestId?: string + ): Promise> { + try { + const body = payload as Record; + + const action = body?.action as string | undefined; + const dataId = (body?.data as Record)?.id as string | undefined; + + if (!action || !dataId) { + return err( + Errors.validation('Invalid Mercado Pago webhook payload: missing action or data.id') + ); + } + + if (signature && requestId) { + const secret = Bun.env.MERCADOPAGO_WEBHOOK_SECRET; + if (secret) { + try { + WebhookSignatureValidator.validate({ + xSignature: signature, + xRequestId: requestId, + dataId, + secret, + toleranceSeconds: 300, + }); + } catch { + return err(Errors.validation('Invalid Mercado Pago webhook signature')); + } + } + } + + let webhookType: WebhookEvent['type']; + + switch (action) { + case 'subscription_authorized_payment': + webhookType = 'activated'; + break; + case 'subscription_cancelled': + webhookType = 'cancelled'; + break; + case 'subscription_updated': + webhookType = 'updated'; + break; + case 'subscription_charge_payment': + webhookType = 'payment_failed'; + break; + default: + logger.info( + { action }, + 'Mercado Pago webhook: unhandled action type, treating as updated' + ); + webhookType = 'updated'; + } + + return ok({ + providerEventId: `mp-${dataId}-${action}`, + type: webhookType, + providerSubscriptionId: dataId, + providerCustomerId: undefined, + data: body as Record, + }); + } catch (error) { + logger.error({ error }, 'MercadoPago webhook parsing failed'); + return err(Errors.validation('Invalid Mercado Pago webhook payload')); + } + }, +}; diff --git a/apps/backend/src/modules/billing/providers/stripe.provider.ts b/apps/backend/src/modules/billing/providers/stripe.provider.ts new file mode 100644 index 0000000..e5c4db2 --- /dev/null +++ b/apps/backend/src/modules/billing/providers/stripe.provider.ts @@ -0,0 +1,165 @@ +import { Errors } from '@/lib/errors'; +import { logger } from '@/lib/logger'; +import type { Result } from '@/lib/result'; +import { err, ok } from '@/lib/result'; +import Stripe from 'stripe'; +import type { + BillingProvider, + CheckoutParams, + CheckoutResult, + WebhookEvent, +} from './billing-provider.interface'; + +function getStripeClient(): Stripe { + const secretKey = Bun.env.STRIPE_SECRET_KEY; + if (!secretKey) { + throw new Error('Missing STRIPE_SECRET_KEY env var'); + } + return new Stripe(secretKey); +} + +let _stripeClient: Stripe | null = null; +function stripe(): Stripe { + if (!_stripeClient) { + _stripeClient = getStripeClient(); + } + return _stripeClient; +} + +function getStripePriceId(planCode: string, currency: string): string { + const key = `STRIPE_PRICE_ID_${currency}_${planCode}` as const; + const priceId = Bun.env[key]; + if (!priceId) { + throw new Error(`Missing env var ${key} for Stripe price ID`); + } + return priceId; +} + +export const stripeBillingProvider: BillingProvider = { + async createCheckout(params: CheckoutParams): Promise> { + try { + const { planCode, complexId, customerEmail, successUrl, cancelUrl } = params; + + const currency = 'USD'; + + const priceId = getStripePriceId(planCode, currency); + + const session = await stripe().checkout.sessions.create({ + mode: 'subscription', + customer_email: customerEmail, + line_items: [ + { + price: priceId, + quantity: 1, + }, + ], + metadata: { + complexId, + planCode, + }, + subscription_data: { + metadata: { + complexId, + planCode, + }, + }, + success_url: successUrl, + cancel_url: cancelUrl, + }); + + if (!session.url || !session.subscription) { + return err(Errors.unexpected('Stripe did not return a checkout URL or subscription ID')); + } + + const subscriptionId = + typeof session.subscription === 'string' ? session.subscription : session.subscription.id; + + return ok({ + checkoutUrl: session.url, + providerSubscriptionId: subscriptionId, + }); + } catch (error) { + logger.error( + { error, params: { planCode: params.planCode } }, + 'Stripe createCheckout failed' + ); + return err(Errors.unexpected('Failed to create Stripe checkout session')); + } + }, + + async cancelSubscription(providerSubscriptionId: string): Promise> { + try { + await stripe().subscriptions.cancel(providerSubscriptionId); + return ok(undefined); + } catch (error) { + logger.error({ error, providerSubscriptionId }, 'Stripe cancelSubscription failed'); + return err(Errors.unexpected('Failed to cancel Stripe subscription')); + } + }, + + async parseWebhook(payload: unknown, signature?: string): Promise> { + if (!signature) { + return err(Errors.validation('Missing Stripe signature')); + } + + const secret = Bun.env.STRIPE_WEBHOOK_SECRET; + if (!secret) { + return err(Errors.unexpected('Missing STRIPE_WEBHOOK_SECRET env var')); + } + + try { + const rawBody = typeof payload === 'string' ? payload : JSON.stringify(payload); + const event = stripe().webhooks.constructEvent(rawBody, signature, secret); + + const eventType = event.type; + const data = event.data.object as unknown as Record; + + let webhookType: WebhookEvent['type']; + let providerSubscriptionId: string | undefined; + let providerCustomerId: string | undefined; + + if (eventType === 'checkout.session.completed') { + webhookType = 'activated'; + providerSubscriptionId = data.subscription as string | undefined; + providerCustomerId = data.customer as string | undefined; + } else if (eventType === 'customer.subscription.updated') { + const status = data.status as string | undefined; + if (status === 'past_due') { + webhookType = 'payment_failed'; + } else if (status === 'active' || status === 'trialing') { + webhookType = 'updated'; + } else if (status === 'canceled' || status === 'unpaid') { + webhookType = 'cancelled'; + } else { + webhookType = 'updated'; + } + providerSubscriptionId = data.id as string | undefined; + providerCustomerId = data.customer as string | undefined; + } else if (eventType === 'customer.subscription.deleted') { + webhookType = 'cancelled'; + providerSubscriptionId = data.id as string | undefined; + providerCustomerId = data.customer as string | undefined; + } else if (eventType === 'invoice.payment_failed') { + webhookType = 'payment_failed'; + providerSubscriptionId = data.subscription as string | undefined; + providerCustomerId = data.customer as string | undefined; + } else { + logger.info({ eventType }, 'Stripe webhook: unhandled event type, skipping'); + webhookType = 'updated'; + providerSubscriptionId = + (data as { subscription?: string })?.subscription ?? `unknown-${event.id}`; + } + + return ok({ + providerEventId: event.id, + type: webhookType, + providerSubscriptionId: providerSubscriptionId ?? `unknown-${event.id}`, + providerCustomerId, + data, + }); + } catch (error) { + logger.error({ error }, 'Stripe webhook parsing failed'); + return err(Errors.validation('Invalid Stripe webhook signature or payload')); + } + }, +}; diff --git a/apps/backend/src/modules/billing/services/billing-access.service.ts b/apps/backend/src/modules/billing/services/billing-access.service.ts new file mode 100644 index 0000000..92e57f4 --- /dev/null +++ b/apps/backend/src/modules/billing/services/billing-access.service.ts @@ -0,0 +1,38 @@ +import { Errors } from '@/lib/errors'; +import { db } from '@/lib/prisma'; +import { type Result, err, ok } from '@/lib/result'; + +export async function canUseApp(complexId: string): Promise> { + const billing = await db.complexBilling.findUnique({ + where: { complexId }, + select: { status: true }, + }); + + if (!billing) { + return ok(true); + } + + if (billing.status === 'TRIAL' || billing.status === 'ACTIVE') { + return ok(true); + } + + if (billing.status === 'CANCELED') { + return err( + Errors.forbidden('Suscripción cancelada. Renueva tu plan para seguir usando la app.') + ); + } + + if (billing.status === 'PAST_DUE') { + return err( + Errors.forbidden( + 'Suscripción con pago pendiente. Regularizá tu deuda para seguir usando la app.' + ) + ); + } + + if (billing.status === 'SUSPENDED') { + return err(Errors.forbidden('Suscripción suspendida. Contactanos para reactivarla.')); + } + + return ok(true); +} diff --git a/apps/backend/src/modules/billing/services/billing-repository.service.ts b/apps/backend/src/modules/billing/services/billing-repository.service.ts new file mode 100644 index 0000000..4e9990d --- /dev/null +++ b/apps/backend/src/modules/billing/services/billing-repository.service.ts @@ -0,0 +1,150 @@ +import { Errors } from '@/lib/errors'; +import { db } from '@/lib/prisma'; +import { type Result, err, ok } from '@/lib/result'; +import { v7 as uuidv7 } from 'uuid'; + +export type BillingProviderEnum = 'STRIPE' | 'MERCADOPAGO' | 'PAYPAL'; +export type BillingStatusEnum = 'TRIAL' | 'ACTIVE' | 'PAST_DUE' | 'CANCELED' | 'SUSPENDED'; + +export type ComplexBillingRow = { + complexId: string; + status: BillingStatusEnum; + planCode: string; + currency: string; + provider: BillingProviderEnum | null; + providerCustomerId: string | null; + providerSubscriptionId: string | null; + providerPreapprovalId: string | null; + currentPeriodStart: Date | null; + currentPeriodEnd: Date | null; + trialEndsAt: Date | null; + canceledAt: Date | null; + suspendedAt: Date | null; + createdAt: Date; + updatedAt: Date; +}; + +export async function getBilling(complexId: string): Promise> { + const billing = await db.complexBilling.findUnique({ + where: { complexId }, + }); + + if (!billing) { + return err(Errors.notFound('Billing record not found for this complex')); + } + + return ok(billing as unknown as ComplexBillingRow); +} + +export async function ensureBilling( + complexId: string, + currency: string +): Promise> { + const existing = await db.complexBilling.findUnique({ + where: { complexId }, + }); + + if (existing) { + return ok(existing as unknown as ComplexBillingRow); + } + + const created = await db.complexBilling.create({ + data: { + complexId, + status: 'TRIAL', + planCode: 'BASIC', + currency, + }, + }); + + return ok(created as unknown as ComplexBillingRow); +} + +export async function updateBillingStatus( + complexId: string, + status: BillingStatusEnum, + extra?: { + provider?: BillingProviderEnum; + providerCustomerId?: string; + providerSubscriptionId?: string; + providerPreapprovalId?: string; + currentPeriodStart?: Date; + currentPeriodEnd?: Date; + } +): Promise> { + try { + const data: Record = { status }; + + if (extra?.provider) data.provider = extra.provider; + if (extra?.providerCustomerId) data.providerCustomerId = extra.providerCustomerId; + if (extra?.providerSubscriptionId) data.providerSubscriptionId = extra.providerSubscriptionId; + if (extra?.providerPreapprovalId) data.providerPreapprovalId = extra.providerPreapprovalId; + if (extra?.currentPeriodStart) data.currentPeriodStart = extra.currentPeriodStart; + if (extra?.currentPeriodEnd) data.currentPeriodEnd = extra.currentPeriodEnd; + + const updated = await db.complexBilling.update({ + where: { complexId }, + data: data as never, + }); + + return ok(updated as unknown as ComplexBillingRow); + } catch { + return err(Errors.unexpected('Failed to update billing status')); + } +} + +export async function recordBillingEvent(params: { + complexId: string; + eventType: string; + provider: BillingProviderEnum; + providerEventId: string | null; + providerData: unknown; + previousStatus: BillingStatusEnum | null; + newStatus: BillingStatusEnum | null; +}): Promise> { + try { + const event = await db.billingEvent.create({ + data: { + id: uuidv7(), + complexId: params.complexId, + eventType: params.eventType, + provider: params.provider, + providerEventId: params.providerEventId, + providerData: params.providerData as never, + previousStatus: params.previousStatus, + newStatus: params.newStatus, + }, + select: { id: true }, + }); + + return ok({ id: event.id }); + } catch (error: unknown) { + const prismaError = error as { code?: string }; + if (prismaError.code === 'P2002') { + return err(Errors.conflict('Webhook event already processed (idempotency)')); + } + return err(Errors.unexpected('Failed to record billing event')); + } +} + +export async function findEventByProviderId( + providerEventId: string +): Promise> { + const event = await db.billingEvent.findUnique({ + where: { providerEventId }, + select: { id: true }, + }); + + return ok(event ?? null); +} + +export async function hasActiveSubscription(complexId: string): Promise> { + const billing = await db.complexBilling.findUnique({ + where: { complexId }, + select: { status: true }, + }); + + if (!billing) return ok(false); + + return ok(billing.status === 'ACTIVE' || billing.status === 'TRIAL'); +} diff --git a/apps/backend/src/modules/billing/services/provider-resolver.service.ts b/apps/backend/src/modules/billing/services/provider-resolver.service.ts new file mode 100644 index 0000000..5f7c077 --- /dev/null +++ b/apps/backend/src/modules/billing/services/provider-resolver.service.ts @@ -0,0 +1,33 @@ +import { Errors } from '@/lib/errors'; +import { db } from '@/lib/prisma'; +import type { Result } from '@/lib/result'; +import { err, ok } from '@/lib/result'; +import type { BillingProvider } from '@/modules/billing/providers/billing-provider.interface'; +import { mercadopagoBillingProvider } from '@/modules/billing/providers/mercadopago.provider'; +import { stripeBillingProvider } from '@/modules/billing/providers/stripe.provider'; + +export const STRIPE = stripeBillingProvider; +export const MERCADOPAGO = mercadopagoBillingProvider; + +export function resolveProviderByCountry(country: string | null): BillingProvider { + if (country === 'AR' || country?.toLowerCase() === 'argentina') { + return MERCADOPAGO; + } + return STRIPE; +} + +export async function getProviderForComplex( + complexId: string +): Promise> { + const complex = await db.complex.findUnique({ + where: { id: complexId }, + select: { country: true }, + }); + + if (!complex) { + return err(Errors.notFound('Complex not found')); + } + + const provider = resolveProviderByCountry(complex.country); + return ok({ provider, country: complex.country }); +} diff --git a/apps/backend/src/modules/public-booking/shared/helpers.ts b/apps/backend/src/modules/public-booking/shared/helpers.ts index 72b0963..48fb15f 100644 --- a/apps/backend/src/modules/public-booking/shared/helpers.ts +++ b/apps/backend/src/modules/public-booking/shared/helpers.ts @@ -173,9 +173,7 @@ export function validateSportSelection( }); } -export async function getComplexWithBookingData( - complexSlug: string -) { +export async function getComplexWithBookingData(complexSlug: string) { const complex = await db.complex.findUnique({ where: { complexSlug }, select: { diff --git a/apps/backend/src/register-routes.ts b/apps/backend/src/register-routes.ts index 57d1707..7a1ae2e 100644 --- a/apps/backend/src/register-routes.ts +++ b/apps/backend/src/register-routes.ts @@ -2,6 +2,7 @@ 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 { billingRoutes } from '@/modules/billing/billing.routes'; import { complexRoutes } from '@/modules/complex/complex.routes'; import { courtRoutes } from '@/modules/court/court.routes'; import { passwordResetRoutes } from '@/modules/password-reset/password-reset.routes'; @@ -27,6 +28,7 @@ export function registerRoutes(app: Hono) { .route('/api/courts', courtRoutes) .route('/api/public-bookings', publicBookingRoutes) .route('/api/admin-bookings', adminBookingRoutes) + .route('/api/billing', billingRoutes) .route('/api/health', healthCheckRoutes); registerEventsRoutes(app); diff --git a/apps/backend/test/billing/duplicate-subscription.test.ts b/apps/backend/test/billing/duplicate-subscription.test.ts new file mode 100644 index 0000000..8d0eeea --- /dev/null +++ b/apps/backend/test/billing/duplicate-subscription.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, it, mock } from 'bun:test'; +import { prismaMock } from '../support/prisma.mock'; + +describe('duplicate-subscription', () => { + it('returns true when status is ACTIVE', async () => { + prismaMock.complexBilling.findUnique.mockResolvedValue({ + status: 'ACTIVE', + } as never); + + const { hasActiveSubscription } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await hasActiveSubscription('complex-active'); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toBe(true); + } + }); + + it('returns true when status is TRIAL', async () => { + prismaMock.complexBilling.findUnique.mockResolvedValue({ + status: 'TRIAL', + } as never); + + const { hasActiveSubscription } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await hasActiveSubscription('complex-trial'); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toBe(true); + } + }); + + it('returns false when status is CANCELED', async () => { + prismaMock.complexBilling.findUnique.mockResolvedValue({ + status: 'CANCELED', + } as never); + + const { hasActiveSubscription } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await hasActiveSubscription('complex-canceled'); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toBe(false); + } + }); + + it('returns false when no billing record exists', async () => { + prismaMock.complexBilling.findUnique.mockResolvedValue(null as never); + + const { hasActiveSubscription } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await hasActiveSubscription('complex-no-billing'); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toBe(false); + } + }); +}); diff --git a/apps/backend/test/billing/event-mapping.test.ts b/apps/backend/test/billing/event-mapping.test.ts new file mode 100644 index 0000000..14e0278 --- /dev/null +++ b/apps/backend/test/billing/event-mapping.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from 'bun:test'; +import { mapWebhookTypeToStatus } from './helpers'; + +describe('event-mapping', () => { + it('maps all webhook event types correctly', () => { + expect(mapWebhookTypeToStatus('activated')).toBe('ACTIVE'); + expect(mapWebhookTypeToStatus('updated')).toBe('ACTIVE'); + expect(mapWebhookTypeToStatus('payment_failed')).toBe('PAST_DUE'); + expect(mapWebhookTypeToStatus('cancelled')).toBe('CANCELED'); + }); + + it('maps Stripe checkout.session.completed -> activated -> ACTIVE', () => { + const status = mapWebhookTypeToStatus('activated'); + expect(status).toBe('ACTIVE'); + }); + + it('maps Stripe customer.subscription.deleted -> cancelled -> CANCELED', () => { + const status = mapWebhookTypeToStatus('cancelled'); + expect(status).toBe('CANCELED'); + }); + + it('maps Mercado Pago subscription_authorized_payment -> activated -> ACTIVE', () => { + const status = mapWebhookTypeToStatus('activated'); + expect(status).toBe('ACTIVE'); + }); + + it('maps Mercado Pago subscription_cancelled -> cancelled -> CANCELED', () => { + const status = mapWebhookTypeToStatus('cancelled'); + expect(status).toBe('CANCELED'); + }); +}); diff --git a/apps/backend/test/billing/helpers.ts b/apps/backend/test/billing/helpers.ts new file mode 100644 index 0000000..6a56f87 --- /dev/null +++ b/apps/backend/test/billing/helpers.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'bun:test'; + +/** + * Helper that replicates the mapWebhookTypeToStatus logic + * used in webhook business files for testability. + */ +export function mapWebhookTypeToStatus( + eventType: 'activated' | 'updated' | 'payment_failed' | 'cancelled' +): 'ACTIVE' | 'PAST_DUE' | 'CANCELED' | null { + switch (eventType) { + case 'activated': + return 'ACTIVE'; + case 'updated': + return 'ACTIVE'; + case 'payment_failed': + return 'PAST_DUE'; + case 'cancelled': + return 'CANCELED'; + default: + return null; + } +} diff --git a/apps/backend/test/billing/idempotency.test.ts b/apps/backend/test/billing/idempotency.test.ts new file mode 100644 index 0000000..134ea5b --- /dev/null +++ b/apps/backend/test/billing/idempotency.test.ts @@ -0,0 +1,83 @@ +import { describe, expect, it, mock } from 'bun:test'; +import { prismaMock } from '../support/prisma.mock'; + +describe('webhook-idempotency', () => { + it('returns conflict when providerEventId already exists', async () => { + const existingEvent = { id: 'event-1' }; + + prismaMock.billingEvent.findUnique.mockResolvedValue(existingEvent as never); + + const { findEventByProviderId } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await findEventByProviderId('mp-duplicate-id'); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toEqual({ id: 'event-1' }); + } + }); + + it('returns null when providerEventId does not exist', async () => { + prismaMock.billingEvent.findUnique.mockResolvedValue(null as never); + + const { findEventByProviderId } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await findEventByProviderId('new-event-id'); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toBeNull(); + } + }); + + it('records a billing event successfully', async () => { + const createdEvent = { id: 'new-uuid' }; + prismaMock.billingEvent.create.mockResolvedValue(createdEvent as never); + + const { recordBillingEvent } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await recordBillingEvent({ + complexId: 'complex-1', + eventType: 'activated', + provider: 'STRIPE', + providerEventId: 'evt_unique', + providerData: { some: 'data' }, + previousStatus: 'TRIAL', + newStatus: 'ACTIVE', + }); + + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value.id).toBe('new-uuid'); + } + }); + + it('returns conflict when billing event create has P2002 (duplicate)', async () => { + const prismaError = new Error('Unique constraint') as Error & { code: string }; + prismaError.code = 'P2002'; + prismaMock.billingEvent.create.mockRejectedValue(prismaError as never); + + const { recordBillingEvent } = await import( + '@/modules/billing/services/billing-repository.service' + ); + + const result = await recordBillingEvent({ + complexId: 'complex-1', + eventType: 'activated', + provider: 'STRIPE', + providerEventId: 'evt_duplicate', + providerData: null, + previousStatus: null, + newStatus: null, + }); + + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error.type).toBe('conflict'); + } + }); +}); diff --git a/apps/backend/test/billing/provider-resolver.test.ts b/apps/backend/test/billing/provider-resolver.test.ts new file mode 100644 index 0000000..c77aa2b --- /dev/null +++ b/apps/backend/test/billing/provider-resolver.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from 'bun:test'; +import { mercadopagoBillingProvider } from '@/modules/billing/providers/mercadopago.provider'; +import { stripeBillingProvider } from '@/modules/billing/providers/stripe.provider'; +import { resolveProviderByCountry } from '@/modules/billing/services/provider-resolver.service'; + +describe('provider-resolver', () => { + it('returns MERCADOPAGO for country AR', () => { + const provider = resolveProviderByCountry('AR'); + expect(provider).toBe(mercadopagoBillingProvider); + }); + + it('returns STRIPE for country BR', () => { + const provider = resolveProviderByCountry('BR'); + expect(provider).toBe(stripeBillingProvider); + }); + + it('returns STRIPE for country US', () => { + const provider = resolveProviderByCountry('US'); + expect(provider).toBe(stripeBillingProvider); + }); + + it('returns STRIPE for null country', () => { + const provider = resolveProviderByCountry(null); + expect(provider).toBe(stripeBillingProvider); + }); + + it('returns STRIPE for empty country', () => { + const provider = resolveProviderByCountry(''); + expect(provider).toBe(stripeBillingProvider); + }); + + it('returns STRIPE for any other ISO code', () => { + const provider = resolveProviderByCountry('CL'); + expect(provider).toBe(stripeBillingProvider); + }); +}); diff --git a/apps/backend/test/billing/status-transitions.test.ts b/apps/backend/test/billing/status-transitions.test.ts new file mode 100644 index 0000000..ef44a36 --- /dev/null +++ b/apps/backend/test/billing/status-transitions.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'bun:test'; +import { mapWebhookTypeToStatus } from './helpers'; + +describe('status-transitions', () => { + it('activated maps to ACTIVE', () => { + expect(mapWebhookTypeToStatus('activated')).toBe('ACTIVE'); + }); + + it('updated maps to ACTIVE', () => { + expect(mapWebhookTypeToStatus('updated')).toBe('ACTIVE'); + }); + + it('payment_failed maps to PAST_DUE', () => { + expect(mapWebhookTypeToStatus('payment_failed')).toBe('PAST_DUE'); + }); + + it('cancelled maps to CANCELED', () => { + expect(mapWebhookTypeToStatus('cancelled')).toBe('CANCELED'); + }); +}); diff --git a/apps/backend/test/support/prisma.mock.ts b/apps/backend/test/support/prisma.mock.ts index fdf608a..137cc69 100644 --- a/apps/backend/test/support/prisma.mock.ts +++ b/apps/backend/test/support/prisma.mock.ts @@ -27,6 +27,8 @@ export const dbMock = { courtBookingLog: prismaMock.courtBookingLog, courtAvailability: prismaMock.courtAvailability, courtPriceRule: prismaMock.courtPriceRule, + complexBilling: prismaMock.complexBilling, + billingEvent: prismaMock.billingEvent, $transaction: transactionMock, }; diff --git a/bun.lock b/bun.lock index 1fee589..1d31db3 100644 --- a/bun.lock +++ b/bun.lock @@ -26,12 +26,14 @@ "dotenv": "^17.4.1", "hono": "4.12.10", "mailtrap": "^4.5.1", + "mercadopago": "^3.1.0", "nodemailer": "^8.0.5", "pg": "^8.20.0", "pino": "10.3.1", "pino-pretty": "13.1.3", "pino-std-serializers": "7.1.0", "prisma": "^7", + "stripe": "^22.2.2", "uuid": "^13.0.0", }, "devDependencies": { @@ -625,7 +627,7 @@ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="], + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="], @@ -731,7 +733,7 @@ "bun-mock-prisma": ["bun-mock-prisma@1.2.1", "", { "peerDependencies": { "bun-types": ">=1.0.0" } }, "sha512-1c6CByUMk9acH7R87lcVoJqPpUWoqHRu6VwipXzU94s03/FXotACOt2DMgGhfz2xw5218BVoPJiH0QQXUwgmWg=="], - "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="], + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], @@ -1197,6 +1199,8 @@ "memoize-one": ["memoize-one@5.2.1", "", {}, "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="], + "mercadopago": ["mercadopago@3.1.0", "", {}, "sha512-3VB8AFpE8eZgm67e22kVbR19k9JC/1j66voLSh7m9tPvkASuRKNH2Y7yb793rO+fIpMtvl+wBj27UY4jIItWYA=="], + "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], @@ -1569,6 +1573,8 @@ "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], + "stripe": ["stripe@22.2.2", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-lRXLiarjW/I2QVa6QuFfz1Ma7Dc2yBQ7vlYH6NEmp5htMJNQGfiWExmOv0McfqY5wMCGV8DLuCvsyVRIPJlUUQ=="], + "strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], diff --git a/docs/billing.md b/docs/billing.md new file mode 100644 index 0000000..bff0fa0 --- /dev/null +++ b/docs/billing.md @@ -0,0 +1,283 @@ +# Billing / Subscriptions Module + +## Architecture + +``` +modules/billing/ +├── billing.routes.ts # Rutas Hono +├── features/ +│ ├── create-checkout/ # POST /api/billing/checkout +│ │ ├── create-checkout.handler.ts +│ │ └── create-checkout.business.ts +│ ├── cancel-subscription/ # POST /api/billing/cancel +│ │ ├── cancel-subscription.handler.ts +│ │ └── cancel-subscription.business.ts +│ ├── get-billing-status/ # GET /api/billing/status +│ │ ├── get-billing-status.handler.ts +│ │ └── get-billing-status.business.ts +│ ├── stripe-webhook/ # POST /api/billing/webhooks/stripe +│ │ ├── stripe-webhook.handler.ts +│ │ └── stripe-webhook.business.ts +│ └── mercadopago-webhook/ # POST /api/billing/webhooks/mercadopago +│ ├── mercadopago-webhook.handler.ts +│ └── mercadopago-webhook.business.ts +├── providers/ +│ ├── billing-provider.interface.ts # BillingProvider abstraction +│ ├── stripe.provider.ts # Stripe implementation +│ └── mercadopago.provider.ts # Mercado Pago implementation +└── services/ + ├── provider-resolver.service.ts # Resuelve Stripe/MP por país + ├── billing-repository.service.ts # DB access (Prisma) + └── billing-access.service.ts # canUseApp() helper +``` + +### Resolución de provider + +| Country | Provider | +|---------|----------| +| `AR` | Mercado Pago | +| Otro / null | Stripe | + +La resolución usa el campo `country` del `Complex` (ISO 3166-1 alpha-2). + +--- + +## Variables de entorno + +``` +# Billing +BILLING_ENV=sandbox|production +FRONTEND_BASE_URL=http://localhost:5173 + +# Stripe +STRIPE_SECRET_KEY=sk_test_xxx +STRIPE_WEBHOOK_SECRET=whsec_xxx +STRIPE_PRICE_ID_USD_BASIC=price_basic_usd +STRIPE_PRICE_ID_USD_ADVANCED=price_advanced_usd +STRIPE_PRICE_ID_USD_ENTERPRISE=price_enterprise_usd + +# Mercado Pago (Argentina) +MERCADOPAGO_ACCESS_TOKEN=TEST-xxx +MERCADOPAGO_WEBHOOK_SECRET=xxx +MERCADOPAGO_PLAN_ID_ARS_BASIC=2c938084... +MERCADOPAGO_PLAN_ID_ARS_ADVANCED=2c938084... +MERCADOPAGO_PLAN_ID_ARS_ENTERPRISE=2c938084... +``` + +### Naming de plans + +Los IDs de prices/plans en Stripe y Mercado Pago se nombran con el código del Plan interno (`BASIC`, `ADVANCED`, `ENTERPRISE`) y la moneda (`USD`, `ARS`): + +``` +STRIPE_PRICE_ID_{CURRENCY}_{PLAN_CODE} +MERCADOPAGO_PLAN_ID_{CURRENCY}_{PLAN_CODE} +``` + +--- + +## Endpoints + +| Método | Ruta | Auth | Descripción | +|--------|------|------|-------------| +| POST | `/api/billing/checkout` | `requireAuth` + cookie | Inicia checkout de suscripción | +| POST | `/api/billing/cancel` | `requireAuth` + cookie | Cancela suscripción activa | +| GET | `/api/billing/status` | `requireAuth` + cookie | Estado actual del billing | +| POST | `/api/billing/webhooks/stripe` | none (firma) | Webhook de Stripe | +| POST | `/api/billing/webhooks/mercadopago` | none (firma) | Webhook de Mercado Pago | + +El `complexId` se obtiene de la cookie `selected-complex-id`. + +--- + +## Estados internos + +``` +TRIAL ──(checkout completed)──► ACTIVE +TRIAL ──(user cancels)────────► CANCELED +ACTIVE ──(payment fails)──────► PAST_DUE +PAST_DUE ──(retry ok)─────────► ACTIVE +PAST_DUE ──(user cancels)─────► CANCELED +ACTIVE ──(user cancels)───────► CANCELED +CANCELED ──(grace ends)───────► SUSPENDED +``` + +| Estado | Significado | +|--------|-------------| +| `TRIAL` | Período de prueba, puede usar la app | +| `ACTIVE` | Suscripción activa, puede usar la app | +| `PAST_DUE` | Pago fallido, acceso restringido | +| `CANCELED` | Cancelado por usuario, acceso restringido | +| `SUSPENDED` | Suspendido, acceso restringido | + +### Helper: `canUseApp(complexId)` + +```typescript +import { canUseApp } from '@/modules/billing/services/billing-access.service'; + +const result = await canUseApp(complexId); +if (!result.ok) { + // Rechazar acceso con mensaje según el estado +} +``` + +Retorna `ok(true)` si el estado es `TRIAL` o `ACTIVE`. Caso contrario retorna un `AppError` tipo `forbidden` con un mensaje específico según el estado. + +--- + +## Flujo de Checkout + +1. **Frontend** → `POST /api/billing/checkout` con `{ planCode: "BASIC" }` +2. **Backend** verifica: + - Usuario tiene acceso al complex (cookie) + - No existe suscripción activa +3. **Backend** resuelve provider según `Complex.country` +4. **Provider** genera URL de checkout (Stripe Checkout Session / Mercado Pago Preapproval) +5. **Backend** guarda/actualiza `ComplexBilling` con status `TRIAL` +6. **Frontend** redirige al usuario a `checkoutUrl` +7. **Usuario** completa pago en el provider +8. **Provider** envía webhook → backend procesa y pasa a `ACTIVE` + +--- + +## Flujo de Webhooks + +### Idempotencia + +Cada webhook tiene un `providerEventId` único (Stripe: `event.id`, MP: `mp-{data.id}-{action}`). El campo `providerEventId` en `BillingEvent` tiene `@unique`. + +**Antes de procesar:** +1. Buscar `BillingEvent` por `providerEventId` +2. Si existe → responder 200 (ya procesado) +3. Si no existe → procesar y crear `BillingEvent` dentro de una transacción + +### Stripe + +```sh +stripe listen --forward-to localhost:3000/api/billing/webhooks/stripe +``` + +Stripe envía los eventos al endpoint con la firma en el header `stripe-signature`. + +**Eventos manejados:** + +| Evento | Acción | +|--------|--------| +| `checkout.session.completed` | Activar suscripción (`ACTIVE`) | +| `customer.subscription.updated` (active) | Actualizar período | +| `customer.subscription.updated` (past_due) | Marcar como `PAST_DUE` | +| `customer.subscription.deleted` | Cancelar (`CANCELED`) | +| `invoice.payment_failed` | Marcar como `PAST_DUE` | + +### Mercado Pago + +Usar ngrok para exponer el servidor local: + +```sh +ngrok http 3000 +# Configurar la URL del webhook en el dashboard de MP: +# https://www.mercadopago.com.ar/developers/panel/webhooks +# Apuntar a: https://{ngrok-id}.ngrok.app/api/billing/webhooks/mercadopago +``` + +**Eventos manejados:** + +| Acción | Tipo | +|--------|------| +| `subscription_authorized_payment` | `activated` → `ACTIVE` | +| `subscription_cancelled` | `cancelled` → `CANCELED` | +| `subscription_updated` | `updated` → `ACTIVE` | +| `subscription_charge_payment` | `payment_failed` → `PAST_DUE` | + +> **Nota:** Los nombres exactos de eventos de Mercado Pago pueden variar. Verificar en el dashboard de desarrolladores de MP durante integración. + +--- + +## Modelo de datos (Prisma) + +### `ComplexBilling` + +| Columna | Tipo | Descripción | +|---------|------|-------------| +| `complexId` | `String @id` | FK a Complex | +| `status` | `BillingStatus` | `TRIAL`, `ACTIVE`, `PAST_DUE`, `CANCELED`, `SUSPENDED` | +| `planCode` | `String` | Código del Plan (BASIC, ADVANCED, ENTERPRISE) | +| `currency` | `String` | `ARS` o `USD` | +| `provider` | `BillingProvider?` | `STRIPE`, `MERCADOPAGO`, `PAYPAL` | +| `providerCustomerId` | `String?` | ID del customer en el provider | +| `providerSubscriptionId` | `String?` | ID de la suscripción en Stripe | +| `providerPreapprovalId` | `String?` | ID del preapproval en MP | +| `currentPeriodStart` | `DateTime?` | Inicio del período actual | +| `currentPeriodEnd` | `DateTime?` | Fin del período actual | +| `trialEndsAt` | `DateTime?` | Fin del trial | +| `canceledAt` | `DateTime?` | Fecha de cancelación | +| `suspendedAt` | `DateTime?` | Fecha de suspensión | + +### `BillingEvent` + +| Columna | Tipo | Descripción | +|---------|------|-------------| +| `id` | `String @id` | UUID | +| `complexId` | `String` | FK a ComplexBilling | +| `eventType` | `String` | Tipo de evento del provider | +| `provider` | `BillingProvider` | Provider que originó el evento | +| `providerEventId` | `String? @unique` | ID único del evento en el provider (idempotencia) | +| `providerData` | `Json?` | Payload completo del webhook | +| `previousStatus` | `BillingStatus?` | Estado anterior | +| `newStatus` | `BillingStatus?` | Nuevo estado | + +--- + +## Agregar un nuevo provider (ej: PayPal) + +1. Crear `providers/paypal.provider.ts` implementando `BillingProvider` +2. Agregar `PAYPAL` al enum `BillingProvider` en Prisma +3. Agregar case en `provider-resolver.service.ts` si aplica +4. Agregar webhook handler en `features/paypal-webhook/` +5. Agregar ruta en `billing.routes.ts` + +--- + +## Pruebas en local + +### Sin cobrar dinero + +- Stripe: Usar claves `sk_test_...`. Stripe automáticamente usa el entorno de prueba con tarjetas de prueba (`4242 4242 4242 4242`). +- Mercado Pago: Usar `BILLING_ENV=sandbox` con `MERCADOPAGO_ACCESS_TOKEN=TEST-...`. + +### Stripe CLI (webhooks locales) + +```sh +# Instalar: https://stripe.com/docs/stripe-cli +stripe login +stripe listen --forward-to localhost:3000/api/billing/webhooks/stripe +# Copiar el webhook secret que muestra y ponerlo en STRIPE_WEBHOOK_SECRET +``` + +### Mercado Pago + ngrok (webhooks locales) + +```sh +ngrok http 3000 +# Configurar webhook en: https://www.mercadopago.com.ar/developers/panel/webhooks +# URL: https://{ngrok-id}.ngrok.app/api/billing/webhooks/mercadopago +``` + +--- + +## Comandos + +```sh +# Instalar dependencias (ya instalado: stripe, mercadopago) +bun add stripe mercadopago + +# Generar cliente Prisma +bun --filter backend prisma:generate + +# Crear migración +bun --filter backend prisma:migrate + +# Tests +bun run test + +# Dev server +bun run dev +``` diff --git a/packages/api-contract/src/billing.ts b/packages/api-contract/src/billing.ts new file mode 100644 index 0000000..31fbbec --- /dev/null +++ b/packages/api-contract/src/billing.ts @@ -0,0 +1,34 @@ +import { z } from 'zod'; + +export const billingProviderSchema = z.enum(['STRIPE', 'MERCADOPAGO', 'PAYPAL']); +export const billingStatusSchema = z.enum(['TRIAL', 'ACTIVE', 'PAST_DUE', 'CANCELED', 'SUSPENDED']); + +export const createCheckoutSchema = z.object({ + planCode: z.string().trim().min(1).max(10), +}); + +export const checkoutResponseSchema = z.object({ + checkoutUrl: z.string(), + subscriptionId: z.string(), +}); + +export const cancelSubscriptionSchema = z.object({}); + +export const billingStatusResponseSchema = z.object({ + complexId: z.string(), + status: billingStatusSchema, + planCode: z.string(), + currency: z.string(), + provider: billingProviderSchema.nullable(), + currentPeriodEnd: z.string().nullable(), + currentPeriodStart: z.string().nullable(), + trialEndsAt: z.string().nullable(), + canceledAt: z.string().nullable(), + suspendedAt: z.string().nullable(), +}); + +export type BillingProvider = z.infer; +export type BillingStatus = z.infer; +export type CreateCheckoutInput = z.infer; +export type CheckoutResponse = z.infer; +export type BillingStatusResponse = z.infer; diff --git a/packages/api-contract/src/index.ts b/packages/api-contract/src/index.ts index b7b9983..809f752 100644 --- a/packages/api-contract/src/index.ts +++ b/packages/api-contract/src/index.ts @@ -155,6 +155,20 @@ export { adminGeoCountrySchema, adminGeoStatsSchema, } from './admin'; +export { + billingProviderSchema, + billingStatusSchema, + billingStatusResponseSchema, + createCheckoutSchema, + checkoutResponseSchema, +} from './billing'; +export type { + BillingProvider, + BillingStatus, + BillingStatusResponse, + CreateCheckoutInput, + CheckoutResponse, +} from './billing'; export type { AdminComplexListItem, AdminComplexStats,