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