@venulog/phasing-engine-schemas 0.2.0-alpha.1 → 0.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/enums/phaseSlotScheduleType.d.ts +4 -0
- package/dist/enums/phaseSlotScheduleType.js +5 -0
- package/dist/event.d.ts +18 -0
- package/dist/event.js +40 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/phaseBooking.d.ts +219 -433
- package/dist/phaseBooking.js +291 -427
- package/dist/phaseSlot.d.ts +60 -57
- package/dist/phaseSlot.js +187 -55
- package/package.json +5 -1
- package/dist/enums/slotStatus.d.ts +0 -5
- package/dist/enums/slotStatus.js +0 -6
package/dist/phaseBooking.js
CHANGED
|
@@ -3,7 +3,7 @@ import { paginationSchema } from './pagination.js';
|
|
|
3
3
|
import { BookingStatus } from './enums/bookingStatus.js';
|
|
4
4
|
import { createSuccessResponseSchema, createMessageDataResponseSchema } from './common.js';
|
|
5
5
|
import { z } from './zod.js';
|
|
6
|
-
import {
|
|
6
|
+
import { PhaseSlotScheduleType } from './enums/phaseSlotScheduleType.js';
|
|
7
7
|
// ------------------------------
|
|
8
8
|
// Query parameters schema
|
|
9
9
|
// ------------------------------
|
|
@@ -25,22 +25,6 @@ export const getEventBookingsQuerySchema = z
|
|
|
25
25
|
})
|
|
26
26
|
.extend(paginationSchema.shape)
|
|
27
27
|
.openapi('GetEventBookingsQuery');
|
|
28
|
-
// ------------------------------
|
|
29
|
-
// Path parameters schema
|
|
30
|
-
// ------------------------------
|
|
31
|
-
export const cancelPhaseSlotParamsSchema = z
|
|
32
|
-
.object({
|
|
33
|
-
slotId: z
|
|
34
|
-
.string()
|
|
35
|
-
.min(1, 'Slot ID is required')
|
|
36
|
-
.transform(val => parseInt(val, 10))
|
|
37
|
-
.refine(val => !isNaN(val) && val > 0, { message: 'Slot ID must be positive' })
|
|
38
|
-
.openapi({
|
|
39
|
-
description: 'The ID of the phase slot to cancel',
|
|
40
|
-
example: '1'
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
.openapi('CancelPhaseSlotParams');
|
|
44
28
|
export const closeEventParamsSchema = z
|
|
45
29
|
.object({
|
|
46
30
|
eventId: z
|
|
@@ -54,17 +38,6 @@ export const closeEventParamsSchema = z
|
|
|
54
38
|
})
|
|
55
39
|
})
|
|
56
40
|
.openapi('CloseEventParams');
|
|
57
|
-
// ------------------------------
|
|
58
|
-
// Request body schemas
|
|
59
|
-
// ------------------------------
|
|
60
|
-
export const cancelPhaseSlotBodySchema = z
|
|
61
|
-
.object({
|
|
62
|
-
reason: z.string().optional().openapi({
|
|
63
|
-
description: 'Optional reason for cancellation (for audit purposes)',
|
|
64
|
-
example: 'Event postponed'
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
.openapi('CancelPhaseSlotBody');
|
|
68
41
|
export const closeEventBodySchema = z
|
|
69
42
|
.object({
|
|
70
43
|
reason: z.string().optional().openapi({
|
|
@@ -80,94 +53,57 @@ export const vehicleTypeSchema = z.object({
|
|
|
80
53
|
id: z.number(),
|
|
81
54
|
name: z.string()
|
|
82
55
|
});
|
|
83
|
-
|
|
56
|
+
// New unified phase slot schedule schema (from database response)
|
|
57
|
+
export const phaseSlotScheduleSchema = z
|
|
84
58
|
.object({
|
|
85
59
|
id: z.number().int().positive().openapi({
|
|
86
|
-
description: 'Unique identifier for the
|
|
60
|
+
description: 'Unique identifier for the schedule',
|
|
87
61
|
example: 1
|
|
88
62
|
}),
|
|
89
63
|
date: z.string().openapi({
|
|
90
|
-
description: 'Date of the
|
|
64
|
+
description: 'Date of the schedule (YYYY-MM-DD format)',
|
|
91
65
|
example: '2025-12-15'
|
|
92
66
|
}),
|
|
93
67
|
start_time: z.string().openapi({
|
|
94
|
-
description: 'Start time
|
|
68
|
+
description: 'Start time (HH:MM format)',
|
|
95
69
|
example: '06:00'
|
|
96
70
|
}),
|
|
97
71
|
end_time: z.string().openapi({
|
|
98
|
-
description: 'End time
|
|
72
|
+
description: 'End time (HH:MM format)',
|
|
99
73
|
example: '09:00'
|
|
100
74
|
}),
|
|
101
75
|
duration: z.number().openapi({
|
|
102
|
-
description: 'Duration
|
|
76
|
+
description: 'Duration in minutes',
|
|
103
77
|
example: 180
|
|
104
78
|
}),
|
|
105
79
|
phase_slot_id: z.number().int().positive().openapi({
|
|
106
80
|
description: 'ID of the associated phase slot',
|
|
107
81
|
example: 101
|
|
108
82
|
}),
|
|
83
|
+
phase_slot_schedule_type: z
|
|
84
|
+
.enum([PhaseSlotScheduleType.ASSEMBLY, PhaseSlotScheduleType.DISMANTLING])
|
|
85
|
+
.openapi({
|
|
86
|
+
description: 'Type of schedule',
|
|
87
|
+
example: PhaseSlotScheduleType.ASSEMBLY
|
|
88
|
+
}),
|
|
109
89
|
created_at: z.string().openapi({
|
|
110
|
-
description: 'Timestamp when
|
|
90
|
+
description: 'Timestamp when schedule was created',
|
|
111
91
|
example: '2025-12-09T10:00:00.000Z'
|
|
112
92
|
}),
|
|
113
93
|
updated_at: z.string().openapi({
|
|
114
|
-
description: 'Timestamp when
|
|
94
|
+
description: 'Timestamp when schedule was updated',
|
|
115
95
|
example: '2025-12-09T10:30:00.000Z'
|
|
116
|
-
})
|
|
117
|
-
})
|
|
118
|
-
.openapi('PhaseSlotAssembly');
|
|
119
|
-
export const phaseSlotDismantlingSchema = z
|
|
120
|
-
.object({
|
|
121
|
-
id: z.number().int().positive().openapi({
|
|
122
|
-
description: 'Unique identifier for the dismantling',
|
|
123
|
-
example: 1
|
|
124
96
|
}),
|
|
125
|
-
|
|
126
|
-
description: '
|
|
127
|
-
example: '
|
|
128
|
-
}),
|
|
129
|
-
start_time: z.string().openapi({
|
|
130
|
-
description: 'Start time of the dismantling (HH:MM format)',
|
|
131
|
-
example: '06:00'
|
|
132
|
-
}),
|
|
133
|
-
end_time: z.string().openapi({
|
|
134
|
-
description: 'End time of the dismantling (HH:MM format)',
|
|
135
|
-
example: '09:00'
|
|
97
|
+
created_by: z.uuid().nullable().openapi({
|
|
98
|
+
description: 'UUID of user who created the schedule',
|
|
99
|
+
example: '550e8400-e29b-41d4-a716-446655440000'
|
|
136
100
|
}),
|
|
137
|
-
|
|
138
|
-
description: '
|
|
139
|
-
example:
|
|
140
|
-
}),
|
|
141
|
-
phase_slot_id: z.number().int().positive().openapi({
|
|
142
|
-
description: 'ID of the associated phase slot',
|
|
143
|
-
example: 101
|
|
144
|
-
}),
|
|
145
|
-
created_at: z.string().openapi({
|
|
146
|
-
description: 'Timestamp when dismantling was created',
|
|
147
|
-
example: '2025-12-09T10:00:00.000Z'
|
|
148
|
-
}),
|
|
149
|
-
updated_at: z.string().openapi({
|
|
150
|
-
description: 'Timestamp when dismantling was updated',
|
|
151
|
-
example: '2025-12-09T10:30:00.000Z'
|
|
101
|
+
updated_by: z.uuid().nullable().openapi({
|
|
102
|
+
description: 'UUID of user who last updated the schedule',
|
|
103
|
+
example: '550e8400-e29b-41d4-a716-446655440000'
|
|
152
104
|
})
|
|
153
105
|
})
|
|
154
|
-
.openapi('
|
|
155
|
-
export const phaseSlotSchema = z.object({
|
|
156
|
-
id: z.number(),
|
|
157
|
-
event_id: z.number(),
|
|
158
|
-
slot_number: z.number(),
|
|
159
|
-
vehicle_type_id: z.number().nullable(),
|
|
160
|
-
company_role: z.string().nullable(),
|
|
161
|
-
status: z.enum(BookingStatus),
|
|
162
|
-
is_active: z.boolean(),
|
|
163
|
-
created_at: z.string(),
|
|
164
|
-
updated_at: z.string(),
|
|
165
|
-
created_by: z.string().nullable(),
|
|
166
|
-
updated_by: z.string().nullable(),
|
|
167
|
-
vehicle_type: vehicleTypeSchema.nullable().optional(),
|
|
168
|
-
assembly: phaseSlotAssemblySchema.nullable().optional(),
|
|
169
|
-
dismantling: phaseSlotDismantlingSchema.nullable().optional()
|
|
170
|
-
});
|
|
106
|
+
.openapi('PhaseSlotSchedule');
|
|
171
107
|
export const companySchema = z.object({
|
|
172
108
|
id: z.number(),
|
|
173
109
|
company_name: z.string(),
|
|
@@ -193,38 +129,127 @@ export const companySchema = z.object({
|
|
|
193
129
|
});
|
|
194
130
|
export const phaseBookingSchema = z.object({
|
|
195
131
|
id: z.number(),
|
|
196
|
-
|
|
197
|
-
phase_slot_id: z.number(),
|
|
132
|
+
phase_slot_schedule_id: z.number(),
|
|
198
133
|
status: z.enum(BookingStatus),
|
|
199
134
|
is_active: z.boolean(),
|
|
200
135
|
created_at: z.string(),
|
|
201
136
|
updated_at: z.string(),
|
|
202
137
|
created_by: z.string().nullable(),
|
|
203
138
|
updated_by: z.string().nullable(),
|
|
204
|
-
|
|
205
|
-
|
|
139
|
+
vehicle: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
140
|
+
company: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
141
|
+
booking_date: z.string().nullable().optional(),
|
|
142
|
+
start_time: z.string().nullable().optional(),
|
|
143
|
+
end_time: z.string().nullable().optional()
|
|
206
144
|
});
|
|
145
|
+
export const companyDetailsSchema = z
|
|
146
|
+
.object({
|
|
147
|
+
company_role: z.string().min(1, 'Company role is required').openapi({
|
|
148
|
+
description: 'Company role',
|
|
149
|
+
example: 'exhibitor'
|
|
150
|
+
}),
|
|
151
|
+
hall: z.string().min(1, 'Hall is required').openapi({
|
|
152
|
+
description: 'Hall location',
|
|
153
|
+
example: 'Hall 1'
|
|
154
|
+
}),
|
|
155
|
+
stand_number: z.string().min(1, 'Stand number is required').openapi({
|
|
156
|
+
description: 'Stand number',
|
|
157
|
+
example: 'A-123'
|
|
158
|
+
}),
|
|
159
|
+
company_name: z.string().min(1, 'Company name is required').openapi({
|
|
160
|
+
description: 'Company name',
|
|
161
|
+
example: 'Acme Corp'
|
|
162
|
+
}),
|
|
163
|
+
business: z.string().min(1, 'Business is required').openapi({
|
|
164
|
+
description: 'Type of business',
|
|
165
|
+
example: 'Technology'
|
|
166
|
+
}),
|
|
167
|
+
departure_city: z.string().min(1, 'Departure city is required').openapi({
|
|
168
|
+
description: 'City of departure',
|
|
169
|
+
example: 'Paris'
|
|
170
|
+
}),
|
|
171
|
+
contact_name: z.string().min(1, 'Contact name is required').openapi({
|
|
172
|
+
description: 'Contact person name',
|
|
173
|
+
example: 'John Doe'
|
|
174
|
+
}),
|
|
175
|
+
email: z.email('Valid email is required').openapi({
|
|
176
|
+
description: 'Contact email',
|
|
177
|
+
example: 'john.doe@acme.com'
|
|
178
|
+
}),
|
|
179
|
+
phone: z.string().min(1, 'Phone is required').openapi({
|
|
180
|
+
description: 'Contact phone number',
|
|
181
|
+
example: '+33 1 23 45 67 89'
|
|
182
|
+
}),
|
|
183
|
+
driver_name: z.string().min(1, 'Driver name is required').openapi({
|
|
184
|
+
description: 'Driver name',
|
|
185
|
+
example: 'Jean Martin'
|
|
186
|
+
}),
|
|
187
|
+
driver_phone: z.string().min(1, 'Driver phone is required').openapi({
|
|
188
|
+
description: 'Driver phone number',
|
|
189
|
+
example: '+33 6 12 34 56 78'
|
|
190
|
+
}),
|
|
191
|
+
transport_company: z.string().min(1, 'Transport company is required').openapi({
|
|
192
|
+
description: 'Transport company name',
|
|
193
|
+
example: 'Fast Transport Ltd'
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
.openapi('CompanyDetails');
|
|
197
|
+
export const vehicleDetailsSchema = z
|
|
198
|
+
.object({
|
|
199
|
+
vehicle_type: z.string().min(1, 'Vehicle type is required').openapi({
|
|
200
|
+
description: 'Type of vehicle',
|
|
201
|
+
example: 'Truck'
|
|
202
|
+
}),
|
|
203
|
+
unloading_method: z.string().min(1, 'Unloading method is required').openapi({
|
|
204
|
+
description: 'Method of unloading',
|
|
205
|
+
example: 'Manual'
|
|
206
|
+
}),
|
|
207
|
+
license_plate: z.string().min(1, 'License plate is required').openapi({
|
|
208
|
+
description: 'Vehicle license plate',
|
|
209
|
+
example: 'AB-123-CD'
|
|
210
|
+
}),
|
|
211
|
+
trailer_registration: z.string().optional().openapi({
|
|
212
|
+
description: 'Trailer registration number',
|
|
213
|
+
example: 'TR-456-EF'
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
.openapi('VehicleDetails');
|
|
207
217
|
export const createBookingBodySchema = z
|
|
208
218
|
.object({
|
|
209
|
-
|
|
219
|
+
// Event & Basic Info
|
|
220
|
+
event_id: z
|
|
210
221
|
.number()
|
|
211
222
|
.int()
|
|
212
223
|
.positive({
|
|
213
|
-
message: '
|
|
224
|
+
message: 'Event ID must be a positive integer'
|
|
214
225
|
})
|
|
215
226
|
.openapi({
|
|
216
|
-
description: 'ID of the
|
|
217
|
-
example:
|
|
227
|
+
description: 'ID of the event to create the booking for',
|
|
228
|
+
example: 1
|
|
218
229
|
}),
|
|
219
|
-
|
|
220
|
-
.
|
|
221
|
-
.
|
|
222
|
-
.positive({
|
|
223
|
-
message: 'Phase slot ID must be a positive integer'
|
|
224
|
-
})
|
|
230
|
+
request_type: z
|
|
231
|
+
.enum([PhaseSlotScheduleType.ASSEMBLY, PhaseSlotScheduleType.DISMANTLING])
|
|
232
|
+
.default(PhaseSlotScheduleType.ASSEMBLY)
|
|
225
233
|
.openapi({
|
|
226
|
-
description: '
|
|
227
|
-
example:
|
|
234
|
+
description: 'Type of request (assembly or dismantling)',
|
|
235
|
+
example: PhaseSlotScheduleType.ASSEMBLY
|
|
236
|
+
}),
|
|
237
|
+
// Time slot selection
|
|
238
|
+
selected_date: z.string().min(1, 'Date is required').openapi({
|
|
239
|
+
description: 'Selected date (YYYY-MM-DD)',
|
|
240
|
+
example: '2025-12-15'
|
|
241
|
+
}),
|
|
242
|
+
selected_time: z.string().min(1, 'Time is required').openapi({
|
|
243
|
+
description: 'Selected time slot (HH:MM)',
|
|
244
|
+
example: '08:00'
|
|
245
|
+
}),
|
|
246
|
+
// Company details
|
|
247
|
+
company: companyDetailsSchema.openapi({
|
|
248
|
+
description: 'Company details including stand, contact, and driver info'
|
|
249
|
+
}),
|
|
250
|
+
// Vehicle details
|
|
251
|
+
vehicle: vehicleDetailsSchema.openapi({
|
|
252
|
+
description: 'Vehicle details'
|
|
228
253
|
})
|
|
229
254
|
})
|
|
230
255
|
.openapi('CreateBookingBody');
|
|
@@ -234,22 +259,32 @@ export const createBookingDataSchema = z
|
|
|
234
259
|
description: 'ID of the created booking',
|
|
235
260
|
example: 789
|
|
236
261
|
}),
|
|
237
|
-
|
|
238
|
-
description: 'ID of the
|
|
239
|
-
example: 123
|
|
240
|
-
}),
|
|
241
|
-
phase_slot_id: z.number().openapi({
|
|
242
|
-
description: 'ID of the booked phase slot',
|
|
262
|
+
phase_slot_schedule_id: z.number().openapi({
|
|
263
|
+
description: 'ID of the phase slot schedule',
|
|
243
264
|
example: 456
|
|
244
265
|
}),
|
|
245
|
-
slot_number: z.number().openapi({
|
|
246
|
-
description: 'Slot number',
|
|
247
|
-
example: 42
|
|
248
|
-
}),
|
|
249
266
|
status: z.enum(BookingStatus).openapi({
|
|
250
267
|
description: 'Booking status',
|
|
251
268
|
example: BookingStatus.BOOKED
|
|
252
269
|
}),
|
|
270
|
+
booking_date: z.string().openapi({
|
|
271
|
+
description: 'Booking date',
|
|
272
|
+
example: '2025-12-15'
|
|
273
|
+
}),
|
|
274
|
+
start_time: z.string().openapi({
|
|
275
|
+
description: 'Start time',
|
|
276
|
+
example: '08:00'
|
|
277
|
+
}),
|
|
278
|
+
end_time: z.string().openapi({
|
|
279
|
+
description: 'End time',
|
|
280
|
+
example: '08:30'
|
|
281
|
+
}),
|
|
282
|
+
company: companyDetailsSchema.openapi({
|
|
283
|
+
description: 'Company details including stand, contact, and driver info'
|
|
284
|
+
}),
|
|
285
|
+
vehicle: vehicleDetailsSchema.openapi({
|
|
286
|
+
description: 'Vehicle details'
|
|
287
|
+
}),
|
|
253
288
|
created_at: z.string().openapi({
|
|
254
289
|
description: 'Timestamp when booking was created',
|
|
255
290
|
example: '2025-12-05T10:30:00.000Z'
|
|
@@ -271,31 +306,6 @@ export const eventBookingsDataSchema = z
|
|
|
271
306
|
})
|
|
272
307
|
.openapi('EventBookingsData');
|
|
273
308
|
export const eventBookingsResponseSchema = createSuccessResponseSchema(eventBookingsDataSchema, 'EventBookingsResponse', 'Event bookings data with phase slot details');
|
|
274
|
-
export const cancelPhaseSlotDataSchema = z
|
|
275
|
-
.object({
|
|
276
|
-
slot_id: z.number().openapi({
|
|
277
|
-
description: 'ID of the cancelled slot',
|
|
278
|
-
example: 1
|
|
279
|
-
}),
|
|
280
|
-
status: z.enum(SlotStatus).openapi({
|
|
281
|
-
description: 'New status of the slot',
|
|
282
|
-
example: SlotStatus.AVAILABLE
|
|
283
|
-
}),
|
|
284
|
-
cancelled_at: z.string().openapi({
|
|
285
|
-
description: 'Timestamp when the slot was cancelled',
|
|
286
|
-
example: '2025-12-03T20:47:00.000Z'
|
|
287
|
-
}),
|
|
288
|
-
cancelled_by: z.string().nullable().openapi({
|
|
289
|
-
description: 'ID of the user who cancelled the slot',
|
|
290
|
-
example: null
|
|
291
|
-
}),
|
|
292
|
-
reason: z.string().nullable().openapi({
|
|
293
|
-
description: 'Reason for cancellation',
|
|
294
|
-
example: 'Event postponed'
|
|
295
|
-
})
|
|
296
|
-
})
|
|
297
|
-
.openapi('CancelPhaseSlotData');
|
|
298
|
-
export const cancelPhaseSlotResponseSchema = createMessageDataResponseSchema(cancelPhaseSlotDataSchema, 'CancelPhaseSlotResponse', 'Phase slot cancelled successfully', 'Details of the cancelled phase slot');
|
|
299
309
|
export const closeEventDataSchema = z
|
|
300
310
|
.object({
|
|
301
311
|
event_id: z.number().openapi({
|
|
@@ -342,7 +352,6 @@ export const confirmBookingResponseSchema = z.object({
|
|
|
342
352
|
booking_id: z.number(),
|
|
343
353
|
booking_status: z.enum(BookingStatus),
|
|
344
354
|
slot_id: z.number(),
|
|
345
|
-
slot_status: z.enum(SlotStatus),
|
|
346
355
|
confirmed_at: z.string(),
|
|
347
356
|
confirmed_by: z.string().nullable()
|
|
348
357
|
})
|
|
@@ -376,10 +385,6 @@ export const refuseBookingDataSchema = z
|
|
|
376
385
|
description: 'ID of the associated phase slot',
|
|
377
386
|
example: 10
|
|
378
387
|
}),
|
|
379
|
-
slot_status: z.enum([SlotStatus.AVAILABLE]).openapi({
|
|
380
|
-
description: 'New status of the phase slot',
|
|
381
|
-
example: SlotStatus.AVAILABLE
|
|
382
|
-
}),
|
|
383
388
|
refused_at: z.string().openapi({
|
|
384
389
|
description: 'ISO 8601 timestamp when the booking was refused',
|
|
385
390
|
example: '2025-12-08T10:30:00.000Z'
|
|
@@ -409,44 +414,15 @@ export const createPhaseSlotsBodySchema = z
|
|
|
409
414
|
}),
|
|
410
415
|
slots: z
|
|
411
416
|
.array(z.object({
|
|
412
|
-
slot_number: z
|
|
413
|
-
.number()
|
|
414
|
-
.int()
|
|
415
|
-
.positive({
|
|
416
|
-
message: 'Slot number must be a positive integer'
|
|
417
|
-
})
|
|
418
|
-
.openapi({
|
|
419
|
-
description: 'Unique slot number within the event',
|
|
420
|
-
example: 42
|
|
421
|
-
}),
|
|
422
|
-
vehicle_type_id: z
|
|
423
|
-
.number()
|
|
424
|
-
.int()
|
|
425
|
-
.positive({
|
|
426
|
-
message: 'Vehicle type ID must be a positive integer'
|
|
427
|
-
})
|
|
428
|
-
.nullable()
|
|
429
|
-
.optional()
|
|
430
|
-
.openapi({
|
|
431
|
-
description: 'Optional vehicle type ID for the slot',
|
|
432
|
-
example: 1
|
|
433
|
-
}),
|
|
434
417
|
company_role: z.string().min(1).nullable().optional().openapi({
|
|
435
418
|
description: 'Optional company role for the slot',
|
|
436
419
|
example: 'buyer'
|
|
437
|
-
}),
|
|
438
|
-
status: z.enum(SlotStatus).optional().openapi({
|
|
439
|
-
description: 'Initial status of the slot (defaults to available)',
|
|
440
|
-
example: SlotStatus.AVAILABLE
|
|
441
420
|
})
|
|
442
421
|
}))
|
|
443
422
|
.min(1, 'At least one slot must be provided')
|
|
444
423
|
.openapi({
|
|
445
424
|
description: 'Array of slots to create',
|
|
446
|
-
example: [
|
|
447
|
-
{ slot_number: 42, vehicle_type_id: 1, company_role: 'buyer' },
|
|
448
|
-
{ slot_number: 43, vehicle_type_id: 2, company_role: 'seller' }
|
|
449
|
-
]
|
|
425
|
+
example: [{ company_role: 'buyer' }, { company_role: 'seller' }]
|
|
450
426
|
})
|
|
451
427
|
})
|
|
452
428
|
.openapi('CreatePhaseSlotsBody');
|
|
@@ -460,22 +436,10 @@ export const createPhaseSlotDataSchema = z
|
|
|
460
436
|
description: 'ID of the event',
|
|
461
437
|
example: 1
|
|
462
438
|
}),
|
|
463
|
-
slot_number: z.number().openapi({
|
|
464
|
-
description: 'Slot number',
|
|
465
|
-
example: 42
|
|
466
|
-
}),
|
|
467
|
-
vehicle_type_id: z.number().nullable().openapi({
|
|
468
|
-
description: 'Vehicle type ID',
|
|
469
|
-
example: 1
|
|
470
|
-
}),
|
|
471
439
|
company_role: z.string().nullable().openapi({
|
|
472
440
|
description: 'Company role',
|
|
473
441
|
example: 'buyer'
|
|
474
442
|
}),
|
|
475
|
-
status: z.enum(SlotStatus).openapi({
|
|
476
|
-
description: 'Slot status',
|
|
477
|
-
example: SlotStatus.AVAILABLE
|
|
478
|
-
}),
|
|
479
443
|
is_active: z.boolean().openapi({
|
|
480
444
|
description: 'Whether the slot is active',
|
|
481
445
|
example: true,
|
|
@@ -507,13 +471,13 @@ export const createPhaseSlotsDataSchema = z
|
|
|
507
471
|
}),
|
|
508
472
|
failed_slots: z
|
|
509
473
|
.array(z.object({
|
|
510
|
-
|
|
511
|
-
description: '
|
|
512
|
-
example:
|
|
474
|
+
index: z.number().openapi({
|
|
475
|
+
description: 'Index of the slot in the request that failed to create',
|
|
476
|
+
example: 0
|
|
513
477
|
}),
|
|
514
478
|
error: z.string().openapi({
|
|
515
479
|
description: 'Error message explaining why the slot creation failed',
|
|
516
|
-
example: '
|
|
480
|
+
example: 'Failed to create slot'
|
|
517
481
|
})
|
|
518
482
|
}))
|
|
519
483
|
.openapi({
|
|
@@ -541,36 +505,9 @@ export const updatePhaseSlotParamsSchema = z
|
|
|
541
505
|
.openapi('UpdatePhaseSlotParams');
|
|
542
506
|
export const updatePhaseSlotBodySchema = z
|
|
543
507
|
.object({
|
|
544
|
-
slot_number: z
|
|
545
|
-
.number()
|
|
546
|
-
.int()
|
|
547
|
-
.positive({
|
|
548
|
-
message: 'Slot number must be a positive integer'
|
|
549
|
-
})
|
|
550
|
-
.optional()
|
|
551
|
-
.openapi({
|
|
552
|
-
description: 'New slot number (must be unique within the event)',
|
|
553
|
-
example: 43
|
|
554
|
-
}),
|
|
555
|
-
vehicle_type_id: z
|
|
556
|
-
.number()
|
|
557
|
-
.int()
|
|
558
|
-
.positive({
|
|
559
|
-
message: 'Vehicle type ID must be a positive integer'
|
|
560
|
-
})
|
|
561
|
-
.nullable()
|
|
562
|
-
.optional()
|
|
563
|
-
.openapi({
|
|
564
|
-
description: 'New vehicle type ID for the slot',
|
|
565
|
-
example: 2
|
|
566
|
-
}),
|
|
567
508
|
company_role: z.string().min(1).nullable().optional().openapi({
|
|
568
509
|
description: 'New company role for the slot',
|
|
569
510
|
example: 'seller'
|
|
570
|
-
}),
|
|
571
|
-
status: z.enum(SlotStatus).optional().openapi({
|
|
572
|
-
description: 'New status for the slot',
|
|
573
|
-
example: SlotStatus.RESERVED
|
|
574
511
|
})
|
|
575
512
|
})
|
|
576
513
|
.refine(data => Object.keys(data).length > 0, {
|
|
@@ -587,22 +524,10 @@ export const updatePhaseSlotDataSchema = z
|
|
|
587
524
|
description: 'ID of the event',
|
|
588
525
|
example: 1
|
|
589
526
|
}),
|
|
590
|
-
slot_number: z.number().openapi({
|
|
591
|
-
description: 'Updated slot number',
|
|
592
|
-
example: 43
|
|
593
|
-
}),
|
|
594
|
-
vehicle_type_id: z.number().nullable().openapi({
|
|
595
|
-
description: 'Updated vehicle type ID',
|
|
596
|
-
example: 2
|
|
597
|
-
}),
|
|
598
527
|
company_role: z.string().nullable().openapi({
|
|
599
528
|
description: 'Updated company role',
|
|
600
529
|
example: 'seller'
|
|
601
530
|
}),
|
|
602
|
-
status: z.enum(SlotStatus).openapi({
|
|
603
|
-
description: 'Updated slot status',
|
|
604
|
-
example: SlotStatus.RESERVED
|
|
605
|
-
}),
|
|
606
531
|
is_active: z.boolean().openapi({
|
|
607
532
|
description: 'Whether the slot is active',
|
|
608
533
|
example: true
|
|
@@ -619,91 +544,29 @@ export const updatePhaseSlotDataSchema = z
|
|
|
619
544
|
.openapi('UpdatePhaseSlotData');
|
|
620
545
|
export const updatePhaseSlotResponseSchema = createMessageDataResponseSchema(updatePhaseSlotDataSchema, 'UpdatePhaseSlotResponse', 'Phase slot updated successfully', 'Details of the updated phase slot');
|
|
621
546
|
// ------------------------------
|
|
622
|
-
// Phase Slot
|
|
547
|
+
// Phase Slot Schedules Schemas
|
|
623
548
|
// ------------------------------
|
|
624
|
-
export const
|
|
549
|
+
export const upsertPhaseSlotScheduleItemSchema = z
|
|
625
550
|
.object({
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
.openapi({
|
|
630
|
-
description: 'Date of the assembly (YYYY-MM-DD format)',
|
|
631
|
-
example: '2025-12-15'
|
|
632
|
-
}),
|
|
633
|
-
start_time: z
|
|
634
|
-
.string()
|
|
635
|
-
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
636
|
-
.optional()
|
|
637
|
-
.openapi({
|
|
638
|
-
description: 'Start time of the assembly (HH:MM format). Defaults to 06:00',
|
|
639
|
-
example: '06:00'
|
|
640
|
-
}),
|
|
641
|
-
end_time: z
|
|
642
|
-
.string()
|
|
643
|
-
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
644
|
-
.optional()
|
|
645
|
-
.openapi({
|
|
646
|
-
description: 'End time of the assembly (HH:MM format). Defaults to 09:00',
|
|
647
|
-
example: '09:00'
|
|
648
|
-
}),
|
|
649
|
-
duration: z.number().positive().optional().openapi({
|
|
650
|
-
description: 'Duration of the assembly in minutes. Defaults to 60',
|
|
651
|
-
example: 180
|
|
551
|
+
id: z.number().int().positive().optional().openapi({
|
|
552
|
+
description: 'Unique identifier for existing schedule (required for updates)',
|
|
553
|
+
example: 1
|
|
652
554
|
}),
|
|
653
555
|
phase_slot_id: z.number().int().positive().openapi({
|
|
654
556
|
description: 'ID of the associated phase slot',
|
|
655
557
|
example: 101
|
|
656
|
-
})
|
|
657
|
-
})
|
|
658
|
-
.openapi('UpsertPhaseSlotAssembly');
|
|
659
|
-
export const upsertPhaseSlotDismantlingSchema = z
|
|
660
|
-
.object({
|
|
558
|
+
}),
|
|
661
559
|
date: z
|
|
662
560
|
.string()
|
|
663
561
|
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format')
|
|
664
562
|
.openapi({
|
|
665
|
-
description: 'Date of the
|
|
563
|
+
description: 'Date of the schedule (YYYY-MM-DD format)',
|
|
666
564
|
example: '2025-12-15'
|
|
667
565
|
}),
|
|
668
566
|
start_time: z
|
|
669
567
|
.string()
|
|
670
568
|
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
671
|
-
.
|
|
672
|
-
.openapi({
|
|
673
|
-
description: 'Start time of the dismantling (HH:MM format). Defaults to 06:00',
|
|
674
|
-
example: '06:00'
|
|
675
|
-
}),
|
|
676
|
-
end_time: z
|
|
677
|
-
.string()
|
|
678
|
-
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
679
|
-
.optional()
|
|
680
|
-
.openapi({
|
|
681
|
-
description: 'End time of the dismantling (HH:MM format). Defaults to 09:00',
|
|
682
|
-
example: '09:00'
|
|
683
|
-
}),
|
|
684
|
-
duration: z.number().positive().optional().openapi({
|
|
685
|
-
description: 'Duration of the dismantling in minutes. Defaults to 60',
|
|
686
|
-
example: 180
|
|
687
|
-
}),
|
|
688
|
-
phase_slot_id: z.number().int().positive().openapi({
|
|
689
|
-
description: 'ID of the associated phase slot',
|
|
690
|
-
example: 101
|
|
691
|
-
})
|
|
692
|
-
})
|
|
693
|
-
.openapi('UpsertPhaseSlotDismantling');
|
|
694
|
-
// ------------------------------
|
|
695
|
-
// Combined Phase Slot Schedules Schemas (Assembly + Dismantling)
|
|
696
|
-
// ------------------------------
|
|
697
|
-
export const phaseSlotScheduleOperationSchema = z
|
|
698
|
-
.object({
|
|
699
|
-
id: z.number().int().positive().optional().openapi({
|
|
700
|
-
description: 'Unique identifier for existing records (required for updates and deletes)',
|
|
701
|
-
example: 1
|
|
702
|
-
}),
|
|
703
|
-
start_time: z
|
|
704
|
-
.string()
|
|
705
|
-
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
706
|
-
.optional()
|
|
569
|
+
.default('06:00')
|
|
707
570
|
.openapi({
|
|
708
571
|
description: 'Start time (HH:MM format)',
|
|
709
572
|
example: '06:00'
|
|
@@ -711,182 +574,183 @@ export const phaseSlotScheduleOperationSchema = z
|
|
|
711
574
|
end_time: z
|
|
712
575
|
.string()
|
|
713
576
|
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
714
|
-
.
|
|
577
|
+
.default('09:00')
|
|
715
578
|
.openapi({
|
|
716
579
|
description: 'End time (HH:MM format)',
|
|
717
580
|
example: '09:00'
|
|
718
581
|
}),
|
|
719
|
-
duration: z.number().positive().
|
|
582
|
+
duration: z.number().positive().default(60).openapi({
|
|
720
583
|
description: 'Duration in minutes',
|
|
721
584
|
example: 180
|
|
722
585
|
}),
|
|
723
|
-
|
|
724
|
-
.
|
|
725
|
-
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format')
|
|
726
|
-
.optional()
|
|
586
|
+
phase_slot_schedule_type: z
|
|
587
|
+
.enum([PhaseSlotScheduleType.ASSEMBLY, PhaseSlotScheduleType.DISMANTLING])
|
|
727
588
|
.openapi({
|
|
728
|
-
description: '
|
|
729
|
-
example:
|
|
730
|
-
}),
|
|
731
|
-
_delete: z.boolean().optional().openapi({
|
|
732
|
-
description: 'Flag to mark this record for deletion. Requires existing id.',
|
|
733
|
-
example: false
|
|
589
|
+
description: 'Type of schedule',
|
|
590
|
+
example: PhaseSlotScheduleType.ASSEMBLY
|
|
734
591
|
})
|
|
735
592
|
})
|
|
736
|
-
.
|
|
737
|
-
|
|
738
|
-
if (data.value._delete === true && !data.value.id) {
|
|
739
|
-
data.issues.push({
|
|
740
|
-
code: 'custom',
|
|
741
|
-
message: 'ID is required when delete is true',
|
|
742
|
-
path: ['id'],
|
|
743
|
-
input: data.value
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
// If delete is false or undefined, date is required
|
|
747
|
-
if ((data.value._delete === false || data.value._delete === undefined) && !data.value.date) {
|
|
748
|
-
data.issues.push({
|
|
749
|
-
code: 'custom',
|
|
750
|
-
message: 'Date is required when delete is false or undefined',
|
|
751
|
-
path: ['date'],
|
|
752
|
-
input: data.value
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
})
|
|
756
|
-
.openapi('PhaseSlotScheduleOperation');
|
|
757
|
-
export const phaseSlotScheduleSchema = z
|
|
593
|
+
.openapi('UpsertPhaseSlotScheduleItem');
|
|
594
|
+
export const deletePhaseSlotScheduleItemSchema = z
|
|
758
595
|
.object({
|
|
759
|
-
|
|
760
|
-
description: 'ID of the
|
|
761
|
-
example:
|
|
762
|
-
}),
|
|
763
|
-
assembly: phaseSlotScheduleOperationSchema.openapi({
|
|
764
|
-
description: 'Assembly operation details with date'
|
|
765
|
-
}),
|
|
766
|
-
dismantling: phaseSlotScheduleOperationSchema.openapi({
|
|
767
|
-
description: 'Dismantling operation details with date'
|
|
596
|
+
id: z.number().int().positive().openapi({
|
|
597
|
+
description: 'ID of the schedule to delete',
|
|
598
|
+
example: 1
|
|
768
599
|
})
|
|
769
600
|
})
|
|
770
|
-
.openapi('
|
|
601
|
+
.openapi('DeletePhaseSlotScheduleItem');
|
|
771
602
|
export const upsertPhaseSlotSchedulesBodySchema = z
|
|
772
603
|
.object({
|
|
773
|
-
|
|
774
|
-
.array(
|
|
775
|
-
.
|
|
604
|
+
upsert: z
|
|
605
|
+
.array(upsertPhaseSlotScheduleItemSchema)
|
|
606
|
+
.optional()
|
|
776
607
|
.openapi({
|
|
777
|
-
description: 'Array of
|
|
608
|
+
description: 'Array of schedules to create or update',
|
|
778
609
|
example: [
|
|
779
610
|
{
|
|
780
611
|
phase_slot_id: 101,
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
},
|
|
787
|
-
dismantling: {
|
|
788
|
-
date: '2025-12-16',
|
|
789
|
-
start_time: '15:00',
|
|
790
|
-
end_time: '18:00',
|
|
791
|
-
duration: 180
|
|
792
|
-
}
|
|
612
|
+
date: '2025-12-15',
|
|
613
|
+
start_time: '06:00',
|
|
614
|
+
end_time: '09:00',
|
|
615
|
+
duration: 180,
|
|
616
|
+
phase_slot_schedule_type: 'assembly'
|
|
793
617
|
},
|
|
794
618
|
{
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
phase_slot_id: 103,
|
|
803
|
-
dismantling: {
|
|
804
|
-
id: 42,
|
|
805
|
-
_delete: true
|
|
806
|
-
}
|
|
619
|
+
id: 5,
|
|
620
|
+
phase_slot_id: 101,
|
|
621
|
+
date: '2025-12-16',
|
|
622
|
+
start_time: '15:00',
|
|
623
|
+
end_time: '18:00',
|
|
624
|
+
duration: 180,
|
|
625
|
+
phase_slot_schedule_type: 'dismantling'
|
|
807
626
|
}
|
|
808
627
|
]
|
|
628
|
+
}),
|
|
629
|
+
delete: z
|
|
630
|
+
.array(deletePhaseSlotScheduleItemSchema)
|
|
631
|
+
.optional()
|
|
632
|
+
.openapi({
|
|
633
|
+
description: 'Array of schedule IDs to delete',
|
|
634
|
+
example: [{ id: 42 }]
|
|
809
635
|
})
|
|
636
|
+
})
|
|
637
|
+
.refine(data => (data.upsert && data.upsert.length > 0) || (data.delete && data.delete.length > 0), {
|
|
638
|
+
message: 'At least one upsert or delete operation is required'
|
|
810
639
|
})
|
|
811
640
|
.openapi('UpsertPhaseSlotSchedulesBody');
|
|
812
641
|
export const upsertPhaseSlotSchedulesDataSchema = z
|
|
813
642
|
.object({
|
|
814
|
-
|
|
815
|
-
description: 'Total number of schedules
|
|
816
|
-
example:
|
|
817
|
-
}),
|
|
818
|
-
total_assemblies_upserted: z.number().int().nonnegative().openapi({
|
|
819
|
-
description: 'Total number of assemblies successfully upserted',
|
|
820
|
-
example: 2
|
|
643
|
+
total_upserted: z.number().int().nonnegative().openapi({
|
|
644
|
+
description: 'Total number of schedules successfully upserted',
|
|
645
|
+
example: 3
|
|
821
646
|
}),
|
|
822
|
-
|
|
823
|
-
description: 'Total number of
|
|
647
|
+
total_deleted: z.number().int().nonnegative().openapi({
|
|
648
|
+
description: 'Total number of schedules successfully deleted',
|
|
824
649
|
example: 1
|
|
825
650
|
}),
|
|
826
|
-
|
|
827
|
-
description: '
|
|
828
|
-
example: 0
|
|
829
|
-
}),
|
|
830
|
-
total_dismantlings_deleted: z.number().int().nonnegative().openapi({
|
|
831
|
-
description: 'Total number of dismantlings successfully deleted',
|
|
832
|
-
example: 0
|
|
833
|
-
}),
|
|
834
|
-
upserted_assemblies: z.array(phaseSlotAssemblySchema).openapi({
|
|
835
|
-
description: 'Array of successfully upserted assemblies'
|
|
836
|
-
}),
|
|
837
|
-
upserted_dismantlings: z.array(phaseSlotDismantlingSchema).openapi({
|
|
838
|
-
description: 'Array of successfully upserted dismantlings'
|
|
839
|
-
}),
|
|
840
|
-
deleted_assemblies: z
|
|
841
|
-
.array(z.object({
|
|
842
|
-
id: z.number().int().positive(),
|
|
843
|
-
phase_slot_id: z.number().int().positive()
|
|
844
|
-
}))
|
|
845
|
-
.openapi({
|
|
846
|
-
description: 'Array of successfully deleted assemblies',
|
|
847
|
-
example: []
|
|
651
|
+
upserted_schedules: z.array(phaseSlotScheduleSchema).openapi({
|
|
652
|
+
description: 'Array of successfully upserted schedules'
|
|
848
653
|
}),
|
|
849
|
-
|
|
654
|
+
deleted_schedules: z
|
|
850
655
|
.array(z.object({
|
|
851
|
-
id: z.number().int().positive()
|
|
852
|
-
phase_slot_id: z.number().int().positive()
|
|
656
|
+
id: z.number().int().positive()
|
|
853
657
|
}))
|
|
854
658
|
.openapi({
|
|
855
|
-
description: 'Array of successfully deleted
|
|
856
|
-
example: []
|
|
659
|
+
description: 'Array of successfully deleted schedule IDs',
|
|
660
|
+
example: [{ id: 42 }]
|
|
857
661
|
}),
|
|
858
662
|
failed_operations: z
|
|
859
663
|
.array(z.object({
|
|
860
|
-
|
|
861
|
-
operation: z.enum(['assembly', 'dismantling']),
|
|
862
|
-
action: z.enum(['upsert', 'delete']),
|
|
664
|
+
operation: z.enum(['upsert', 'delete']),
|
|
863
665
|
error: z.string(),
|
|
864
|
-
data: z.union([
|
|
865
|
-
z.object({
|
|
866
|
-
id: z.number().int().positive().optional(),
|
|
867
|
-
date: z.string().optional(),
|
|
868
|
-
start_time: z.string().optional(),
|
|
869
|
-
end_time: z.string().optional(),
|
|
870
|
-
duration: z.number().positive().optional(),
|
|
871
|
-
_delete: z.boolean().optional()
|
|
872
|
-
}),
|
|
873
|
-
z.object({
|
|
874
|
-
id: z.number().int().positive()
|
|
875
|
-
})
|
|
876
|
-
])
|
|
666
|
+
data: z.union([upsertPhaseSlotScheduleItemSchema, deletePhaseSlotScheduleItemSchema])
|
|
877
667
|
}))
|
|
878
668
|
.openapi({
|
|
879
669
|
description: 'Array of operations that failed to process',
|
|
880
670
|
example: [
|
|
881
671
|
{
|
|
882
|
-
|
|
883
|
-
operation: 'assembly',
|
|
884
|
-
action: 'upsert',
|
|
672
|
+
operation: 'upsert',
|
|
885
673
|
error: 'Phase slot 999 not found or inactive',
|
|
886
|
-
data: {
|
|
674
|
+
data: {
|
|
675
|
+
phase_slot_id: 999,
|
|
676
|
+
date: '2025-12-15',
|
|
677
|
+
start_time: '06:00',
|
|
678
|
+
end_time: '09:00',
|
|
679
|
+
duration: 180,
|
|
680
|
+
phase_slot_schedule_type: 'assembly'
|
|
681
|
+
}
|
|
887
682
|
}
|
|
888
683
|
]
|
|
889
684
|
})
|
|
890
685
|
})
|
|
891
686
|
.openapi('UpsertPhaseSlotSchedulesData');
|
|
892
|
-
export const upsertPhaseSlotSchedulesResponseSchema = createMessageDataResponseSchema(upsertPhaseSlotSchedulesDataSchema, 'UpsertPhaseSlotSchedulesResponse', '
|
|
687
|
+
export const upsertPhaseSlotSchedulesResponseSchema = createMessageDataResponseSchema(upsertPhaseSlotSchedulesDataSchema, 'UpsertPhaseSlotSchedulesResponse', 'Phase slot schedules operation completed', 'Results of the upsert/delete operations');
|
|
688
|
+
// ------------------------------
|
|
689
|
+
// Check Slot Availability schemas
|
|
690
|
+
// ------------------------------
|
|
691
|
+
export const checkSlotAvailabilityQuerySchema = z
|
|
692
|
+
.object({
|
|
693
|
+
schedule_id: z
|
|
694
|
+
.string()
|
|
695
|
+
.min(1)
|
|
696
|
+
.transform(val => parseInt(val, 10))
|
|
697
|
+
.refine(val => !isNaN(val) && val > 0, {
|
|
698
|
+
message: 'Schedule ID must be a positive number'
|
|
699
|
+
})
|
|
700
|
+
.openapi({
|
|
701
|
+
description: 'The ID of the phase slot schedule',
|
|
702
|
+
example: '1'
|
|
703
|
+
}),
|
|
704
|
+
date: z
|
|
705
|
+
.string()
|
|
706
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format')
|
|
707
|
+
.openapi({
|
|
708
|
+
description: 'The date to check availability (YYYY-MM-DD)',
|
|
709
|
+
example: '2025-12-15'
|
|
710
|
+
}),
|
|
711
|
+
start_time: z
|
|
712
|
+
.string()
|
|
713
|
+
.regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
|
|
714
|
+
.openapi({
|
|
715
|
+
description: 'The start time to check availability (HH:MM)',
|
|
716
|
+
example: '08:00'
|
|
717
|
+
})
|
|
718
|
+
})
|
|
719
|
+
.openapi('CheckSlotAvailabilityQuery');
|
|
720
|
+
export const checkSlotAvailabilityDataSchema = z
|
|
721
|
+
.object({
|
|
722
|
+
schedule_id: z.number().openapi({
|
|
723
|
+
description: 'ID of the phase slot schedule',
|
|
724
|
+
example: 1
|
|
725
|
+
}),
|
|
726
|
+
date: z.string().openapi({
|
|
727
|
+
description: 'Date checked',
|
|
728
|
+
example: '2025-12-15'
|
|
729
|
+
}),
|
|
730
|
+
start_time: z.string().openapi({
|
|
731
|
+
description: 'Time slot checked',
|
|
732
|
+
example: '08:00'
|
|
733
|
+
}),
|
|
734
|
+
is_available: z.boolean().openapi({
|
|
735
|
+
description: 'Whether the slot is available for booking',
|
|
736
|
+
example: true
|
|
737
|
+
}),
|
|
738
|
+
max_capacity: z.number().openapi({
|
|
739
|
+
description: 'Maximum booking capacity',
|
|
740
|
+
example: 5
|
|
741
|
+
}),
|
|
742
|
+
current_bookings: z.number().openapi({
|
|
743
|
+
description: 'Current number of total bookings',
|
|
744
|
+
example: 3
|
|
745
|
+
}),
|
|
746
|
+
confirmed_bookings: z.number().openapi({
|
|
747
|
+
description: 'Current number of confirmed bookings',
|
|
748
|
+
example: 1
|
|
749
|
+
}),
|
|
750
|
+
available_capacity: z.number().openapi({
|
|
751
|
+
description: 'Remaining available capacity',
|
|
752
|
+
example: 2
|
|
753
|
+
})
|
|
754
|
+
})
|
|
755
|
+
.openapi('CheckSlotAvailabilityData');
|
|
756
|
+
export const checkSlotAvailabilityResponseSchema = createSuccessResponseSchema(checkSlotAvailabilityDataSchema, 'CheckSlotAvailabilityResponse', 'Slot availability information with capacity details');
|