@htlkg/data 0.0.19 → 0.0.21
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/client/index.d.ts +257 -1
- package/dist/client/index.js +59 -1
- package/dist/client/index.js.map +1 -1
- package/dist/common-DSxswsZ3.d.ts +40 -0
- package/dist/hooks/index.d.ts +162 -10
- package/dist/hooks/index.js +191 -33
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +9 -5
- package/dist/index.js +789 -13
- package/dist/index.js.map +1 -1
- package/dist/mutations/index.d.ts +342 -4
- package/dist/mutations/index.js +486 -0
- package/dist/mutations/index.js.map +1 -1
- package/dist/{productInstances-BA3cNsYc.d.ts → productInstances-BpQv1oLS.d.ts} +2 -40
- package/dist/queries/index.d.ts +113 -2
- package/dist/queries/index.js +192 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/reservations-C0FNm__0.d.ts +154 -0
- package/dist/reservations-CdDfkcZ_.d.ts +172 -0
- package/package.json +14 -13
- package/src/client/index.ts +18 -0
- package/src/client/reservations.ts +336 -0
- package/src/hooks/createDataHook.test.ts +534 -0
- package/src/hooks/createDataHook.ts +20 -13
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useContacts.test.ts +159 -0
- package/src/hooks/useContacts.ts +176 -0
- package/src/hooks/useReservations.ts +145 -0
- package/src/mutations/contacts.test.ts +604 -0
- package/src/mutations/contacts.ts +554 -0
- package/src/mutations/index.ts +32 -0
- package/src/mutations/productInstances/productInstances.test.ts +3 -3
- package/src/mutations/reservations.test.ts +459 -0
- package/src/mutations/reservations.ts +452 -0
- package/src/queries/contacts.test.ts +505 -0
- package/src/queries/contacts.ts +237 -0
- package/src/queries/index.ts +21 -0
- package/src/queries/reservations.test.ts +374 -0
- package/src/queries/reservations.ts +247 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reservation Mutation Functions
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe mutation functions for creating, updating, and deleting reservations.
|
|
5
|
+
* Includes date validation and status transition rules.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
checkRestoreEligibility,
|
|
10
|
+
DEFAULT_SOFT_DELETE_RETENTION_DAYS,
|
|
11
|
+
} from "../queries/systemSettings";
|
|
12
|
+
import type { CreateAuditFields, UpdateWithSoftDeleteFields } from "./common";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Reservation status type
|
|
16
|
+
*/
|
|
17
|
+
export type ReservationStatus = "confirmed" | "checked_in" | "checked_out" | "cancelled" | "no_show";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Valid status transitions for reservations
|
|
21
|
+
* Maps current status -> allowed next statuses
|
|
22
|
+
*/
|
|
23
|
+
const STATUS_TRANSITIONS: Record<ReservationStatus, ReservationStatus[]> = {
|
|
24
|
+
confirmed: ["checked_in", "cancelled", "no_show"],
|
|
25
|
+
checked_in: ["checked_out", "cancelled"],
|
|
26
|
+
checked_out: [], // Terminal state - no transitions allowed
|
|
27
|
+
cancelled: [], // Terminal state - no transitions allowed
|
|
28
|
+
no_show: [], // Terminal state - no transitions allowed
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validation error class for reservation operations
|
|
33
|
+
*/
|
|
34
|
+
export class ReservationValidationError extends Error {
|
|
35
|
+
constructor(message: string) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "ReservationValidationError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Validate check-in and check-out dates
|
|
43
|
+
* @throws {ReservationValidationError} if dates are invalid
|
|
44
|
+
*/
|
|
45
|
+
function validateDates(checkIn: string, checkOut: string): void {
|
|
46
|
+
const checkInDate = new Date(checkIn);
|
|
47
|
+
const checkOutDate = new Date(checkOut);
|
|
48
|
+
|
|
49
|
+
// Check if dates are valid
|
|
50
|
+
if (isNaN(checkInDate.getTime())) {
|
|
51
|
+
throw new ReservationValidationError("Invalid check-in date");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isNaN(checkOutDate.getTime())) {
|
|
55
|
+
throw new ReservationValidationError("Invalid check-out date");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check-out must be after check-in
|
|
59
|
+
if (checkOutDate <= checkInDate) {
|
|
60
|
+
throw new ReservationValidationError(
|
|
61
|
+
"Check-out date must be after check-in date"
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Calculate minimum stay (at least a few hours)
|
|
66
|
+
const minStayHours = 4;
|
|
67
|
+
const stayDuration = checkOutDate.getTime() - checkInDate.getTime();
|
|
68
|
+
const hoursDiff = stayDuration / (1000 * 60 * 60);
|
|
69
|
+
|
|
70
|
+
if (hoursDiff < minStayHours) {
|
|
71
|
+
throw new ReservationValidationError(
|
|
72
|
+
`Minimum stay is ${minStayHours} hours`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validate status transition
|
|
79
|
+
* @throws {ReservationValidationError} if transition is not allowed
|
|
80
|
+
*/
|
|
81
|
+
function validateStatusTransition(
|
|
82
|
+
currentStatus: ReservationStatus,
|
|
83
|
+
newStatus: ReservationStatus
|
|
84
|
+
): void {
|
|
85
|
+
const allowedTransitions = STATUS_TRANSITIONS[currentStatus];
|
|
86
|
+
|
|
87
|
+
if (!allowedTransitions.includes(newStatus)) {
|
|
88
|
+
throw new ReservationValidationError(
|
|
89
|
+
`Invalid status transition from '${currentStatus}' to '${newStatus}'. ` +
|
|
90
|
+
`Allowed transitions: ${allowedTransitions.length > 0 ? allowedTransitions.join(", ") : "none (terminal state)"}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Input type for creating a reservation
|
|
97
|
+
*/
|
|
98
|
+
export interface CreateReservationInput extends CreateAuditFields {
|
|
99
|
+
brandId: string;
|
|
100
|
+
visitId: string;
|
|
101
|
+
confirmationCode: string;
|
|
102
|
+
checkIn: string;
|
|
103
|
+
checkOut: string;
|
|
104
|
+
status?: "confirmed" | "checked_in" | "checked_out" | "cancelled" | "no_show";
|
|
105
|
+
source?: string;
|
|
106
|
+
channel?: string;
|
|
107
|
+
roomType?: string;
|
|
108
|
+
room?: string;
|
|
109
|
+
totalAmount?: number;
|
|
110
|
+
currency?: string;
|
|
111
|
+
nights?: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Input type for updating a reservation
|
|
116
|
+
*/
|
|
117
|
+
export interface UpdateReservationInput extends UpdateWithSoftDeleteFields {
|
|
118
|
+
id: string;
|
|
119
|
+
brandId?: string;
|
|
120
|
+
visitId?: string;
|
|
121
|
+
confirmationCode?: string;
|
|
122
|
+
checkIn?: string;
|
|
123
|
+
checkOut?: string;
|
|
124
|
+
status?: "confirmed" | "checked_in" | "checked_out" | "cancelled" | "no_show";
|
|
125
|
+
source?: string;
|
|
126
|
+
channel?: string;
|
|
127
|
+
roomType?: string;
|
|
128
|
+
room?: string;
|
|
129
|
+
totalAmount?: number;
|
|
130
|
+
currency?: string;
|
|
131
|
+
nights?: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Create a new reservation with date validation
|
|
136
|
+
*
|
|
137
|
+
* @throws {ReservationValidationError} if dates are invalid
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* import { createReservation } from '@htlkg/data/mutations';
|
|
142
|
+
* import { generateClient } from '@htlkg/data/client';
|
|
143
|
+
*
|
|
144
|
+
* const client = generateClient<Schema>();
|
|
145
|
+
* const reservation = await createReservation(client, {
|
|
146
|
+
* brandId: 'brand-123',
|
|
147
|
+
* visitId: 'visit-456',
|
|
148
|
+
* confirmationCode: 'ABC123',
|
|
149
|
+
* checkIn: '2024-01-01',
|
|
150
|
+
* checkOut: '2024-01-05',
|
|
151
|
+
* status: 'confirmed'
|
|
152
|
+
* });
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export async function createReservation<TClient = any>(
|
|
156
|
+
client: TClient,
|
|
157
|
+
input: CreateReservationInput,
|
|
158
|
+
): Promise<any | null> {
|
|
159
|
+
try {
|
|
160
|
+
// Validate dates before creating
|
|
161
|
+
validateDates(input.checkIn, input.checkOut);
|
|
162
|
+
|
|
163
|
+
// Calculate nights if not provided
|
|
164
|
+
if (!input.nights) {
|
|
165
|
+
const checkInDate = new Date(input.checkIn);
|
|
166
|
+
const checkOutDate = new Date(input.checkOut);
|
|
167
|
+
const diffTime = checkOutDate.getTime() - checkInDate.getTime();
|
|
168
|
+
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
169
|
+
input.nights = diffDays;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const { data, errors } = await (client as any).models.Reservation.create(input);
|
|
173
|
+
|
|
174
|
+
if (errors) {
|
|
175
|
+
console.error("[createReservation] GraphQL errors:", errors);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return data;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (error instanceof ReservationValidationError) {
|
|
182
|
+
console.error("[createReservation] Validation error:", error.message);
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
console.error("[createReservation] Error creating reservation:", error);
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Update an existing reservation with validation
|
|
192
|
+
*
|
|
193
|
+
* @throws {ReservationValidationError} if dates or status transition is invalid
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* import { updateReservation } from '@htlkg/data/mutations';
|
|
198
|
+
* import { generateClient } from '@htlkg/data/client';
|
|
199
|
+
*
|
|
200
|
+
* const client = generateClient<Schema>();
|
|
201
|
+
* const reservation = await updateReservation(client, {
|
|
202
|
+
* id: 'reservation-123',
|
|
203
|
+
* status: 'checked_in',
|
|
204
|
+
* room: '201'
|
|
205
|
+
* });
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
export async function updateReservation<TClient = any>(
|
|
209
|
+
client: TClient,
|
|
210
|
+
input: UpdateReservationInput,
|
|
211
|
+
): Promise<any | null> {
|
|
212
|
+
try {
|
|
213
|
+
// If both dates are being updated, validate them
|
|
214
|
+
if (input.checkIn && input.checkOut) {
|
|
215
|
+
validateDates(input.checkIn, input.checkOut);
|
|
216
|
+
|
|
217
|
+
// Recalculate nights if dates changed
|
|
218
|
+
const checkInDate = new Date(input.checkIn);
|
|
219
|
+
const checkOutDate = new Date(input.checkOut);
|
|
220
|
+
const diffTime = checkOutDate.getTime() - checkInDate.getTime();
|
|
221
|
+
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
222
|
+
input.nights = diffDays;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// If status is being updated, validate the transition
|
|
226
|
+
if (input.status) {
|
|
227
|
+
// Get current reservation to check current status
|
|
228
|
+
const { data: currentReservation, errors: getErrors } = await (
|
|
229
|
+
client as any
|
|
230
|
+
).models.Reservation.get({ id: input.id });
|
|
231
|
+
|
|
232
|
+
if (getErrors || !currentReservation) {
|
|
233
|
+
console.error("[updateReservation] Error fetching current reservation:", getErrors);
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const currentStatus = currentReservation.status as ReservationStatus;
|
|
238
|
+
validateStatusTransition(currentStatus, input.status as ReservationStatus);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const { data, errors } = await (client as any).models.Reservation.update(input);
|
|
242
|
+
|
|
243
|
+
if (errors) {
|
|
244
|
+
console.error("[updateReservation] GraphQL errors:", errors);
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return data;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error instanceof ReservationValidationError) {
|
|
251
|
+
console.error("[updateReservation] Validation error:", error.message);
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
console.error("[updateReservation] Error updating reservation:", error);
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Soft delete a reservation (sets deletedAt/deletedBy instead of removing)
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* import { softDeleteReservation } from '@htlkg/data/mutations';
|
|
265
|
+
* import { generateClient } from '@htlkg/data/client';
|
|
266
|
+
*
|
|
267
|
+
* const client = generateClient<Schema>();
|
|
268
|
+
* await softDeleteReservation(client, 'reservation-123', 'admin@example.com');
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
export async function softDeleteReservation<TClient = any>(
|
|
272
|
+
client: TClient,
|
|
273
|
+
id: string,
|
|
274
|
+
deletedBy: string,
|
|
275
|
+
): Promise<boolean> {
|
|
276
|
+
try {
|
|
277
|
+
const { errors } = await (client as any).models.Reservation.update({
|
|
278
|
+
id,
|
|
279
|
+
deletedAt: new Date().toISOString(),
|
|
280
|
+
deletedBy,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
if (errors) {
|
|
284
|
+
console.error("[softDeleteReservation] GraphQL errors:", errors);
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return true;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.error("[softDeleteReservation] Error soft-deleting reservation:", error);
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Restore a soft-deleted reservation
|
|
297
|
+
* Checks retention period before allowing restoration
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* ```typescript
|
|
301
|
+
* import { restoreReservation } from '@htlkg/data/mutations';
|
|
302
|
+
* import { generateClient } from '@htlkg/data/client';
|
|
303
|
+
*
|
|
304
|
+
* const client = generateClient<Schema>();
|
|
305
|
+
* await restoreReservation(client, 'reservation-123');
|
|
306
|
+
* // Or with custom retention days:
|
|
307
|
+
* await restoreReservation(client, 'reservation-123', 60);
|
|
308
|
+
* ```
|
|
309
|
+
*/
|
|
310
|
+
export async function restoreReservation<TClient = any>(
|
|
311
|
+
client: TClient,
|
|
312
|
+
id: string,
|
|
313
|
+
retentionDays: number = DEFAULT_SOFT_DELETE_RETENTION_DAYS,
|
|
314
|
+
): Promise<{ success: boolean; error?: string }> {
|
|
315
|
+
try {
|
|
316
|
+
// First, get the reservation to check its deletedAt timestamp
|
|
317
|
+
const { data: reservation, errors: getErrors } = await (
|
|
318
|
+
client as any
|
|
319
|
+
).models.Reservation.get({ id });
|
|
320
|
+
|
|
321
|
+
if (getErrors || !reservation) {
|
|
322
|
+
console.error("[restoreReservation] Error fetching reservation:", getErrors);
|
|
323
|
+
return { success: false, error: "Reservation not found" };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Check if restoration is allowed based on retention period
|
|
327
|
+
const eligibility = checkRestoreEligibility(reservation.deletedAt, retentionDays);
|
|
328
|
+
|
|
329
|
+
if (!eligibility.canRestore) {
|
|
330
|
+
const errorMsg = `Cannot restore reservation. Retention period of ${retentionDays} days has expired. Item was deleted ${eligibility.daysExpired} days ago.`;
|
|
331
|
+
console.error("[restoreReservation]", errorMsg);
|
|
332
|
+
return { success: false, error: errorMsg };
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const { errors } = await (client as any).models.Reservation.update({
|
|
336
|
+
id,
|
|
337
|
+
deletedAt: null,
|
|
338
|
+
deletedBy: null,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
if (errors) {
|
|
342
|
+
console.error("[restoreReservation] GraphQL errors:", errors);
|
|
343
|
+
return { success: false, error: "Failed to restore reservation" };
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return { success: true };
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.error("[restoreReservation] Error restoring reservation:", error);
|
|
349
|
+
throw error;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Hard delete a reservation (permanently removes from database)
|
|
355
|
+
* Use with caution - prefer softDeleteReservation for recoverable deletion
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```typescript
|
|
359
|
+
* import { deleteReservation } from '@htlkg/data/mutations';
|
|
360
|
+
* import { generateClient } from '@htlkg/data/client';
|
|
361
|
+
*
|
|
362
|
+
* const client = generateClient<Schema>();
|
|
363
|
+
* await deleteReservation(client, 'reservation-123');
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
export async function deleteReservation<TClient = any>(
|
|
367
|
+
client: TClient,
|
|
368
|
+
id: string,
|
|
369
|
+
): Promise<boolean> {
|
|
370
|
+
try {
|
|
371
|
+
const { errors } = await (client as any).models.Reservation.delete({ id });
|
|
372
|
+
|
|
373
|
+
if (errors) {
|
|
374
|
+
console.error("[deleteReservation] GraphQL errors:", errors);
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return true;
|
|
379
|
+
} catch (error) {
|
|
380
|
+
console.error("[deleteReservation] Error deleting reservation:", error);
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Update reservation status with validation
|
|
387
|
+
*
|
|
388
|
+
* Validates that the status transition is allowed based on current status.
|
|
389
|
+
* Status transition rules:
|
|
390
|
+
* - confirmed → checked_in, cancelled, no_show
|
|
391
|
+
* - checked_in → checked_out, cancelled
|
|
392
|
+
* - checked_out → (terminal state, no transitions)
|
|
393
|
+
* - cancelled → (terminal state, no transitions)
|
|
394
|
+
* - no_show → (terminal state, no transitions)
|
|
395
|
+
*
|
|
396
|
+
* @throws {ReservationValidationError} if status transition is invalid
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```typescript
|
|
400
|
+
* import { updateReservationStatus } from '@htlkg/data/mutations';
|
|
401
|
+
* import { generateClient } from '@htlkg/data/client';
|
|
402
|
+
*
|
|
403
|
+
* const client = generateClient<Schema>();
|
|
404
|
+
* const reservation = await updateReservationStatus(
|
|
405
|
+
* client,
|
|
406
|
+
* 'reservation-123',
|
|
407
|
+
* 'checked_in'
|
|
408
|
+
* );
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
export async function updateReservationStatus<TClient = any>(
|
|
412
|
+
client: TClient,
|
|
413
|
+
id: string,
|
|
414
|
+
newStatus: ReservationStatus,
|
|
415
|
+
): Promise<any | null> {
|
|
416
|
+
try {
|
|
417
|
+
// Get current reservation to check current status
|
|
418
|
+
const { data: currentReservation, errors: getErrors } = await (
|
|
419
|
+
client as any
|
|
420
|
+
).models.Reservation.get({ id });
|
|
421
|
+
|
|
422
|
+
if (getErrors || !currentReservation) {
|
|
423
|
+
console.error("[updateReservationStatus] Error fetching reservation:", getErrors);
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const currentStatus = currentReservation.status as ReservationStatus;
|
|
428
|
+
|
|
429
|
+
// Validate status transition
|
|
430
|
+
validateStatusTransition(currentStatus, newStatus);
|
|
431
|
+
|
|
432
|
+
// Perform the update
|
|
433
|
+
const { data, errors } = await (client as any).models.Reservation.update({
|
|
434
|
+
id,
|
|
435
|
+
status: newStatus,
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
if (errors) {
|
|
439
|
+
console.error("[updateReservationStatus] GraphQL errors:", errors);
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return data;
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (error instanceof ReservationValidationError) {
|
|
446
|
+
console.error("[updateReservationStatus] Validation error:", error.message);
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
console.error("[updateReservationStatus] Error updating status:", error);
|
|
450
|
+
throw error;
|
|
451
|
+
}
|
|
452
|
+
}
|