@voyantjs/hospitality 0.1.0

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.
@@ -0,0 +1,1007 @@
1
+ import { and, asc, desc, eq, gte, ilike, lte, or, sql } from "drizzle-orm";
2
+ import { housekeepingTasks, maintenanceBlocks, mealPlans, ratePlanInventoryOverrides, ratePlanRoomTypes, ratePlans, roomBlocks, roomInventory, roomTypeBedConfigs, roomTypeRates, roomTypes, roomUnitStatusEvents, roomUnits, stayBookingItems, stayCheckpoints, stayDailyRates, stayFolioLines, stayFolios, stayOperations, stayRules, stayServicePosts, } from "./schema.js";
3
+ async function paginate(rowsQuery, countQuery, limit, offset) {
4
+ const [data, countResult] = await Promise.all([rowsQuery, countQuery]);
5
+ return { data, total: countResult[0]?.count ?? 0, limit, offset };
6
+ }
7
+ function toDateOrNull(value) {
8
+ return value ? new Date(value) : null;
9
+ }
10
+ export const hospitalityService = {
11
+ async listRoomTypes(db, query) {
12
+ const conditions = [];
13
+ if (query.propertyId)
14
+ conditions.push(eq(roomTypes.propertyId, query.propertyId));
15
+ if (query.active !== undefined)
16
+ conditions.push(eq(roomTypes.active, query.active));
17
+ if (query.inventoryMode)
18
+ conditions.push(eq(roomTypes.inventoryMode, query.inventoryMode));
19
+ if (query.search) {
20
+ const term = `%${query.search}%`;
21
+ conditions.push(or(ilike(roomTypes.name, term), ilike(roomTypes.code, term)));
22
+ }
23
+ const where = conditions.length ? and(...conditions) : undefined;
24
+ return paginate(db
25
+ .select()
26
+ .from(roomTypes)
27
+ .where(where)
28
+ .limit(query.limit)
29
+ .offset(query.offset)
30
+ .orderBy(asc(roomTypes.sortOrder), asc(roomTypes.name)), db.select({ count: sql `count(*)::int` }).from(roomTypes).where(where), query.limit, query.offset);
31
+ },
32
+ async getRoomTypeById(db, id) {
33
+ const [row] = await db.select().from(roomTypes).where(eq(roomTypes.id, id)).limit(1);
34
+ return row ?? null;
35
+ },
36
+ async createRoomType(db, data) {
37
+ const [row] = await db.insert(roomTypes).values(data).returning();
38
+ return row ?? null;
39
+ },
40
+ async updateRoomType(db, id, data) {
41
+ const [row] = await db
42
+ .update(roomTypes)
43
+ .set({ ...data, updatedAt: new Date() })
44
+ .where(eq(roomTypes.id, id))
45
+ .returning();
46
+ return row ?? null;
47
+ },
48
+ async deleteRoomType(db, id) {
49
+ const [row] = await db
50
+ .delete(roomTypes)
51
+ .where(eq(roomTypes.id, id))
52
+ .returning({ id: roomTypes.id });
53
+ return row ?? null;
54
+ },
55
+ async listRoomTypeBedConfigs(db, query) {
56
+ const conditions = [];
57
+ if (query.roomTypeId)
58
+ conditions.push(eq(roomTypeBedConfigs.roomTypeId, query.roomTypeId));
59
+ if (query.bedType)
60
+ conditions.push(eq(roomTypeBedConfigs.bedType, query.bedType));
61
+ const where = conditions.length ? and(...conditions) : undefined;
62
+ return paginate(db
63
+ .select()
64
+ .from(roomTypeBedConfigs)
65
+ .where(where)
66
+ .limit(query.limit)
67
+ .offset(query.offset)
68
+ .orderBy(desc(roomTypeBedConfigs.isPrimary), asc(roomTypeBedConfigs.createdAt)), db.select({ count: sql `count(*)::int` }).from(roomTypeBedConfigs).where(where), query.limit, query.offset);
69
+ },
70
+ async getRoomTypeBedConfigById(db, id) {
71
+ const [row] = await db
72
+ .select()
73
+ .from(roomTypeBedConfigs)
74
+ .where(eq(roomTypeBedConfigs.id, id))
75
+ .limit(1);
76
+ return row ?? null;
77
+ },
78
+ async createRoomTypeBedConfig(db, data) {
79
+ const [row] = await db.insert(roomTypeBedConfigs).values(data).returning();
80
+ return row ?? null;
81
+ },
82
+ async updateRoomTypeBedConfig(db, id, data) {
83
+ const [row] = await db
84
+ .update(roomTypeBedConfigs)
85
+ .set({ ...data, updatedAt: new Date() })
86
+ .where(eq(roomTypeBedConfigs.id, id))
87
+ .returning();
88
+ return row ?? null;
89
+ },
90
+ async deleteRoomTypeBedConfig(db, id) {
91
+ const [row] = await db
92
+ .delete(roomTypeBedConfigs)
93
+ .where(eq(roomTypeBedConfigs.id, id))
94
+ .returning({ id: roomTypeBedConfigs.id });
95
+ return row ?? null;
96
+ },
97
+ async listRoomUnits(db, query) {
98
+ const conditions = [];
99
+ if (query.propertyId)
100
+ conditions.push(eq(roomUnits.propertyId, query.propertyId));
101
+ if (query.roomTypeId)
102
+ conditions.push(eq(roomUnits.roomTypeId, query.roomTypeId));
103
+ if (query.status)
104
+ conditions.push(eq(roomUnits.status, query.status));
105
+ if (query.search) {
106
+ const term = `%${query.search}%`;
107
+ conditions.push(or(ilike(roomUnits.code, term), ilike(roomUnits.roomNumber, term), ilike(roomUnits.notes, term)));
108
+ }
109
+ const where = conditions.length ? and(...conditions) : undefined;
110
+ return paginate(db
111
+ .select()
112
+ .from(roomUnits)
113
+ .where(where)
114
+ .limit(query.limit)
115
+ .offset(query.offset)
116
+ .orderBy(asc(roomUnits.roomNumber), asc(roomUnits.code)), db.select({ count: sql `count(*)::int` }).from(roomUnits).where(where), query.limit, query.offset);
117
+ },
118
+ async getRoomUnitById(db, id) {
119
+ const [row] = await db.select().from(roomUnits).where(eq(roomUnits.id, id)).limit(1);
120
+ return row ?? null;
121
+ },
122
+ async createRoomUnit(db, data) {
123
+ const [row] = await db.insert(roomUnits).values(data).returning();
124
+ return row ?? null;
125
+ },
126
+ async updateRoomUnit(db, id, data) {
127
+ const [row] = await db
128
+ .update(roomUnits)
129
+ .set({ ...data, updatedAt: new Date() })
130
+ .where(eq(roomUnits.id, id))
131
+ .returning();
132
+ return row ?? null;
133
+ },
134
+ async deleteRoomUnit(db, id) {
135
+ const [row] = await db
136
+ .delete(roomUnits)
137
+ .where(eq(roomUnits.id, id))
138
+ .returning({ id: roomUnits.id });
139
+ return row ?? null;
140
+ },
141
+ async listMealPlans(db, query) {
142
+ const conditions = [];
143
+ if (query.propertyId)
144
+ conditions.push(eq(mealPlans.propertyId, query.propertyId));
145
+ if (query.active !== undefined)
146
+ conditions.push(eq(mealPlans.active, query.active));
147
+ if (query.search) {
148
+ const term = `%${query.search}%`;
149
+ conditions.push(or(ilike(mealPlans.name, term), ilike(mealPlans.code, term)));
150
+ }
151
+ const where = conditions.length ? and(...conditions) : undefined;
152
+ return paginate(db
153
+ .select()
154
+ .from(mealPlans)
155
+ .where(where)
156
+ .limit(query.limit)
157
+ .offset(query.offset)
158
+ .orderBy(asc(mealPlans.sortOrder), asc(mealPlans.name)), db.select({ count: sql `count(*)::int` }).from(mealPlans).where(where), query.limit, query.offset);
159
+ },
160
+ async getMealPlanById(db, id) {
161
+ const [row] = await db.select().from(mealPlans).where(eq(mealPlans.id, id)).limit(1);
162
+ return row ?? null;
163
+ },
164
+ async createMealPlan(db, data) {
165
+ const [row] = await db.insert(mealPlans).values(data).returning();
166
+ return row ?? null;
167
+ },
168
+ async updateMealPlan(db, id, data) {
169
+ const [row] = await db
170
+ .update(mealPlans)
171
+ .set({ ...data, updatedAt: new Date() })
172
+ .where(eq(mealPlans.id, id))
173
+ .returning();
174
+ return row ?? null;
175
+ },
176
+ async deleteMealPlan(db, id) {
177
+ const [row] = await db
178
+ .delete(mealPlans)
179
+ .where(eq(mealPlans.id, id))
180
+ .returning({ id: mealPlans.id });
181
+ return row ?? null;
182
+ },
183
+ async listRatePlans(db, query) {
184
+ const conditions = [];
185
+ if (query.propertyId)
186
+ conditions.push(eq(ratePlans.propertyId, query.propertyId));
187
+ if (query.mealPlanId)
188
+ conditions.push(eq(ratePlans.mealPlanId, query.mealPlanId));
189
+ if (query.marketId)
190
+ conditions.push(eq(ratePlans.marketId, query.marketId));
191
+ if (query.active !== undefined)
192
+ conditions.push(eq(ratePlans.active, query.active));
193
+ if (query.search) {
194
+ const term = `%${query.search}%`;
195
+ conditions.push(or(ilike(ratePlans.name, term), ilike(ratePlans.code, term)));
196
+ }
197
+ const where = conditions.length ? and(...conditions) : undefined;
198
+ return paginate(db
199
+ .select()
200
+ .from(ratePlans)
201
+ .where(where)
202
+ .limit(query.limit)
203
+ .offset(query.offset)
204
+ .orderBy(asc(ratePlans.sortOrder), asc(ratePlans.name)), db.select({ count: sql `count(*)::int` }).from(ratePlans).where(where), query.limit, query.offset);
205
+ },
206
+ async getRatePlanById(db, id) {
207
+ const [row] = await db.select().from(ratePlans).where(eq(ratePlans.id, id)).limit(1);
208
+ return row ?? null;
209
+ },
210
+ async createRatePlan(db, data) {
211
+ const [row] = await db.insert(ratePlans).values(data).returning();
212
+ return row ?? null;
213
+ },
214
+ async updateRatePlan(db, id, data) {
215
+ const [row] = await db
216
+ .update(ratePlans)
217
+ .set({ ...data, updatedAt: new Date() })
218
+ .where(eq(ratePlans.id, id))
219
+ .returning();
220
+ return row ?? null;
221
+ },
222
+ async deleteRatePlan(db, id) {
223
+ const [row] = await db
224
+ .delete(ratePlans)
225
+ .where(eq(ratePlans.id, id))
226
+ .returning({ id: ratePlans.id });
227
+ return row ?? null;
228
+ },
229
+ async listRatePlanRoomTypes(db, query) {
230
+ const conditions = [];
231
+ if (query.ratePlanId)
232
+ conditions.push(eq(ratePlanRoomTypes.ratePlanId, query.ratePlanId));
233
+ if (query.roomTypeId)
234
+ conditions.push(eq(ratePlanRoomTypes.roomTypeId, query.roomTypeId));
235
+ if (query.productId)
236
+ conditions.push(eq(ratePlanRoomTypes.productId, query.productId));
237
+ if (query.active !== undefined)
238
+ conditions.push(eq(ratePlanRoomTypes.active, query.active));
239
+ const where = conditions.length ? and(...conditions) : undefined;
240
+ return paginate(db
241
+ .select()
242
+ .from(ratePlanRoomTypes)
243
+ .where(where)
244
+ .limit(query.limit)
245
+ .offset(query.offset)
246
+ .orderBy(asc(ratePlanRoomTypes.sortOrder), asc(ratePlanRoomTypes.createdAt)), db.select({ count: sql `count(*)::int` }).from(ratePlanRoomTypes).where(where), query.limit, query.offset);
247
+ },
248
+ async getRatePlanRoomTypeById(db, id) {
249
+ const [row] = await db
250
+ .select()
251
+ .from(ratePlanRoomTypes)
252
+ .where(eq(ratePlanRoomTypes.id, id))
253
+ .limit(1);
254
+ return row ?? null;
255
+ },
256
+ async createRatePlanRoomType(db, data) {
257
+ const [row] = await db.insert(ratePlanRoomTypes).values(data).returning();
258
+ return row ?? null;
259
+ },
260
+ async updateRatePlanRoomType(db, id, data) {
261
+ const [row] = await db
262
+ .update(ratePlanRoomTypes)
263
+ .set({ ...data, updatedAt: new Date() })
264
+ .where(eq(ratePlanRoomTypes.id, id))
265
+ .returning();
266
+ return row ?? null;
267
+ },
268
+ async deleteRatePlanRoomType(db, id) {
269
+ const [row] = await db
270
+ .delete(ratePlanRoomTypes)
271
+ .where(eq(ratePlanRoomTypes.id, id))
272
+ .returning({ id: ratePlanRoomTypes.id });
273
+ return row ?? null;
274
+ },
275
+ async listStayRules(db, query) {
276
+ const conditions = [];
277
+ if (query.propertyId)
278
+ conditions.push(eq(stayRules.propertyId, query.propertyId));
279
+ if (query.ratePlanId)
280
+ conditions.push(eq(stayRules.ratePlanId, query.ratePlanId));
281
+ if (query.roomTypeId)
282
+ conditions.push(eq(stayRules.roomTypeId, query.roomTypeId));
283
+ if (query.active !== undefined)
284
+ conditions.push(eq(stayRules.active, query.active));
285
+ const where = conditions.length ? and(...conditions) : undefined;
286
+ return paginate(db
287
+ .select()
288
+ .from(stayRules)
289
+ .where(where)
290
+ .limit(query.limit)
291
+ .offset(query.offset)
292
+ .orderBy(desc(stayRules.priority), asc(stayRules.createdAt)), db.select({ count: sql `count(*)::int` }).from(stayRules).where(where), query.limit, query.offset);
293
+ },
294
+ async getStayRuleById(db, id) {
295
+ const [row] = await db.select().from(stayRules).where(eq(stayRules.id, id)).limit(1);
296
+ return row ?? null;
297
+ },
298
+ async createStayRule(db, data) {
299
+ const [row] = await db.insert(stayRules).values(data).returning();
300
+ return row ?? null;
301
+ },
302
+ async updateStayRule(db, id, data) {
303
+ const [row] = await db
304
+ .update(stayRules)
305
+ .set({ ...data, updatedAt: new Date() })
306
+ .where(eq(stayRules.id, id))
307
+ .returning();
308
+ return row ?? null;
309
+ },
310
+ async deleteStayRule(db, id) {
311
+ const [row] = await db
312
+ .delete(stayRules)
313
+ .where(eq(stayRules.id, id))
314
+ .returning({ id: stayRules.id });
315
+ return row ?? null;
316
+ },
317
+ async listRoomInventory(db, query) {
318
+ const conditions = [];
319
+ if (query.propertyId)
320
+ conditions.push(eq(roomInventory.propertyId, query.propertyId));
321
+ if (query.roomTypeId)
322
+ conditions.push(eq(roomInventory.roomTypeId, query.roomTypeId));
323
+ if (query.stopSell !== undefined)
324
+ conditions.push(eq(roomInventory.stopSell, query.stopSell));
325
+ if (query.dateFrom)
326
+ conditions.push(gte(roomInventory.date, query.dateFrom));
327
+ if (query.dateTo)
328
+ conditions.push(lte(roomInventory.date, query.dateTo));
329
+ const where = conditions.length ? and(...conditions) : undefined;
330
+ return paginate(db
331
+ .select()
332
+ .from(roomInventory)
333
+ .where(where)
334
+ .limit(query.limit)
335
+ .offset(query.offset)
336
+ .orderBy(asc(roomInventory.date)), db.select({ count: sql `count(*)::int` }).from(roomInventory).where(where), query.limit, query.offset);
337
+ },
338
+ async getRoomInventoryById(db, id) {
339
+ const [row] = await db.select().from(roomInventory).where(eq(roomInventory.id, id)).limit(1);
340
+ return row ?? null;
341
+ },
342
+ async createRoomInventory(db, data) {
343
+ const [row] = await db.insert(roomInventory).values(data).returning();
344
+ return row ?? null;
345
+ },
346
+ async updateRoomInventory(db, id, data) {
347
+ const [row] = await db
348
+ .update(roomInventory)
349
+ .set({ ...data, updatedAt: new Date() })
350
+ .where(eq(roomInventory.id, id))
351
+ .returning();
352
+ return row ?? null;
353
+ },
354
+ async deleteRoomInventory(db, id) {
355
+ const [row] = await db
356
+ .delete(roomInventory)
357
+ .where(eq(roomInventory.id, id))
358
+ .returning({ id: roomInventory.id });
359
+ return row ?? null;
360
+ },
361
+ async listRatePlanInventoryOverrides(db, query) {
362
+ const conditions = [];
363
+ if (query.ratePlanId)
364
+ conditions.push(eq(ratePlanInventoryOverrides.ratePlanId, query.ratePlanId));
365
+ if (query.roomTypeId)
366
+ conditions.push(eq(ratePlanInventoryOverrides.roomTypeId, query.roomTypeId));
367
+ if (query.dateFrom)
368
+ conditions.push(gte(ratePlanInventoryOverrides.date, query.dateFrom));
369
+ if (query.dateTo)
370
+ conditions.push(lte(ratePlanInventoryOverrides.date, query.dateTo));
371
+ const where = conditions.length ? and(...conditions) : undefined;
372
+ return paginate(db
373
+ .select()
374
+ .from(ratePlanInventoryOverrides)
375
+ .where(where)
376
+ .limit(query.limit)
377
+ .offset(query.offset)
378
+ .orderBy(asc(ratePlanInventoryOverrides.date)), db
379
+ .select({ count: sql `count(*)::int` })
380
+ .from(ratePlanInventoryOverrides)
381
+ .where(where), query.limit, query.offset);
382
+ },
383
+ async getRatePlanInventoryOverrideById(db, id) {
384
+ const [row] = await db
385
+ .select()
386
+ .from(ratePlanInventoryOverrides)
387
+ .where(eq(ratePlanInventoryOverrides.id, id))
388
+ .limit(1);
389
+ return row ?? null;
390
+ },
391
+ async createRatePlanInventoryOverride(db, data) {
392
+ const [row] = await db.insert(ratePlanInventoryOverrides).values(data).returning();
393
+ return row ?? null;
394
+ },
395
+ async updateRatePlanInventoryOverride(db, id, data) {
396
+ const [row] = await db
397
+ .update(ratePlanInventoryOverrides)
398
+ .set({ ...data, updatedAt: new Date() })
399
+ .where(eq(ratePlanInventoryOverrides.id, id))
400
+ .returning();
401
+ return row ?? null;
402
+ },
403
+ async deleteRatePlanInventoryOverride(db, id) {
404
+ const [row] = await db
405
+ .delete(ratePlanInventoryOverrides)
406
+ .where(eq(ratePlanInventoryOverrides.id, id))
407
+ .returning({ id: ratePlanInventoryOverrides.id });
408
+ return row ?? null;
409
+ },
410
+ async listRoomTypeRates(db, query) {
411
+ const conditions = [];
412
+ if (query.ratePlanId)
413
+ conditions.push(eq(roomTypeRates.ratePlanId, query.ratePlanId));
414
+ if (query.roomTypeId)
415
+ conditions.push(eq(roomTypeRates.roomTypeId, query.roomTypeId));
416
+ if (query.priceScheduleId)
417
+ conditions.push(eq(roomTypeRates.priceScheduleId, query.priceScheduleId));
418
+ if (query.active !== undefined)
419
+ conditions.push(eq(roomTypeRates.active, query.active));
420
+ const where = conditions.length ? and(...conditions) : undefined;
421
+ return paginate(db
422
+ .select()
423
+ .from(roomTypeRates)
424
+ .where(where)
425
+ .limit(query.limit)
426
+ .offset(query.offset)
427
+ .orderBy(asc(roomTypeRates.createdAt)), db.select({ count: sql `count(*)::int` }).from(roomTypeRates).where(where), query.limit, query.offset);
428
+ },
429
+ async getRoomTypeRateById(db, id) {
430
+ const [row] = await db.select().from(roomTypeRates).where(eq(roomTypeRates.id, id)).limit(1);
431
+ return row ?? null;
432
+ },
433
+ async createRoomTypeRate(db, data) {
434
+ const [row] = await db.insert(roomTypeRates).values(data).returning();
435
+ return row ?? null;
436
+ },
437
+ async updateRoomTypeRate(db, id, data) {
438
+ const [row] = await db
439
+ .update(roomTypeRates)
440
+ .set({ ...data, updatedAt: new Date() })
441
+ .where(eq(roomTypeRates.id, id))
442
+ .returning();
443
+ return row ?? null;
444
+ },
445
+ async deleteRoomTypeRate(db, id) {
446
+ const [row] = await db
447
+ .delete(roomTypeRates)
448
+ .where(eq(roomTypeRates.id, id))
449
+ .returning({ id: roomTypeRates.id });
450
+ return row ?? null;
451
+ },
452
+ async listStayBookingItems(db, query) {
453
+ const conditions = [];
454
+ if (query.bookingItemId)
455
+ conditions.push(eq(stayBookingItems.bookingItemId, query.bookingItemId));
456
+ if (query.propertyId)
457
+ conditions.push(eq(stayBookingItems.propertyId, query.propertyId));
458
+ if (query.roomTypeId)
459
+ conditions.push(eq(stayBookingItems.roomTypeId, query.roomTypeId));
460
+ if (query.roomUnitId)
461
+ conditions.push(eq(stayBookingItems.roomUnitId, query.roomUnitId));
462
+ if (query.ratePlanId)
463
+ conditions.push(eq(stayBookingItems.ratePlanId, query.ratePlanId));
464
+ if (query.status)
465
+ conditions.push(eq(stayBookingItems.status, query.status));
466
+ if (query.dateFrom)
467
+ conditions.push(gte(stayBookingItems.checkInDate, query.dateFrom));
468
+ if (query.dateTo)
469
+ conditions.push(lte(stayBookingItems.checkOutDate, query.dateTo));
470
+ const where = conditions.length ? and(...conditions) : undefined;
471
+ return paginate(db
472
+ .select()
473
+ .from(stayBookingItems)
474
+ .where(where)
475
+ .limit(query.limit)
476
+ .offset(query.offset)
477
+ .orderBy(desc(stayBookingItems.checkInDate)), db.select({ count: sql `count(*)::int` }).from(stayBookingItems).where(where), query.limit, query.offset);
478
+ },
479
+ async getStayBookingItemById(db, id) {
480
+ const [row] = await db
481
+ .select()
482
+ .from(stayBookingItems)
483
+ .where(eq(stayBookingItems.id, id))
484
+ .limit(1);
485
+ return row ?? null;
486
+ },
487
+ async createStayBookingItem(db, data) {
488
+ const [row] = await db.insert(stayBookingItems).values(data).returning();
489
+ return row ?? null;
490
+ },
491
+ async updateStayBookingItem(db, id, data) {
492
+ const [row] = await db
493
+ .update(stayBookingItems)
494
+ .set({ ...data, updatedAt: new Date() })
495
+ .where(eq(stayBookingItems.id, id))
496
+ .returning();
497
+ return row ?? null;
498
+ },
499
+ async deleteStayBookingItem(db, id) {
500
+ const [row] = await db
501
+ .delete(stayBookingItems)
502
+ .where(eq(stayBookingItems.id, id))
503
+ .returning({ id: stayBookingItems.id });
504
+ return row ?? null;
505
+ },
506
+ async listStayDailyRates(db, query) {
507
+ const conditions = [];
508
+ if (query.stayBookingItemId)
509
+ conditions.push(eq(stayDailyRates.stayBookingItemId, query.stayBookingItemId));
510
+ if (query.dateFrom)
511
+ conditions.push(gte(stayDailyRates.date, query.dateFrom));
512
+ if (query.dateTo)
513
+ conditions.push(lte(stayDailyRates.date, query.dateTo));
514
+ const where = conditions.length ? and(...conditions) : undefined;
515
+ return paginate(db
516
+ .select()
517
+ .from(stayDailyRates)
518
+ .where(where)
519
+ .limit(query.limit)
520
+ .offset(query.offset)
521
+ .orderBy(asc(stayDailyRates.date)), db.select({ count: sql `count(*)::int` }).from(stayDailyRates).where(where), query.limit, query.offset);
522
+ },
523
+ async getStayDailyRateById(db, id) {
524
+ const [row] = await db.select().from(stayDailyRates).where(eq(stayDailyRates.id, id)).limit(1);
525
+ return row ?? null;
526
+ },
527
+ async createStayDailyRate(db, data) {
528
+ const [row] = await db.insert(stayDailyRates).values(data).returning();
529
+ return row ?? null;
530
+ },
531
+ async updateStayDailyRate(db, id, data) {
532
+ const [row] = await db
533
+ .update(stayDailyRates)
534
+ .set({ ...data, updatedAt: new Date() })
535
+ .where(eq(stayDailyRates.id, id))
536
+ .returning();
537
+ return row ?? null;
538
+ },
539
+ async deleteStayDailyRate(db, id) {
540
+ const [row] = await db
541
+ .delete(stayDailyRates)
542
+ .where(eq(stayDailyRates.id, id))
543
+ .returning({ id: stayDailyRates.id });
544
+ return row ?? null;
545
+ },
546
+ async listRoomBlocks(db, query) {
547
+ const conditions = [];
548
+ if (query.propertyId)
549
+ conditions.push(eq(roomBlocks.propertyId, query.propertyId));
550
+ if (query.roomTypeId)
551
+ conditions.push(eq(roomBlocks.roomTypeId, query.roomTypeId));
552
+ if (query.roomUnitId)
553
+ conditions.push(eq(roomBlocks.roomUnitId, query.roomUnitId));
554
+ if (query.status)
555
+ conditions.push(eq(roomBlocks.status, query.status));
556
+ if (query.startsOn)
557
+ conditions.push(gte(roomBlocks.startsOn, query.startsOn));
558
+ if (query.endsOn)
559
+ conditions.push(lte(roomBlocks.endsOn, query.endsOn));
560
+ const where = conditions.length ? and(...conditions) : undefined;
561
+ return paginate(db
562
+ .select()
563
+ .from(roomBlocks)
564
+ .where(where)
565
+ .limit(query.limit)
566
+ .offset(query.offset)
567
+ .orderBy(desc(roomBlocks.startsOn)), db.select({ count: sql `count(*)::int` }).from(roomBlocks).where(where), query.limit, query.offset);
568
+ },
569
+ async getRoomBlockById(db, id) {
570
+ const [row] = await db.select().from(roomBlocks).where(eq(roomBlocks.id, id)).limit(1);
571
+ return row ?? null;
572
+ },
573
+ async createRoomBlock(db, data) {
574
+ const [row] = await db
575
+ .insert(roomBlocks)
576
+ .values({ ...data, releaseAt: toDateOrNull(data.releaseAt) })
577
+ .returning();
578
+ return row ?? null;
579
+ },
580
+ async updateRoomBlock(db, id, data) {
581
+ const [row] = await db
582
+ .update(roomBlocks)
583
+ .set({ ...data, releaseAt: toDateOrNull(data.releaseAt), updatedAt: new Date() })
584
+ .where(eq(roomBlocks.id, id))
585
+ .returning();
586
+ return row ?? null;
587
+ },
588
+ async deleteRoomBlock(db, id) {
589
+ const [row] = await db
590
+ .delete(roomBlocks)
591
+ .where(eq(roomBlocks.id, id))
592
+ .returning({ id: roomBlocks.id });
593
+ return row ?? null;
594
+ },
595
+ async listRoomUnitStatusEvents(db, query) {
596
+ const conditions = [];
597
+ if (query.roomUnitId)
598
+ conditions.push(eq(roomUnitStatusEvents.roomUnitId, query.roomUnitId));
599
+ if (query.statusCode)
600
+ conditions.push(eq(roomUnitStatusEvents.statusCode, query.statusCode));
601
+ const where = conditions.length ? and(...conditions) : undefined;
602
+ return paginate(db
603
+ .select()
604
+ .from(roomUnitStatusEvents)
605
+ .where(where)
606
+ .limit(query.limit)
607
+ .offset(query.offset)
608
+ .orderBy(desc(roomUnitStatusEvents.effectiveFrom)), db.select({ count: sql `count(*)::int` }).from(roomUnitStatusEvents).where(where), query.limit, query.offset);
609
+ },
610
+ async getRoomUnitStatusEventById(db, id) {
611
+ const [row] = await db
612
+ .select()
613
+ .from(roomUnitStatusEvents)
614
+ .where(eq(roomUnitStatusEvents.id, id))
615
+ .limit(1);
616
+ return row ?? null;
617
+ },
618
+ async createRoomUnitStatusEvent(db, data) {
619
+ const [row] = await db
620
+ .insert(roomUnitStatusEvents)
621
+ .values({
622
+ ...data,
623
+ effectiveFrom: toDateOrNull(data.effectiveFrom) ?? new Date(),
624
+ effectiveTo: toDateOrNull(data.effectiveTo),
625
+ })
626
+ .returning();
627
+ return row ?? null;
628
+ },
629
+ async updateRoomUnitStatusEvent(db, id, data) {
630
+ const [row] = await db
631
+ .update(roomUnitStatusEvents)
632
+ .set({
633
+ ...data,
634
+ effectiveFrom: data.effectiveFrom ? new Date(data.effectiveFrom) : undefined,
635
+ effectiveTo: data.effectiveTo ? new Date(data.effectiveTo) : undefined,
636
+ })
637
+ .where(eq(roomUnitStatusEvents.id, id))
638
+ .returning();
639
+ return row ?? null;
640
+ },
641
+ async deleteRoomUnitStatusEvent(db, id) {
642
+ const [row] = await db
643
+ .delete(roomUnitStatusEvents)
644
+ .where(eq(roomUnitStatusEvents.id, id))
645
+ .returning({ id: roomUnitStatusEvents.id });
646
+ return row ?? null;
647
+ },
648
+ async listMaintenanceBlocks(db, query) {
649
+ const conditions = [];
650
+ if (query.propertyId)
651
+ conditions.push(eq(maintenanceBlocks.propertyId, query.propertyId));
652
+ if (query.roomTypeId)
653
+ conditions.push(eq(maintenanceBlocks.roomTypeId, query.roomTypeId));
654
+ if (query.roomUnitId)
655
+ conditions.push(eq(maintenanceBlocks.roomUnitId, query.roomUnitId));
656
+ if (query.status)
657
+ conditions.push(eq(maintenanceBlocks.status, query.status));
658
+ if (query.startsOn)
659
+ conditions.push(gte(maintenanceBlocks.startsOn, query.startsOn));
660
+ if (query.endsOn)
661
+ conditions.push(lte(maintenanceBlocks.endsOn, query.endsOn));
662
+ const where = conditions.length ? and(...conditions) : undefined;
663
+ return paginate(db
664
+ .select()
665
+ .from(maintenanceBlocks)
666
+ .where(where)
667
+ .limit(query.limit)
668
+ .offset(query.offset)
669
+ .orderBy(desc(maintenanceBlocks.startsOn)), db.select({ count: sql `count(*)::int` }).from(maintenanceBlocks).where(where), query.limit, query.offset);
670
+ },
671
+ async getMaintenanceBlockById(db, id) {
672
+ const [row] = await db
673
+ .select()
674
+ .from(maintenanceBlocks)
675
+ .where(eq(maintenanceBlocks.id, id))
676
+ .limit(1);
677
+ return row ?? null;
678
+ },
679
+ async createMaintenanceBlock(db, data) {
680
+ const [row] = await db.insert(maintenanceBlocks).values(data).returning();
681
+ return row ?? null;
682
+ },
683
+ async updateMaintenanceBlock(db, id, data) {
684
+ const [row] = await db
685
+ .update(maintenanceBlocks)
686
+ .set({ ...data, updatedAt: new Date() })
687
+ .where(eq(maintenanceBlocks.id, id))
688
+ .returning();
689
+ return row ?? null;
690
+ },
691
+ async deleteMaintenanceBlock(db, id) {
692
+ const [row] = await db
693
+ .delete(maintenanceBlocks)
694
+ .where(eq(maintenanceBlocks.id, id))
695
+ .returning({ id: maintenanceBlocks.id });
696
+ return row ?? null;
697
+ },
698
+ async listHousekeepingTasks(db, query) {
699
+ const conditions = [];
700
+ if (query.propertyId)
701
+ conditions.push(eq(housekeepingTasks.propertyId, query.propertyId));
702
+ if (query.roomUnitId)
703
+ conditions.push(eq(housekeepingTasks.roomUnitId, query.roomUnitId));
704
+ if (query.stayBookingItemId)
705
+ conditions.push(eq(housekeepingTasks.stayBookingItemId, query.stayBookingItemId));
706
+ if (query.status)
707
+ conditions.push(eq(housekeepingTasks.status, query.status));
708
+ if (query.taskType)
709
+ conditions.push(eq(housekeepingTasks.taskType, query.taskType));
710
+ const where = conditions.length ? and(...conditions) : undefined;
711
+ return paginate(db
712
+ .select()
713
+ .from(housekeepingTasks)
714
+ .where(where)
715
+ .limit(query.limit)
716
+ .offset(query.offset)
717
+ .orderBy(asc(housekeepingTasks.priority), asc(housekeepingTasks.dueAt)), db.select({ count: sql `count(*)::int` }).from(housekeepingTasks).where(where), query.limit, query.offset);
718
+ },
719
+ async getHousekeepingTaskById(db, id) {
720
+ const [row] = await db
721
+ .select()
722
+ .from(housekeepingTasks)
723
+ .where(eq(housekeepingTasks.id, id))
724
+ .limit(1);
725
+ return row ?? null;
726
+ },
727
+ async createHousekeepingTask(db, data) {
728
+ const [row] = await db
729
+ .insert(housekeepingTasks)
730
+ .values({
731
+ ...data,
732
+ dueAt: toDateOrNull(data.dueAt),
733
+ startedAt: toDateOrNull(data.startedAt),
734
+ completedAt: toDateOrNull(data.completedAt),
735
+ })
736
+ .returning();
737
+ return row ?? null;
738
+ },
739
+ async updateHousekeepingTask(db, id, data) {
740
+ const [row] = await db
741
+ .update(housekeepingTasks)
742
+ .set({
743
+ ...data,
744
+ dueAt: toDateOrNull(data.dueAt),
745
+ startedAt: toDateOrNull(data.startedAt),
746
+ completedAt: toDateOrNull(data.completedAt),
747
+ updatedAt: new Date(),
748
+ })
749
+ .where(eq(housekeepingTasks.id, id))
750
+ .returning();
751
+ return row ?? null;
752
+ },
753
+ async deleteHousekeepingTask(db, id) {
754
+ const [row] = await db
755
+ .delete(housekeepingTasks)
756
+ .where(eq(housekeepingTasks.id, id))
757
+ .returning({ id: housekeepingTasks.id });
758
+ return row ?? null;
759
+ },
760
+ async listStayOperations(db, query) {
761
+ const conditions = [];
762
+ if (query.stayBookingItemId)
763
+ conditions.push(eq(stayOperations.stayBookingItemId, query.stayBookingItemId));
764
+ if (query.propertyId)
765
+ conditions.push(eq(stayOperations.propertyId, query.propertyId));
766
+ if (query.roomUnitId)
767
+ conditions.push(eq(stayOperations.roomUnitId, query.roomUnitId));
768
+ if (query.operationStatus)
769
+ conditions.push(eq(stayOperations.operationStatus, query.operationStatus));
770
+ const where = conditions.length ? and(...conditions) : undefined;
771
+ return paginate(db
772
+ .select()
773
+ .from(stayOperations)
774
+ .where(where)
775
+ .limit(query.limit)
776
+ .offset(query.offset)
777
+ .orderBy(desc(stayOperations.createdAt)), db.select({ count: sql `count(*)::int` }).from(stayOperations).where(where), query.limit, query.offset);
778
+ },
779
+ async getStayOperationById(db, id) {
780
+ const [row] = await db.select().from(stayOperations).where(eq(stayOperations.id, id)).limit(1);
781
+ return row ?? null;
782
+ },
783
+ async createStayOperation(db, data) {
784
+ const [row] = await db
785
+ .insert(stayOperations)
786
+ .values({
787
+ ...data,
788
+ expectedArrivalAt: toDateOrNull(data.expectedArrivalAt),
789
+ expectedDepartureAt: toDateOrNull(data.expectedDepartureAt),
790
+ checkedInAt: toDateOrNull(data.checkedInAt),
791
+ checkedOutAt: toDateOrNull(data.checkedOutAt),
792
+ noShowRecordedAt: toDateOrNull(data.noShowRecordedAt),
793
+ })
794
+ .returning();
795
+ return row ?? null;
796
+ },
797
+ async updateStayOperation(db, id, data) {
798
+ const [row] = await db
799
+ .update(stayOperations)
800
+ .set({
801
+ ...data,
802
+ expectedArrivalAt: toDateOrNull(data.expectedArrivalAt),
803
+ expectedDepartureAt: toDateOrNull(data.expectedDepartureAt),
804
+ checkedInAt: toDateOrNull(data.checkedInAt),
805
+ checkedOutAt: toDateOrNull(data.checkedOutAt),
806
+ noShowRecordedAt: toDateOrNull(data.noShowRecordedAt),
807
+ updatedAt: new Date(),
808
+ })
809
+ .where(eq(stayOperations.id, id))
810
+ .returning();
811
+ return row ?? null;
812
+ },
813
+ async deleteStayOperation(db, id) {
814
+ const [row] = await db
815
+ .delete(stayOperations)
816
+ .where(eq(stayOperations.id, id))
817
+ .returning({ id: stayOperations.id });
818
+ return row ?? null;
819
+ },
820
+ async listStayCheckpoints(db, query) {
821
+ const conditions = [];
822
+ if (query.stayOperationId)
823
+ conditions.push(eq(stayCheckpoints.stayOperationId, query.stayOperationId));
824
+ if (query.checkpointType)
825
+ conditions.push(eq(stayCheckpoints.checkpointType, query.checkpointType));
826
+ const where = conditions.length ? and(...conditions) : undefined;
827
+ return paginate(db
828
+ .select()
829
+ .from(stayCheckpoints)
830
+ .where(where)
831
+ .limit(query.limit)
832
+ .offset(query.offset)
833
+ .orderBy(desc(stayCheckpoints.occurredAt)), db.select({ count: sql `count(*)::int` }).from(stayCheckpoints).where(where), query.limit, query.offset);
834
+ },
835
+ async getStayCheckpointById(db, id) {
836
+ const [row] = await db.select().from(stayCheckpoints).where(eq(stayCheckpoints.id, id)).limit(1);
837
+ return row ?? null;
838
+ },
839
+ async createStayCheckpoint(db, data) {
840
+ const [row] = await db
841
+ .insert(stayCheckpoints)
842
+ .values({ ...data, occurredAt: toDateOrNull(data.occurredAt) ?? new Date() })
843
+ .returning();
844
+ return row ?? null;
845
+ },
846
+ async updateStayCheckpoint(db, id, data) {
847
+ const [row] = await db
848
+ .update(stayCheckpoints)
849
+ .set({
850
+ ...data,
851
+ occurredAt: data.occurredAt ? new Date(data.occurredAt) : undefined,
852
+ })
853
+ .where(eq(stayCheckpoints.id, id))
854
+ .returning();
855
+ return row ?? null;
856
+ },
857
+ async deleteStayCheckpoint(db, id) {
858
+ const [row] = await db
859
+ .delete(stayCheckpoints)
860
+ .where(eq(stayCheckpoints.id, id))
861
+ .returning({ id: stayCheckpoints.id });
862
+ return row ?? null;
863
+ },
864
+ async listStayServicePosts(db, query) {
865
+ const conditions = [];
866
+ if (query.stayOperationId)
867
+ conditions.push(eq(stayServicePosts.stayOperationId, query.stayOperationId));
868
+ if (query.bookingItemId)
869
+ conditions.push(eq(stayServicePosts.bookingItemId, query.bookingItemId));
870
+ if (query.kind)
871
+ conditions.push(eq(stayServicePosts.kind, query.kind));
872
+ if (query.serviceDateFrom)
873
+ conditions.push(gte(stayServicePosts.serviceDate, query.serviceDateFrom));
874
+ if (query.serviceDateTo)
875
+ conditions.push(lte(stayServicePosts.serviceDate, query.serviceDateTo));
876
+ const where = conditions.length ? and(...conditions) : undefined;
877
+ return paginate(db
878
+ .select()
879
+ .from(stayServicePosts)
880
+ .where(where)
881
+ .limit(query.limit)
882
+ .offset(query.offset)
883
+ .orderBy(desc(stayServicePosts.serviceDate)), db.select({ count: sql `count(*)::int` }).from(stayServicePosts).where(where), query.limit, query.offset);
884
+ },
885
+ async getStayServicePostById(db, id) {
886
+ const [row] = await db
887
+ .select()
888
+ .from(stayServicePosts)
889
+ .where(eq(stayServicePosts.id, id))
890
+ .limit(1);
891
+ return row ?? null;
892
+ },
893
+ async createStayServicePost(db, data) {
894
+ const [row] = await db.insert(stayServicePosts).values(data).returning();
895
+ return row ?? null;
896
+ },
897
+ async updateStayServicePost(db, id, data) {
898
+ const [row] = await db
899
+ .update(stayServicePosts)
900
+ .set({ ...data, updatedAt: new Date() })
901
+ .where(eq(stayServicePosts.id, id))
902
+ .returning();
903
+ return row ?? null;
904
+ },
905
+ async deleteStayServicePost(db, id) {
906
+ const [row] = await db
907
+ .delete(stayServicePosts)
908
+ .where(eq(stayServicePosts.id, id))
909
+ .returning({ id: stayServicePosts.id });
910
+ return row ?? null;
911
+ },
912
+ async listStayFolios(db, query) {
913
+ const conditions = [];
914
+ if (query.stayOperationId)
915
+ conditions.push(eq(stayFolios.stayOperationId, query.stayOperationId));
916
+ if (query.status)
917
+ conditions.push(eq(stayFolios.status, query.status));
918
+ const where = conditions.length ? and(...conditions) : undefined;
919
+ return paginate(db
920
+ .select()
921
+ .from(stayFolios)
922
+ .where(where)
923
+ .limit(query.limit)
924
+ .offset(query.offset)
925
+ .orderBy(desc(stayFolios.openedAt)), db.select({ count: sql `count(*)::int` }).from(stayFolios).where(where), query.limit, query.offset);
926
+ },
927
+ async getStayFolioById(db, id) {
928
+ const [row] = await db.select().from(stayFolios).where(eq(stayFolios.id, id)).limit(1);
929
+ return row ?? null;
930
+ },
931
+ async createStayFolio(db, data) {
932
+ const [row] = await db
933
+ .insert(stayFolios)
934
+ .values({
935
+ ...data,
936
+ openedAt: toDateOrNull(data.openedAt) ?? new Date(),
937
+ closedAt: toDateOrNull(data.closedAt),
938
+ })
939
+ .returning();
940
+ return row ?? null;
941
+ },
942
+ async updateStayFolio(db, id, data) {
943
+ const [row] = await db
944
+ .update(stayFolios)
945
+ .set({
946
+ ...data,
947
+ openedAt: data.openedAt ? new Date(data.openedAt) : undefined,
948
+ closedAt: data.closedAt ? new Date(data.closedAt) : undefined,
949
+ updatedAt: new Date(),
950
+ })
951
+ .where(eq(stayFolios.id, id))
952
+ .returning();
953
+ return row ?? null;
954
+ },
955
+ async deleteStayFolio(db, id) {
956
+ const [row] = await db
957
+ .delete(stayFolios)
958
+ .where(eq(stayFolios.id, id))
959
+ .returning({ id: stayFolios.id });
960
+ return row ?? null;
961
+ },
962
+ async listStayFolioLines(db, query) {
963
+ const conditions = [];
964
+ if (query.stayFolioId)
965
+ conditions.push(eq(stayFolioLines.stayFolioId, query.stayFolioId));
966
+ if (query.servicePostId)
967
+ conditions.push(eq(stayFolioLines.servicePostId, query.servicePostId));
968
+ const where = conditions.length ? and(...conditions) : undefined;
969
+ return paginate(db
970
+ .select()
971
+ .from(stayFolioLines)
972
+ .where(where)
973
+ .limit(query.limit)
974
+ .offset(query.offset)
975
+ .orderBy(desc(stayFolioLines.postedAt)), db.select({ count: sql `count(*)::int` }).from(stayFolioLines).where(where), query.limit, query.offset);
976
+ },
977
+ async getStayFolioLineById(db, id) {
978
+ const [row] = await db.select().from(stayFolioLines).where(eq(stayFolioLines.id, id)).limit(1);
979
+ return row ?? null;
980
+ },
981
+ async createStayFolioLine(db, data) {
982
+ const [row] = await db
983
+ .insert(stayFolioLines)
984
+ .values({ ...data, postedAt: toDateOrNull(data.postedAt) ?? new Date() })
985
+ .returning();
986
+ return row ?? null;
987
+ },
988
+ async updateStayFolioLine(db, id, data) {
989
+ const [row] = await db
990
+ .update(stayFolioLines)
991
+ .set({
992
+ ...data,
993
+ postedAt: data.postedAt ? new Date(data.postedAt) : undefined,
994
+ updatedAt: new Date(),
995
+ })
996
+ .where(eq(stayFolioLines.id, id))
997
+ .returning();
998
+ return row ?? null;
999
+ },
1000
+ async deleteStayFolioLine(db, id) {
1001
+ const [row] = await db
1002
+ .delete(stayFolioLines)
1003
+ .where(eq(stayFolioLines.id, id))
1004
+ .returning({ id: stayFolioLines.id });
1005
+ return row ?? null;
1006
+ },
1007
+ };