feat: add recurring bookings feature with related handlers and services

- Introduced recurring booking groups with the ability to create and cancel them.
- Added database migrations for recurring bookings, including new tables and relationships.
- Implemented handlers for creating and canceling recurring bookings in the admin booking module.
- Enhanced existing booking services to support recurring bookings logic.
- Updated API contract to include new schemas for recurring bookings.
- Refactored existing code for improved readability and maintainability.
This commit is contained in:
Jose Selesan
2026-06-16 11:58:06 -03:00
parent 1b5eb253f2
commit 1318e3bf57
38 changed files with 2025 additions and 265 deletions

View File

@@ -14,6 +14,7 @@ model Complex {
users ComplexUser[] users ComplexUser[]
invitations ComplexInvitation[] invitations ComplexInvitation[]
courts Court[] courts Court[]
recurringGroups RecurringBookingGroup[]
@@index([planCode]) @@index([planCode])
@@index([complexSlug]) @@index([complexSlug])

View File

@@ -15,6 +15,11 @@ enum CourtBookingStatus {
NOSHOW NOSHOW
} }
enum RecurringBookingGroupStatus {
ACTIVE
CANCELLED
}
model Sport { model Sport {
id String @id @db.Uuid id String @id @db.Uuid
name String @unique name String @unique
@@ -44,6 +49,7 @@ model Court {
priceRules CourtPriceRule[] priceRules CourtPriceRule[]
bookings CourtBooking[] bookings CourtBooking[]
maintenances CourtMaintenance[] maintenances CourtMaintenance[]
recurringGroups RecurringBookingGroup[]
@@index([complexId]) @@index([complexId])
@@index([sportId]) @@index([sportId])
@@ -105,13 +111,16 @@ model CourtBooking {
customerPhone String @map("customer_phone") @db.VarChar(30) customerPhone String @map("customer_phone") @db.VarChar(30)
customerEmail String @map("customer_email") @db.VarChar(254) customerEmail String @map("customer_email") @db.VarChar(254)
status CourtBookingStatus @default(CONFIRMED) status CourtBookingStatus @default(CONFIRMED)
recurringGroupId String? @map("recurring_group_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at") updatedAt DateTime @updatedAt @map("updated_at")
court Court @relation(fields: [courtId], references: [id], onDelete: Cascade) court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)
recurringGroup RecurringBookingGroup? @relation(fields: [recurringGroupId], references: [id])
@@unique([courtId, bookingDate, startTime]) @@unique([courtId, bookingDate, startTime])
@@index([courtId, bookingDate]) @@index([courtId, bookingDate])
@@index([bookingDate]) @@index([bookingDate])
@@index([recurringGroupId])
@@map("court_bookings") @@map("court_bookings")
} }
@@ -132,3 +141,28 @@ model CourtBookingLog {
@@map("court_booking_logs") @@map("court_booking_logs")
@@index([courtId, newStatus]) @@index([courtId, newStatus])
} }
model RecurringBookingGroup {
id String @id @db.Uuid
complexId String @map("complex_id") @db.Uuid
courtId String @map("court_id") @db.Uuid
startTime String @map("start_time") @db.VarChar(5)
endTime String @map("end_time") @db.VarChar(5)
dayOfWeek DayOfWeek @map("day_of_week")
startDate DateTime @map("start_date") @db.Date
endDate DateTime? @map("end_date") @db.Date
status RecurringBookingGroupStatus @default(ACTIVE)
customerName String @map("customer_name") @db.VarChar(120)
customerPhone String @map("customer_phone") @db.VarChar(30)
customerEmail String @map("customer_email") @db.VarChar(254)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
court Court @relation(fields: [courtId], references: [id], onDelete: Cascade)
complex Complex @relation(fields: [complexId], references: [id], onDelete: Cascade)
bookings CourtBooking[]
@@index([complexId])
@@index([courtId])
@@index([status])
@@map("recurring_booking_groups")
}

View File

@@ -0,0 +1,46 @@
-- CreateEnum
CREATE TYPE "RecurringBookingGroupStatus" AS ENUM ('ACTIVE', 'CANCELLED');
-- AlterTable
ALTER TABLE "court_bookings" ADD COLUMN "recurring_group_id" UUID;
-- CreateTable
CREATE TABLE "recurring_booking_groups" (
"id" UUID NOT NULL,
"complex_id" UUID NOT NULL,
"court_id" UUID NOT NULL,
"start_time" VARCHAR(5) NOT NULL,
"end_time" VARCHAR(5) NOT NULL,
"day_of_week" "DayOfWeek" NOT NULL,
"start_date" DATE NOT NULL,
"end_date" DATE,
"status" "RecurringBookingGroupStatus" NOT NULL DEFAULT 'ACTIVE',
"customer_name" VARCHAR(120) NOT NULL,
"customer_phone" VARCHAR(30) NOT NULL,
"customer_email" VARCHAR(254) NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "recurring_booking_groups_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "recurring_booking_groups_complex_id_idx" ON "recurring_booking_groups"("complex_id");
-- CreateIndex
CREATE INDEX "recurring_booking_groups_court_id_idx" ON "recurring_booking_groups"("court_id");
-- CreateIndex
CREATE INDEX "recurring_booking_groups_status_idx" ON "recurring_booking_groups"("status");
-- CreateIndex
CREATE INDEX "court_bookings_recurring_group_id_idx" ON "court_bookings"("recurring_group_id");
-- AddForeignKey
ALTER TABLE "court_bookings" ADD CONSTRAINT "court_bookings_recurring_group_id_fkey" FOREIGN KEY ("recurring_group_id") REFERENCES "recurring_booking_groups"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "recurring_booking_groups" ADD CONSTRAINT "recurring_booking_groups_court_id_fkey" FOREIGN KEY ("court_id") REFERENCES "courts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "recurring_booking_groups" ADD CONSTRAINT "recurring_booking_groups_complex_id_fkey" FOREIGN KEY ("complex_id") REFERENCES "complexes"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -21,6 +21,7 @@ export const planSeeds = [
publicBookingPage: true, publicBookingPage: true,
advancedReports: false, advancedReports: false,
whatsappReminders: false, whatsappReminders: false,
fixedSlots: false,
}, },
pricing: { pricing: {
overrides: { overrides: {
@@ -51,6 +52,7 @@ export const planSeeds = [
publicBookingPage: true, publicBookingPage: true,
advancedReports: true, advancedReports: true,
whatsappReminders: true, whatsappReminders: true,
fixedSlots: true,
}, },
pricing: { pricing: {
overrides: { overrides: {
@@ -81,6 +83,7 @@ export const planSeeds = [
publicBookingPage: true, publicBookingPage: true,
advancedReports: true, advancedReports: true,
whatsappReminders: true, whatsappReminders: true,
fixedSlots: true,
}, },
pricing: { pricing: {
overrides: { overrides: {

View File

@@ -87,6 +87,11 @@ export type CourtBooking = Prisma.CourtBookingModel
* *
*/ */
export type CourtBookingLog = Prisma.CourtBookingLogModel export type CourtBookingLog = Prisma.CourtBookingLogModel
/**
* Model RecurringBookingGroup
*
*/
export type RecurringBookingGroup = Prisma.RecurringBookingGroupModel
/** /**
* Model PasswordResetRequest * Model PasswordResetRequest
* *

View File

@@ -111,6 +111,11 @@ export type CourtBooking = Prisma.CourtBookingModel
* *
*/ */
export type CourtBookingLog = Prisma.CourtBookingLogModel export type CourtBookingLog = Prisma.CourtBookingLogModel
/**
* Model RecurringBookingGroup
*
*/
export type RecurringBookingGroup = Prisma.RecurringBookingGroupModel
/** /**
* Model PasswordResetRequest * Model PasswordResetRequest
* *

View File

@@ -314,6 +314,18 @@ export type EnumCourtBookingStatusFilter<$PrismaModel = never> = {
not?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel> | $Enums.CourtBookingStatus not?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel> | $Enums.CourtBookingStatus
} }
export type UuidNullableFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
mode?: Prisma.QueryMode
not?: Prisma.NestedUuidNullableFilter<$PrismaModel> | string | null
}
export type EnumCourtBookingStatusWithAggregatesFilter<$PrismaModel = never> = { export type EnumCourtBookingStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.CourtBookingStatus | Prisma.EnumCourtBookingStatusFieldRefInput<$PrismaModel> equals?: $Enums.CourtBookingStatus | Prisma.EnumCourtBookingStatusFieldRefInput<$PrismaModel>
in?: $Enums.CourtBookingStatus[] | Prisma.ListEnumCourtBookingStatusFieldRefInput<$PrismaModel> in?: $Enums.CourtBookingStatus[] | Prisma.ListEnumCourtBookingStatusFieldRefInput<$PrismaModel>
@@ -324,6 +336,38 @@ export type EnumCourtBookingStatusWithAggregatesFilter<$PrismaModel = never> = {
_max?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel> _max?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel>
} }
export type UuidNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
mode?: Prisma.QueryMode
not?: Prisma.NestedUuidNullableWithAggregatesFilter<$PrismaModel> | string | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedStringNullableFilter<$PrismaModel>
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}
export type EnumRecurringBookingGroupStatusFilter<$PrismaModel = never> = {
equals?: $Enums.RecurringBookingGroupStatus | Prisma.EnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
in?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel> | $Enums.RecurringBookingGroupStatus
}
export type EnumRecurringBookingGroupStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.RecurringBookingGroupStatus | Prisma.EnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
in?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumRecurringBookingGroupStatusWithAggregatesFilter<$PrismaModel> | $Enums.RecurringBookingGroupStatus
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel>
_max?: Prisma.NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel>
}
export type JsonFilter<$PrismaModel = never> = export type JsonFilter<$PrismaModel = never> =
| Prisma.PatchUndefined< | Prisma.PatchUndefined<
Prisma.Either<Required<JsonFilterBase<$PrismaModel>>, Exclude<keyof Required<JsonFilterBase<$PrismaModel>>, 'path'>>, Prisma.Either<Required<JsonFilterBase<$PrismaModel>>, Exclude<keyof Required<JsonFilterBase<$PrismaModel>>, 'path'>>,
@@ -686,6 +730,17 @@ export type NestedEnumCourtBookingStatusFilter<$PrismaModel = never> = {
not?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel> | $Enums.CourtBookingStatus not?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel> | $Enums.CourtBookingStatus
} }
export type NestedUuidNullableFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
not?: Prisma.NestedUuidNullableFilter<$PrismaModel> | string | null
}
export type NestedEnumCourtBookingStatusWithAggregatesFilter<$PrismaModel = never> = { export type NestedEnumCourtBookingStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.CourtBookingStatus | Prisma.EnumCourtBookingStatusFieldRefInput<$PrismaModel> equals?: $Enums.CourtBookingStatus | Prisma.EnumCourtBookingStatusFieldRefInput<$PrismaModel>
in?: $Enums.CourtBookingStatus[] | Prisma.ListEnumCourtBookingStatusFieldRefInput<$PrismaModel> in?: $Enums.CourtBookingStatus[] | Prisma.ListEnumCourtBookingStatusFieldRefInput<$PrismaModel>
@@ -696,6 +751,37 @@ export type NestedEnumCourtBookingStatusWithAggregatesFilter<$PrismaModel = neve
_max?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel> _max?: Prisma.NestedEnumCourtBookingStatusFilter<$PrismaModel>
} }
export type NestedUuidNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
not?: Prisma.NestedUuidNullableWithAggregatesFilter<$PrismaModel> | string | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedStringNullableFilter<$PrismaModel>
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}
export type NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel = never> = {
equals?: $Enums.RecurringBookingGroupStatus | Prisma.EnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
in?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel> | $Enums.RecurringBookingGroupStatus
}
export type NestedEnumRecurringBookingGroupStatusWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.RecurringBookingGroupStatus | Prisma.EnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
in?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
notIn?: $Enums.RecurringBookingGroupStatus[] | Prisma.ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel>
not?: Prisma.NestedEnumRecurringBookingGroupStatusWithAggregatesFilter<$PrismaModel> | $Enums.RecurringBookingGroupStatus
_count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel>
_max?: Prisma.NestedEnumRecurringBookingGroupStatusFilter<$PrismaModel>
}
export type NestedJsonFilter<$PrismaModel = never> = export type NestedJsonFilter<$PrismaModel = never> =
| Prisma.PatchUndefined< | Prisma.PatchUndefined<
Prisma.Either<Required<NestedJsonFilterBase<$PrismaModel>>, Exclude<keyof Required<NestedJsonFilterBase<$PrismaModel>>, 'path'>>, Prisma.Either<Required<NestedJsonFilterBase<$PrismaModel>>, Exclude<keyof Required<NestedJsonFilterBase<$PrismaModel>>, 'path'>>,

View File

@@ -38,3 +38,11 @@ export const CourtBookingStatus = {
} as const } as const
export type CourtBookingStatus = (typeof CourtBookingStatus)[keyof typeof CourtBookingStatus] export type CourtBookingStatus = (typeof CourtBookingStatus)[keyof typeof CourtBookingStatus]
export const RecurringBookingGroupStatus = {
ACTIVE: 'ACTIVE',
CANCELLED: 'CANCELLED'
} as const
export type RecurringBookingGroupStatus = (typeof RecurringBookingGroupStatus)[keyof typeof RecurringBookingGroupStatus]

File diff suppressed because one or more lines are too long

View File

@@ -398,6 +398,7 @@ export const ModelName = {
CourtPriceRule: 'CourtPriceRule', CourtPriceRule: 'CourtPriceRule',
CourtBooking: 'CourtBooking', CourtBooking: 'CourtBooking',
CourtBookingLog: 'CourtBookingLog', CourtBookingLog: 'CourtBookingLog',
RecurringBookingGroup: 'RecurringBookingGroup',
PasswordResetRequest: 'PasswordResetRequest', PasswordResetRequest: 'PasswordResetRequest',
Plan: 'Plan' Plan: 'Plan'
} as const } as const
@@ -415,7 +416,7 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
omit: GlobalOmitOptions omit: GlobalOmitOptions
} }
meta: { meta: {
modelProps: "user" | "session" | "account" | "verification" | "complex" | "complexUser" | "complexInvitation" | "sport" | "court" | "courtMaintenance" | "courtAvailability" | "courtPriceRule" | "courtBooking" | "courtBookingLog" | "passwordResetRequest" | "plan" modelProps: "user" | "session" | "account" | "verification" | "complex" | "complexUser" | "complexInvitation" | "sport" | "court" | "courtMaintenance" | "courtAvailability" | "courtPriceRule" | "courtBooking" | "courtBookingLog" | "recurringBookingGroup" | "passwordResetRequest" | "plan"
txIsolationLevel: TransactionIsolationLevel txIsolationLevel: TransactionIsolationLevel
} }
model: { model: {
@@ -1455,6 +1456,80 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
} }
} }
} }
RecurringBookingGroup: {
payload: Prisma.$RecurringBookingGroupPayload<ExtArgs>
fields: Prisma.RecurringBookingGroupFieldRefs
operations: {
findUnique: {
args: Prisma.RecurringBookingGroupFindUniqueArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload> | null
}
findUniqueOrThrow: {
args: Prisma.RecurringBookingGroupFindUniqueOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>
}
findFirst: {
args: Prisma.RecurringBookingGroupFindFirstArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload> | null
}
findFirstOrThrow: {
args: Prisma.RecurringBookingGroupFindFirstOrThrowArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>
}
findMany: {
args: Prisma.RecurringBookingGroupFindManyArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>[]
}
create: {
args: Prisma.RecurringBookingGroupCreateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>
}
createMany: {
args: Prisma.RecurringBookingGroupCreateManyArgs<ExtArgs>
result: BatchPayload
}
createManyAndReturn: {
args: Prisma.RecurringBookingGroupCreateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>[]
}
delete: {
args: Prisma.RecurringBookingGroupDeleteArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>
}
update: {
args: Prisma.RecurringBookingGroupUpdateArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>
}
deleteMany: {
args: Prisma.RecurringBookingGroupDeleteManyArgs<ExtArgs>
result: BatchPayload
}
updateMany: {
args: Prisma.RecurringBookingGroupUpdateManyArgs<ExtArgs>
result: BatchPayload
}
updateManyAndReturn: {
args: Prisma.RecurringBookingGroupUpdateManyAndReturnArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>[]
}
upsert: {
args: Prisma.RecurringBookingGroupUpsertArgs<ExtArgs>
result: runtime.Types.Utils.PayloadToResult<Prisma.$RecurringBookingGroupPayload>
}
aggregate: {
args: Prisma.RecurringBookingGroupAggregateArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.AggregateRecurringBookingGroup>
}
groupBy: {
args: Prisma.RecurringBookingGroupGroupByArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.RecurringBookingGroupGroupByOutputType>[]
}
count: {
args: Prisma.RecurringBookingGroupCountArgs<ExtArgs>
result: runtime.Types.Utils.Optional<Prisma.RecurringBookingGroupCountAggregateOutputType> | number
}
}
}
PasswordResetRequest: { PasswordResetRequest: {
payload: Prisma.$PasswordResetRequestPayload<ExtArgs> payload: Prisma.$PasswordResetRequestPayload<ExtArgs>
fields: Prisma.PasswordResetRequestFieldRefs fields: Prisma.PasswordResetRequestFieldRefs
@@ -1832,6 +1907,7 @@ export const CourtBookingScalarFieldEnum = {
customerPhone: 'customerPhone', customerPhone: 'customerPhone',
customerEmail: 'customerEmail', customerEmail: 'customerEmail',
status: 'status', status: 'status',
recurringGroupId: 'recurringGroupId',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const
@@ -1857,6 +1933,26 @@ export const CourtBookingLogScalarFieldEnum = {
export type CourtBookingLogScalarFieldEnum = (typeof CourtBookingLogScalarFieldEnum)[keyof typeof CourtBookingLogScalarFieldEnum] export type CourtBookingLogScalarFieldEnum = (typeof CourtBookingLogScalarFieldEnum)[keyof typeof CourtBookingLogScalarFieldEnum]
export const RecurringBookingGroupScalarFieldEnum = {
id: 'id',
complexId: 'complexId',
courtId: 'courtId',
startTime: 'startTime',
endTime: 'endTime',
dayOfWeek: 'dayOfWeek',
startDate: 'startDate',
endDate: 'endDate',
status: 'status',
customerName: 'customerName',
customerPhone: 'customerPhone',
customerEmail: 'customerEmail',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type RecurringBookingGroupScalarFieldEnum = (typeof RecurringBookingGroupScalarFieldEnum)[keyof typeof RecurringBookingGroupScalarFieldEnum]
export const PasswordResetRequestScalarFieldEnum = { export const PasswordResetRequestScalarFieldEnum = {
id: 'id', id: 'id',
email: 'email', email: 'email',
@@ -2049,6 +2145,20 @@ export type ListEnumCourtBookingStatusFieldRefInput<$PrismaModel> = FieldRefInpu
/**
* Reference to a field of type 'RecurringBookingGroupStatus'
*/
export type EnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'RecurringBookingGroupStatus'>
/**
* Reference to a field of type 'RecurringBookingGroupStatus[]'
*/
export type ListEnumRecurringBookingGroupStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'RecurringBookingGroupStatus[]'>
/** /**
* Reference to a field of type 'Json' * Reference to a field of type 'Json'
*/ */
@@ -2171,6 +2281,7 @@ export type GlobalOmitConfig = {
courtPriceRule?: Prisma.CourtPriceRuleOmit courtPriceRule?: Prisma.CourtPriceRuleOmit
courtBooking?: Prisma.CourtBookingOmit courtBooking?: Prisma.CourtBookingOmit
courtBookingLog?: Prisma.CourtBookingLogOmit courtBookingLog?: Prisma.CourtBookingLogOmit
recurringBookingGroup?: Prisma.RecurringBookingGroupOmit
passwordResetRequest?: Prisma.PasswordResetRequestOmit passwordResetRequest?: Prisma.PasswordResetRequestOmit
plan?: Prisma.PlanOmit plan?: Prisma.PlanOmit
} }

View File

@@ -65,6 +65,7 @@ export const ModelName = {
CourtPriceRule: 'CourtPriceRule', CourtPriceRule: 'CourtPriceRule',
CourtBooking: 'CourtBooking', CourtBooking: 'CourtBooking',
CourtBookingLog: 'CourtBookingLog', CourtBookingLog: 'CourtBookingLog',
RecurringBookingGroup: 'RecurringBookingGroup',
PasswordResetRequest: 'PasswordResetRequest', PasswordResetRequest: 'PasswordResetRequest',
Plan: 'Plan' Plan: 'Plan'
} as const } as const
@@ -275,6 +276,7 @@ export const CourtBookingScalarFieldEnum = {
customerPhone: 'customerPhone', customerPhone: 'customerPhone',
customerEmail: 'customerEmail', customerEmail: 'customerEmail',
status: 'status', status: 'status',
recurringGroupId: 'recurringGroupId',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const
@@ -300,6 +302,26 @@ export const CourtBookingLogScalarFieldEnum = {
export type CourtBookingLogScalarFieldEnum = (typeof CourtBookingLogScalarFieldEnum)[keyof typeof CourtBookingLogScalarFieldEnum] export type CourtBookingLogScalarFieldEnum = (typeof CourtBookingLogScalarFieldEnum)[keyof typeof CourtBookingLogScalarFieldEnum]
export const RecurringBookingGroupScalarFieldEnum = {
id: 'id',
complexId: 'complexId',
courtId: 'courtId',
startTime: 'startTime',
endTime: 'endTime',
dayOfWeek: 'dayOfWeek',
startDate: 'startDate',
endDate: 'endDate',
status: 'status',
customerName: 'customerName',
customerPhone: 'customerPhone',
customerEmail: 'customerEmail',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
} as const
export type RecurringBookingGroupScalarFieldEnum = (typeof RecurringBookingGroupScalarFieldEnum)[keyof typeof RecurringBookingGroupScalarFieldEnum]
export const PasswordResetRequestScalarFieldEnum = { export const PasswordResetRequestScalarFieldEnum = {
id: 'id', id: 'id',
email: 'email', email: 'email',

View File

@@ -22,6 +22,7 @@ export type * from './models/CourtAvailability'
export type * from './models/CourtPriceRule' export type * from './models/CourtPriceRule'
export type * from './models/CourtBooking' export type * from './models/CourtBooking'
export type * from './models/CourtBookingLog' export type * from './models/CourtBookingLog'
export type * from './models/RecurringBookingGroup'
export type * from './models/PasswordResetRequest' export type * from './models/PasswordResetRequest'
export type * from './models/Plan' export type * from './models/Plan'
export type * from './commonInputTypes' export type * from './commonInputTypes'

View File

@@ -234,6 +234,7 @@ export type ComplexWhereInput = {
users?: Prisma.ComplexUserListRelationFilter users?: Prisma.ComplexUserListRelationFilter
invitations?: Prisma.ComplexInvitationListRelationFilter invitations?: Prisma.ComplexInvitationListRelationFilter
courts?: Prisma.CourtListRelationFilter courts?: Prisma.CourtListRelationFilter
recurringGroups?: Prisma.RecurringBookingGroupListRelationFilter
} }
export type ComplexOrderByWithRelationInput = { export type ComplexOrderByWithRelationInput = {
@@ -252,6 +253,7 @@ export type ComplexOrderByWithRelationInput = {
users?: Prisma.ComplexUserOrderByRelationAggregateInput users?: Prisma.ComplexUserOrderByRelationAggregateInput
invitations?: Prisma.ComplexInvitationOrderByRelationAggregateInput invitations?: Prisma.ComplexInvitationOrderByRelationAggregateInput
courts?: Prisma.CourtOrderByRelationAggregateInput courts?: Prisma.CourtOrderByRelationAggregateInput
recurringGroups?: Prisma.RecurringBookingGroupOrderByRelationAggregateInput
} }
export type ComplexWhereUniqueInput = Prisma.AtLeast<{ export type ComplexWhereUniqueInput = Prisma.AtLeast<{
@@ -273,6 +275,7 @@ export type ComplexWhereUniqueInput = Prisma.AtLeast<{
users?: Prisma.ComplexUserListRelationFilter users?: Prisma.ComplexUserListRelationFilter
invitations?: Prisma.ComplexInvitationListRelationFilter invitations?: Prisma.ComplexInvitationListRelationFilter
courts?: Prisma.CourtListRelationFilter courts?: Prisma.CourtListRelationFilter
recurringGroups?: Prisma.RecurringBookingGroupListRelationFilter
}, "id" | "complexSlug"> }, "id" | "complexSlug">
export type ComplexOrderByWithAggregationInput = { export type ComplexOrderByWithAggregationInput = {
@@ -324,6 +327,7 @@ export type ComplexCreateInput = {
users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput
invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput
} }
export type ComplexUncheckedCreateInput = { export type ComplexUncheckedCreateInput = {
@@ -341,6 +345,7 @@ export type ComplexUncheckedCreateInput = {
users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput
invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput
} }
export type ComplexUpdateInput = { export type ComplexUpdateInput = {
@@ -358,6 +363,7 @@ export type ComplexUpdateInput = {
users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput
invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput
} }
export type ComplexUncheckedUpdateInput = { export type ComplexUncheckedUpdateInput = {
@@ -375,6 +381,7 @@ export type ComplexUncheckedUpdateInput = {
users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput
invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput
} }
export type ComplexCreateManyInput = { export type ComplexCreateManyInput = {
@@ -517,6 +524,20 @@ export type ComplexUpdateOneRequiredWithoutCourtsNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.ComplexUpdateToOneWithWhereWithoutCourtsInput, Prisma.ComplexUpdateWithoutCourtsInput>, Prisma.ComplexUncheckedUpdateWithoutCourtsInput> update?: Prisma.XOR<Prisma.XOR<Prisma.ComplexUpdateToOneWithWhereWithoutCourtsInput, Prisma.ComplexUpdateWithoutCourtsInput>, Prisma.ComplexUncheckedUpdateWithoutCourtsInput>
} }
export type ComplexCreateNestedOneWithoutRecurringGroupsInput = {
create?: Prisma.XOR<Prisma.ComplexCreateWithoutRecurringGroupsInput, Prisma.ComplexUncheckedCreateWithoutRecurringGroupsInput>
connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutRecurringGroupsInput
connect?: Prisma.ComplexWhereUniqueInput
}
export type ComplexUpdateOneRequiredWithoutRecurringGroupsNestedInput = {
create?: Prisma.XOR<Prisma.ComplexCreateWithoutRecurringGroupsInput, Prisma.ComplexUncheckedCreateWithoutRecurringGroupsInput>
connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutRecurringGroupsInput
upsert?: Prisma.ComplexUpsertWithoutRecurringGroupsInput
connect?: Prisma.ComplexWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.ComplexUpdateToOneWithWhereWithoutRecurringGroupsInput, Prisma.ComplexUpdateWithoutRecurringGroupsInput>, Prisma.ComplexUncheckedUpdateWithoutRecurringGroupsInput>
}
export type ComplexCreateNestedManyWithoutPlanInput = { export type ComplexCreateNestedManyWithoutPlanInput = {
create?: Prisma.XOR<Prisma.ComplexCreateWithoutPlanInput, Prisma.ComplexUncheckedCreateWithoutPlanInput> | Prisma.ComplexCreateWithoutPlanInput[] | Prisma.ComplexUncheckedCreateWithoutPlanInput[] create?: Prisma.XOR<Prisma.ComplexCreateWithoutPlanInput, Prisma.ComplexUncheckedCreateWithoutPlanInput> | Prisma.ComplexCreateWithoutPlanInput[] | Prisma.ComplexUncheckedCreateWithoutPlanInput[]
connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutPlanInput | Prisma.ComplexCreateOrConnectWithoutPlanInput[] connectOrCreate?: Prisma.ComplexCreateOrConnectWithoutPlanInput | Prisma.ComplexCreateOrConnectWithoutPlanInput[]
@@ -573,6 +594,7 @@ export type ComplexCreateWithoutUsersInput = {
plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput
invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput
} }
export type ComplexUncheckedCreateWithoutUsersInput = { export type ComplexUncheckedCreateWithoutUsersInput = {
@@ -589,6 +611,7 @@ export type ComplexUncheckedCreateWithoutUsersInput = {
updatedAt?: Date | string updatedAt?: Date | string
invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput
} }
export type ComplexCreateOrConnectWithoutUsersInput = { export type ComplexCreateOrConnectWithoutUsersInput = {
@@ -621,6 +644,7 @@ export type ComplexUpdateWithoutUsersInput = {
plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput
invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput
} }
export type ComplexUncheckedUpdateWithoutUsersInput = { export type ComplexUncheckedUpdateWithoutUsersInput = {
@@ -637,6 +661,7 @@ export type ComplexUncheckedUpdateWithoutUsersInput = {
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput
} }
export type ComplexCreateWithoutInvitationsInput = { export type ComplexCreateWithoutInvitationsInput = {
@@ -653,6 +678,7 @@ export type ComplexCreateWithoutInvitationsInput = {
plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput
users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput
} }
export type ComplexUncheckedCreateWithoutInvitationsInput = { export type ComplexUncheckedCreateWithoutInvitationsInput = {
@@ -669,6 +695,7 @@ export type ComplexUncheckedCreateWithoutInvitationsInput = {
updatedAt?: Date | string updatedAt?: Date | string
users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput
} }
export type ComplexCreateOrConnectWithoutInvitationsInput = { export type ComplexCreateOrConnectWithoutInvitationsInput = {
@@ -701,6 +728,7 @@ export type ComplexUpdateWithoutInvitationsInput = {
plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput
users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput
} }
export type ComplexUncheckedUpdateWithoutInvitationsInput = { export type ComplexUncheckedUpdateWithoutInvitationsInput = {
@@ -717,6 +745,7 @@ export type ComplexUncheckedUpdateWithoutInvitationsInput = {
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput
} }
export type ComplexCreateWithoutCourtsInput = { export type ComplexCreateWithoutCourtsInput = {
@@ -733,6 +762,7 @@ export type ComplexCreateWithoutCourtsInput = {
plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput plan?: Prisma.PlanCreateNestedOneWithoutComplexesInput
users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput
invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput
} }
export type ComplexUncheckedCreateWithoutCourtsInput = { export type ComplexUncheckedCreateWithoutCourtsInput = {
@@ -749,6 +779,7 @@ export type ComplexUncheckedCreateWithoutCourtsInput = {
updatedAt?: Date | string updatedAt?: Date | string
users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput
invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput
} }
export type ComplexCreateOrConnectWithoutCourtsInput = { export type ComplexCreateOrConnectWithoutCourtsInput = {
@@ -781,6 +812,7 @@ export type ComplexUpdateWithoutCourtsInput = {
plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput plan?: Prisma.PlanUpdateOneWithoutComplexesNestedInput
users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput
invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput
} }
export type ComplexUncheckedUpdateWithoutCourtsInput = { export type ComplexUncheckedUpdateWithoutCourtsInput = {
@@ -797,6 +829,91 @@ export type ComplexUncheckedUpdateWithoutCourtsInput = {
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput
invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput
}
export type ComplexCreateWithoutRecurringGroupsInput = {
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
}
export type ComplexUncheckedCreateWithoutRecurringGroupsInput = {
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
}
export type ComplexCreateOrConnectWithoutRecurringGroupsInput = {
where: Prisma.ComplexWhereUniqueInput
create: Prisma.XOR<Prisma.ComplexCreateWithoutRecurringGroupsInput, Prisma.ComplexUncheckedCreateWithoutRecurringGroupsInput>
}
export type ComplexUpsertWithoutRecurringGroupsInput = {
update: Prisma.XOR<Prisma.ComplexUpdateWithoutRecurringGroupsInput, Prisma.ComplexUncheckedUpdateWithoutRecurringGroupsInput>
create: Prisma.XOR<Prisma.ComplexCreateWithoutRecurringGroupsInput, Prisma.ComplexUncheckedCreateWithoutRecurringGroupsInput>
where?: Prisma.ComplexWhereInput
}
export type ComplexUpdateToOneWithWhereWithoutRecurringGroupsInput = {
where?: Prisma.ComplexWhereInput
data: Prisma.XOR<Prisma.ComplexUpdateWithoutRecurringGroupsInput, Prisma.ComplexUncheckedUpdateWithoutRecurringGroupsInput>
}
export type ComplexUpdateWithoutRecurringGroupsInput = {
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
}
export type ComplexUncheckedUpdateWithoutRecurringGroupsInput = {
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
} }
export type ComplexCreateWithoutPlanInput = { export type ComplexCreateWithoutPlanInput = {
@@ -813,6 +930,7 @@ export type ComplexCreateWithoutPlanInput = {
users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserCreateNestedManyWithoutComplexInput
invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtCreateNestedManyWithoutComplexInput courts?: Prisma.CourtCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutComplexInput
} }
export type ComplexUncheckedCreateWithoutPlanInput = { export type ComplexUncheckedCreateWithoutPlanInput = {
@@ -829,6 +947,7 @@ export type ComplexUncheckedCreateWithoutPlanInput = {
users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput users?: Prisma.ComplexUserUncheckedCreateNestedManyWithoutComplexInput
invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput invitations?: Prisma.ComplexInvitationUncheckedCreateNestedManyWithoutComplexInput
courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput courts?: Prisma.CourtUncheckedCreateNestedManyWithoutComplexInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutComplexInput
} }
export type ComplexCreateOrConnectWithoutPlanInput = { export type ComplexCreateOrConnectWithoutPlanInput = {
@@ -901,6 +1020,7 @@ export type ComplexUpdateWithoutPlanInput = {
users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUpdateManyWithoutComplexNestedInput
invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutComplexNestedInput
} }
export type ComplexUncheckedUpdateWithoutPlanInput = { export type ComplexUncheckedUpdateWithoutPlanInput = {
@@ -917,6 +1037,7 @@ export type ComplexUncheckedUpdateWithoutPlanInput = {
users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput users?: Prisma.ComplexUserUncheckedUpdateManyWithoutComplexNestedInput
invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput invitations?: Prisma.ComplexInvitationUncheckedUpdateManyWithoutComplexNestedInput
courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput courts?: Prisma.CourtUncheckedUpdateManyWithoutComplexNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutComplexNestedInput
} }
export type ComplexUncheckedUpdateManyWithoutPlanInput = { export type ComplexUncheckedUpdateManyWithoutPlanInput = {
@@ -941,12 +1062,14 @@ export type ComplexCountOutputType = {
users: number users: number
invitations: number invitations: number
courts: number courts: number
recurringGroups: number
} }
export type ComplexCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type ComplexCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
users?: boolean | ComplexCountOutputTypeCountUsersArgs users?: boolean | ComplexCountOutputTypeCountUsersArgs
invitations?: boolean | ComplexCountOutputTypeCountInvitationsArgs invitations?: boolean | ComplexCountOutputTypeCountInvitationsArgs
courts?: boolean | ComplexCountOutputTypeCountCourtsArgs courts?: boolean | ComplexCountOutputTypeCountCourtsArgs
recurringGroups?: boolean | ComplexCountOutputTypeCountRecurringGroupsArgs
} }
/** /**
@@ -980,6 +1103,13 @@ export type ComplexCountOutputTypeCountCourtsArgs<ExtArgs extends runtime.Types.
where?: Prisma.CourtWhereInput where?: Prisma.CourtWhereInput
} }
/**
* ComplexCountOutputType without action
*/
export type ComplexCountOutputTypeCountRecurringGroupsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.RecurringBookingGroupWhereInput
}
export type ComplexSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type ComplexSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
@@ -997,6 +1127,7 @@ export type ComplexSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs
users?: boolean | Prisma.Complex$usersArgs<ExtArgs> users?: boolean | Prisma.Complex$usersArgs<ExtArgs>
invitations?: boolean | Prisma.Complex$invitationsArgs<ExtArgs> invitations?: boolean | Prisma.Complex$invitationsArgs<ExtArgs>
courts?: boolean | Prisma.Complex$courtsArgs<ExtArgs> courts?: boolean | Prisma.Complex$courtsArgs<ExtArgs>
recurringGroups?: boolean | Prisma.Complex$recurringGroupsArgs<ExtArgs>
_count?: boolean | Prisma.ComplexCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.ComplexCountOutputTypeDefaultArgs<ExtArgs>
}, ExtArgs["result"]["complex"]> }, ExtArgs["result"]["complex"]>
@@ -1050,6 +1181,7 @@ export type ComplexInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs
users?: boolean | Prisma.Complex$usersArgs<ExtArgs> users?: boolean | Prisma.Complex$usersArgs<ExtArgs>
invitations?: boolean | Prisma.Complex$invitationsArgs<ExtArgs> invitations?: boolean | Prisma.Complex$invitationsArgs<ExtArgs>
courts?: boolean | Prisma.Complex$courtsArgs<ExtArgs> courts?: boolean | Prisma.Complex$courtsArgs<ExtArgs>
recurringGroups?: boolean | Prisma.Complex$recurringGroupsArgs<ExtArgs>
_count?: boolean | Prisma.ComplexCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.ComplexCountOutputTypeDefaultArgs<ExtArgs>
} }
export type ComplexIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type ComplexIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
@@ -1066,6 +1198,7 @@ export type $ComplexPayload<ExtArgs extends runtime.Types.Extensions.InternalArg
users: Prisma.$ComplexUserPayload<ExtArgs>[] users: Prisma.$ComplexUserPayload<ExtArgs>[]
invitations: Prisma.$ComplexInvitationPayload<ExtArgs>[] invitations: Prisma.$ComplexInvitationPayload<ExtArgs>[]
courts: Prisma.$CourtPayload<ExtArgs>[] courts: Prisma.$CourtPayload<ExtArgs>[]
recurringGroups: Prisma.$RecurringBookingGroupPayload<ExtArgs>[]
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string id: string
@@ -1477,6 +1610,7 @@ export interface Prisma__ComplexClient<T, Null = never, ExtArgs extends runtime.
users<T extends Prisma.Complex$usersArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$usersArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$ComplexUserPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> users<T extends Prisma.Complex$usersArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$usersArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$ComplexUserPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
invitations<T extends Prisma.Complex$invitationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$invitationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$ComplexInvitationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> invitations<T extends Prisma.Complex$invitationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$invitationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$ComplexInvitationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
courts<T extends Prisma.Complex$courtsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$courtsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> courts<T extends Prisma.Complex$courtsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$courtsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
recurringGroups<T extends Prisma.Complex$recurringGroupsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Complex$recurringGroupsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$RecurringBookingGroupPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
/** /**
* Attaches callbacks for the resolution and/or rejection of the Promise. * Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved. * @param onfulfilled The callback to execute when the Promise is resolved.
@@ -2008,6 +2142,30 @@ export type Complex$courtsArgs<ExtArgs extends runtime.Types.Extensions.Internal
distinct?: Prisma.CourtScalarFieldEnum | Prisma.CourtScalarFieldEnum[] distinct?: Prisma.CourtScalarFieldEnum | Prisma.CourtScalarFieldEnum[]
} }
/**
* Complex.recurringGroups
*/
export type Complex$recurringGroupsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the RecurringBookingGroup
*/
select?: Prisma.RecurringBookingGroupSelect<ExtArgs> | null
/**
* Omit specific fields from the RecurringBookingGroup
*/
omit?: Prisma.RecurringBookingGroupOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.RecurringBookingGroupInclude<ExtArgs> | null
where?: Prisma.RecurringBookingGroupWhereInput
orderBy?: Prisma.RecurringBookingGroupOrderByWithRelationInput | Prisma.RecurringBookingGroupOrderByWithRelationInput[]
cursor?: Prisma.RecurringBookingGroupWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.RecurringBookingGroupScalarFieldEnum | Prisma.RecurringBookingGroupScalarFieldEnum[]
}
/** /**
* Complex without action * Complex without action
*/ */

View File

@@ -266,6 +266,7 @@ export type CourtWhereInput = {
priceRules?: Prisma.CourtPriceRuleListRelationFilter priceRules?: Prisma.CourtPriceRuleListRelationFilter
bookings?: Prisma.CourtBookingListRelationFilter bookings?: Prisma.CourtBookingListRelationFilter
maintenances?: Prisma.CourtMaintenanceListRelationFilter maintenances?: Prisma.CourtMaintenanceListRelationFilter
recurringGroups?: Prisma.RecurringBookingGroupListRelationFilter
} }
export type CourtOrderByWithRelationInput = { export type CourtOrderByWithRelationInput = {
@@ -285,6 +286,7 @@ export type CourtOrderByWithRelationInput = {
priceRules?: Prisma.CourtPriceRuleOrderByRelationAggregateInput priceRules?: Prisma.CourtPriceRuleOrderByRelationAggregateInput
bookings?: Prisma.CourtBookingOrderByRelationAggregateInput bookings?: Prisma.CourtBookingOrderByRelationAggregateInput
maintenances?: Prisma.CourtMaintenanceOrderByRelationAggregateInput maintenances?: Prisma.CourtMaintenanceOrderByRelationAggregateInput
recurringGroups?: Prisma.RecurringBookingGroupOrderByRelationAggregateInput
} }
export type CourtWhereUniqueInput = Prisma.AtLeast<{ export type CourtWhereUniqueInput = Prisma.AtLeast<{
@@ -307,6 +309,7 @@ export type CourtWhereUniqueInput = Prisma.AtLeast<{
priceRules?: Prisma.CourtPriceRuleListRelationFilter priceRules?: Prisma.CourtPriceRuleListRelationFilter
bookings?: Prisma.CourtBookingListRelationFilter bookings?: Prisma.CourtBookingListRelationFilter
maintenances?: Prisma.CourtMaintenanceListRelationFilter maintenances?: Prisma.CourtMaintenanceListRelationFilter
recurringGroups?: Prisma.RecurringBookingGroupListRelationFilter
}, "id"> }, "id">
export type CourtOrderByWithAggregationInput = { export type CourtOrderByWithAggregationInput = {
@@ -358,6 +361,7 @@ export type CourtCreateInput = {
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateInput = { export type CourtUncheckedCreateInput = {
@@ -375,6 +379,7 @@ export type CourtUncheckedCreateInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtUpdateInput = { export type CourtUpdateInput = {
@@ -392,6 +397,7 @@ export type CourtUpdateInput = {
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateInput = { export type CourtUncheckedUpdateInput = {
@@ -409,6 +415,7 @@ export type CourtUncheckedUpdateInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtCreateManyInput = { export type CourtCreateManyInput = {
@@ -668,6 +675,20 @@ export type CourtUpdateOneRequiredWithoutBookingsNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.CourtUpdateToOneWithWhereWithoutBookingsInput, Prisma.CourtUpdateWithoutBookingsInput>, Prisma.CourtUncheckedUpdateWithoutBookingsInput> update?: Prisma.XOR<Prisma.XOR<Prisma.CourtUpdateToOneWithWhereWithoutBookingsInput, Prisma.CourtUpdateWithoutBookingsInput>, Prisma.CourtUncheckedUpdateWithoutBookingsInput>
} }
export type CourtCreateNestedOneWithoutRecurringGroupsInput = {
create?: Prisma.XOR<Prisma.CourtCreateWithoutRecurringGroupsInput, Prisma.CourtUncheckedCreateWithoutRecurringGroupsInput>
connectOrCreate?: Prisma.CourtCreateOrConnectWithoutRecurringGroupsInput
connect?: Prisma.CourtWhereUniqueInput
}
export type CourtUpdateOneRequiredWithoutRecurringGroupsNestedInput = {
create?: Prisma.XOR<Prisma.CourtCreateWithoutRecurringGroupsInput, Prisma.CourtUncheckedCreateWithoutRecurringGroupsInput>
connectOrCreate?: Prisma.CourtCreateOrConnectWithoutRecurringGroupsInput
upsert?: Prisma.CourtUpsertWithoutRecurringGroupsInput
connect?: Prisma.CourtWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.CourtUpdateToOneWithWhereWithoutRecurringGroupsInput, Prisma.CourtUpdateWithoutRecurringGroupsInput>, Prisma.CourtUncheckedUpdateWithoutRecurringGroupsInput>
}
export type CourtCreateWithoutComplexInput = { export type CourtCreateWithoutComplexInput = {
id: string id: string
name: string name: string
@@ -682,6 +703,7 @@ export type CourtCreateWithoutComplexInput = {
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateWithoutComplexInput = { export type CourtUncheckedCreateWithoutComplexInput = {
@@ -698,6 +720,7 @@ export type CourtUncheckedCreateWithoutComplexInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtCreateOrConnectWithoutComplexInput = { export type CourtCreateOrConnectWithoutComplexInput = {
@@ -756,6 +779,7 @@ export type CourtCreateWithoutSportInput = {
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateWithoutSportInput = { export type CourtUncheckedCreateWithoutSportInput = {
@@ -772,6 +796,7 @@ export type CourtUncheckedCreateWithoutSportInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtCreateOrConnectWithoutSportInput = { export type CourtCreateOrConnectWithoutSportInput = {
@@ -814,6 +839,7 @@ export type CourtCreateWithoutMaintenancesInput = {
availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateWithoutMaintenancesInput = { export type CourtUncheckedCreateWithoutMaintenancesInput = {
@@ -830,6 +856,7 @@ export type CourtUncheckedCreateWithoutMaintenancesInput = {
availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtCreateOrConnectWithoutMaintenancesInput = { export type CourtCreateOrConnectWithoutMaintenancesInput = {
@@ -862,6 +889,7 @@ export type CourtUpdateWithoutMaintenancesInput = {
availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateWithoutMaintenancesInput = { export type CourtUncheckedUpdateWithoutMaintenancesInput = {
@@ -878,6 +906,7 @@ export type CourtUncheckedUpdateWithoutMaintenancesInput = {
availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtCreateWithoutAvailabilitiesInput = { export type CourtCreateWithoutAvailabilitiesInput = {
@@ -894,6 +923,7 @@ export type CourtCreateWithoutAvailabilitiesInput = {
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateWithoutAvailabilitiesInput = { export type CourtUncheckedCreateWithoutAvailabilitiesInput = {
@@ -910,6 +940,7 @@ export type CourtUncheckedCreateWithoutAvailabilitiesInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtCreateOrConnectWithoutAvailabilitiesInput = { export type CourtCreateOrConnectWithoutAvailabilitiesInput = {
@@ -942,6 +973,7 @@ export type CourtUpdateWithoutAvailabilitiesInput = {
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateWithoutAvailabilitiesInput = { export type CourtUncheckedUpdateWithoutAvailabilitiesInput = {
@@ -958,6 +990,7 @@ export type CourtUncheckedUpdateWithoutAvailabilitiesInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtCreateWithoutPriceRulesInput = { export type CourtCreateWithoutPriceRulesInput = {
@@ -974,6 +1007,7 @@ export type CourtCreateWithoutPriceRulesInput = {
availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateWithoutPriceRulesInput = { export type CourtUncheckedCreateWithoutPriceRulesInput = {
@@ -990,6 +1024,7 @@ export type CourtUncheckedCreateWithoutPriceRulesInput = {
availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtCreateOrConnectWithoutPriceRulesInput = { export type CourtCreateOrConnectWithoutPriceRulesInput = {
@@ -1022,6 +1057,7 @@ export type CourtUpdateWithoutPriceRulesInput = {
availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateWithoutPriceRulesInput = { export type CourtUncheckedUpdateWithoutPriceRulesInput = {
@@ -1038,6 +1074,7 @@ export type CourtUncheckedUpdateWithoutPriceRulesInput = {
availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtCreateWithoutBookingsInput = { export type CourtCreateWithoutBookingsInput = {
@@ -1054,6 +1091,7 @@ export type CourtCreateWithoutBookingsInput = {
availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupCreateNestedManyWithoutCourtInput
} }
export type CourtUncheckedCreateWithoutBookingsInput = { export type CourtUncheckedCreateWithoutBookingsInput = {
@@ -1070,6 +1108,7 @@ export type CourtUncheckedCreateWithoutBookingsInput = {
availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedCreateNestedManyWithoutCourtInput
} }
export type CourtCreateOrConnectWithoutBookingsInput = { export type CourtCreateOrConnectWithoutBookingsInput = {
@@ -1102,6 +1141,7 @@ export type CourtUpdateWithoutBookingsInput = {
availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateWithoutBookingsInput = { export type CourtUncheckedUpdateWithoutBookingsInput = {
@@ -1118,6 +1158,91 @@ export type CourtUncheckedUpdateWithoutBookingsInput = {
availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
}
export type CourtCreateWithoutRecurringGroupsInput = {
id: string
name: string
slotDurationMinutes: number
basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string
isUnderMaintenance?: boolean
maintenanceReason?: string | null
createdAt?: Date | string
updatedAt?: Date | string
complex: Prisma.ComplexCreateNestedOneWithoutCourtsInput
sport: Prisma.SportCreateNestedOneWithoutCourtsInput
availabilities?: Prisma.CourtAvailabilityCreateNestedManyWithoutCourtInput
priceRules?: Prisma.CourtPriceRuleCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceCreateNestedManyWithoutCourtInput
}
export type CourtUncheckedCreateWithoutRecurringGroupsInput = {
id: string
complexId: string
sportId: string
name: string
slotDurationMinutes: number
basePrice: runtime.Decimal | runtime.DecimalJsLike | number | string
isUnderMaintenance?: boolean
maintenanceReason?: string | null
createdAt?: Date | string
updatedAt?: Date | string
availabilities?: Prisma.CourtAvailabilityUncheckedCreateNestedManyWithoutCourtInput
priceRules?: Prisma.CourtPriceRuleUncheckedCreateNestedManyWithoutCourtInput
bookings?: Prisma.CourtBookingUncheckedCreateNestedManyWithoutCourtInput
maintenances?: Prisma.CourtMaintenanceUncheckedCreateNestedManyWithoutCourtInput
}
export type CourtCreateOrConnectWithoutRecurringGroupsInput = {
where: Prisma.CourtWhereUniqueInput
create: Prisma.XOR<Prisma.CourtCreateWithoutRecurringGroupsInput, Prisma.CourtUncheckedCreateWithoutRecurringGroupsInput>
}
export type CourtUpsertWithoutRecurringGroupsInput = {
update: Prisma.XOR<Prisma.CourtUpdateWithoutRecurringGroupsInput, Prisma.CourtUncheckedUpdateWithoutRecurringGroupsInput>
create: Prisma.XOR<Prisma.CourtCreateWithoutRecurringGroupsInput, Prisma.CourtUncheckedCreateWithoutRecurringGroupsInput>
where?: Prisma.CourtWhereInput
}
export type CourtUpdateToOneWithWhereWithoutRecurringGroupsInput = {
where?: Prisma.CourtWhereInput
data: Prisma.XOR<Prisma.CourtUpdateWithoutRecurringGroupsInput, Prisma.CourtUncheckedUpdateWithoutRecurringGroupsInput>
}
export type CourtUpdateWithoutRecurringGroupsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number
basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean
maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
complex?: Prisma.ComplexUpdateOneRequiredWithoutCourtsNestedInput
sport?: Prisma.SportUpdateOneRequiredWithoutCourtsNestedInput
availabilities?: Prisma.CourtAvailabilityUpdateManyWithoutCourtNestedInput
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
}
export type CourtUncheckedUpdateWithoutRecurringGroupsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
complexId?: Prisma.StringFieldUpdateOperationsInput | string
sportId?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
slotDurationMinutes?: Prisma.IntFieldUpdateOperationsInput | number
basePrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
isUnderMaintenance?: Prisma.BoolFieldUpdateOperationsInput | boolean
maintenanceReason?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
availabilities?: Prisma.CourtAvailabilityUncheckedUpdateManyWithoutCourtNestedInput
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtCreateManyComplexInput = { export type CourtCreateManyComplexInput = {
@@ -1146,6 +1271,7 @@ export type CourtUpdateWithoutComplexInput = {
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateWithoutComplexInput = { export type CourtUncheckedUpdateWithoutComplexInput = {
@@ -1162,6 +1288,7 @@ export type CourtUncheckedUpdateWithoutComplexInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateManyWithoutComplexInput = { export type CourtUncheckedUpdateManyWithoutComplexInput = {
@@ -1202,6 +1329,7 @@ export type CourtUpdateWithoutSportInput = {
priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateWithoutSportInput = { export type CourtUncheckedUpdateWithoutSportInput = {
@@ -1218,6 +1346,7 @@ export type CourtUncheckedUpdateWithoutSportInput = {
priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput priceRules?: Prisma.CourtPriceRuleUncheckedUpdateManyWithoutCourtNestedInput
bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput bookings?: Prisma.CourtBookingUncheckedUpdateManyWithoutCourtNestedInput
maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput maintenances?: Prisma.CourtMaintenanceUncheckedUpdateManyWithoutCourtNestedInput
recurringGroups?: Prisma.RecurringBookingGroupUncheckedUpdateManyWithoutCourtNestedInput
} }
export type CourtUncheckedUpdateManyWithoutSportInput = { export type CourtUncheckedUpdateManyWithoutSportInput = {
@@ -1242,6 +1371,7 @@ export type CourtCountOutputType = {
priceRules: number priceRules: number
bookings: number bookings: number
maintenances: number maintenances: number
recurringGroups: number
} }
export type CourtCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type CourtCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
@@ -1249,6 +1379,7 @@ export type CourtCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.
priceRules?: boolean | CourtCountOutputTypeCountPriceRulesArgs priceRules?: boolean | CourtCountOutputTypeCountPriceRulesArgs
bookings?: boolean | CourtCountOutputTypeCountBookingsArgs bookings?: boolean | CourtCountOutputTypeCountBookingsArgs
maintenances?: boolean | CourtCountOutputTypeCountMaintenancesArgs maintenances?: boolean | CourtCountOutputTypeCountMaintenancesArgs
recurringGroups?: boolean | CourtCountOutputTypeCountRecurringGroupsArgs
} }
/** /**
@@ -1289,6 +1420,13 @@ export type CourtCountOutputTypeCountMaintenancesArgs<ExtArgs extends runtime.Ty
where?: Prisma.CourtMaintenanceWhereInput where?: Prisma.CourtMaintenanceWhereInput
} }
/**
* CourtCountOutputType without action
*/
export type CourtCountOutputTypeCountRecurringGroupsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.RecurringBookingGroupWhereInput
}
export type CourtSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type CourtSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
@@ -1307,6 +1445,7 @@ export type CourtSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs =
priceRules?: boolean | Prisma.Court$priceRulesArgs<ExtArgs> priceRules?: boolean | Prisma.Court$priceRulesArgs<ExtArgs>
bookings?: boolean | Prisma.Court$bookingsArgs<ExtArgs> bookings?: boolean | Prisma.Court$bookingsArgs<ExtArgs>
maintenances?: boolean | Prisma.Court$maintenancesArgs<ExtArgs> maintenances?: boolean | Prisma.Court$maintenancesArgs<ExtArgs>
recurringGroups?: boolean | Prisma.Court$recurringGroupsArgs<ExtArgs>
_count?: boolean | Prisma.CourtCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.CourtCountOutputTypeDefaultArgs<ExtArgs>
}, ExtArgs["result"]["court"]> }, ExtArgs["result"]["court"]>
@@ -1361,6 +1500,7 @@ export type CourtInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs =
priceRules?: boolean | Prisma.Court$priceRulesArgs<ExtArgs> priceRules?: boolean | Prisma.Court$priceRulesArgs<ExtArgs>
bookings?: boolean | Prisma.Court$bookingsArgs<ExtArgs> bookings?: boolean | Prisma.Court$bookingsArgs<ExtArgs>
maintenances?: boolean | Prisma.Court$maintenancesArgs<ExtArgs> maintenances?: boolean | Prisma.Court$maintenancesArgs<ExtArgs>
recurringGroups?: boolean | Prisma.Court$recurringGroupsArgs<ExtArgs>
_count?: boolean | Prisma.CourtCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.CourtCountOutputTypeDefaultArgs<ExtArgs>
} }
export type CourtIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type CourtIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
@@ -1381,6 +1521,7 @@ export type $CourtPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs
priceRules: Prisma.$CourtPriceRulePayload<ExtArgs>[] priceRules: Prisma.$CourtPriceRulePayload<ExtArgs>[]
bookings: Prisma.$CourtBookingPayload<ExtArgs>[] bookings: Prisma.$CourtBookingPayload<ExtArgs>[]
maintenances: Prisma.$CourtMaintenancePayload<ExtArgs>[] maintenances: Prisma.$CourtMaintenancePayload<ExtArgs>[]
recurringGroups: Prisma.$RecurringBookingGroupPayload<ExtArgs>[]
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string id: string
@@ -1793,6 +1934,7 @@ export interface Prisma__CourtClient<T, Null = never, ExtArgs extends runtime.Ty
priceRules<T extends Prisma.Court$priceRulesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$priceRulesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtPriceRulePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> priceRules<T extends Prisma.Court$priceRulesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$priceRulesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtPriceRulePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
bookings<T extends Prisma.Court$bookingsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$bookingsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtBookingPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> bookings<T extends Prisma.Court$bookingsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$bookingsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtBookingPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
maintenances<T extends Prisma.Court$maintenancesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$maintenancesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtMaintenancePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> maintenances<T extends Prisma.Court$maintenancesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$maintenancesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$CourtMaintenancePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
recurringGroups<T extends Prisma.Court$recurringGroupsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Court$recurringGroupsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$RecurringBookingGroupPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
/** /**
* Attaches callbacks for the resolution and/or rejection of the Promise. * Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved. * @param onfulfilled The callback to execute when the Promise is resolved.
@@ -2328,6 +2470,30 @@ export type Court$maintenancesArgs<ExtArgs extends runtime.Types.Extensions.Inte
distinct?: Prisma.CourtMaintenanceScalarFieldEnum | Prisma.CourtMaintenanceScalarFieldEnum[] distinct?: Prisma.CourtMaintenanceScalarFieldEnum | Prisma.CourtMaintenanceScalarFieldEnum[]
} }
/**
* Court.recurringGroups
*/
export type Court$recurringGroupsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the RecurringBookingGroup
*/
select?: Prisma.RecurringBookingGroupSelect<ExtArgs> | null
/**
* Omit specific fields from the RecurringBookingGroup
*/
omit?: Prisma.RecurringBookingGroupOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.RecurringBookingGroupInclude<ExtArgs> | null
where?: Prisma.RecurringBookingGroupWhereInput
orderBy?: Prisma.RecurringBookingGroupOrderByWithRelationInput | Prisma.RecurringBookingGroupOrderByWithRelationInput[]
cursor?: Prisma.RecurringBookingGroupWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.RecurringBookingGroupScalarFieldEnum | Prisma.RecurringBookingGroupScalarFieldEnum[]
}
/** /**
* Court without action * Court without action
*/ */

View File

@@ -35,6 +35,7 @@ export type CourtBookingMinAggregateOutputType = {
customerPhone: string | null customerPhone: string | null
customerEmail: string | null customerEmail: string | null
status: $Enums.CourtBookingStatus | null status: $Enums.CourtBookingStatus | null
recurringGroupId: string | null
createdAt: Date | null createdAt: Date | null
updatedAt: Date | null updatedAt: Date | null
} }
@@ -50,6 +51,7 @@ export type CourtBookingMaxAggregateOutputType = {
customerPhone: string | null customerPhone: string | null
customerEmail: string | null customerEmail: string | null
status: $Enums.CourtBookingStatus | null status: $Enums.CourtBookingStatus | null
recurringGroupId: string | null
createdAt: Date | null createdAt: Date | null
updatedAt: Date | null updatedAt: Date | null
} }
@@ -65,6 +67,7 @@ export type CourtBookingCountAggregateOutputType = {
customerPhone: number customerPhone: number
customerEmail: number customerEmail: number
status: number status: number
recurringGroupId: number
createdAt: number createdAt: number
updatedAt: number updatedAt: number
_all: number _all: number
@@ -82,6 +85,7 @@ export type CourtBookingMinAggregateInputType = {
customerPhone?: true customerPhone?: true
customerEmail?: true customerEmail?: true
status?: true status?: true
recurringGroupId?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
} }
@@ -97,6 +101,7 @@ export type CourtBookingMaxAggregateInputType = {
customerPhone?: true customerPhone?: true
customerEmail?: true customerEmail?: true
status?: true status?: true
recurringGroupId?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
} }
@@ -112,6 +117,7 @@ export type CourtBookingCountAggregateInputType = {
customerPhone?: true customerPhone?: true
customerEmail?: true customerEmail?: true
status?: true status?: true
recurringGroupId?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
_all?: true _all?: true
@@ -200,6 +206,7 @@ export type CourtBookingGroupByOutputType = {
customerPhone: string customerPhone: string
customerEmail: string customerEmail: string
status: $Enums.CourtBookingStatus status: $Enums.CourtBookingStatus
recurringGroupId: string | null
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
_count: CourtBookingCountAggregateOutputType | null _count: CourtBookingCountAggregateOutputType | null
@@ -236,9 +243,11 @@ export type CourtBookingWhereInput = {
customerPhone?: Prisma.StringFilter<"CourtBooking"> | string customerPhone?: Prisma.StringFilter<"CourtBooking"> | string
customerEmail?: Prisma.StringFilter<"CourtBooking"> | string customerEmail?: Prisma.StringFilter<"CourtBooking"> | string
status?: Prisma.EnumCourtBookingStatusFilter<"CourtBooking"> | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFilter<"CourtBooking"> | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.UuidNullableFilter<"CourtBooking"> | string | null
createdAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string createdAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string updatedAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string
court?: Prisma.XOR<Prisma.CourtScalarRelationFilter, Prisma.CourtWhereInput> court?: Prisma.XOR<Prisma.CourtScalarRelationFilter, Prisma.CourtWhereInput>
recurringGroup?: Prisma.XOR<Prisma.RecurringBookingGroupNullableScalarRelationFilter, Prisma.RecurringBookingGroupWhereInput> | null
} }
export type CourtBookingOrderByWithRelationInput = { export type CourtBookingOrderByWithRelationInput = {
@@ -252,9 +261,11 @@ export type CourtBookingOrderByWithRelationInput = {
customerPhone?: Prisma.SortOrder customerPhone?: Prisma.SortOrder
customerEmail?: Prisma.SortOrder customerEmail?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
recurringGroupId?: Prisma.SortOrderInput | Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
court?: Prisma.CourtOrderByWithRelationInput court?: Prisma.CourtOrderByWithRelationInput
recurringGroup?: Prisma.RecurringBookingGroupOrderByWithRelationInput
} }
export type CourtBookingWhereUniqueInput = Prisma.AtLeast<{ export type CourtBookingWhereUniqueInput = Prisma.AtLeast<{
@@ -272,9 +283,11 @@ export type CourtBookingWhereUniqueInput = Prisma.AtLeast<{
customerPhone?: Prisma.StringFilter<"CourtBooking"> | string customerPhone?: Prisma.StringFilter<"CourtBooking"> | string
customerEmail?: Prisma.StringFilter<"CourtBooking"> | string customerEmail?: Prisma.StringFilter<"CourtBooking"> | string
status?: Prisma.EnumCourtBookingStatusFilter<"CourtBooking"> | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFilter<"CourtBooking"> | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.UuidNullableFilter<"CourtBooking"> | string | null
createdAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string createdAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string updatedAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string
court?: Prisma.XOR<Prisma.CourtScalarRelationFilter, Prisma.CourtWhereInput> court?: Prisma.XOR<Prisma.CourtScalarRelationFilter, Prisma.CourtWhereInput>
recurringGroup?: Prisma.XOR<Prisma.RecurringBookingGroupNullableScalarRelationFilter, Prisma.RecurringBookingGroupWhereInput> | null
}, "id" | "bookingCode" | "courtId_bookingDate_startTime"> }, "id" | "bookingCode" | "courtId_bookingDate_startTime">
export type CourtBookingOrderByWithAggregationInput = { export type CourtBookingOrderByWithAggregationInput = {
@@ -288,6 +301,7 @@ export type CourtBookingOrderByWithAggregationInput = {
customerPhone?: Prisma.SortOrder customerPhone?: Prisma.SortOrder
customerEmail?: Prisma.SortOrder customerEmail?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
recurringGroupId?: Prisma.SortOrderInput | Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
_count?: Prisma.CourtBookingCountOrderByAggregateInput _count?: Prisma.CourtBookingCountOrderByAggregateInput
@@ -309,6 +323,7 @@ export type CourtBookingScalarWhereWithAggregatesInput = {
customerPhone?: Prisma.StringWithAggregatesFilter<"CourtBooking"> | string customerPhone?: Prisma.StringWithAggregatesFilter<"CourtBooking"> | string
customerEmail?: Prisma.StringWithAggregatesFilter<"CourtBooking"> | string customerEmail?: Prisma.StringWithAggregatesFilter<"CourtBooking"> | string
status?: Prisma.EnumCourtBookingStatusWithAggregatesFilter<"CourtBooking"> | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusWithAggregatesFilter<"CourtBooking"> | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.UuidNullableWithAggregatesFilter<"CourtBooking"> | string | null
createdAt?: Prisma.DateTimeWithAggregatesFilter<"CourtBooking"> | Date | string createdAt?: Prisma.DateTimeWithAggregatesFilter<"CourtBooking"> | Date | string
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"CourtBooking"> | Date | string updatedAt?: Prisma.DateTimeWithAggregatesFilter<"CourtBooking"> | Date | string
} }
@@ -326,6 +341,7 @@ export type CourtBookingCreateInput = {
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
court: Prisma.CourtCreateNestedOneWithoutBookingsInput court: Prisma.CourtCreateNestedOneWithoutBookingsInput
recurringGroup?: Prisma.RecurringBookingGroupCreateNestedOneWithoutBookingsInput
} }
export type CourtBookingUncheckedCreateInput = { export type CourtBookingUncheckedCreateInput = {
@@ -339,6 +355,7 @@ export type CourtBookingUncheckedCreateInput = {
customerPhone: string customerPhone: string
customerEmail: string customerEmail: string
status?: $Enums.CourtBookingStatus status?: $Enums.CourtBookingStatus
recurringGroupId?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -356,6 +373,7 @@ export type CourtBookingUpdateInput = {
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
court?: Prisma.CourtUpdateOneRequiredWithoutBookingsNestedInput court?: Prisma.CourtUpdateOneRequiredWithoutBookingsNestedInput
recurringGroup?: Prisma.RecurringBookingGroupUpdateOneWithoutBookingsNestedInput
} }
export type CourtBookingUncheckedUpdateInput = { export type CourtBookingUncheckedUpdateInput = {
@@ -369,6 +387,7 @@ export type CourtBookingUncheckedUpdateInput = {
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -384,6 +403,7 @@ export type CourtBookingCreateManyInput = {
customerPhone: string customerPhone: string
customerEmail: string customerEmail: string
status?: $Enums.CourtBookingStatus status?: $Enums.CourtBookingStatus
recurringGroupId?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -413,6 +433,7 @@ export type CourtBookingUncheckedUpdateManyInput = {
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -444,6 +465,7 @@ export type CourtBookingCountOrderByAggregateInput = {
customerPhone?: Prisma.SortOrder customerPhone?: Prisma.SortOrder
customerEmail?: Prisma.SortOrder customerEmail?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
recurringGroupId?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -459,6 +481,7 @@ export type CourtBookingMaxOrderByAggregateInput = {
customerPhone?: Prisma.SortOrder customerPhone?: Prisma.SortOrder
customerEmail?: Prisma.SortOrder customerEmail?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
recurringGroupId?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -474,6 +497,7 @@ export type CourtBookingMinOrderByAggregateInput = {
customerPhone?: Prisma.SortOrder customerPhone?: Prisma.SortOrder
customerEmail?: Prisma.SortOrder customerEmail?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
recurringGroupId?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -524,6 +548,48 @@ export type EnumCourtBookingStatusFieldUpdateOperationsInput = {
set?: $Enums.CourtBookingStatus set?: $Enums.CourtBookingStatus
} }
export type CourtBookingCreateNestedManyWithoutRecurringGroupInput = {
create?: Prisma.XOR<Prisma.CourtBookingCreateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput> | Prisma.CourtBookingCreateWithoutRecurringGroupInput[] | Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput[]
connectOrCreate?: Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput | Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput[]
createMany?: Prisma.CourtBookingCreateManyRecurringGroupInputEnvelope
connect?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
}
export type CourtBookingUncheckedCreateNestedManyWithoutRecurringGroupInput = {
create?: Prisma.XOR<Prisma.CourtBookingCreateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput> | Prisma.CourtBookingCreateWithoutRecurringGroupInput[] | Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput[]
connectOrCreate?: Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput | Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput[]
createMany?: Prisma.CourtBookingCreateManyRecurringGroupInputEnvelope
connect?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
}
export type CourtBookingUpdateManyWithoutRecurringGroupNestedInput = {
create?: Prisma.XOR<Prisma.CourtBookingCreateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput> | Prisma.CourtBookingCreateWithoutRecurringGroupInput[] | Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput[]
connectOrCreate?: Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput | Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput[]
upsert?: Prisma.CourtBookingUpsertWithWhereUniqueWithoutRecurringGroupInput | Prisma.CourtBookingUpsertWithWhereUniqueWithoutRecurringGroupInput[]
createMany?: Prisma.CourtBookingCreateManyRecurringGroupInputEnvelope
set?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
disconnect?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
delete?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
connect?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
update?: Prisma.CourtBookingUpdateWithWhereUniqueWithoutRecurringGroupInput | Prisma.CourtBookingUpdateWithWhereUniqueWithoutRecurringGroupInput[]
updateMany?: Prisma.CourtBookingUpdateManyWithWhereWithoutRecurringGroupInput | Prisma.CourtBookingUpdateManyWithWhereWithoutRecurringGroupInput[]
deleteMany?: Prisma.CourtBookingScalarWhereInput | Prisma.CourtBookingScalarWhereInput[]
}
export type CourtBookingUncheckedUpdateManyWithoutRecurringGroupNestedInput = {
create?: Prisma.XOR<Prisma.CourtBookingCreateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput> | Prisma.CourtBookingCreateWithoutRecurringGroupInput[] | Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput[]
connectOrCreate?: Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput | Prisma.CourtBookingCreateOrConnectWithoutRecurringGroupInput[]
upsert?: Prisma.CourtBookingUpsertWithWhereUniqueWithoutRecurringGroupInput | Prisma.CourtBookingUpsertWithWhereUniqueWithoutRecurringGroupInput[]
createMany?: Prisma.CourtBookingCreateManyRecurringGroupInputEnvelope
set?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
disconnect?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
delete?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
connect?: Prisma.CourtBookingWhereUniqueInput | Prisma.CourtBookingWhereUniqueInput[]
update?: Prisma.CourtBookingUpdateWithWhereUniqueWithoutRecurringGroupInput | Prisma.CourtBookingUpdateWithWhereUniqueWithoutRecurringGroupInput[]
updateMany?: Prisma.CourtBookingUpdateManyWithWhereWithoutRecurringGroupInput | Prisma.CourtBookingUpdateManyWithWhereWithoutRecurringGroupInput[]
deleteMany?: Prisma.CourtBookingScalarWhereInput | Prisma.CourtBookingScalarWhereInput[]
}
export type CourtBookingCreateWithoutCourtInput = { export type CourtBookingCreateWithoutCourtInput = {
id: string id: string
bookingCode: string bookingCode: string
@@ -536,6 +602,7 @@ export type CourtBookingCreateWithoutCourtInput = {
status?: $Enums.CourtBookingStatus status?: $Enums.CourtBookingStatus
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
recurringGroup?: Prisma.RecurringBookingGroupCreateNestedOneWithoutBookingsInput
} }
export type CourtBookingUncheckedCreateWithoutCourtInput = { export type CourtBookingUncheckedCreateWithoutCourtInput = {
@@ -548,6 +615,7 @@ export type CourtBookingUncheckedCreateWithoutCourtInput = {
customerPhone: string customerPhone: string
customerEmail: string customerEmail: string
status?: $Enums.CourtBookingStatus status?: $Enums.CourtBookingStatus
recurringGroupId?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -592,10 +660,67 @@ export type CourtBookingScalarWhereInput = {
customerPhone?: Prisma.StringFilter<"CourtBooking"> | string customerPhone?: Prisma.StringFilter<"CourtBooking"> | string
customerEmail?: Prisma.StringFilter<"CourtBooking"> | string customerEmail?: Prisma.StringFilter<"CourtBooking"> | string
status?: Prisma.EnumCourtBookingStatusFilter<"CourtBooking"> | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFilter<"CourtBooking"> | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.UuidNullableFilter<"CourtBooking"> | string | null
createdAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string createdAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string updatedAt?: Prisma.DateTimeFilter<"CourtBooking"> | Date | string
} }
export type CourtBookingCreateWithoutRecurringGroupInput = {
id: string
bookingCode: string
bookingDate: Date | string
startTime: string
endTime: string
customerName: string
customerPhone: string
customerEmail: string
status?: $Enums.CourtBookingStatus
createdAt?: Date | string
updatedAt?: Date | string
court: Prisma.CourtCreateNestedOneWithoutBookingsInput
}
export type CourtBookingUncheckedCreateWithoutRecurringGroupInput = {
id: string
bookingCode: string
courtId: string
bookingDate: Date | string
startTime: string
endTime: string
customerName: string
customerPhone: string
customerEmail: string
status?: $Enums.CourtBookingStatus
createdAt?: Date | string
updatedAt?: Date | string
}
export type CourtBookingCreateOrConnectWithoutRecurringGroupInput = {
where: Prisma.CourtBookingWhereUniqueInput
create: Prisma.XOR<Prisma.CourtBookingCreateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput>
}
export type CourtBookingCreateManyRecurringGroupInputEnvelope = {
data: Prisma.CourtBookingCreateManyRecurringGroupInput | Prisma.CourtBookingCreateManyRecurringGroupInput[]
skipDuplicates?: boolean
}
export type CourtBookingUpsertWithWhereUniqueWithoutRecurringGroupInput = {
where: Prisma.CourtBookingWhereUniqueInput
update: Prisma.XOR<Prisma.CourtBookingUpdateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedUpdateWithoutRecurringGroupInput>
create: Prisma.XOR<Prisma.CourtBookingCreateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedCreateWithoutRecurringGroupInput>
}
export type CourtBookingUpdateWithWhereUniqueWithoutRecurringGroupInput = {
where: Prisma.CourtBookingWhereUniqueInput
data: Prisma.XOR<Prisma.CourtBookingUpdateWithoutRecurringGroupInput, Prisma.CourtBookingUncheckedUpdateWithoutRecurringGroupInput>
}
export type CourtBookingUpdateManyWithWhereWithoutRecurringGroupInput = {
where: Prisma.CourtBookingScalarWhereInput
data: Prisma.XOR<Prisma.CourtBookingUpdateManyMutationInput, Prisma.CourtBookingUncheckedUpdateManyWithoutRecurringGroupInput>
}
export type CourtBookingCreateManyCourtInput = { export type CourtBookingCreateManyCourtInput = {
id: string id: string
bookingCode: string bookingCode: string
@@ -606,6 +731,7 @@ export type CourtBookingCreateManyCourtInput = {
customerPhone: string customerPhone: string
customerEmail: string customerEmail: string
status?: $Enums.CourtBookingStatus status?: $Enums.CourtBookingStatus
recurringGroupId?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -622,6 +748,7 @@ export type CourtBookingUpdateWithoutCourtInput = {
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
recurringGroup?: Prisma.RecurringBookingGroupUpdateOneWithoutBookingsNestedInput
} }
export type CourtBookingUncheckedUpdateWithoutCourtInput = { export type CourtBookingUncheckedUpdateWithoutCourtInput = {
@@ -634,6 +761,7 @@ export type CourtBookingUncheckedUpdateWithoutCourtInput = {
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -648,6 +776,67 @@ export type CourtBookingUncheckedUpdateManyWithoutCourtInput = {
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
recurringGroupId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
}
export type CourtBookingCreateManyRecurringGroupInput = {
id: string
bookingCode: string
courtId: string
bookingDate: Date | string
startTime: string
endTime: string
customerName: string
customerPhone: string
customerEmail: string
status?: $Enums.CourtBookingStatus
createdAt?: Date | string
updatedAt?: Date | string
}
export type CourtBookingUpdateWithoutRecurringGroupInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
bookingCode?: Prisma.StringFieldUpdateOperationsInput | string
bookingDate?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
startTime?: Prisma.StringFieldUpdateOperationsInput | string
endTime?: Prisma.StringFieldUpdateOperationsInput | string
customerName?: Prisma.StringFieldUpdateOperationsInput | string
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
court?: Prisma.CourtUpdateOneRequiredWithoutBookingsNestedInput
}
export type CourtBookingUncheckedUpdateWithoutRecurringGroupInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
bookingCode?: Prisma.StringFieldUpdateOperationsInput | string
courtId?: Prisma.StringFieldUpdateOperationsInput | string
bookingDate?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
startTime?: Prisma.StringFieldUpdateOperationsInput | string
endTime?: Prisma.StringFieldUpdateOperationsInput | string
customerName?: Prisma.StringFieldUpdateOperationsInput | string
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
}
export type CourtBookingUncheckedUpdateManyWithoutRecurringGroupInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
bookingCode?: Prisma.StringFieldUpdateOperationsInput | string
courtId?: Prisma.StringFieldUpdateOperationsInput | string
bookingDate?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
startTime?: Prisma.StringFieldUpdateOperationsInput | string
endTime?: Prisma.StringFieldUpdateOperationsInput | string
customerName?: Prisma.StringFieldUpdateOperationsInput | string
customerPhone?: Prisma.StringFieldUpdateOperationsInput | string
customerEmail?: Prisma.StringFieldUpdateOperationsInput | string
status?: Prisma.EnumCourtBookingStatusFieldUpdateOperationsInput | $Enums.CourtBookingStatus
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -665,9 +854,11 @@ export type CourtBookingSelect<ExtArgs extends runtime.Types.Extensions.Internal
customerPhone?: boolean customerPhone?: boolean
customerEmail?: boolean customerEmail?: boolean
status?: boolean status?: boolean
recurringGroupId?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
court?: boolean | Prisma.CourtDefaultArgs<ExtArgs> court?: boolean | Prisma.CourtDefaultArgs<ExtArgs>
recurringGroup?: boolean | Prisma.CourtBooking$recurringGroupArgs<ExtArgs>
}, ExtArgs["result"]["courtBooking"]> }, ExtArgs["result"]["courtBooking"]>
export type CourtBookingSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type CourtBookingSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
@@ -681,9 +872,11 @@ export type CourtBookingSelectCreateManyAndReturn<ExtArgs extends runtime.Types.
customerPhone?: boolean customerPhone?: boolean
customerEmail?: boolean customerEmail?: boolean
status?: boolean status?: boolean
recurringGroupId?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
court?: boolean | Prisma.CourtDefaultArgs<ExtArgs> court?: boolean | Prisma.CourtDefaultArgs<ExtArgs>
recurringGroup?: boolean | Prisma.CourtBooking$recurringGroupArgs<ExtArgs>
}, ExtArgs["result"]["courtBooking"]> }, ExtArgs["result"]["courtBooking"]>
export type CourtBookingSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type CourtBookingSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
@@ -697,9 +890,11 @@ export type CourtBookingSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.
customerPhone?: boolean customerPhone?: boolean
customerEmail?: boolean customerEmail?: boolean
status?: boolean status?: boolean
recurringGroupId?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
court?: boolean | Prisma.CourtDefaultArgs<ExtArgs> court?: boolean | Prisma.CourtDefaultArgs<ExtArgs>
recurringGroup?: boolean | Prisma.CourtBooking$recurringGroupArgs<ExtArgs>
}, ExtArgs["result"]["courtBooking"]> }, ExtArgs["result"]["courtBooking"]>
export type CourtBookingSelectScalar = { export type CourtBookingSelectScalar = {
@@ -713,25 +908,30 @@ export type CourtBookingSelectScalar = {
customerPhone?: boolean customerPhone?: boolean
customerEmail?: boolean customerEmail?: boolean
status?: boolean status?: boolean
recurringGroupId?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
} }
export type CourtBookingOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "bookingCode" | "courtId" | "bookingDate" | "startTime" | "endTime" | "customerName" | "customerPhone" | "customerEmail" | "status" | "createdAt" | "updatedAt", ExtArgs["result"]["courtBooking"]> export type CourtBookingOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "bookingCode" | "courtId" | "bookingDate" | "startTime" | "endTime" | "customerName" | "customerPhone" | "customerEmail" | "status" | "recurringGroupId" | "createdAt" | "updatedAt", ExtArgs["result"]["courtBooking"]>
export type CourtBookingInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type CourtBookingInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
court?: boolean | Prisma.CourtDefaultArgs<ExtArgs> court?: boolean | Prisma.CourtDefaultArgs<ExtArgs>
recurringGroup?: boolean | Prisma.CourtBooking$recurringGroupArgs<ExtArgs>
} }
export type CourtBookingIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type CourtBookingIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
court?: boolean | Prisma.CourtDefaultArgs<ExtArgs> court?: boolean | Prisma.CourtDefaultArgs<ExtArgs>
recurringGroup?: boolean | Prisma.CourtBooking$recurringGroupArgs<ExtArgs>
} }
export type CourtBookingIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type CourtBookingIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
court?: boolean | Prisma.CourtDefaultArgs<ExtArgs> court?: boolean | Prisma.CourtDefaultArgs<ExtArgs>
recurringGroup?: boolean | Prisma.CourtBooking$recurringGroupArgs<ExtArgs>
} }
export type $CourtBookingPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type $CourtBookingPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
name: "CourtBooking" name: "CourtBooking"
objects: { objects: {
court: Prisma.$CourtPayload<ExtArgs> court: Prisma.$CourtPayload<ExtArgs>
recurringGroup: Prisma.$RecurringBookingGroupPayload<ExtArgs> | null
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string id: string
@@ -744,6 +944,7 @@ export type $CourtBookingPayload<ExtArgs extends runtime.Types.Extensions.Intern
customerPhone: string customerPhone: string
customerEmail: string customerEmail: string
status: $Enums.CourtBookingStatus status: $Enums.CourtBookingStatus
recurringGroupId: string | null
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
}, ExtArgs["result"]["courtBooking"]> }, ExtArgs["result"]["courtBooking"]>
@@ -1141,6 +1342,7 @@ readonly fields: CourtBookingFieldRefs;
export interface Prisma__CourtBookingClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> { export interface Prisma__CourtBookingClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> {
readonly [Symbol.toStringTag]: "PrismaPromise" readonly [Symbol.toStringTag]: "PrismaPromise"
court<T extends Prisma.CourtDefaultArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.CourtDefaultArgs<ExtArgs>>): Prisma.Prisma__CourtClient<runtime.Types.Result.GetResult<Prisma.$CourtPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> court<T extends Prisma.CourtDefaultArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.CourtDefaultArgs<ExtArgs>>): Prisma.Prisma__CourtClient<runtime.Types.Result.GetResult<Prisma.$CourtPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions>
recurringGroup<T extends Prisma.CourtBooking$recurringGroupArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.CourtBooking$recurringGroupArgs<ExtArgs>>): Prisma.Prisma__RecurringBookingGroupClient<runtime.Types.Result.GetResult<Prisma.$RecurringBookingGroupPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
/** /**
* Attaches callbacks for the resolution and/or rejection of the Promise. * Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved. * @param onfulfilled The callback to execute when the Promise is resolved.
@@ -1180,6 +1382,7 @@ export interface CourtBookingFieldRefs {
readonly customerPhone: Prisma.FieldRef<"CourtBooking", 'String'> readonly customerPhone: Prisma.FieldRef<"CourtBooking", 'String'>
readonly customerEmail: Prisma.FieldRef<"CourtBooking", 'String'> readonly customerEmail: Prisma.FieldRef<"CourtBooking", 'String'>
readonly status: Prisma.FieldRef<"CourtBooking", 'CourtBookingStatus'> readonly status: Prisma.FieldRef<"CourtBooking", 'CourtBookingStatus'>
readonly recurringGroupId: Prisma.FieldRef<"CourtBooking", 'String'>
readonly createdAt: Prisma.FieldRef<"CourtBooking", 'DateTime'> readonly createdAt: Prisma.FieldRef<"CourtBooking", 'DateTime'>
readonly updatedAt: Prisma.FieldRef<"CourtBooking", 'DateTime'> readonly updatedAt: Prisma.FieldRef<"CourtBooking", 'DateTime'>
} }
@@ -1582,6 +1785,25 @@ export type CourtBookingDeleteManyArgs<ExtArgs extends runtime.Types.Extensions.
limit?: number limit?: number
} }
/**
* CourtBooking.recurringGroup
*/
export type CourtBooking$recurringGroupArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the RecurringBookingGroup
*/
select?: Prisma.RecurringBookingGroupSelect<ExtArgs> | null
/**
* Omit specific fields from the RecurringBookingGroup
*/
omit?: Prisma.RecurringBookingGroupOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.RecurringBookingGroupInclude<ExtArgs> | null
where?: Prisma.RecurringBookingGroupWhereInput
}
/** /**
* CourtBooking without action * CourtBooking without action
*/ */

View File

@@ -1,11 +1,14 @@
import { requireAuth } from '@/middlewares/require-auth.middleware'; import { requireAuth } from '@/middlewares/require-auth.middleware';
import { cancelRecurringGroupHandler } from '@/modules/admin-booking/handlers/cancel-recurring-group.handler';
import { createAdminBookingHandler } from '@/modules/admin-booking/handlers/create-admin-booking.handler'; import { createAdminBookingHandler } from '@/modules/admin-booking/handlers/create-admin-booking.handler';
import { createAdminRecurringBookingHandler } from '@/modules/admin-booking/handlers/create-admin-recurring-booking.handler';
import { listAdminBookingsHandler } from '@/modules/admin-booking/handlers/list-admin-bookings.handler'; import { listAdminBookingsHandler } from '@/modules/admin-booking/handlers/list-admin-bookings.handler';
import { updateAdminBookingStatusHandler } from '@/modules/admin-booking/handlers/update-admin-booking-status.handler'; import { updateAdminBookingStatusHandler } from '@/modules/admin-booking/handlers/update-admin-booking-status.handler';
import type { AppEnv } from '@/types/hono'; import type { AppEnv } from '@/types/hono';
import { zValidator } from '@hono/zod-validator'; import { zValidator } from '@hono/zod-validator';
import { import {
createAdminBookingSchema, createAdminBookingSchema,
createRecurringBookingSchema,
listAdminBookingsQuerySchema, listAdminBookingsQuerySchema,
updateAdminBookingStatusSchema, updateAdminBookingStatusSchema,
} from '@repo/api-contract'; } from '@repo/api-contract';
@@ -15,6 +18,7 @@ import { z } from 'zod';
export const adminBookingRoutes = new Hono<AppEnv>(); export const adminBookingRoutes = new Hono<AppEnv>();
const complexIdParamsSchema = z.object({ complexId: z.uuid() }); const complexIdParamsSchema = z.object({ complexId: z.uuid() });
const bookingIdParamsSchema = z.object({ id: z.uuid() }); const bookingIdParamsSchema = z.object({ id: z.uuid() });
const groupIdParamsSchema = z.object({ groupId: z.uuid() });
adminBookingRoutes.use('*', requireAuth); adminBookingRoutes.use('*', requireAuth);
@@ -32,6 +36,19 @@ adminBookingRoutes.post(
createAdminBookingHandler createAdminBookingHandler
); );
adminBookingRoutes.post(
'/complex/:complexId/recurring',
zValidator('param', complexIdParamsSchema),
zValidator('json', createRecurringBookingSchema),
createAdminRecurringBookingHandler
);
adminBookingRoutes.post(
'/recurring/:groupId/cancel',
zValidator('param', groupIdParamsSchema),
cancelRecurringGroupHandler
);
adminBookingRoutes.patch( adminBookingRoutes.patch(
'/:id/status', '/:id/status',
zValidator('param', bookingIdParamsSchema), zValidator('param', bookingIdParamsSchema),

View File

@@ -0,0 +1,20 @@
import { AdminBookingServiceError } from '@/modules/admin-booking/services/admin-booking.service';
import { cancelRecurringGroup } from '@/modules/admin-booking/services/admin-recurring-booking.service';
import type { AppContext } from '@/types/hono';
type GroupIdParams = { groupId: string };
export async function cancelRecurringGroupHandler(c: AppContext) {
const { groupId } = c.req.valid('param' as never) as GroupIdParams;
const user = c.get('user');
try {
const result = await cancelRecurringGroup(user.id, groupId);
return c.json(result);
} catch (error) {
if (error instanceof AdminBookingServiceError) {
return c.json({ message: error.message }, error.status);
}
throw error;
}
}

View File

@@ -0,0 +1,40 @@
import { AdminBookingServiceError } from '@/modules/admin-booking/services/admin-booking.service';
import { createAdminRecurringBooking } from '@/modules/admin-booking/services/admin-recurring-booking.service';
import { sendBookingConfirmation } from '@/services/booking-email.service';
import type { AppContext } from '@/types/hono';
import type { CreateRecurringBookingInput } from '@repo/api-contract';
type ComplexIdParams = { complexId: string };
export async function createAdminRecurringBookingHandler(c: AppContext) {
const { complexId } = c.req.valid('param' as never) as ComplexIdParams;
const payload = c.req.valid('json' as never) as CreateRecurringBookingInput;
const user = c.get('user');
try {
const group = await createAdminRecurringBooking(user.id, complexId, payload);
const firstBooking = group.bookings[0];
if (firstBooking?.customerEmail) {
void sendBookingConfirmation({
bookingCode: firstBooking.bookingCode,
complexName: firstBooking.complexName,
date: firstBooking.date,
startTime: firstBooking.startTime,
endTime: firstBooking.endTime,
courtName: firstBooking.courtName,
sportName: firstBooking.sport.name,
customerName: firstBooking.customerName,
customerEmail: firstBooking.customerEmail,
price: firstBooking.price,
});
}
return c.json(group, 201);
} catch (error) {
if (error instanceof AdminBookingServiceError) {
return c.json({ message: error.message }, error.status);
}
throw error;
}
}

View File

@@ -202,6 +202,7 @@ function mapBookingResponse(booking: {
customerPhone: string; customerPhone: string;
customerEmail: string; customerEmail: string;
status: 'CONFIRMED' | 'CANCELLED' | 'COMPLETED' | 'NOSHOW'; status: 'CONFIRMED' | 'CANCELLED' | 'COMPLETED' | 'NOSHOW';
recurringGroupId: string | null;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
court: { court: {
@@ -239,6 +240,7 @@ function mapBookingResponse(booking: {
customerEmail: booking.customerEmail, customerEmail: booking.customerEmail,
price: booking.price ?? 0, price: booking.price ?? 0,
status: booking.status, status: booking.status,
recurringGroupId: booking.recurringGroupId,
createdAt: booking.createdAt.toISOString(), createdAt: booking.createdAt.toISOString(),
updatedAt: booking.updatedAt.toISOString(), updatedAt: booking.updatedAt.toISOString(),
}; };
@@ -431,6 +433,7 @@ export async function createAdminBooking(
customerPhone: input.customerPhone.trim(), customerPhone: input.customerPhone.trim(),
customerEmail: input.customerEmail?.trim() ?? '', customerEmail: input.customerEmail?.trim() ?? '',
status: 'CONFIRMED', status: 'CONFIRMED',
recurringGroupId: null,
}, },
include: { include: {
court: { court: {

View File

@@ -0,0 +1,576 @@
import { randomInt } from 'node:crypto';
import { DayOfWeek as DayOfWeekEnum } from '@/generated/prisma/enums';
import { db } from '@/lib/prisma';
import { isSlotInPast } from '@/lib/slot-validator';
import {
evaluatePlanUsage,
isFeatureEnabled,
parsePlanRules,
} from '@/modules/plan/services/plan-rules.service';
import type { CreateRecurringBookingInput, RecurringBookingGroup } from '@repo/api-contract';
import { v7 as uuidv7 } from 'uuid';
import { AdminBookingServiceError } from './admin-booking.service';
const BOOKING_CODE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
const BOOKING_CODE_LENGTH = 6;
const MAX_RECURRING_WEEKS = 52;
const DAY_OF_WEEK_BY_INDEX = [
DayOfWeekEnum.SUNDAY,
DayOfWeekEnum.MONDAY,
DayOfWeekEnum.TUESDAY,
DayOfWeekEnum.WEDNESDAY,
DayOfWeekEnum.THURSDAY,
DayOfWeekEnum.FRIDAY,
DayOfWeekEnum.SATURDAY,
] as const;
type DayOfWeek = (typeof DAY_OF_WEEK_BY_INDEX)[number];
function toMinutes(value: string): number {
const [hours, minutes] = value.split(':').map((part) => Number(part));
return hours * 60 + minutes;
}
function minutesToTime(minutes: number): string {
const safeMinutes = Math.max(0, minutes);
const hours = Math.floor(safeMinutes / 60);
const mins = safeMinutes % 60;
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;
}
function parseIsoDate(date: string): Date {
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
if (!match) {
throw new AdminBookingServiceError('La fecha debe tener formato YYYY-MM-DD.', 400);
}
const year = Number(match[1]);
const month = Number(match[2]);
const day = Number(match[3]);
const parsed = new Date(Date.UTC(year, month - 1, day));
if (
Number.isNaN(parsed.getTime()) ||
parsed.getUTCFullYear() !== year ||
parsed.getUTCMonth() + 1 !== month ||
parsed.getUTCDate() !== day
) {
throw new AdminBookingServiceError('La fecha enviada no es valida.', 400);
}
return parsed;
}
function formatIsoDate(date: Date): string {
return date.toISOString().slice(0, 10);
}
function getDayOfWeekValue(date: Date): DayOfWeek {
const dayOfWeek = DAY_OF_WEEK_BY_INDEX[date.getUTCDay()];
if (!dayOfWeek) {
throw new AdminBookingServiceError('No se pudo resolver el dia de la semana.', 400);
}
return dayOfWeek;
}
function generateBookingCode(): string {
let code = '';
for (let index = 0; index < BOOKING_CODE_LENGTH; index += 1) {
code += BOOKING_CODE_ALPHABET[randomInt(0, BOOKING_CODE_ALPHABET.length)];
}
return code;
}
function buildSlots(
availability: Array<{
startTime: string;
endTime: string;
}>,
slotDurationMinutes: number
) {
const slots: Array<{ startTime: string; endTime: string }> = [];
for (const range of availability) {
const start = toMinutes(range.startTime);
const end = toMinutes(range.endTime);
for (
let current = start;
current + slotDurationMinutes <= end;
current += slotDurationMinutes
) {
slots.push({
startTime: minutesToTime(current),
endTime: minutesToTime(current + slotDurationMinutes),
});
}
}
return slots;
}
async function ensureComplexAccess(complexId: string, userId: string) {
const complexUser = await db.complexUser.findUnique({
where: {
complexId_userId: {
complexId,
userId,
},
},
include: {
complex: {
select: {
id: true,
complexName: true,
plan: {
select: {
rules: true,
},
},
},
},
},
});
if (!complexUser) {
throw new AdminBookingServiceError('No tienes permisos para administrar este complejo.', 403);
}
return complexUser.complex;
}
function* generateRecurringDates(
startDate: Date,
endDate: Date | null,
dayOfWeek: number
): Generator<Date> {
const current = new Date(startDate);
current.setUTCDate(current.getUTCDate() + ((dayOfWeek - current.getUTCDay() + 7) % 7));
if (current < startDate) {
current.setUTCDate(current.getUTCDate() + 7);
}
const maxDate = endDate ?? new Date(startDate);
if (!endDate) {
maxDate.setUTCDate(maxDate.getUTCDate() + MAX_RECURRING_WEEKS * 7);
}
while (current <= maxDate) {
yield new Date(current);
current.setUTCDate(current.getUTCDate() + 7);
}
}
function mapBookingResponse(booking: {
id: string;
bookingCode: string;
bookingDate: Date;
startTime: string;
endTime: string;
customerName: string;
customerPhone: string;
customerEmail: string;
status: 'CONFIRMED' | 'CANCELLED' | 'COMPLETED' | 'NOSHOW';
recurringGroupId: string | null;
createdAt: Date;
updatedAt: Date;
court: {
id: string;
name: string;
complex: {
id: string;
complexName: string;
};
sport: {
id: string;
name: string;
slug: string;
};
};
price?: number;
}) {
return {
id: booking.id,
bookingCode: booking.bookingCode,
complexId: booking.court.complex.id,
complexName: booking.court.complex.complexName,
courtId: booking.court.id,
courtName: booking.court.name,
sport: {
id: booking.court.sport.id,
name: booking.court.sport.name,
slug: booking.court.sport.slug,
},
date: formatIsoDate(booking.bookingDate),
startTime: booking.startTime,
endTime: booking.endTime,
customerName: booking.customerName,
customerPhone: booking.customerPhone,
customerEmail: booking.customerEmail,
price: booking.price ?? 0,
status: booking.status,
recurringGroupId: booking.recurringGroupId,
createdAt: booking.createdAt.toISOString(),
updatedAt: booking.updatedAt.toISOString(),
};
}
export async function createAdminRecurringBooking(
userId: string,
complexId: string,
input: CreateRecurringBookingInput
): Promise<RecurringBookingGroup> {
const complex = await ensureComplexAccess(complexId, userId);
const adminUser = await db.user.findUnique({
where: { id: userId },
select: { emailVerified: true },
});
if (!adminUser?.emailVerified) {
throw new AdminBookingServiceError('Debés verificar tu email para poder crear reservas.', 403);
}
if (!complex.plan) {
throw new AdminBookingServiceError('El complejo no tiene un plan asignado.', 403);
}
const rules = parsePlanRules(complex.plan.rules);
if (!isFeatureEnabled(rules, 'fixedSlots')) {
throw new AdminBookingServiceError(
'Tu plan no permite la creación de turnos fijos. Comunicate con el administrador.',
403
);
}
const startDate = parseIsoDate(input.date);
const dayOfWeek = getDayOfWeekValue(startDate);
const endDate = input.recurringEndDate ? parseIsoDate(input.recurringEndDate) : null;
if (endDate && endDate <= startDate) {
throw new AdminBookingServiceError(
'La fecha de fin debe ser posterior a la fecha de inicio.',
400
);
}
const court = await db.court.findFirst({
where: {
id: input.courtId,
complexId,
},
include: {
availabilities: {
where: {
dayOfWeek,
},
orderBy: {
startTime: 'asc',
},
},
sport: {
select: {
id: true,
name: true,
slug: true,
},
},
priceRules: {
where: { isActive: true },
orderBy: [{ dayOfWeek: 'asc' }, { startTime: 'asc' }],
},
},
});
if (!court) {
throw new AdminBookingServiceError('La cancha seleccionada no existe en el complejo.', 404);
}
const validSlots = buildSlots(court.availabilities, court.slotDurationMinutes);
const selectedEndMinutes = toMinutes(input.startTime) + court.slotDurationMinutes;
const selectedSlot = {
startTime: input.startTime,
endTime: minutesToTime(selectedEndMinutes),
};
const slotExists = validSlots.some(
(slot) => slot.startTime === selectedSlot.startTime && slot.endTime === selectedSlot.endTime
);
if (!slotExists) {
throw new AdminBookingServiceError(
'El horario seleccionado no esta disponible para esa cancha.',
409
);
}
if (isSlotInPast(startDate, input.startTime, court.slotDurationMinutes)) {
throw new AdminBookingServiceError('La fecha de inicio no puede estar en el pasado.', 400);
}
const recurringDates = Array.from(
generateRecurringDates(startDate, endDate, startDate.getUTCDay())
);
if (recurringDates.length === 0) {
throw new AdminBookingServiceError(
'No se generaron fechas para la reserva periódica. Verifica las fechas ingresadas.',
400
);
}
for (let attempt = 0; attempt < 5; attempt += 1) {
try {
const result = await db.$transaction(async (tx) => {
const groupId = uuidv7();
const bookingsForDate = await tx.courtBooking.count({
where: {
startTime: selectedSlot.startTime,
bookingDate: startDate,
status: 'CONFIRMED',
court: {
complexId,
},
},
});
const courtsCount = await tx.court.count({
where: { complexId },
});
const violations = evaluatePlanUsage(rules, {
courtsCount,
bookingsToday: bookingsForDate,
});
const maxBookingsViolation = violations.find(
(v) => v.code === 'MAX_BOOKINGS_PER_DAY_REACHED'
);
if (maxBookingsViolation) {
throw new AdminBookingServiceError(maxBookingsViolation.message, 409);
}
const group = await tx.recurringBookingGroup.create({
data: {
id: groupId,
complexId,
courtId: court.id,
startTime: selectedSlot.startTime,
endTime: selectedSlot.endTime,
dayOfWeek,
startDate,
endDate,
status: 'ACTIVE',
customerName: input.customerName.trim(),
customerPhone: input.customerPhone.trim(),
customerEmail: input.customerEmail?.trim() ?? '',
},
});
const createdBookings = [];
for (const date of recurringDates) {
if (isSlotInPast(date, input.startTime, court.slotDurationMinutes)) {
continue;
}
const overlappingBooking = await tx.courtBooking.findFirst({
where: {
courtId: court.id,
bookingDate: date,
status: 'CONFIRMED',
startTime: {
lt: selectedSlot.endTime,
},
endTime: {
gt: selectedSlot.startTime,
},
},
});
if (overlappingBooking) {
throw new AdminBookingServiceError(
`El horario seleccionado ya fue reservado para el dia ${formatIsoDate(date)}.`,
409
);
}
const booking = await tx.courtBooking.create({
data: {
id: uuidv7(),
bookingCode: generateBookingCode(),
courtId: court.id,
bookingDate: date,
startTime: selectedSlot.startTime,
endTime: selectedSlot.endTime,
customerName: input.customerName.trim(),
customerPhone: input.customerPhone.trim(),
customerEmail: input.customerEmail?.trim() ?? '',
status: 'CONFIRMED',
recurringGroupId: groupId,
},
include: {
court: {
select: {
id: true,
name: true,
sport: {
select: {
id: true,
name: true,
slug: true,
},
},
complex: {
select: {
id: true,
complexName: true,
},
},
},
},
},
});
createdBookings.push(booking);
}
return { group, bookings: createdBookings };
});
return {
id: result.group.id,
complexId,
courtId: court.id,
startTime: result.group.startTime,
endTime: result.group.endTime,
dayOfWeek: result.group.dayOfWeek,
startDate: formatIsoDate(result.group.startDate),
endDate: result.group.endDate ? formatIsoDate(result.group.endDate) : null,
status: 'ACTIVE' as const,
customerName: result.group.customerName,
customerPhone: result.group.customerPhone,
customerEmail: result.group.customerEmail,
bookings: result.bookings.map((b) => mapBookingResponse(b)),
createdAt: result.group.createdAt.toISOString(),
updatedAt: result.group.updatedAt.toISOString(),
};
} catch (error) {
if (error instanceof AdminBookingServiceError) {
throw error;
}
const prismaError = error as {
code?: string;
meta?: {
target?: string[] | string;
};
};
if (prismaError.code === 'P2002') {
const targets = Array.isArray(prismaError.meta?.target)
? prismaError.meta?.target
: [prismaError.meta?.target];
const isBookingCodeCollision = targets.some((target) =>
String(target).includes('booking_code')
);
if (isBookingCodeCollision) {
continue;
}
throw new AdminBookingServiceError('El horario seleccionado ya fue reservado.', 409);
}
throw error;
}
}
throw new AdminBookingServiceError(
'No se pudo generar un codigo de reserva unico. Intenta nuevamente.',
409
);
}
export async function cancelRecurringGroup(userId: string, groupId: string) {
const group = await db.recurringBookingGroup.findUnique({
where: { id: groupId },
include: {
complex: {
select: {
id: true,
users: {
where: { userId },
select: { userId: true },
},
},
},
},
});
if (!group) {
throw new AdminBookingServiceError('Grupo de reservas no encontrado.', 404);
}
if (group.complex.users.length === 0) {
throw new AdminBookingServiceError('No tienes permisos para administrar este complejo.', 403);
}
if (group.status === 'CANCELLED') {
throw new AdminBookingServiceError('El grupo ya fue cancelado anteriormente.', 409);
}
const now = new Date();
const todayStart = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
await db.$transaction(async (tx) => {
await tx.recurringBookingGroup.update({
where: { id: groupId },
data: { status: 'CANCELLED' },
});
const futureBookings = await tx.courtBooking.findMany({
where: {
recurringGroupId: groupId,
bookingDate: { gte: todayStart },
status: 'CONFIRMED',
},
});
for (const booking of futureBookings) {
await tx.courtBookingLog.create({
data: {
id: uuidv7(),
bookingCode: booking.bookingCode,
courtId: booking.courtId,
bookingDate: booking.bookingDate,
startTime: booking.startTime,
endTime: booking.endTime,
customerName: booking.customerName,
customerPhone: booking.customerPhone,
customerEmail: booking.customerEmail,
previousStatus: booking.status,
newStatus: 'CANCELLED',
changedAt: new Date(),
},
});
await tx.courtBooking.delete({
where: { id: booking.id },
});
}
});
return { ok: true };
}

View File

@@ -1,5 +1,6 @@
import { Prisma } from '@/generated/prisma/client'; import { Prisma } from '@/generated/prisma/client';
import { db } from '@/lib/prisma'; import { db } from '@/lib/prisma';
import { parsePlanRules } from '@/modules/plan/services/plan-rules.service';
import { v7 as uuidv7 } from 'uuid'; import { v7 as uuidv7 } from 'uuid';
export type CreateComplexInput = { export type CreateComplexInput = {
@@ -185,7 +186,11 @@ export async function listMyComplexes(userId: string) {
const complexUsers = await db.complexUser.findMany({ const complexUsers = await db.complexUser.findMany({
where: { userId }, where: { userId },
include: { include: {
complex: true, complex: {
include: {
plan: true,
},
},
}, },
orderBy: { orderBy: {
createdAt: 'asc', createdAt: 'asc',
@@ -195,6 +200,9 @@ export async function listMyComplexes(userId: string) {
return complexUsers.map((complexUser) => ({ return complexUsers.map((complexUser) => ({
...complexUser.complex, ...complexUser.complex,
role: complexUser.role, role: complexUser.role,
planFeatures: complexUser.complex.plan
? parsePlanRules(complexUser.complex.plan.rules).features
: null,
})); }));
} }
@@ -207,7 +215,11 @@ export async function getCurrentComplex(userId: string, complexId: string) {
}, },
}, },
include: { include: {
complex: true, complex: {
include: {
plan: true,
},
},
}, },
}); });
@@ -216,6 +228,9 @@ export async function getCurrentComplex(userId: string, complexId: string) {
return { return {
...complexUser.complex, ...complexUser.complex,
role: complexUser.role, role: complexUser.role,
planFeatures: complexUser.complex.plan
? parsePlanRules(complexUser.complex.plan.rules).features
: null,
}; };
} }
@@ -228,7 +243,11 @@ export async function selectComplex(userId: string, complexId: string) {
}, },
}, },
include: { include: {
complex: true, complex: {
include: {
plan: true,
},
},
}, },
}); });
@@ -237,6 +256,9 @@ export async function selectComplex(userId: string, complexId: string) {
return { return {
...complexUser.complex, ...complexUser.complex,
role: complexUser.role, role: complexUser.role,
planFeatures: complexUser.complex.plan
? parsePlanRules(complexUser.complex.plan.rules).features
: null,
}; };
} }

View File

@@ -14,6 +14,7 @@ function makeV1Rules(): PlanRules {
publicBookingPage: false, publicBookingPage: false,
advancedReports: false, advancedReports: false,
whatsappReminders: false, whatsappReminders: false,
fixedSlots: false,
}, },
}; };
} }
@@ -28,6 +29,7 @@ function makeV2Rules(overrides?: Record<string, { amount: number; currency: stri
publicBookingPage: true, publicBookingPage: true,
advancedReports: true, advancedReports: true,
whatsappReminders: true, whatsappReminders: true,
fixedSlots: true,
}, },
...(overrides ? { pricing: { overrides } } : {}), ...(overrides ? { pricing: { overrides } } : {}),
}; };

View File

@@ -50,6 +50,7 @@ type PlanFormRules = {
publicBookingPage: boolean; publicBookingPage: boolean;
advancedReports: boolean; advancedReports: boolean;
whatsappReminders: boolean; whatsappReminders: boolean;
fixedSlots: boolean;
}; };
policies: { policies: {
maxAdvanceBookingDays: number | ''; maxAdvanceBookingDays: number | '';
@@ -85,6 +86,7 @@ function getDefaultRules(): PlanFormRules {
publicBookingPage: false, publicBookingPage: false,
advancedReports: false, advancedReports: false,
whatsappReminders: false, whatsappReminders: false,
fixedSlots: false,
}, },
policies: { policies: {
maxAdvanceBookingDays: '', maxAdvanceBookingDays: '',
@@ -113,6 +115,7 @@ function initRules(plan?: Plan): PlanFormRules {
publicBookingPage: (features?.publicBookingPage as boolean) ?? false, publicBookingPage: (features?.publicBookingPage as boolean) ?? false,
advancedReports: (features?.advancedReports as boolean) ?? false, advancedReports: (features?.advancedReports as boolean) ?? false,
whatsappReminders: (features?.whatsappReminders as boolean) ?? false, whatsappReminders: (features?.whatsappReminders as boolean) ?? false,
fixedSlots: (features?.fixedSlots as boolean) ?? false,
}, },
policies: { policies: {
maxAdvanceBookingDays: (policies?.maxAdvanceBookingDays as number | undefined) ?? '', maxAdvanceBookingDays: (policies?.maxAdvanceBookingDays as number | undefined) ?? '',
@@ -437,6 +440,7 @@ function PlanFormDialog({
['publicBookingPage', 'Página de reservas pública'], ['publicBookingPage', 'Página de reservas pública'],
['advancedReports', 'Reportes avanzados'], ['advancedReports', 'Reportes avanzados'],
['whatsappReminders', 'Recordatorios por WhatsApp'], ['whatsappReminders', 'Recordatorios por WhatsApp'],
['fixedSlots', 'Turnos fijos'],
] as const ] as const
).map(([key, label]) => ( ).map(([key, label]) => (
<div key={key} className="flex items-center justify-between"> <div key={key} className="flex items-center justify-between">

View File

@@ -1,5 +1,5 @@
import { ApiClientError, apiClient } from '@/lib/api-client'; import { ApiClientError, apiClient } from '@/lib/api-client';
import type { AdminBooking, ComplexWithRole, Court } from '@repo/api-contract'; import type { AdminBooking, ComplexWithRole, Court, PlanFeatureFlags } from '@repo/api-contract';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { import {
type ReactNode, type ReactNode,
@@ -44,6 +44,16 @@ interface CreateManualBookingPayload {
customerEmail: string; customerEmail: string;
} }
interface CreateRecurringBookingPayload {
courtId: string;
date: string;
startTime: string;
customerName: string;
customerPhone: string;
customerEmail: string;
recurringEndDate?: string;
}
interface BookingContextValue { interface BookingContextValue {
complex: ComplexWithRole; complex: ComplexWithRole;
courts: Court[]; courts: Court[];
@@ -66,6 +76,8 @@ interface BookingContextValue {
createBookingError: string | null; createBookingError: string | null;
isCreatingBooking: boolean; isCreatingBooking: boolean;
bookingToolsOpen: boolean; bookingToolsOpen: boolean;
planFeatures: PlanFeatureFlags | null;
isRecurringEnabled: boolean;
setSelectedDate: (date: string) => void; setSelectedDate: (date: string) => void;
moveSelectedDate: (amount: number) => void; moveSelectedDate: (amount: number) => void;
setSelectedSportId: (sportId: string) => void; setSelectedSportId: (sportId: string) => void;
@@ -75,6 +87,7 @@ interface BookingContextValue {
openCreateBooking: (draft?: Partial<BookingSlotDraft>) => void; openCreateBooking: (draft?: Partial<BookingSlotDraft>) => void;
closeCreateBooking: () => void; closeCreateBooking: () => void;
createBooking: (payload: CreateManualBookingPayload) => Promise<void>; createBooking: (payload: CreateManualBookingPayload) => Promise<void>;
createRecurringBooking: (payload: CreateRecurringBookingPayload) => Promise<void>;
updateBookingStatus: (bookingId: string, status: 'CANCELLED' | 'COMPLETED' | 'NOSHOW') => void; updateBookingStatus: (bookingId: string, status: 'CANCELLED' | 'COMPLETED' | 'NOSHOW') => void;
exportDayReport: () => void; exportDayReport: () => void;
openBookingTools: (segment?: BookingTimelineSegment) => void; openBookingTools: (segment?: BookingTimelineSegment) => void;
@@ -325,6 +338,26 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
}, },
}); });
const createRecurringBookingMutation = useMutation({
mutationFn: (payload: CreateRecurringBookingPayload) =>
apiClient.adminBookings.createRecurring(complex.id, {
date: payload.date,
courtId: payload.courtId,
startTime: payload.startTime,
customerName: payload.customerName,
customerPhone: payload.customerPhone,
customerEmail: payload.customerEmail,
isRecurring: true,
recurringEndDate: payload.recurringEndDate,
}),
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: ['admin-bookings', complex.id] });
await queryClient.invalidateQueries({ queryKey: ['manual-booking-availability'] });
setIsCreateBookingOpen(false);
setSelectedSlot(null);
},
});
const updateStatusMutation = useMutation({ const updateStatusMutation = useMutation({
mutationFn: (payload: { bookingId: string; status: 'CANCELLED' | 'COMPLETED' | 'NOSHOW' }) => mutationFn: (payload: { bookingId: string; status: 'CANCELLED' | 'COMPLETED' | 'NOSHOW' }) =>
apiClient.adminBookings.updateStatus(payload.bookingId, { status: payload.status }), apiClient.adminBookings.updateStatus(payload.bookingId, { status: payload.status }),
@@ -413,6 +446,16 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
}, [bookings, complex.complexSlug, selectedDate]); }, [bookings, complex.complexSlug, selectedDate]);
const planFeatures = complex.planFeatures ?? null;
const isRecurringEnabled = planFeatures?.fixedSlots ?? false;
const createRecurringBooking = useCallback(
async (payload: CreateRecurringBookingPayload) => {
await createRecurringBookingMutation.mutateAsync(payload);
},
[createRecurringBookingMutation]
);
const value = useMemo<BookingContextValue>( const value = useMemo<BookingContextValue>(
() => ({ () => ({
complex, complex,
@@ -438,10 +481,17 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
) )
: null, : null,
isCreateBookingOpen, isCreateBookingOpen,
createBookingError: createBookingMutation.isError createBookingError:
? extractMessage(createBookingMutation.error, 'No pudimos crear la reserva.') createBookingMutation.isError || createRecurringBookingMutation.isError
? extractMessage(
createBookingMutation.error ?? createRecurringBookingMutation.error,
'No pudimos crear la reserva.'
)
: null, : null,
isCreatingBooking: createBookingMutation.isPending, isCreatingBooking:
createBookingMutation.isPending || createRecurringBookingMutation.isPending,
planFeatures,
isRecurringEnabled,
setSelectedDate, setSelectedDate,
moveSelectedDate: (amount) => setSelectedDate((date) => addDaysIso(date, amount)), moveSelectedDate: (amount) => setSelectedDate((date) => addDaysIso(date, amount)),
setSelectedSportId, setSelectedSportId,
@@ -451,6 +501,7 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
openCreateBooking, openCreateBooking,
closeCreateBooking, closeCreateBooking,
createBooking, createBooking,
createRecurringBooking,
updateBookingStatus, updateBookingStatus,
exportDayReport, exportDayReport,
bookingToolsOpen, bookingToolsOpen,
@@ -473,10 +524,16 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
createBookingMutation.error, createBookingMutation.error,
createBookingMutation.isError, createBookingMutation.isError,
createBookingMutation.isPending, createBookingMutation.isPending,
createRecurringBooking,
createRecurringBookingMutation.error,
createRecurringBookingMutation.isError,
createRecurringBookingMutation.isPending,
currentTime, currentTime,
exportDayReport, exportDayReport,
isCreateBookingOpen, isCreateBookingOpen,
openCreateBooking, openCreateBooking,
planFeatures,
isRecurringEnabled,
schedules, schedules,
selectedDate, selectedDate,
selectedSlot, selectedSlot,

View File

@@ -18,6 +18,7 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from '@/components/ui/select'; } from '@/components/ui/select';
import { Separator } from '@/components/ui/separator';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
@@ -60,12 +61,16 @@ export function BookingCreateDialog() {
isCreatingBooking, isCreatingBooking,
closeCreateBooking, closeCreateBooking,
createBooking, createBooking,
createRecurringBooking,
isRecurringEnabled,
} = useBooking(); } = useBooking();
const [date, setDate] = useState(selectedSlot?.date ?? selectedDate); const [date, setDate] = useState(selectedSlot?.date ?? selectedDate);
const [sportId, setSportId] = useState(selectedSlot?.sportId ?? 'all'); const [sportId, setSportId] = useState(selectedSlot?.sportId ?? 'all');
const [courtId, setCourtId] = useState(selectedSlot?.courtId ?? ''); const [courtId, setCourtId] = useState(selectedSlot?.courtId ?? '');
const [startTime, setStartTime] = useState(selectedSlot?.startTime ?? ''); const [startTime, setStartTime] = useState(selectedSlot?.startTime ?? '');
const [isRecurring, setIsRecurring] = useState(false);
const [recurringEndDate, setRecurringEndDate] = useState<string | undefined>(undefined);
const { const {
register, register,
@@ -90,6 +95,8 @@ export function BookingCreateDialog() {
setSportId(selectedSlot?.sportId ?? 'all'); setSportId(selectedSlot?.sportId ?? 'all');
setCourtId(selectedSlot?.courtId ?? ''); setCourtId(selectedSlot?.courtId ?? '');
setStartTime(selectedSlot?.startTime ?? ''); setStartTime(selectedSlot?.startTime ?? '');
setIsRecurring(false);
setRecurringEndDate(undefined);
reset(); reset();
if (selectedSlot?.courtId && selectedSlot?.startTime) { if (selectedSlot?.courtId && selectedSlot?.startTime) {
@@ -155,6 +162,17 @@ export function BookingCreateDialog() {
}, [availableStartTimes, startTime]); }, [availableStartTimes, startTime]);
const onSubmit = async (values: BookingForm) => { const onSubmit = async (values: BookingForm) => {
if (isRecurring) {
await createRecurringBooking({
courtId,
date,
startTime,
customerName: values.customerName,
customerPhone: values.customerPhone,
customerEmail: values.customerEmail,
recurringEndDate,
});
} else {
await createBooking({ await createBooking({
courtId, courtId,
date, date,
@@ -163,6 +181,7 @@ export function BookingCreateDialog() {
customerPhone: values.customerPhone, customerPhone: values.customerPhone,
customerEmail: values.customerEmail, customerEmail: values.customerEmail,
}); });
}
}; };
return ( return (
@@ -260,6 +279,52 @@ export function BookingCreateDialog() {
</Field> </Field>
</div> </div>
{isRecurringEnabled && (
<>
<Separator />
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<p className="text-sm font-medium">Repetir todas las semanas</p>
<p className="text-xs text-muted-foreground">
{isRecurring
? `Se creará una reserva todos los ${getDayOfWeekLabel(date)} a las ${startTime || '...'}`
: 'Crea turnos fijos en el mismo horario'}
</p>
</div>
<Button
type="button"
variant={isRecurring ? 'default' : 'outline'}
size="sm"
onClick={() => setIsRecurring(!isRecurring)}
className="shrink-0"
>
{isRecurring ? 'Activado' : 'Desactivado'}
</Button>
</div>
{isRecurring && (
<Field>
<FieldLabel>
Repetir hasta{' '}
<span className="text-muted-foreground font-normal">(opcional)</span>
</FieldLabel>
<DatePicker
value={fromIsoDateLocal(recurringEndDate ?? '')}
onChange={(nextDate) => {
setRecurringEndDate(nextDate ? toIsoDateLocal(nextDate) : undefined);
}}
/>
<p className="mt-1 text-xs text-muted-foreground">
Si no se selecciona una fecha, se repetirá por tiempo indefinido.
</p>
</Field>
)}
</>
)}
<Separator />
<Field data-invalid={Boolean(errors.customerName)}> <Field data-invalid={Boolean(errors.customerName)}>
<FieldLabel htmlFor="customerName">Nombre</FieldLabel> <FieldLabel htmlFor="customerName">Nombre</FieldLabel>
<Input <Input
@@ -312,10 +377,29 @@ export function BookingCreateDialog() {
form="booking-create-form" form="booking-create-form"
disabled={!isValid || isCreatingBooking || !courtId || !startTime} disabled={!isValid || isCreatingBooking || !courtId || !startTime}
> >
{isCreatingBooking ? 'Guardando...' : 'Crear reserva'} {isCreatingBooking
? isRecurring
? 'Creando turnos...'
: 'Guardando...'
: isRecurring
? 'Crear turno fijo'
: 'Crear reserva'}
</Button> </Button>
</ResponsiveDialogFooter> </ResponsiveDialogFooter>
</ResponsiveDialogContent> </ResponsiveDialogContent>
</ResponsiveDialog> </ResponsiveDialog>
); );
} }
function getDayOfWeekLabel(dateIso: string): string {
const labels: Record<string, string> = {
MONDAY: 'lunes',
TUESDAY: 'martes',
WEDNESDAY: 'miércoles',
THURSDAY: 'jueves',
FRIDAY: 'viernes',
SATURDAY: 'sábado',
SUNDAY: 'domingo',
};
return labels[getDayOfWeek(dateIso)] ?? '';
}

View File

@@ -13,6 +13,7 @@ const FEATURE_LABELS: Record<string, string> = {
onlinePayments: 'Pagos online', onlinePayments: 'Pagos online',
advancedReports: 'Reportes avanzados', advancedReports: 'Reportes avanzados',
whatsappReminders: 'Recordatorios WhatsApp', whatsappReminders: 'Recordatorios WhatsApp',
fixedSlots: 'Turnos fijos',
}; };
export function PlanSelectStep({ form, plans }: PlanSelectStepProps) { export function PlanSelectStep({ form, plans }: PlanSelectStepProps) {
@@ -24,6 +25,7 @@ export function PlanSelectStep({ form, plans }: PlanSelectStepProps) {
'onlinePayments', 'onlinePayments',
'advancedReports', 'advancedReports',
'whatsappReminders', 'whatsappReminders',
'fixedSlots',
] as const; ] as const;
return ( return (

View File

@@ -74,6 +74,8 @@ export const apiClient = {
adminBookings: { adminBookings: {
listByComplex: api.listByComplex, listByComplex: api.listByComplex,
create: api.createAdmin, create: api.createAdmin,
createRecurring: api.createRecurring,
cancelRecurringGroup: api.cancelRecurringGroup,
updateStatus: api.updateStatus, updateStatus: api.updateStatus,
}, },
}; };

View File

@@ -15,5 +15,7 @@ export {
getConfirmation, getConfirmation,
listByComplex, listByComplex,
createAdmin, createAdmin,
createRecurring,
cancelRecurringGroup,
updateStatus, updateStatus,
} from './resources/bookings'; } from './resources/bookings';

View File

@@ -6,8 +6,10 @@ import type {
PublicAvailabilityResponse, PublicAvailabilityResponse,
PublicBooking, PublicBooking,
PublicBookingConfirmation, PublicBookingConfirmation,
RecurringBookingGroup,
UpdateAdminBookingStatusInput, UpdateAdminBookingStatusInput,
} from '@repo/api-contract'; } from '@repo/api-contract';
import type { CreateRecurringBookingInput } from '@repo/api-contract';
import { http } from '../http'; import { http } from '../http';
export async function getAvailability( export async function getAvailability(
@@ -52,6 +54,21 @@ export async function createAdmin(complexId: string, payload: CreateAdminBooking
return response.data; return response.data;
} }
export async function createRecurring(complexId: string, payload: CreateRecurringBookingInput) {
const response = await http.post<RecurringBookingGroup>(
`/api/admin-bookings/complex/${complexId}/recurring`,
payload
);
return response.data;
}
export async function cancelRecurringGroup(groupId: string) {
const response = await http.post<{ ok: boolean }>(
`/api/admin-bookings/recurring/${groupId}/cancel`
);
return response.data;
}
export async function cancelPublic(complexSlug: string, payload: CancelPublicBookingInput) { export async function cancelPublic(complexSlug: string, payload: CancelPublicBookingInput) {
const response = await http.post<PublicBooking>( const response = await http.post<PublicBooking>(
`/api/public-bookings/complex/${complexSlug}/cancel`, `/api/public-bookings/complex/${complexSlug}/cancel`,

View File

@@ -1,16 +1,18 @@
import { z } from 'zod' import { z } from 'zod';
const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/ const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/;
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/ const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
const BOOKING_CODE_REGEX = /^[A-Z0-9]{6,8}$/ const BOOKING_CODE_REGEX = /^[A-Z0-9]{6,8}$/;
export const bookingStatusSchema = z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED', 'NOSHOW']) export const bookingStatusSchema = z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED', 'NOSHOW']);
export const recurringGroupStatusSchema = z.enum(['ACTIVE', 'CANCELLED']);
export const adminBookingSportSchema = z.object({ export const adminBookingSportSchema = z.object({
id: z.uuid(), id: z.uuid(),
name: z.string(), name: z.string(),
slug: z.string(), slug: z.string(),
}) });
export const adminBookingSchema = z.object({ export const adminBookingSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -28,17 +30,18 @@ export const adminBookingSchema = z.object({
customerEmail: z.string(), customerEmail: z.string(),
price: z.number().nonnegative(), price: z.number().nonnegative(),
status: bookingStatusSchema, status: bookingStatusSchema,
recurringGroupId: z.string().uuid().nullable().optional(),
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
updatedAt: z.string().datetime(), updatedAt: z.string().datetime(),
}) });
export const listAdminBookingsQuerySchema = z.object({ export const listAdminBookingsQuerySchema = z.object({
fromDate: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'), fromDate: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
}) });
export const listAdminBookingsResponseSchema = z.object({ export const listAdminBookingsResponseSchema = z.object({
bookings: z.array(adminBookingSchema), bookings: z.array(adminBookingSchema),
}) });
export const createAdminBookingSchema = z.object({ export const createAdminBookingSchema = z.object({
date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'), date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
@@ -54,20 +57,46 @@ export const createAdminBookingSchema = z.object({
.trim() .trim()
.min(6, 'El telefono debe tener al menos 6 caracteres.') .min(6, 'El telefono debe tener al menos 6 caracteres.')
.max(30, 'El telefono no puede superar los 30 caracteres.'), .max(30, 'El telefono no puede superar los 30 caracteres.'),
customerEmail: z customerEmail: z.string().email('El email ingresado no es valido.').or(z.literal('')),
.string() });
.email('El email ingresado no es valido.')
.or(z.literal('')),
})
export const updateAdminBookingStatusSchema = z.object({ export const updateAdminBookingStatusSchema = z.object({
status: z.enum(['CANCELLED', 'COMPLETED', 'NOSHOW']), status: z.enum(['CANCELLED', 'COMPLETED', 'NOSHOW']),
}) });
export type BookingStatus = z.infer<typeof bookingStatusSchema> export const createRecurringBookingSchema = createAdminBookingSchema.extend({
export type AdminBookingSport = z.infer<typeof adminBookingSportSchema> isRecurring: z.literal(true),
export type AdminBooking = z.infer<typeof adminBookingSchema> recurringEndDate: z
export type ListAdminBookingsQuery = z.infer<typeof listAdminBookingsQuerySchema> .string()
export type ListAdminBookingsResponse = z.infer<typeof listAdminBookingsResponseSchema> .regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.')
export type CreateAdminBookingInput = z.infer<typeof createAdminBookingSchema> .optional(),
export type UpdateAdminBookingStatusInput = z.infer<typeof updateAdminBookingStatusSchema> });
export const recurringBookingGroupSchema = z.object({
id: z.uuid(),
complexId: z.uuid(),
courtId: z.uuid(),
startTime: z.string().regex(TIME_REGEX),
endTime: z.string().regex(TIME_REGEX),
dayOfWeek: z.enum(['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']),
startDate: z.string().regex(ISO_DATE_REGEX),
endDate: z.string().regex(ISO_DATE_REGEX).nullable(),
status: recurringGroupStatusSchema,
customerName: z.string(),
customerPhone: z.string(),
customerEmail: z.string(),
bookings: z.array(adminBookingSchema),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
});
export type BookingStatus = z.infer<typeof bookingStatusSchema>;
export type RecurringGroupStatus = z.infer<typeof recurringGroupStatusSchema>;
export type AdminBookingSport = z.infer<typeof adminBookingSportSchema>;
export type AdminBooking = z.infer<typeof adminBookingSchema>;
export type ListAdminBookingsQuery = z.infer<typeof listAdminBookingsQuerySchema>;
export type ListAdminBookingsResponse = z.infer<typeof listAdminBookingsResponseSchema>;
export type CreateAdminBookingInput = z.infer<typeof createAdminBookingSchema>;
export type CreateRecurringBookingInput = z.infer<typeof createRecurringBookingSchema>;
export type RecurringBookingGroup = z.infer<typeof recurringBookingGroupSchema>;
export type UpdateAdminBookingStatusInput = z.infer<typeof updateAdminBookingStatusSchema>;

View File

@@ -1,6 +1,6 @@
import { z } from 'zod' import { z } from 'zod';
export const adminPaymentStatusSchema = z.enum(['active', 'no_plan', 'expired']) export const adminPaymentStatusSchema = z.enum(['active', 'no_plan', 'expired']);
export const adminComplexListItemSchema = z.object({ export const adminComplexListItemSchema = z.object({
id: z.string(), id: z.string(),
@@ -13,7 +13,7 @@ export const adminComplexListItemSchema = z.object({
courtCount: z.number().int().nonnegative(), courtCount: z.number().int().nonnegative(),
avgBookingsPerDay: z.number().nonnegative(), avgBookingsPerDay: z.number().nonnegative(),
paymentStatus: adminPaymentStatusSchema, paymentStatus: adminPaymentStatusSchema,
}) });
export const adminComplexStatsSchema = z.object({ export const adminComplexStatsSchema = z.object({
id: z.string(), id: z.string(),
@@ -34,20 +34,20 @@ export const adminComplexStatsSchema = z.object({
noshow: z.number().int().nonnegative(), noshow: z.number().int().nonnegative(),
}), }),
paymentStatus: adminPaymentStatusSchema, paymentStatus: adminPaymentStatusSchema,
}) });
export const adminCreatePlanSchema = z.object({ export const adminCreatePlanSchema = z.object({
code: z.string().trim().min(1).max(10), code: z.string().trim().min(1).max(10),
name: z.string().trim().min(1).max(30), name: z.string().trim().min(1).max(30),
price: z.number().nonnegative(), price: z.number().nonnegative(),
rules: z.any(), rules: z.any(),
}) });
export const adminUpdatePlanSchema = z.object({ export const adminUpdatePlanSchema = z.object({
name: z.string().trim().min(1).max(30).optional(), name: z.string().trim().min(1).max(30).optional(),
price: z.number().nonnegative().optional(), price: z.number().nonnegative().optional(),
rules: z.any().optional(), rules: z.any().optional(),
}) });
export const adminUserSchema = z.object({ export const adminUserSchema = z.object({
id: z.string(), id: z.string(),
@@ -60,18 +60,18 @@ export const adminUserSchema = z.object({
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
complexCount: z.number().int().nonnegative(), complexCount: z.number().int().nonnegative(),
activeSessions: z.number().int().nonnegative(), activeSessions: z.number().int().nonnegative(),
}) });
export const adminBlockUserSchema = z.object({ export const adminBlockUserSchema = z.object({
banReason: z.string().max(500).optional(), banReason: z.string().max(500).optional(),
}) });
export const adminGlobalStatsSchema = z.object({ export const adminGlobalStatsSchema = z.object({
totalComplexes: z.number().int().nonnegative(), totalComplexes: z.number().int().nonnegative(),
totalUsers: z.number().int().nonnegative(), totalUsers: z.number().int().nonnegative(),
totalCourts: z.number().int().nonnegative(), totalCourts: z.number().int().nonnegative(),
totalBookings: z.number().int().nonnegative(), totalBookings: z.number().int().nonnegative(),
}) });
export const adminUserSessionSchema = z.object({ export const adminUserSessionSchema = z.object({
id: z.string(), id: z.string(),
@@ -82,35 +82,35 @@ export const adminUserSessionSchema = z.object({
city: z.string().nullable(), city: z.string().nullable(),
country: z.string().nullable(), country: z.string().nullable(),
countryCode: z.string().nullable(), countryCode: z.string().nullable(),
}) });
export type AdminComplexListItem = z.infer<typeof adminComplexListItemSchema> export type AdminComplexListItem = z.infer<typeof adminComplexListItemSchema>;
export type AdminComplexStats = z.infer<typeof adminComplexStatsSchema> export type AdminComplexStats = z.infer<typeof adminComplexStatsSchema>;
export type AdminCreatePlanInput = z.infer<typeof adminCreatePlanSchema> export type AdminCreatePlanInput = z.infer<typeof adminCreatePlanSchema>;
export type AdminUpdatePlanInput = z.infer<typeof adminUpdatePlanSchema> export type AdminUpdatePlanInput = z.infer<typeof adminUpdatePlanSchema>;
export type AdminUser = z.infer<typeof adminUserSchema> export type AdminUser = z.infer<typeof adminUserSchema>;
export type AdminBlockUserInput = z.infer<typeof adminBlockUserSchema> export type AdminBlockUserInput = z.infer<typeof adminBlockUserSchema>;
export type AdminGlobalStats = z.infer<typeof adminGlobalStatsSchema> export type AdminGlobalStats = z.infer<typeof adminGlobalStatsSchema>;
export type AdminPaymentStatus = z.infer<typeof adminPaymentStatusSchema> export type AdminPaymentStatus = z.infer<typeof adminPaymentStatusSchema>;
export type AdminUserSession = z.infer<typeof adminUserSessionSchema> export type AdminUserSession = z.infer<typeof adminUserSessionSchema>;
export const adminGeoCitySchema = z.object({ export const adminGeoCitySchema = z.object({
city: z.string(), city: z.string(),
userCount: z.number().int().nonnegative(), userCount: z.number().int().nonnegative(),
}) });
export const adminGeoCountrySchema = z.object({ export const adminGeoCountrySchema = z.object({
country: z.string(), country: z.string(),
countryCode: z.string(), countryCode: z.string(),
totalUsers: z.number().int().nonnegative(), totalUsers: z.number().int().nonnegative(),
cities: z.array(adminGeoCitySchema), cities: z.array(adminGeoCitySchema),
}) });
export const adminGeoStatsSchema = z.object({ export const adminGeoStatsSchema = z.object({
countries: z.array(adminGeoCountrySchema), countries: z.array(adminGeoCountrySchema),
totalUniqueCountries: z.number().int().nonnegative(), totalUniqueCountries: z.number().int().nonnegative(),
}) });
export type AdminGeoCity = z.infer<typeof adminGeoCitySchema> export type AdminGeoCity = z.infer<typeof adminGeoCitySchema>;
export type AdminGeoCountry = z.infer<typeof adminGeoCountrySchema> export type AdminGeoCountry = z.infer<typeof adminGeoCountrySchema>;
export type AdminGeoStats = z.infer<typeof adminGeoStatsSchema> export type AdminGeoStats = z.infer<typeof adminGeoStatsSchema>;

View File

@@ -1,4 +1,5 @@
import { z } from 'zod' import { z } from 'zod';
import { planFeatureFlagsSchema } from './plan';
const dayOfWeekEnum = z.enum([ const dayOfWeekEnum = z.enum([
'MONDAY', 'MONDAY',
@@ -8,7 +9,7 @@ const dayOfWeekEnum = z.enum([
'FRIDAY', 'FRIDAY',
'SATURDAY', 'SATURDAY',
'SUNDAY', 'SUNDAY',
]) ]);
export const complexSchema = z.object({ export const complexSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -22,7 +23,7 @@ export const complexSchema = z.object({
planCode: z.string().max(10).nullable(), planCode: z.string().max(10).nullable(),
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
updatedAt: z.string().datetime(), updatedAt: z.string().datetime(),
}) });
export const createComplexSchema = z export const createComplexSchema = z
.object({ .object({
@@ -36,21 +37,13 @@ export const createComplexSchema = z
.trim() .trim()
.min(5, 'La direccion debe tener al menos 5 caracteres.') .min(5, 'La direccion debe tener al menos 5 caracteres.')
.max(200, 'La direccion no puede superar los 200 caracteres.'), .max(200, 'La direccion no puede superar los 200 caracteres.'),
city: z city: z.string().trim().max(100, 'La ciudad no puede superar los 100 caracteres.').optional(),
.string()
.trim()
.max(100, 'La ciudad no puede superar los 100 caracteres.')
.optional(),
state: z state: z
.string() .string()
.trim() .trim()
.max(100, 'La provincia/estado no puede superar los 100 caracteres.') .max(100, 'La provincia/estado no puede superar los 100 caracteres.')
.optional(), .optional(),
country: z country: z.string().trim().max(100, 'El país no puede superar los 100 caracteres.').optional(),
.string()
.trim()
.max(100, 'El país no puede superar los 100 caracteres.')
.optional(),
planCode: z planCode: z
.string() .string()
.trim() .trim()
@@ -70,31 +63,31 @@ export const createComplexSchema = z
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
path: ['courtSportId'], path: ['courtSportId'],
message: 'Debes seleccionar un deporte.', message: 'Debes seleccionar un deporte.',
}) });
} }
if (!data.courtStartTime || !/^\d{2}:\d{2}$/.test(data.courtStartTime)) { if (!data.courtStartTime || !/^\d{2}:\d{2}$/.test(data.courtStartTime)) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
path: ['courtStartTime'], path: ['courtStartTime'],
message: 'La hora de inicio debe tener formato HH:mm.', message: 'La hora de inicio debe tener formato HH:mm.',
}) });
} }
if (!data.courtEndTime || !/^\d{2}:\d{2}$/.test(data.courtEndTime)) { if (!data.courtEndTime || !/^\d{2}:\d{2}$/.test(data.courtEndTime)) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
path: ['courtEndTime'], path: ['courtEndTime'],
message: 'La hora de fin debe tener formato HH:mm.', message: 'La hora de fin debe tener formato HH:mm.',
}) });
} }
if (!data.courtDaysOfWeek || data.courtDaysOfWeek.length === 0) { if (!data.courtDaysOfWeek || data.courtDaysOfWeek.length === 0) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
path: ['courtDaysOfWeek'], path: ['courtDaysOfWeek'],
message: 'Debes seleccionar al menos un día.', message: 'Debes seleccionar al menos un día.',
}) });
} }
} }
}) });
export const updateComplexSchema = z export const updateComplexSchema = z
.object({ .object({
@@ -154,16 +147,16 @@ export const updateComplexSchema = z
payload.country !== undefined || payload.country !== undefined ||
payload.complexSlug || payload.complexSlug ||
payload.adminEmail || payload.adminEmail ||
payload.planCode !== undefined, payload.planCode !== undefined
), ),
{ {
message: 'Debes enviar al menos un campo para actualizar.', message: 'Debes enviar al menos un campo para actualizar.',
}, }
) );
export const complexUserRoleSchema = z.enum(['ADMIN', 'EMPLOYEE']) export const complexUserRoleSchema = z.enum(['ADMIN', 'EMPLOYEE']);
export type ComplexUserRole = z.infer<typeof complexUserRoleSchema> export type ComplexUserRole = z.infer<typeof complexUserRoleSchema>;
export const complexMemberSchema = z.object({ export const complexMemberSchema = z.object({
userId: z.string(), userId: z.string(),
@@ -172,13 +165,13 @@ export const complexMemberSchema = z.object({
avatarUrl: z.url(), avatarUrl: z.url(),
role: complexUserRoleSchema, role: complexUserRoleSchema,
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
}) });
export type ComplexMember = z.infer<typeof complexMemberSchema> export type ComplexMember = z.infer<typeof complexMemberSchema>;
export const complexInvitationStatusSchema = z.enum(['PENDING', 'ACCEPTED', 'REVOKED', 'EXPIRED']) export const complexInvitationStatusSchema = z.enum(['PENDING', 'ACCEPTED', 'REVOKED', 'EXPIRED']);
export type ComplexInvitationStatus = z.infer<typeof complexInvitationStatusSchema> export type ComplexInvitationStatus = z.infer<typeof complexInvitationStatusSchema>;
export const complexInvitationSchema = z.object({ export const complexInvitationSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -189,62 +182,63 @@ export const complexInvitationSchema = z.object({
expiresAt: z.string().datetime(), expiresAt: z.string().datetime(),
acceptedAt: z.string().datetime().nullable(), acceptedAt: z.string().datetime().nullable(),
revokedAt: z.string().datetime().nullable(), revokedAt: z.string().datetime().nullable(),
}) });
export type ComplexInvitation = z.infer<typeof complexInvitationSchema> export type ComplexInvitation = z.infer<typeof complexInvitationSchema>;
export const complexUsersOverviewSchema = z.object({ export const complexUsersOverviewSchema = z.object({
members: z.array(complexMemberSchema), members: z.array(complexMemberSchema),
invitations: z.array(complexInvitationSchema), invitations: z.array(complexInvitationSchema),
}) });
export type ComplexUsersOverview = z.infer<typeof complexUsersOverviewSchema> export type ComplexUsersOverview = z.infer<typeof complexUsersOverviewSchema>;
export const inviteComplexUserSchema = z.object({ export const inviteComplexUserSchema = z.object({
email: z.email('El email debe ser válido.'), email: z.email('El email debe ser válido.'),
}) });
export type InviteComplexUserInput = z.infer<typeof inviteComplexUserSchema> export type InviteComplexUserInput = z.infer<typeof inviteComplexUserSchema>;
export const acceptComplexInvitationsSchema = z.object({ export const acceptComplexInvitationsSchema = z.object({
inviteToken: z.string().min(1, 'El token de invitación no puede estar vacío.').optional(), inviteToken: z.string().min(1, 'El token de invitación no puede estar vacío.').optional(),
}) });
export type AcceptComplexInvitationsInput = z.infer<typeof acceptComplexInvitationsSchema> export type AcceptComplexInvitationsInput = z.infer<typeof acceptComplexInvitationsSchema>;
export const revokeComplexUserSchema = z.object({ export const revokeComplexUserSchema = z.object({
userId: z.string().min(1, 'El userId no puede estar vacío.'), userId: z.string().min(1, 'El userId no puede estar vacío.'),
}) });
export type RevokeComplexUserInput = z.infer<typeof revokeComplexUserSchema> export type RevokeComplexUserInput = z.infer<typeof revokeComplexUserSchema>;
export const selectComplexSchema = z.object({ export const selectComplexSchema = z.object({
complexId: z.string().uuid(), complexId: z.string().uuid(),
}) });
export type SelectComplexInput = z.infer<typeof selectComplexSchema> export type SelectComplexInput = z.infer<typeof selectComplexSchema>;
export const complexWithRoleSchema = complexSchema.merge( export const complexWithRoleSchema = complexSchema.merge(
z.object({ z.object({
role: complexUserRoleSchema, role: complexUserRoleSchema,
planFeatures: planFeatureFlagsSchema.nullable(),
}) })
) );
export type ComplexWithRole = z.infer<typeof complexWithRoleSchema> export type ComplexWithRole = z.infer<typeof complexWithRoleSchema>;
export type Complex = z.infer<typeof complexSchema> export type Complex = z.infer<typeof complexSchema>;
export type CreateComplexInput = z.infer<typeof createComplexSchema> export type CreateComplexInput = z.infer<typeof createComplexSchema>;
export type UpdateComplexInput = z.infer<typeof updateComplexSchema> export type UpdateComplexInput = z.infer<typeof updateComplexSchema>;
export type CreateComplexPayload = CreateComplexInput export type CreateComplexPayload = CreateComplexInput;
export type CreateComplexResponse = Complex export type CreateComplexResponse = Complex;
export type UpdateComplexPayload = UpdateComplexInput export type UpdateComplexPayload = UpdateComplexInput;
export type UpdateComplexResponse = Complex export type UpdateComplexResponse = Complex;
export type InviteComplexUserResponse = { export type InviteComplexUserResponse = {
invitation: ComplexInvitation invitation: ComplexInvitation;
} };
export type AcceptComplexInvitationsResponse = { export type AcceptComplexInvitationsResponse = {
acceptedCount: number acceptedCount: number;
} };
export type CancelComplexInvitationResponse = { export type CancelComplexInvitationResponse = {
ok: boolean ok: boolean;
} };

View File

@@ -1,65 +1,65 @@
import { z } from 'zod' import { z } from 'zod';
const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/ const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/;
function toMinutes(value: string): number { function toMinutes(value: string): number {
const [hours, minutes] = value.split(':').map((part) => Number(part)) const [hours, minutes] = value.split(':').map((part) => Number(part));
return hours * 60 + minutes return hours * 60 + minutes;
} }
function hasOverlaps( function hasOverlaps(
availability: Array<{ availability: Array<{
dayOfWeek: DayOfWeek dayOfWeek: DayOfWeek;
startTime: string startTime: string;
endTime: string endTime: string;
}>, }>
): boolean { ): boolean {
const grouped = new Map< const grouped = new Map<
DayOfWeek, DayOfWeek,
Array<{ Array<{
start: number start: number;
end: number end: number;
}> }>
>() >();
for (const range of availability) { for (const range of availability) {
const start = toMinutes(range.startTime) const start = toMinutes(range.startTime);
const end = toMinutes(range.endTime) const end = toMinutes(range.endTime);
const current = grouped.get(range.dayOfWeek) ?? [] const current = grouped.get(range.dayOfWeek) ?? [];
current.push({ start, end }) current.push({ start, end });
grouped.set(range.dayOfWeek, current) grouped.set(range.dayOfWeek, current);
} }
for (const ranges of grouped.values()) { for (const ranges of grouped.values()) {
ranges.sort((a, b) => a.start - b.start) ranges.sort((a, b) => a.start - b.start);
for (let index = 1; index < ranges.length; index += 1) { for (let index = 1; index < ranges.length; index += 1) {
const previous = ranges[index - 1] const previous = ranges[index - 1];
const current = ranges[index] const current = ranges[index];
if (previous.end > current.start) { if (previous.end > current.start) {
return true return true;
} }
} }
} }
return false return false;
} }
function refineAvailability( function refineAvailability(
availability: Array<{ availability: Array<{
dayOfWeek: DayOfWeek dayOfWeek: DayOfWeek;
startTime: string startTime: string;
endTime: string endTime: string;
}>, }>,
context: z.RefinementCtx, context: z.RefinementCtx
) { ) {
for (const range of availability) { for (const range of availability) {
if (toMinutes(range.startTime) >= toMinutes(range.endTime)) { if (toMinutes(range.startTime) >= toMinutes(range.endTime)) {
context.addIssue({ context.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: `El rango ${range.startTime}-${range.endTime} es invalido. La hora de inicio debe ser menor a la de fin.`, message: `El rango ${range.startTime}-${range.endTime} es invalido. La hora de inicio debe ser menor a la de fin.`,
}) });
} }
} }
@@ -67,7 +67,7 @@ function refineAvailability(
context.addIssue({ context.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: 'Hay rangos horarios superpuestos para el mismo dia.', message: 'Hay rangos horarios superpuestos para el mismo dia.',
}) });
} }
} }
@@ -79,22 +79,22 @@ export const dayOfWeekSchema = z.enum([
'FRIDAY', 'FRIDAY',
'SATURDAY', 'SATURDAY',
'SUNDAY', 'SUNDAY',
]) ]);
export type DayOfWeek = z.infer<typeof dayOfWeekSchema> export type DayOfWeek = z.infer<typeof dayOfWeekSchema>;
export const courtAvailabilitySchema = z.object({ export const courtAvailabilitySchema = z.object({
id: z.uuid(), id: z.uuid(),
dayOfWeek: dayOfWeekSchema, dayOfWeek: dayOfWeekSchema,
startTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'), startTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'),
endTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'), endTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'),
}) });
export const courtAvailabilityInputSchema = z.object({ export const courtAvailabilityInputSchema = z.object({
dayOfWeek: dayOfWeekSchema, dayOfWeek: dayOfWeekSchema,
startTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'), startTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'),
endTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'), endTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'),
}) });
export const courtPriceRuleSchema = z.object({ export const courtPriceRuleSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -103,13 +103,13 @@ export const courtPriceRuleSchema = z.object({
endTime: z.string().nullable(), endTime: z.string().nullable(),
price: z.number().nonnegative(), price: z.number().nonnegative(),
isActive: z.boolean(), isActive: z.boolean(),
}) });
export const courtSportSchema = z.object({ export const courtSportSchema = z.object({
id: z.uuid(), id: z.uuid(),
name: z.string(), name: z.string(),
slug: z.string(), slug: z.string(),
}) });
export const courtSchema = z.object({ export const courtSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -124,7 +124,7 @@ export const courtSchema = z.object({
hasCustomPricing: z.boolean(), hasCustomPricing: z.boolean(),
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
updatedAt: z.string().datetime(), updatedAt: z.string().datetime(),
}) });
export const createCourtSchema = z export const createCourtSchema = z
.object({ .object({
@@ -139,9 +139,11 @@ export const createCourtSchema = z
.min(15, 'La duracion minima por turno es 15 minutos.') .min(15, 'La duracion minima por turno es 15 minutos.')
.max(480, 'La duracion maxima por turno es 480 minutos.'), .max(480, 'La duracion maxima por turno es 480 minutos.'),
basePrice: z.number().nonnegative('El precio base no puede ser negativo.'), basePrice: z.number().nonnegative('El precio base no puede ser negativo.'),
availability: z.array(courtAvailabilityInputSchema).min(1, 'Debes definir al menos un rango horario.'), availability: z
.array(courtAvailabilityInputSchema)
.min(1, 'Debes definir al menos un rango horario.'),
}) })
.superRefine((payload, context) => refineAvailability(payload.availability, context)) .superRefine((payload, context) => refineAvailability(payload.availability, context));
export const updateCourtSchema = z export const updateCourtSchema = z
.object({ .object({
@@ -158,7 +160,10 @@ export const updateCourtSchema = z
.max(480, 'La duracion maxima por turno es 480 minutos.') .max(480, 'La duracion maxima por turno es 480 minutos.')
.optional(), .optional(),
basePrice: z.number().nonnegative('El precio base no puede ser negativo.').optional(), basePrice: z.number().nonnegative('El precio base no puede ser negativo.').optional(),
availability: z.array(courtAvailabilityInputSchema).min(1, 'Debes definir al menos un rango horario.').optional(), availability: z
.array(courtAvailabilityInputSchema)
.min(1, 'Debes definir al menos un rango horario.')
.optional(),
}) })
.superRefine((payload, context) => { .superRefine((payload, context) => {
if ( if (
@@ -171,17 +176,17 @@ export const updateCourtSchema = z
context.addIssue({ context.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: 'Debes enviar al menos un campo para actualizar.', message: 'Debes enviar al menos un campo para actualizar.',
}) });
} }
if (payload.availability) { if (payload.availability) {
refineAvailability(payload.availability, context) refineAvailability(payload.availability, context);
} }
}) });
export type Court = z.infer<typeof courtSchema> export type Court = z.infer<typeof courtSchema>;
export type CourtAvailability = z.infer<typeof courtAvailabilitySchema> export type CourtAvailability = z.infer<typeof courtAvailabilitySchema>;
export type CourtAvailabilityInput = z.infer<typeof courtAvailabilityInputSchema> export type CourtAvailabilityInput = z.infer<typeof courtAvailabilityInputSchema>;
export type CourtPriceRule = z.infer<typeof courtPriceRuleSchema> export type CourtPriceRule = z.infer<typeof courtPriceRuleSchema>;
export type CreateCourtInput = z.infer<typeof createCourtSchema> export type CreateCourtInput = z.infer<typeof createCourtSchema>;
export type UpdateCourtInput = z.infer<typeof updateCourtSchema> export type UpdateCourtInput = z.infer<typeof updateCourtSchema>;

View File

@@ -6,7 +6,7 @@ export {
planSummarySchema, planSummarySchema,
planWithFeaturesSchema, planWithFeaturesSchema,
planLimitsSchema, planLimitsSchema,
} from './plan' } from './plan';
export type { export type {
Plan, Plan,
PlanFeatureFlags, PlanFeatureFlags,
@@ -15,7 +15,7 @@ export type {
PlanSummary, PlanSummary,
PlanWithFeatures, PlanWithFeatures,
PlanLimits, PlanLimits,
} from './plan' } from './plan';
export { export {
acceptComplexInvitationsSchema, acceptComplexInvitationsSchema,
complexInvitationSchema, complexInvitationSchema,
@@ -30,7 +30,7 @@ export {
revokeComplexUserSchema, revokeComplexUserSchema,
selectComplexSchema, selectComplexSchema,
updateComplexSchema, updateComplexSchema,
} from './complex' } from './complex';
export type { export type {
AcceptComplexInvitationsInput, AcceptComplexInvitationsInput,
AcceptComplexInvitationsResponse, AcceptComplexInvitationsResponse,
@@ -52,7 +52,7 @@ export type {
UpdateComplexPayload, UpdateComplexPayload,
UpdateComplexResponse, UpdateComplexResponse,
RevokeComplexUserInput, RevokeComplexUserInput,
} from './complex' } from './complex';
export { export {
dayOfWeekSchema, dayOfWeekSchema,
courtAvailabilityInputSchema, courtAvailabilityInputSchema,
@@ -61,7 +61,7 @@ export {
courtSchema, courtSchema,
createCourtSchema, createCourtSchema,
updateCourtSchema, updateCourtSchema,
} from './court' } from './court';
export type { export type {
DayOfWeek, DayOfWeek,
Court, Court,
@@ -70,25 +70,31 @@ export type {
CourtPriceRule, CourtPriceRule,
CreateCourtInput, CreateCourtInput,
UpdateCourtInput, UpdateCourtInput,
} from './court' } from './court';
export { export {
adminBookingSchema, adminBookingSchema,
adminBookingSportSchema, adminBookingSportSchema,
bookingStatusSchema, bookingStatusSchema,
createAdminBookingSchema, createAdminBookingSchema,
createRecurringBookingSchema,
listAdminBookingsQuerySchema, listAdminBookingsQuerySchema,
listAdminBookingsResponseSchema, listAdminBookingsResponseSchema,
recurringBookingGroupSchema,
recurringGroupStatusSchema,
updateAdminBookingStatusSchema, updateAdminBookingStatusSchema,
} from './admin-booking' } from './admin-booking';
export type { export type {
AdminBooking, AdminBooking,
AdminBookingSport, AdminBookingSport,
BookingStatus, BookingStatus,
CreateAdminBookingInput, CreateAdminBookingInput,
CreateRecurringBookingInput,
ListAdminBookingsQuery, ListAdminBookingsQuery,
ListAdminBookingsResponse, ListAdminBookingsResponse,
RecurringBookingGroup,
RecurringGroupStatus,
UpdateAdminBookingStatusInput, UpdateAdminBookingStatusInput,
} from './admin-booking' } from './admin-booking';
export { export {
createPublicBookingSchema, createPublicBookingSchema,
publicAvailabilityCourtSchema, publicAvailabilityCourtSchema,
@@ -99,7 +105,7 @@ export {
publicBookingSlotSchema, publicBookingSlotSchema,
publicBookingSportSchema, publicBookingSportSchema,
cancelPublicBookingSchema, cancelPublicBookingSchema,
} from './public-booking' } from './public-booking';
export type { export type {
CreatePublicBookingInput, CreatePublicBookingInput,
CancelPublicBookingInput, CancelPublicBookingInput,
@@ -110,15 +116,15 @@ export type {
PublicBookingConfirmation, PublicBookingConfirmation,
PublicBookingSlot, PublicBookingSlot,
PublicBookingSport, PublicBookingSport,
} from './public-booking' } from './public-booking';
export { sportSchema, createSportSchema, updateSportSchema } from './sport' export { sportSchema, createSportSchema, updateSportSchema } from './sport';
export type { Sport, CreateSportInput, UpdateSportInput } from './sport' export type { Sport, CreateSportInput, UpdateSportInput } from './sport';
export { export {
userProfileSchema, userProfileSchema,
passwordResetStartSchema, passwordResetStartSchema,
passwordResetVerifySchema, passwordResetVerifySchema,
passwordResetResendSchema, passwordResetResendSchema,
} from './user' } from './user';
export type { export type {
UserProfile, UserProfile,
UserProfileResponse, UserProfileResponse,
@@ -128,7 +134,7 @@ export type {
PasswordResetStartResponse, PasswordResetStartResponse,
PasswordResetVerifyResponse, PasswordResetVerifyResponse,
PasswordResetResendResponse, PasswordResetResendResponse,
} from './user' } from './user';
export { export {
adminComplexListItemSchema, adminComplexListItemSchema,
adminComplexStatsSchema, adminComplexStatsSchema,
@@ -142,7 +148,7 @@ export {
adminGeoCitySchema, adminGeoCitySchema,
adminGeoCountrySchema, adminGeoCountrySchema,
adminGeoStatsSchema, adminGeoStatsSchema,
} from './admin' } from './admin';
export type { export type {
AdminComplexListItem, AdminComplexListItem,
AdminComplexStats, AdminComplexStats,
@@ -156,4 +162,4 @@ export type {
AdminGeoCity, AdminGeoCity,
AdminGeoCountry, AdminGeoCountry,
AdminGeoStats, AdminGeoStats,
} from './admin' } from './admin';

View File

@@ -1,14 +1,15 @@
import { z } from 'zod' import { z } from 'zod';
const nonNegativeInt = z.int().nonnegative() const nonNegativeInt = z.int().nonnegative();
const positiveInt = z.int().positive() const positiveInt = z.int().positive();
export const planFeatureFlagsSchema = z.object({ export const planFeatureFlagsSchema = z.object({
onlinePayments: z.boolean().default(false), onlinePayments: z.boolean().default(false),
publicBookingPage: z.boolean().default(false), publicBookingPage: z.boolean().default(false),
advancedReports: z.boolean().default(false), advancedReports: z.boolean().default(false),
whatsappReminders: z.boolean().default(false), whatsappReminders: z.boolean().default(false),
}) fixedSlots: z.boolean().default(false),
});
export const planRulesV1Schema = z.object({ export const planRulesV1Schema = z.object({
version: z.literal('v1'), version: z.literal('v1'),
@@ -31,13 +32,14 @@ export const planRulesV1Schema = z.object({
publicBookingPage: false, publicBookingPage: false,
advancedReports: false, advancedReports: false,
whatsappReminders: false, whatsappReminders: false,
fixedSlots: false,
}), }),
}) });
export const planPriceOverrideSchema = z.object({ export const planPriceOverrideSchema = z.object({
amount: z.number().nonnegative(), amount: z.number().nonnegative(),
currency: z.string().length(3), currency: z.string().length(3),
}) });
export const planRulesV2Schema = planRulesV1Schema.extend({ export const planRulesV2Schema = planRulesV1Schema.extend({
version: z.literal('v2'), version: z.literal('v2'),
@@ -46,12 +48,12 @@ export const planRulesV2Schema = planRulesV1Schema.extend({
overrides: z.record(z.string(), planPriceOverrideSchema), overrides: z.record(z.string(), planPriceOverrideSchema),
}) })
.optional(), .optional(),
}) });
export const planRulesSchema = z.discriminatedUnion('version', [ export const planRulesSchema = z.discriminatedUnion('version', [
planRulesV1Schema, planRulesV1Schema,
planRulesV2Schema, planRulesV2Schema,
]) ]);
export const planSchema = z.object({ export const planSchema = z.object({
code: z.string().trim().min(1).max(10), code: z.string().trim().min(1).max(10),
@@ -59,13 +61,13 @@ export const planSchema = z.object({
price: z.number().nonnegative(), price: z.number().nonnegative(),
lastUpdatedAt: z.string().datetime(), lastUpdatedAt: z.string().datetime(),
rules: planRulesSchema, rules: planRulesSchema,
}) });
export const planSummarySchema = z.object({ export const planSummarySchema = z.object({
code: z.string().trim().min(1).max(10), code: z.string().trim().min(1).max(10),
name: z.string().trim().min(1).max(30), name: z.string().trim().min(1).max(30),
price: z.number().nonnegative(), price: z.number().nonnegative(),
}) });
export const planLimitsSchema = z.object({ export const planLimitsSchema = z.object({
maxCourts: positiveInt, maxCourts: positiveInt,
@@ -73,7 +75,7 @@ export const planLimitsSchema = z.object({
maxActiveUsers: positiveInt.optional(), maxActiveUsers: positiveInt.optional(),
maxConcurrentBookingsPerSlot: positiveInt.optional(), maxConcurrentBookingsPerSlot: positiveInt.optional(),
maxSports: positiveInt.optional(), maxSports: positiveInt.optional(),
}) });
export const planWithFeaturesSchema = z.object({ export const planWithFeaturesSchema = z.object({
code: z.string().trim().min(1).max(10), code: z.string().trim().min(1).max(10),
@@ -82,13 +84,13 @@ export const planWithFeaturesSchema = z.object({
currency: z.string().length(3), currency: z.string().length(3),
features: planFeatureFlagsSchema, features: planFeatureFlagsSchema,
limits: planLimitsSchema, limits: planLimitsSchema,
}) });
export type PlanFeatureFlags = z.infer<typeof planFeatureFlagsSchema> export type PlanFeatureFlags = z.infer<typeof planFeatureFlagsSchema>;
export type PlanRulesV1 = z.infer<typeof planRulesV1Schema> export type PlanRulesV1 = z.infer<typeof planRulesV1Schema>;
export type PlanRulesV2 = z.infer<typeof planRulesV2Schema> export type PlanRulesV2 = z.infer<typeof planRulesV2Schema>;
export type PlanRules = z.infer<typeof planRulesSchema> export type PlanRules = z.infer<typeof planRulesSchema>;
export type Plan = z.infer<typeof planSchema> export type Plan = z.infer<typeof planSchema>;
export type PlanSummary = z.infer<typeof planSummarySchema> export type PlanSummary = z.infer<typeof planSummarySchema>;
export type PlanWithFeatures = z.infer<typeof planWithFeaturesSchema> export type PlanWithFeatures = z.infer<typeof planWithFeaturesSchema>;
export type PlanLimits = z.infer<typeof planLimitsSchema> export type PlanLimits = z.infer<typeof planLimitsSchema>;

View File

@@ -1,26 +1,26 @@
import { z } from 'zod' import { z } from 'zod';
import { dayOfWeekSchema } from './court' import { dayOfWeekSchema } from './court';
const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/ const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/;
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/ const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
const BOOKING_CODE_REGEX = /^[A-Z0-9]{6,8}$/ const BOOKING_CODE_REGEX = /^[A-Z0-9]{6,8}$/;
export const publicAvailabilityQuerySchema = z.object({ export const publicAvailabilityQuerySchema = z.object({
date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'), date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
sportId: z.uuid('El sportId debe ser un UUID valido.').optional(), sportId: z.uuid('El sportId debe ser un UUID valido.').optional(),
}) });
export const publicBookingSportSchema = z.object({ export const publicBookingSportSchema = z.object({
id: z.uuid(), id: z.uuid(),
name: z.string(), name: z.string(),
slug: z.string(), slug: z.string(),
}) });
export const publicBookingSlotSchema = z.object({ export const publicBookingSlotSchema = z.object({
startTime: z.string().regex(TIME_REGEX), startTime: z.string().regex(TIME_REGEX),
endTime: z.string().regex(TIME_REGEX), endTime: z.string().regex(TIME_REGEX),
price: z.number().nonnegative(), price: z.number().nonnegative(),
}) });
export const publicAvailabilityCourtSchema = z.object({ export const publicAvailabilityCourtSchema = z.object({
courtId: z.uuid(), courtId: z.uuid(),
@@ -29,7 +29,7 @@ export const publicAvailabilityCourtSchema = z.object({
slotDurationMinutes: z.int().positive(), slotDurationMinutes: z.int().positive(),
availabilityDay: dayOfWeekSchema, availabilityDay: dayOfWeekSchema,
availableSlots: z.array(publicBookingSlotSchema), availableSlots: z.array(publicBookingSlotSchema),
}) });
export const publicAvailabilityResponseSchema = z.object({ export const publicAvailabilityResponseSchema = z.object({
complexId: z.uuid(), complexId: z.uuid(),
@@ -40,7 +40,7 @@ export const publicAvailabilityResponseSchema = z.object({
sportSelectionRequired: z.boolean(), sportSelectionRequired: z.boolean(),
sports: z.array(publicBookingSportSchema), sports: z.array(publicBookingSportSchema),
courts: z.array(publicAvailabilityCourtSchema), courts: z.array(publicAvailabilityCourtSchema),
}) });
export const createPublicBookingSchema = z.object({ export const createPublicBookingSchema = z.object({
date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'), date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
@@ -57,10 +57,8 @@ export const createPublicBookingSchema = z.object({
.trim() .trim()
.min(6, 'El telefono debe tener al menos 6 caracteres.') .min(6, 'El telefono debe tener al menos 6 caracteres.')
.max(30, 'El telefono no puede superar los 30 caracteres.'), .max(30, 'El telefono no puede superar los 30 caracteres.'),
customerEmail: z customerEmail: z.string().email('El email ingresado no es valido.'),
.string() });
.email('El email ingresado no es valido.'),
})
export const cancelPublicBookingSchema = z.object({ export const cancelPublicBookingSchema = z.object({
bookingCode: z.string().regex(BOOKING_CODE_REGEX, 'El codigo de reserva no es valido.'), bookingCode: z.string().regex(BOOKING_CODE_REGEX, 'El codigo de reserva no es valido.'),
@@ -69,7 +67,7 @@ export const cancelPublicBookingSchema = z.object({
.trim() .trim()
.min(6, 'El telefono debe tener al menos 6 caracteres.') .min(6, 'El telefono debe tener al menos 6 caracteres.')
.max(30, 'El telefono no puede superar los 30 caracteres.'), .max(30, 'El telefono no puede superar los 30 caracteres.'),
}) });
export const publicBookingSchema = z.object({ export const publicBookingSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -89,7 +87,7 @@ export const publicBookingSchema = z.object({
status: z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED']), status: z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED']),
price: z.number().nonnegative(), price: z.number().nonnegative(),
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
}) });
export const publicBookingConfirmationSchema = z.object({ export const publicBookingConfirmationSchema = z.object({
bookingCode: z.string().regex(BOOKING_CODE_REGEX), bookingCode: z.string().regex(BOOKING_CODE_REGEX),
@@ -105,14 +103,14 @@ export const publicBookingConfirmationSchema = z.object({
status: z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED']), status: z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED']),
customerEmail: z.string(), customerEmail: z.string(),
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
}) });
export type PublicAvailabilityQuery = z.infer<typeof publicAvailabilityQuerySchema> export type PublicAvailabilityQuery = z.infer<typeof publicAvailabilityQuerySchema>;
export type PublicBookingSport = z.infer<typeof publicBookingSportSchema> export type PublicBookingSport = z.infer<typeof publicBookingSportSchema>;
export type PublicBookingSlot = z.infer<typeof publicBookingSlotSchema> export type PublicBookingSlot = z.infer<typeof publicBookingSlotSchema>;
export type PublicAvailabilityCourt = z.infer<typeof publicAvailabilityCourtSchema> export type PublicAvailabilityCourt = z.infer<typeof publicAvailabilityCourtSchema>;
export type PublicAvailabilityResponse = z.infer<typeof publicAvailabilityResponseSchema> export type PublicAvailabilityResponse = z.infer<typeof publicAvailabilityResponseSchema>;
export type CreatePublicBookingInput = z.infer<typeof createPublicBookingSchema> export type CreatePublicBookingInput = z.infer<typeof createPublicBookingSchema>;
export type CancelPublicBookingInput = z.infer<typeof cancelPublicBookingSchema> export type CancelPublicBookingInput = z.infer<typeof cancelPublicBookingSchema>;
export type PublicBooking = z.infer<typeof publicBookingSchema> export type PublicBooking = z.infer<typeof publicBookingSchema>;
export type PublicBookingConfirmation = z.infer<typeof publicBookingConfirmationSchema> export type PublicBookingConfirmation = z.infer<typeof publicBookingConfirmationSchema>;

View File

@@ -1,4 +1,4 @@
import { z } from 'zod' import { z } from 'zod';
export const sportSchema = z.object({ export const sportSchema = z.object({
id: z.uuid(), id: z.uuid(),
@@ -7,7 +7,7 @@ export const sportSchema = z.object({
isActive: z.boolean(), isActive: z.boolean(),
createdAt: z.string().datetime(), createdAt: z.string().datetime(),
updatedAt: z.string().datetime(), updatedAt: z.string().datetime(),
}) });
export const createSportSchema = z.object({ export const createSportSchema = z.object({
name: z name: z
@@ -15,7 +15,7 @@ export const createSportSchema = z.object({
.trim() .trim()
.min(2, 'El deporte debe tener al menos 2 caracteres.') .min(2, 'El deporte debe tener al menos 2 caracteres.')
.max(80, 'El deporte no puede superar los 80 caracteres.'), .max(80, 'El deporte no puede superar los 80 caracteres.'),
}) });
export const updateSportSchema = z export const updateSportSchema = z
.object({ .object({
@@ -29,8 +29,8 @@ export const updateSportSchema = z
}) })
.refine((payload) => payload.name !== undefined || payload.isActive !== undefined, { .refine((payload) => payload.name !== undefined || payload.isActive !== undefined, {
message: 'Debes enviar al menos un campo para actualizar.', message: 'Debes enviar al menos un campo para actualizar.',
}) });
export type Sport = z.infer<typeof sportSchema> export type Sport = z.infer<typeof sportSchema>;
export type CreateSportInput = z.infer<typeof createSportSchema> export type CreateSportInput = z.infer<typeof createSportSchema>;
export type UpdateSportInput = z.infer<typeof updateSportSchema> export type UpdateSportInput = z.infer<typeof updateSportSchema>;

View File

@@ -1,4 +1,4 @@
import { z } from 'zod' import { z } from 'zod';
export const userProfileSchema = z.object({ export const userProfileSchema = z.object({
id: z.string(), id: z.string(),
@@ -7,30 +7,30 @@ export const userProfileSchema = z.object({
role: z.string(), role: z.string(),
avatarUrl: z.url().nullable(), avatarUrl: z.url().nullable(),
createdAt: z.string(), createdAt: z.string(),
}) });
export type UserProfile = z.infer<typeof userProfileSchema> export type UserProfile = z.infer<typeof userProfileSchema>;
export type UserProfileResponse = UserProfile export type UserProfileResponse = UserProfile;
export const passwordResetStartSchema = z.object({ export const passwordResetStartSchema = z.object({
email: z.string().email('Ingresá un email válido.'), email: z.string().email('Ingresá un email válido.'),
}) });
export type PasswordResetStartInput = z.infer<typeof passwordResetStartSchema> export type PasswordResetStartInput = z.infer<typeof passwordResetStartSchema>;
export const passwordResetVerifySchema = z.object({ export const passwordResetVerifySchema = z.object({
requestId: z.string().uuid('Request ID inválido.'), requestId: z.string().uuid('Request ID inválido.'),
otp: z.string().length(6, 'El código debe tener 6 dígitos.'), otp: z.string().length(6, 'El código debe tener 6 dígitos.'),
newPassword: z.string().min(6, 'La contraseña debe tener al menos 6 caracteres.'), newPassword: z.string().min(6, 'La contraseña debe tener al menos 6 caracteres.'),
}) });
export type PasswordResetVerifyInput = z.infer<typeof passwordResetVerifySchema> export type PasswordResetVerifyInput = z.infer<typeof passwordResetVerifySchema>;
export const passwordResetResendSchema = z.object({ export const passwordResetResendSchema = z.object({
requestId: z.string().uuid('Request ID inválido.'), requestId: z.string().uuid('Request ID inválido.'),
}) });
export type PasswordResetResendInput = z.infer<typeof passwordResetResendSchema> export type PasswordResetResendInput = z.infer<typeof passwordResetResendSchema>;
export type PasswordResetStartResponse = { export type PasswordResetStartResponse = {
message: string; message: string;
@@ -38,11 +38,11 @@ export type PasswordResetStartResponse = {
email: string; email: string;
expiresAt: string; expiresAt: string;
cooldownSeconds: number; cooldownSeconds: number;
} };
export type PasswordResetVerifyResponse = { export type PasswordResetVerifyResponse = {
message: string; message: string;
} };
export type PasswordResetResendResponse = { export type PasswordResetResendResponse = {
message: string; message: string;
@@ -50,4 +50,4 @@ export type PasswordResetResendResponse = {
email: string; email: string;
expiresAt: string; expiresAt: string;
cooldownSeconds: number; cooldownSeconds: number;
} };