@7365admin1/module-hygiene 4.21.0 → 4.22.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.
package/dist/index.mjs CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  BadRequestError,
18
18
  useCache,
19
19
  makeCacheKey,
20
+ paginate,
20
21
  logger
21
22
  } from "@7365admin1/node-server-utils";
22
23
  function useHygieneDashboardRepository() {
@@ -25,72 +26,57 @@ function useHygieneDashboardRepository() {
25
26
  throw new InternalServerError("Unable to connect to server.");
26
27
  }
27
28
  const dashboard_namespace_collection = "hygiene.dashboard";
28
- const feedback_namespace_collection = "feedbacks";
29
29
  const cleaning_schedule_namespace_collection = "site.cleaning.schedules";
30
30
  const area_checklist_namespace_collection = "site.cleaning.schedule.areas";
31
- const schedule_task_namespace_collection = "site.schedule-tasks";
32
31
  const supply_namespace_collection = "site.supplies";
33
- const request_item_namespace_collection = "site.supply.requests";
34
- const feedbackCollection = db.collection(feedback_namespace_collection);
32
+ const work_order_namespace_collection = "work-orders2";
35
33
  const areaChecklistCollection = db.collection(
36
34
  area_checklist_namespace_collection
37
35
  );
38
- const scheduleTaskCollection = db.collection(
39
- schedule_task_namespace_collection
40
- );
41
36
  const supplyCollection = db.collection(supply_namespace_collection);
42
- const requestItemCollection = db.collection(
43
- request_item_namespace_collection
44
- );
37
+ const workOrderCollection = db.collection(work_order_namespace_collection);
38
+ const attendanceCollection = db.collection("site.attendances");
39
+ const feedbackCollection = db.collection("feedbacks2");
45
40
  const { setCache, getCache } = useCache(dashboard_namespace_collection);
41
+ const workOrderServiceMap = {
42
+ security_agency: "Security",
43
+ cleaning_services: "Cleaning",
44
+ mechanical_electrical_services: "M&E",
45
+ landscaping_services: "Landscape",
46
+ pest_control_services: "Pest Control",
47
+ pool_maintenance_services: "Pool Maintenance"
48
+ };
49
+ function areaChecklistScheduleLookup(site, serviceType, createdAtRange) {
50
+ return [
51
+ { $match: { serviceType } },
52
+ {
53
+ $lookup: {
54
+ from: cleaning_schedule_namespace_collection,
55
+ localField: "schedule",
56
+ foreignField: "_id",
57
+ as: "scheduleDoc",
58
+ pipeline: [
59
+ {
60
+ $match: {
61
+ site,
62
+ serviceType,
63
+ createdAt: createdAtRange
64
+ }
65
+ }
66
+ ]
67
+ }
68
+ },
69
+ { $unwind: { path: "$scheduleDoc", preserveNullAndEmptyArrays: false } }
70
+ ];
71
+ }
46
72
  async function getHygieneDashboard({
47
73
  site,
48
- feedbackPeriod = "today",
49
- commonAreaPeriod = "today",
50
- toiletAreaPeriod = "today",
51
- scheduleTaskPeriod = "today",
52
- supplyPeriod = "today",
53
- requestItemPeriod = "today"
74
+ serviceType,
75
+ period = "today"
54
76
  }) {
55
- const countQueries = {
56
- feedback: {},
57
- commonArea: {},
58
- toiletArea: {},
59
- scheduleTask: {},
60
- supply: {},
61
- requestItem: {}
62
- };
63
- const yesterDayQueries = {
64
- feedback: {},
65
- commonArea: {},
66
- toiletArea: {},
67
- scheduleTask: {},
68
- supply: {},
69
- requestItem: {}
70
- };
71
- const todayQueries = {
72
- feedback: {},
73
- commonArea: {},
74
- toiletArea: {},
75
- scheduleTask: {},
76
- supply: {},
77
- requestItem: {}
78
- };
79
- const cacheOptions = {
80
- feedbackPeriod,
81
- commonAreaPeriod,
82
- toiletAreaPeriod,
83
- scheduleTaskPeriod,
84
- supplyPeriod,
85
- requestItemPeriod
86
- };
77
+ const cacheOptions = { serviceType, period };
87
78
  try {
88
79
  site = new ObjectId(site);
89
- Object.keys(countQueries).forEach((key) => {
90
- countQueries[key].site = site;
91
- yesterDayQueries[key].site = site;
92
- todayQueries[key].site = site;
93
- });
94
80
  cacheOptions.site = site.toString();
95
81
  } catch (error) {
96
82
  throw new BadRequestError("Invalid site ID format.");
@@ -118,32 +104,28 @@ function useHygieneDashboardRepository() {
118
104
  });
119
105
  return singaporeMoment.toDate();
120
106
  }
121
- function applyPeriodToQuery(query, period) {
122
- const today = /* @__PURE__ */ new Date();
123
- today.setHours(0, 0, 0, 0);
124
- if (period === "today") {
125
- query.createdAt = {
126
- $gte: today,
127
- $lte: formatEndDate(today)
128
- };
129
- } else if (period === "thisWeek" || period === "thisMonth") {
130
- const filterDate = period === "thisWeek" ? 7 : 30;
131
- const filterStartDate = /* @__PURE__ */ new Date();
132
- filterStartDate.setDate(today.getDate() - filterDate);
133
- filterStartDate.setHours(0, 0, 0, 0);
134
- query.createdAt = {
135
- $gte: filterStartDate,
136
- $lte: formatEndDate(/* @__PURE__ */ new Date())
137
- };
107
+ function getDateRange(p) {
108
+ const start = /* @__PURE__ */ new Date();
109
+ start.setHours(0, 0, 0, 0);
110
+ if (p === "today") {
111
+ return { $gte: start, $lte: formatEndDate(start) };
138
112
  }
139
- }
113
+ const days = p === "thisWeek" ? 7 : 30;
114
+ const rangeStart = /* @__PURE__ */ new Date();
115
+ rangeStart.setDate(start.getDate() - days);
116
+ rangeStart.setHours(0, 0, 0, 0);
117
+ return { $gte: rangeStart, $lte: formatEndDate(/* @__PURE__ */ new Date()) };
118
+ }
119
+ const calculatePercentageChange = (currentCount, previousCount) => {
120
+ if (previousCount === 0) {
121
+ return currentCount > 0 ? 100 : 0;
122
+ }
123
+ return Math.round(
124
+ (currentCount - previousCount) / previousCount * 100 * 100
125
+ ) / 100;
126
+ };
127
+ const workOrderService = workOrderServiceMap[serviceType] ?? serviceType;
140
128
  try {
141
- applyPeriodToQuery(countQueries.feedback, feedbackPeriod);
142
- applyPeriodToQuery(countQueries.commonArea, commonAreaPeriod);
143
- applyPeriodToQuery(countQueries.toiletArea, toiletAreaPeriod);
144
- applyPeriodToQuery(countQueries.scheduleTask, scheduleTaskPeriod);
145
- applyPeriodToQuery(countQueries.supply, supplyPeriod);
146
- applyPeriodToQuery(countQueries.requestItem, requestItemPeriod);
147
129
  const today = /* @__PURE__ */ new Date();
148
130
  today.setHours(0, 0, 0, 0);
149
131
  const yesterday = /* @__PURE__ */ new Date();
@@ -151,359 +133,566 @@ function useHygieneDashboardRepository() {
151
133
  yesterday.setHours(0, 0, 0, 0);
152
134
  const yesterdayEnd = new Date(yesterday);
153
135
  yesterdayEnd.setHours(23, 59, 59, 999);
154
- Object.keys(yesterDayQueries).forEach((key) => {
155
- yesterDayQueries[key].createdAt = {
156
- $gte: yesterday,
157
- $lte: yesterdayEnd
158
- };
159
- });
160
- Object.keys(todayQueries).forEach((key) => {
161
- todayQueries[key].createdAt = {
162
- $gte: today,
163
- $lte: formatEndDate(/* @__PURE__ */ new Date())
164
- };
165
- });
166
- const calculatePercentageChange = (currentCount, previousCount) => {
167
- if (previousCount === 0) {
168
- return currentCount > 0 ? 100 : 0;
169
- }
170
- return Math.round(
171
- (currentCount - previousCount) / previousCount * 100 * 100
172
- ) / 100;
173
- };
136
+ const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
137
+ const periodRange = getDateRange(period);
174
138
  const [
175
- feedbackReport,
176
- commonAreaChecklistReport,
177
- toiletAreaChecklistReport,
178
- scheduleTaskReport,
179
- supplyReport,
180
- requestItemReport
139
+ workOrderReport,
140
+ supplyAlertReport,
141
+ taskCompletedReport,
142
+ yesterdayWorkOrderReport,
143
+ todayWorkOrderReport,
144
+ yesterdayTaskCompletedReport,
145
+ todayTaskCompletedReport
181
146
  ] = await Promise.all([
182
- feedbackCollection.aggregate([
147
+ // 1. Open work orders (period-filtered) with inProgress breakdown
148
+ workOrderCollection.aggregate([
183
149
  {
184
150
  $match: {
185
- ...countQueries.feedback,
186
- category: "cleaning_services",
187
- status: "to-do"
151
+ site,
152
+ service: workOrderService,
153
+ createdAt: periodRange,
154
+ status: { $nin: ["completed"] }
188
155
  }
189
156
  },
157
+ {
158
+ $facet: {
159
+ total: [{ $count: "count" }],
160
+ inProgress: [
161
+ { $match: { status: "in-progress" } },
162
+ { $count: "count" }
163
+ ]
164
+ }
165
+ }
166
+ ]).toArray(),
167
+ // 2. Supply alert — out-of-stock active supplies for site+serviceType
168
+ supplyCollection.aggregate([
169
+ { $match: { site, serviceType, qty: 0, status: "active" } },
190
170
  { $count: "count" }
191
171
  ]).toArray(),
172
+ // 3. Task completed — area checklists (period-filtered via schedule join)
192
173
  areaChecklistCollection.aggregate([
193
- { $match: { type: "common" } },
174
+ ...areaChecklistScheduleLookup(site, serviceType, periodRange),
194
175
  {
195
- $lookup: {
196
- from: cleaning_schedule_namespace_collection,
197
- localField: "schedule",
198
- foreignField: "_id",
199
- as: "scheduleDoc",
200
- pipeline: countQueries.commonArea.createdAt ? [
201
- {
202
- $match: {
203
- site,
204
- createdAt: countQueries.commonArea.createdAt
205
- }
206
- }
207
- ] : [{ $match: { site } }]
176
+ $facet: {
177
+ total: [{ $count: "count" }],
178
+ completed: [
179
+ { $match: { status: "completed" } },
180
+ { $count: "count" }
181
+ ],
182
+ inProgress: [
183
+ { $match: { status: { $in: ["open", "ongoing"] } } },
184
+ { $count: "count" }
185
+ ]
208
186
  }
209
- },
187
+ }
188
+ ]).toArray(),
189
+ // 4. Yesterday open work orders (for % change)
190
+ workOrderCollection.aggregate([
210
191
  {
211
- $unwind: {
212
- path: "$scheduleDoc",
213
- preserveNullAndEmptyArrays: false
192
+ $match: {
193
+ site,
194
+ service: workOrderService,
195
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
196
+ status: { $nin: ["completed"] }
214
197
  }
215
198
  },
216
199
  { $count: "count" }
217
200
  ]).toArray(),
218
- areaChecklistCollection.aggregate([
219
- { $match: { type: "toilet" } },
201
+ // 5. Today open work orders (for % change)
202
+ workOrderCollection.aggregate([
220
203
  {
221
- $lookup: {
222
- from: cleaning_schedule_namespace_collection,
223
- localField: "schedule",
224
- foreignField: "_id",
225
- as: "scheduleDoc",
226
- pipeline: countQueries.toiletArea.createdAt ? [
227
- {
228
- $match: {
229
- site,
230
- createdAt: countQueries.toiletArea.createdAt
231
- }
232
- }
233
- ] : [{ $match: { site } }]
234
- }
235
- },
236
- {
237
- $unwind: {
238
- path: "$scheduleDoc",
239
- preserveNullAndEmptyArrays: false
204
+ $match: {
205
+ site,
206
+ service: workOrderService,
207
+ createdAt: { $gte: today, $lte: todayEnd },
208
+ status: { $nin: ["completed"] }
240
209
  }
241
210
  },
242
211
  { $count: "count" }
243
212
  ]).toArray(),
244
- scheduleTaskCollection.aggregate([
245
- { $match: countQueries.scheduleTask },
213
+ // 6. Yesterday task completed — area checklists (for % change)
214
+ areaChecklistCollection.aggregate([
215
+ ...areaChecklistScheduleLookup(site, serviceType, {
216
+ $gte: yesterday,
217
+ $lte: yesterdayEnd
218
+ }),
219
+ { $match: { status: "completed" } },
246
220
  { $count: "count" }
247
221
  ]).toArray(),
248
- supplyCollection.aggregate([{ $match: countQueries.supply }, { $count: "count" }]).toArray(),
249
- requestItemCollection.aggregate([
250
- { $match: countQueries.requestItem },
222
+ // 7. Today task completed area checklists (for % change)
223
+ areaChecklistCollection.aggregate([
224
+ ...areaChecklistScheduleLookup(site, serviceType, {
225
+ $gte: today,
226
+ $lte: todayEnd
227
+ }),
228
+ { $match: { status: "completed" } },
251
229
  { $count: "count" }
252
230
  ]).toArray()
253
231
  ]);
254
- const [
255
- yesterdayFeedbackCount,
256
- yesterdayCommonAreaChecklistCount,
257
- yesterdayToiletAreaChecklistCount,
258
- yesterdayScheduledTaskCount,
259
- yesterdaySupplyCount,
260
- yesterdayRequestItemCount
261
- ] = await Promise.all([
262
- feedbackCollection.aggregate([
232
+ const wFacet = workOrderReport[0] ?? { total: [], inProgress: [] };
233
+ const tFacet = taskCompletedReport[0] ?? {
234
+ total: [],
235
+ completed: [],
236
+ inProgress: []
237
+ };
238
+ const result = {
239
+ openWorkOrder: {
240
+ count: wFacet.total[0]?.count ?? 0,
241
+ inProgress: wFacet.inProgress[0]?.count ?? 0,
242
+ percentage: calculatePercentageChange(
243
+ todayWorkOrderReport[0]?.count ?? 0,
244
+ yesterdayWorkOrderReport[0]?.count ?? 0
245
+ )
246
+ },
247
+ supplyAlert: {
248
+ count: supplyAlertReport[0]?.count ?? 0,
249
+ percentage: 0
250
+ },
251
+ taskCompleted: {
252
+ completed: tFacet.completed[0]?.count ?? 0,
253
+ total: tFacet.total[0]?.count ?? 0,
254
+ inProgress: tFacet.inProgress[0]?.count ?? 0,
255
+ percentage: calculatePercentageChange(
256
+ todayTaskCompletedReport[0]?.count ?? 0,
257
+ yesterdayTaskCompletedReport[0]?.count ?? 0
258
+ )
259
+ }
260
+ };
261
+ setCache(dashboardCacheKey, result, 15 * 60).then(() => {
262
+ logger.info(`Cache set for dashboard: ${dashboardCacheKey}`);
263
+ }).catch((err) => {
264
+ logger.error(
265
+ `Failed to set cache for dashboard: ${dashboardCacheKey}`,
266
+ err
267
+ );
268
+ });
269
+ return result;
270
+ } catch (error) {
271
+ throw error;
272
+ }
273
+ }
274
+ async function getWeeklyActivity({
275
+ site,
276
+ serviceType
277
+ }) {
278
+ const cacheOptions = { serviceType };
279
+ try {
280
+ site = new ObjectId(site);
281
+ cacheOptions.site = site.toString();
282
+ } catch {
283
+ throw new BadRequestError("Invalid site ID format.");
284
+ }
285
+ const cacheKey = makeCacheKey(
286
+ `${dashboard_namespace_collection}:weeklyActivity`,
287
+ cacheOptions
288
+ );
289
+ const cachedData = await getCache(cacheKey);
290
+ if (cachedData) {
291
+ logger.info(`Cache hit for weeklyActivity: ${cacheKey}`);
292
+ return cachedData;
293
+ }
294
+ const workOrderService = workOrderServiceMap[serviceType] ?? serviceType;
295
+ const weekStart = moment.tz("Asia/Singapore").startOf("isoWeek").toDate();
296
+ const weekEnd = moment.tz("Asia/Singapore").endOf("isoWeek").toDate();
297
+ const weekRange = { $gte: weekStart, $lte: weekEnd };
298
+ const dayLabels = {
299
+ 1: "Sun",
300
+ 2: "Mon",
301
+ 3: "Tue",
302
+ 4: "Wed",
303
+ 5: "Thu",
304
+ 6: "Fri",
305
+ 7: "Sat"
306
+ };
307
+ const dayOrder = [2, 3, 4, 5, 6, 7, 1];
308
+ try {
309
+ const [workOrderByDay, taskCompletedByDay] = await Promise.all([
310
+ workOrderCollection.aggregate([
263
311
  {
264
- $match: {
265
- ...yesterDayQueries.feedback,
266
- category: "cleaning_services",
267
- status: "to-do"
268
- }
312
+ $match: { site, service: workOrderService, createdAt: weekRange }
269
313
  },
270
- { $count: "count" }
314
+ {
315
+ $group: { _id: { $dayOfWeek: "$createdAt" }, count: { $sum: 1 } }
316
+ }
271
317
  ]).toArray(),
272
318
  areaChecklistCollection.aggregate([
273
- { $match: { type: "common" } },
319
+ ...areaChecklistScheduleLookup(site, serviceType, weekRange),
320
+ { $match: { status: "completed" } },
274
321
  {
275
- $lookup: {
276
- from: cleaning_schedule_namespace_collection,
277
- localField: "schedule",
278
- foreignField: "_id",
279
- as: "scheduleDoc",
280
- pipeline: [
281
- {
282
- $match: {
283
- site,
284
- createdAt: yesterDayQueries.commonArea.createdAt
285
- }
286
- }
287
- ]
322
+ $group: {
323
+ _id: { $dayOfWeek: "$completedAt" },
324
+ count: { $sum: 1 }
288
325
  }
289
- },
326
+ }
327
+ ]).toArray()
328
+ ]);
329
+ const workOrderMap = new Map(
330
+ workOrderByDay.map((d) => [d._id, d.count])
331
+ );
332
+ const taskMap = new Map(
333
+ taskCompletedByDay.map((d) => [d._id, d.count])
334
+ );
335
+ const result = dayOrder.map((dow) => ({
336
+ day: dayLabels[dow],
337
+ workOrder: workOrderMap.get(dow) ?? 0,
338
+ taskCompleted: taskMap.get(dow) ?? 0
339
+ }));
340
+ setCache(cacheKey, result, 15 * 60).then(() => {
341
+ logger.info(`Cache set for weeklyActivity: ${cacheKey}`);
342
+ }).catch((err) => {
343
+ logger.error(
344
+ `Failed to set cache for weeklyActivity: ${cacheKey}`,
345
+ err
346
+ );
347
+ });
348
+ return result;
349
+ } catch (error) {
350
+ throw error;
351
+ }
352
+ }
353
+ async function getTodayTaskSchedule({
354
+ site,
355
+ serviceType,
356
+ page = 1,
357
+ limit = 10
358
+ }) {
359
+ page = page > 0 ? page - 1 : 0;
360
+ const cacheOptions = { serviceType, page, limit };
361
+ try {
362
+ site = new ObjectId(site);
363
+ cacheOptions.site = site.toString();
364
+ } catch {
365
+ throw new BadRequestError("Invalid site ID format.");
366
+ }
367
+ const cacheKey = makeCacheKey(
368
+ `${dashboard_namespace_collection}:todayTaskSchedule`,
369
+ cacheOptions
370
+ );
371
+ const cachedData = await getCache(cacheKey);
372
+ if (cachedData) {
373
+ logger.info(`Cache hit for todayTaskSchedule: ${cacheKey}`);
374
+ return cachedData;
375
+ }
376
+ const todayStart = moment.tz("Asia/Singapore").startOf("day").toDate();
377
+ const todayEnd = moment.tz("Asia/Singapore").endOf("day").toDate();
378
+ const todayRange = { $gte: todayStart, $lte: todayEnd };
379
+ try {
380
+ const [items, countResult] = await Promise.all([
381
+ areaChecklistCollection.aggregate([
382
+ ...areaChecklistScheduleLookup(site, serviceType, todayRange),
290
383
  {
291
- $unwind: {
292
- path: "$scheduleDoc",
293
- preserveNullAndEmptyArrays: false
384
+ $addFields: {
385
+ _assigneeId: {
386
+ $reduce: {
387
+ input: { $ifNull: ["$checklist", []] },
388
+ initialValue: null,
389
+ in: {
390
+ $cond: {
391
+ if: { $ne: ["$$value", null] },
392
+ then: "$$value",
393
+ else: {
394
+ $reduce: {
395
+ input: { $ifNull: ["$$this.units", []] },
396
+ initialValue: null,
397
+ in: {
398
+ $cond: {
399
+ if: { $ne: ["$$value", null] },
400
+ then: "$$value",
401
+ else: {
402
+ $cond: {
403
+ if: { $gt: ["$$this.completedBy", null] },
404
+ then: "$$this.completedBy",
405
+ else: null
406
+ }
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
294
416
  }
295
417
  },
296
- { $count: "count" }
297
- ]).toArray(),
298
- areaChecklistCollection.aggregate([
299
- { $match: { type: "toilet" } },
300
418
  {
301
419
  $lookup: {
302
- from: cleaning_schedule_namespace_collection,
303
- localField: "schedule",
420
+ from: "users",
421
+ localField: "_assigneeId",
304
422
  foreignField: "_id",
305
- as: "scheduleDoc",
306
- pipeline: [
307
- {
308
- $match: {
309
- site,
310
- createdAt: yesterDayQueries.toiletArea.createdAt
311
- }
312
- }
313
- ]
423
+ as: "_assigneeDoc"
314
424
  }
315
425
  },
426
+ { $sort: { createdAt: -1, _id: -1 } },
316
427
  {
317
- $unwind: {
318
- path: "$scheduleDoc",
319
- preserveNullAndEmptyArrays: false
428
+ $project: {
429
+ name: 1,
430
+ type: 1,
431
+ status: 1,
432
+ assigneeName: { $arrayElemAt: ["$_assigneeDoc.name", 0] }
320
433
  }
321
434
  },
322
- { $count: "count" }
435
+ { $skip: page * limit },
436
+ { $limit: limit }
323
437
  ]).toArray(),
324
- scheduleTaskCollection.aggregate([
325
- { $match: yesterDayQueries.scheduleTask },
326
- { $count: "count" }
327
- ]).toArray(),
328
- supplyCollection.aggregate([{ $match: yesterDayQueries.supply }, { $count: "count" }]).toArray(),
329
- requestItemCollection.aggregate([
330
- { $match: yesterDayQueries.requestItem },
438
+ areaChecklistCollection.aggregate([
439
+ ...areaChecklistScheduleLookup(site, serviceType, todayRange),
331
440
  { $count: "count" }
332
441
  ]).toArray()
333
442
  ]);
334
- const [
335
- todayFeedbackCount,
336
- todayCommonAreaChecklistCount,
337
- todayToiletAreaChecklistCount,
338
- todayScheduledTaskCount,
339
- todaySupplyCount,
340
- todayRequestItemCount
341
- ] = await Promise.all([
342
- feedbackCollection.aggregate([
443
+ const length = countResult[0]?.count ?? 0;
444
+ const data = paginate(items, page, limit, length);
445
+ setCache(cacheKey, data, 15 * 60).then(() => {
446
+ logger.info(`Cache set for todayTaskSchedule: ${cacheKey}`);
447
+ }).catch((err) => {
448
+ logger.error(
449
+ `Failed to set cache for todayTaskSchedule: ${cacheKey}`,
450
+ err
451
+ );
452
+ });
453
+ return data;
454
+ } catch (error) {
455
+ throw error;
456
+ }
457
+ }
458
+ async function getStaffAttendance({
459
+ site,
460
+ serviceType,
461
+ page = 1,
462
+ limit = 10
463
+ }) {
464
+ page = page > 0 ? page - 1 : 0;
465
+ const cacheOptions = { serviceType, page, limit };
466
+ try {
467
+ site = new ObjectId(site);
468
+ cacheOptions.site = site.toString();
469
+ } catch {
470
+ throw new BadRequestError("Invalid site ID format.");
471
+ }
472
+ const cacheKey = makeCacheKey(
473
+ `${dashboard_namespace_collection}:staffAttendance`,
474
+ cacheOptions
475
+ );
476
+ const cachedData = await getCache(cacheKey);
477
+ if (cachedData) {
478
+ logger.info(`Cache hit for staffAttendance: ${cacheKey}`);
479
+ return cachedData;
480
+ }
481
+ const todayStart = moment.tz("Asia/Singapore").startOf("day").toDate();
482
+ const todayEnd = moment.tz("Asia/Singapore").endOf("day").toDate();
483
+ const todayStartStr = todayStart.toISOString();
484
+ const todayEndStr = todayEnd.toISOString();
485
+ try {
486
+ const [items, length] = await Promise.all([
487
+ attendanceCollection.aggregate([
343
488
  {
344
489
  $match: {
345
- ...todayQueries.feedback,
346
- category: "cleaning_services",
347
- status: "to-do"
490
+ site,
491
+ serviceType,
492
+ $or: [
493
+ { createdAt: { $gte: todayStart, $lte: todayEnd } },
494
+ { createdAt: { $gte: todayStartStr, $lte: todayEndStr } }
495
+ ]
348
496
  }
349
497
  },
350
- { $count: "count" }
351
- ]).toArray(),
352
- areaChecklistCollection.aggregate([
353
- { $match: { type: "common" } },
354
498
  {
355
499
  $lookup: {
356
- from: cleaning_schedule_namespace_collection,
357
- localField: "schedule",
500
+ from: "users",
501
+ localField: "user",
358
502
  foreignField: "_id",
359
- as: "scheduleDoc",
503
+ as: "_userDoc"
504
+ }
505
+ },
506
+ {
507
+ $lookup: {
508
+ from: "members",
509
+ let: { userId: "$user", siteId: "$site", type: "$serviceType" },
360
510
  pipeline: [
361
511
  {
362
512
  $match: {
363
- site,
364
- createdAt: todayQueries.commonArea.createdAt
513
+ $expr: {
514
+ $and: [
515
+ { $eq: ["$user", "$$userId"] },
516
+ { $eq: ["$siteId", "$$siteId"] },
517
+ { $eq: ["$type", "$$type"] },
518
+ { $ne: ["$status", "deleted"] }
519
+ ]
520
+ }
365
521
  }
366
522
  }
367
- ]
523
+ ],
524
+ as: "_memberDoc"
368
525
  }
369
526
  },
370
527
  {
371
528
  $unwind: {
372
- path: "$scheduleDoc",
373
- preserveNullAndEmptyArrays: false
529
+ path: "$_memberDoc",
530
+ preserveNullAndEmptyArrays: true
374
531
  }
375
532
  },
376
- { $count: "count" }
377
- ]).toArray(),
378
- areaChecklistCollection.aggregate([
379
- { $match: { type: "toilet" } },
380
533
  {
381
534
  $lookup: {
382
- from: cleaning_schedule_namespace_collection,
383
- localField: "schedule",
535
+ from: "roles",
536
+ localField: "_memberDoc.role",
384
537
  foreignField: "_id",
385
- as: "scheduleDoc",
386
- pipeline: [
387
- {
388
- $match: {
389
- site,
390
- createdAt: todayQueries.toiletArea.createdAt
391
- }
392
- }
393
- ]
538
+ as: "_roleDoc"
394
539
  }
395
540
  },
396
541
  {
397
542
  $unwind: {
398
- path: "$scheduleDoc",
399
- preserveNullAndEmptyArrays: false
543
+ path: "$_roleDoc",
544
+ preserveNullAndEmptyArrays: true
400
545
  }
401
546
  },
402
- { $count: "count" }
547
+ { $sort: { createdAt: -1, _id: -1 } },
548
+ {
549
+ $project: {
550
+ checkIn: 1,
551
+ checkOut: 1,
552
+ createdAt: 1,
553
+ userName: { $arrayElemAt: ["$_userDoc.name", 0] },
554
+ userRole: { $ifNull: ["$_roleDoc.name", ""] },
555
+ totalHours: {
556
+ $round: [
557
+ {
558
+ $divide: [
559
+ {
560
+ $subtract: [
561
+ {
562
+ $toDate: {
563
+ $ifNull: ["$checkOut.timestamp", "$$NOW"]
564
+ }
565
+ },
566
+ { $toDate: "$checkIn.timestamp" }
567
+ ]
568
+ },
569
+ 36e5
570
+ ]
571
+ },
572
+ 2
573
+ ]
574
+ }
575
+ }
576
+ },
577
+ { $skip: page * limit },
578
+ { $limit: limit }
403
579
  ]).toArray(),
404
- scheduleTaskCollection.aggregate([
405
- { $match: todayQueries.scheduleTask },
406
- { $count: "count" }
580
+ attendanceCollection.countDocuments({
581
+ site,
582
+ serviceType,
583
+ $or: [
584
+ { createdAt: { $gte: todayStart, $lte: todayEnd } },
585
+ { createdAt: { $gte: todayStartStr, $lte: todayEndStr } }
586
+ ]
587
+ })
588
+ ]);
589
+ const data = paginate(items, page, limit, length);
590
+ setCache(cacheKey, data, 15 * 60).then(() => {
591
+ logger.info(`Cache set for staffAttendance: ${cacheKey}`);
592
+ }).catch((err) => {
593
+ logger.error(
594
+ `Failed to set cache for staffAttendance: ${cacheKey}`,
595
+ err
596
+ );
597
+ });
598
+ return data;
599
+ } catch (error) {
600
+ throw error;
601
+ }
602
+ }
603
+ async function getRecentFeedbacks({
604
+ site,
605
+ serviceType,
606
+ page = 1,
607
+ limit = 10
608
+ }) {
609
+ page = page > 0 ? page - 1 : 0;
610
+ const cacheOptions = { serviceType, page, limit };
611
+ try {
612
+ site = new ObjectId(site);
613
+ cacheOptions.site = site.toString();
614
+ } catch {
615
+ throw new BadRequestError("Invalid site ID format.");
616
+ }
617
+ const cacheKey = makeCacheKey(
618
+ `${dashboard_namespace_collection}:recentFeedbacks`,
619
+ cacheOptions
620
+ );
621
+ const cachedData = await getCache(cacheKey);
622
+ if (cachedData) {
623
+ logger.info(`Cache hit for recentFeedbacks: ${cacheKey}`);
624
+ return cachedData;
625
+ }
626
+ const workOrderService = workOrderServiceMap[serviceType] ?? serviceType;
627
+ try {
628
+ const [items, length] = await Promise.all([
629
+ feedbackCollection.aggregate([
630
+ { $match: { site, service: workOrderService } },
631
+ { $sort: { createdAt: -1, _id: -1 } },
632
+ {
633
+ $lookup: {
634
+ from: "users",
635
+ localField: "createdBy",
636
+ foreignField: "_id",
637
+ as: "_createdByDoc"
638
+ }
639
+ },
640
+ {
641
+ $project: {
642
+ description: 1,
643
+ subject: 1,
644
+ app: 1,
645
+ status: 1,
646
+ createdAt: 1,
647
+ createdByName: { $arrayElemAt: ["$_createdByDoc.name", 0] }
648
+ }
649
+ },
650
+ { $skip: page * limit },
651
+ { $limit: limit }
407
652
  ]).toArray(),
408
- supplyCollection.aggregate([{ $match: todayQueries.supply }, { $count: "count" }]).toArray(),
409
- requestItemCollection.aggregate([
410
- { $match: todayQueries.requestItem },
411
- { $count: "count" }
412
- ]).toArray()
653
+ feedbackCollection.countDocuments({ site, service: workOrderService })
413
654
  ]);
414
- const resultYesterday = {
415
- feedbackCount: yesterdayFeedbackCount[0]?.count || 0,
416
- commonAreaChecklistCount: yesterdayCommonAreaChecklistCount[0]?.count || 0,
417
- toiletAreaChecklistCount: yesterdayToiletAreaChecklistCount[0]?.count || 0,
418
- scheduleTaskCount: yesterdayScheduledTaskCount[0]?.count || 0,
419
- supplyCount: yesterdaySupplyCount[0]?.count || 0,
420
- requestItemCount: yesterdayRequestItemCount[0]?.count || 0
421
- };
422
- const resultToday = {
423
- feedbackCount: todayFeedbackCount[0]?.count || 0,
424
- commonAreaChecklistCount: todayCommonAreaChecklistCount[0]?.count || 0,
425
- toiletAreaChecklistCount: todayToiletAreaChecklistCount[0]?.count || 0,
426
- scheduleTaskCount: todayScheduledTaskCount[0]?.count || 0,
427
- supplyCount: todaySupplyCount[0]?.count || 0,
428
- requestItemCount: todayRequestItemCount[0]?.count || 0
429
- };
430
- const result = {
431
- feedback: {
432
- count: feedbackReport[0]?.count || 0,
433
- percentage: calculatePercentageChange(
434
- resultToday.feedbackCount,
435
- resultYesterday.feedbackCount
436
- )
437
- },
438
- commonAreaChecklist: {
439
- count: commonAreaChecklistReport[0]?.count || 0,
440
- percentage: calculatePercentageChange(
441
- resultToday.commonAreaChecklistCount,
442
- resultYesterday.commonAreaChecklistCount
443
- )
444
- },
445
- toiletAreaChecklist: {
446
- count: toiletAreaChecklistReport[0]?.count || 0,
447
- percentage: calculatePercentageChange(
448
- resultToday.toiletAreaChecklistCount,
449
- resultYesterday.toiletAreaChecklistCount
450
- )
451
- },
452
- scheduleTask: {
453
- count: scheduleTaskReport[0]?.count || 0,
454
- percentage: calculatePercentageChange(
455
- resultToday.scheduleTaskCount,
456
- resultYesterday.scheduleTaskCount
457
- )
458
- },
459
- supply: {
460
- count: supplyReport[0]?.count || 0,
461
- percentage: calculatePercentageChange(
462
- resultToday.supplyCount,
463
- resultYesterday.supplyCount
464
- )
465
- },
466
- requestItem: {
467
- count: requestItemReport[0]?.count || 0,
468
- percentage: calculatePercentageChange(
469
- resultToday.requestItemCount,
470
- resultYesterday.requestItemCount
471
- )
472
- }
473
- };
474
- setCache(dashboardCacheKey, result, 15 * 60).then(() => {
475
- logger.info(`Cache set for dashboard: ${dashboardCacheKey}`);
655
+ const data = paginate(items, page, limit, length);
656
+ setCache(cacheKey, data, 15 * 60).then(() => {
657
+ logger.info(`Cache set for recentFeedbacks: ${cacheKey}`);
476
658
  }).catch((err) => {
477
659
  logger.error(
478
- `Failed to set cache for dashboard: ${dashboardCacheKey}`,
660
+ `Failed to set cache for recentFeedbacks: ${cacheKey}`,
479
661
  err
480
662
  );
481
663
  });
482
- return result;
664
+ return data;
483
665
  } catch (error) {
484
666
  throw error;
485
667
  }
486
668
  }
487
669
  return {
488
- getHygieneDashboard
670
+ getHygieneDashboard,
671
+ getWeeklyActivity,
672
+ getTodayTaskSchedule,
673
+ getStaffAttendance,
674
+ getRecentFeedbacks
489
675
  };
490
676
  }
491
677
 
492
678
  // src/controllers/hygiene-dashboard.controller.ts
493
679
  import Joi from "joi";
494
680
  import { BadRequestError as BadRequestError2, logger as logger2 } from "@7365admin1/node-server-utils";
681
+ import { AppServiceType } from "@7365admin1/core";
495
682
  function useHygieneDashboardController() {
496
- const { getHygieneDashboard: _getHygieneDashboard } = useHygieneDashboardRepository();
683
+ const {
684
+ getHygieneDashboard: _getHygieneDashboard,
685
+ getWeeklyActivity: _getWeeklyActivity,
686
+ getTodayTaskSchedule: _getTodayTaskSchedule,
687
+ getStaffAttendance: _getStaffAttendance,
688
+ getRecentFeedbacks: _getRecentFeedbacks
689
+ } = useHygieneDashboardRepository();
497
690
  async function getHygieneDashboard(req, res, next) {
498
691
  const query = { ...req.query, ...req.params };
499
692
  const validation = Joi.object({
500
693
  site: Joi.string().hex().required(),
501
- feedbackPeriod: Joi.string().valid(...allowedPeriods).optional(),
502
- commonAreaPeriod: Joi.string().valid(...allowedPeriods).optional(),
503
- toiletAreaPeriod: Joi.string().valid(...allowedPeriods).optional(),
504
- scheduleTaskPeriod: Joi.string().valid(...allowedPeriods).optional(),
505
- supplyPeriod: Joi.string().valid(...allowedPeriods).optional(),
506
- requestItemPeriod: Joi.string().valid(...allowedPeriods).optional()
694
+ serviceType: Joi.string().valid(...Object.values(AppServiceType)).required(),
695
+ period: Joi.string().valid(...allowedPeriods).optional()
507
696
  });
508
697
  const { error } = validation.validate(query);
509
698
  if (error) {
@@ -512,21 +701,136 @@ function useHygieneDashboardController() {
512
701
  return;
513
702
  }
514
703
  const site = req.params.site ?? "";
515
- const feedbackPeriod = req.query.feedbackPeriod || "today";
516
- const commonAreaPeriod = req.query.commonAreaPeriod || "today";
517
- const toiletAreaPeriod = req.query.toiletAreaPeriod || "today";
518
- const scheduleTaskPeriod = req.query.scheduleTaskPeriod || "today";
519
- const supplyPeriod = req.query.supplyPeriod || "today";
520
- const requestItemPeriod = req.query.requestItemPeriod || "today";
704
+ const serviceType = req.params.serviceType;
705
+ const period = req.query.period || "today";
521
706
  try {
522
707
  const data = await _getHygieneDashboard({
523
708
  site,
524
- feedbackPeriod,
525
- commonAreaPeriod,
526
- toiletAreaPeriod,
527
- scheduleTaskPeriod,
528
- supplyPeriod,
529
- requestItemPeriod
709
+ period,
710
+ serviceType
711
+ });
712
+ res.json(data);
713
+ return;
714
+ } catch (error2) {
715
+ logger2.log({ level: "error", message: error2.message });
716
+ next(error2);
717
+ return;
718
+ }
719
+ }
720
+ async function getWeeklyActivity(req, res, next) {
721
+ const query = { ...req.params };
722
+ const validation = Joi.object({
723
+ site: Joi.string().hex().required(),
724
+ serviceType: Joi.string().valid(...Object.values(AppServiceType)).required()
725
+ });
726
+ const { error } = validation.validate(query);
727
+ if (error) {
728
+ logger2.log({ level: "error", message: error.message });
729
+ next(new BadRequestError2(error.message));
730
+ return;
731
+ }
732
+ const site = req.params.site;
733
+ const serviceType = req.params.serviceType;
734
+ try {
735
+ const data = await _getWeeklyActivity({ site, serviceType });
736
+ res.json(data);
737
+ return;
738
+ } catch (error2) {
739
+ logger2.log({ level: "error", message: error2.message });
740
+ next(error2);
741
+ return;
742
+ }
743
+ }
744
+ async function getTodayTaskSchedule(req, res, next) {
745
+ const query = { ...req.query, ...req.params };
746
+ const validation = Joi.object({
747
+ site: Joi.string().hex().required(),
748
+ serviceType: Joi.string().valid(...Object.values(AppServiceType)).required(),
749
+ page: Joi.number().min(1).optional().allow("", null),
750
+ limit: Joi.number().min(1).optional().allow("", null)
751
+ });
752
+ const { error } = validation.validate(query);
753
+ if (error) {
754
+ logger2.log({ level: "error", message: error.message });
755
+ next(new BadRequestError2(error.message));
756
+ return;
757
+ }
758
+ const site = req.params.site;
759
+ const serviceType = req.params.serviceType;
760
+ const page = parseInt(req.query.page) ?? 1;
761
+ const limit = parseInt(req.query.limit) ?? 10;
762
+ try {
763
+ const data = await _getTodayTaskSchedule({
764
+ site,
765
+ serviceType,
766
+ page,
767
+ limit
768
+ });
769
+ res.json(data);
770
+ return;
771
+ } catch (error2) {
772
+ logger2.log({ level: "error", message: error2.message });
773
+ next(error2);
774
+ return;
775
+ }
776
+ }
777
+ async function getStaffAttendance(req, res, next) {
778
+ const query = { ...req.query, ...req.params };
779
+ const validation = Joi.object({
780
+ site: Joi.string().hex().required(),
781
+ serviceType: Joi.string().valid(...Object.values(AppServiceType)).required(),
782
+ page: Joi.number().min(1).optional().allow("", null),
783
+ limit: Joi.number().min(1).optional().allow("", null)
784
+ });
785
+ const { error } = validation.validate(query);
786
+ if (error) {
787
+ logger2.log({ level: "error", message: error.message });
788
+ next(new BadRequestError2(error.message));
789
+ return;
790
+ }
791
+ const site = req.params.site;
792
+ const serviceType = req.params.serviceType;
793
+ const page = parseInt(req.query.page) ?? 1;
794
+ const limit = parseInt(req.query.limit) ?? 10;
795
+ try {
796
+ const data = await _getStaffAttendance({
797
+ site,
798
+ serviceType,
799
+ page,
800
+ limit
801
+ });
802
+ res.json(data);
803
+ return;
804
+ } catch (error2) {
805
+ logger2.log({ level: "error", message: error2.message });
806
+ next(error2);
807
+ return;
808
+ }
809
+ }
810
+ async function getRecentFeedbacks(req, res, next) {
811
+ const query = { ...req.query, ...req.params };
812
+ const validation = Joi.object({
813
+ site: Joi.string().hex().required(),
814
+ serviceType: Joi.string().valid(...Object.values(AppServiceType)).required(),
815
+ page: Joi.number().min(1).optional().allow("", null),
816
+ limit: Joi.number().min(1).optional().allow("", null)
817
+ });
818
+ const { error } = validation.validate(query);
819
+ if (error) {
820
+ logger2.log({ level: "error", message: error.message });
821
+ next(new BadRequestError2(error.message));
822
+ return;
823
+ }
824
+ const site = req.params.site;
825
+ const serviceType = req.params.serviceType;
826
+ const page = parseInt(req.query.page) ?? 1;
827
+ const limit = parseInt(req.query.limit) ?? 10;
828
+ try {
829
+ const data = await _getRecentFeedbacks({
830
+ site,
831
+ serviceType,
832
+ page,
833
+ limit
530
834
  });
531
835
  res.json(data);
532
836
  return;
@@ -537,7 +841,11 @@ function useHygieneDashboardController() {
537
841
  }
538
842
  }
539
843
  return {
540
- getHygieneDashboard
844
+ getHygieneDashboard,
845
+ getWeeklyActivity,
846
+ getTodayTaskSchedule,
847
+ getStaffAttendance,
848
+ getRecentFeedbacks
541
849
  };
542
850
  }
543
851
 
@@ -545,10 +853,10 @@ function useHygieneDashboardController() {
545
853
  import Joi2 from "joi";
546
854
  import { ObjectId as ObjectId2 } from "mongodb";
547
855
  import { BadRequestError as BadRequestError3, logger as logger3 } from "@7365admin1/node-server-utils";
548
- import { AppServiceType } from "@7365admin1/core";
856
+ import { AppServiceType as AppServiceType2 } from "@7365admin1/core";
549
857
  var areaSchema = Joi2.object({
550
858
  site: Joi2.string().hex().required(),
551
- serviceType: Joi2.string().valid(...Object.values(AppServiceType)).required(),
859
+ serviceType: Joi2.string().valid(...Object.values(AppServiceType2)).required(),
552
860
  name: Joi2.string().required(),
553
861
  type: Joi2.string().valid(...allowedTypes).required(),
554
862
  set: Joi2.number().min(0).optional(),
@@ -605,7 +913,7 @@ import { ObjectId as ObjectId3 } from "mongodb";
605
913
  import {
606
914
  useAtlas as useAtlas2,
607
915
  InternalServerError as InternalServerError2,
608
- paginate,
916
+ paginate as paginate2,
609
917
  BadRequestError as BadRequestError4,
610
918
  useCache as useCache2,
611
919
  logger as logger4,
@@ -740,7 +1048,7 @@ function useAreaRepo() {
740
1048
  { $limit: limit }
741
1049
  ]).toArray();
742
1050
  const length = await collection.countDocuments(query);
743
- const data = paginate(items, page, limit, length);
1051
+ const data = paginate2(items, page, limit, length);
744
1052
  setCache(cacheKey, data, 15 * 60).then(() => {
745
1053
  logger4.info(`Cache set for key: ${cacheKey}`);
746
1054
  }).catch((err) => {
@@ -1062,7 +1370,7 @@ import { ObjectId as ObjectId5 } from "mongodb";
1062
1370
  import {
1063
1371
  useAtlas as useAtlas3,
1064
1372
  InternalServerError as InternalServerError3,
1065
- paginate as paginate2,
1373
+ paginate as paginate3,
1066
1374
  BadRequestError as BadRequestError6,
1067
1375
  useCache as useCache3,
1068
1376
  logger as logger7,
@@ -1073,10 +1381,10 @@ import {
1073
1381
  import Joi3 from "joi";
1074
1382
  import { ObjectId as ObjectId4 } from "mongodb";
1075
1383
  import { BadRequestError as BadRequestError5, logger as logger6 } from "@7365admin1/node-server-utils";
1076
- import { AppServiceType as AppServiceType2 } from "@7365admin1/core";
1384
+ import { AppServiceType as AppServiceType3 } from "@7365admin1/core";
1077
1385
  var unitSchema = Joi3.object({
1078
1386
  site: Joi3.string().hex().required(),
1079
- serviceType: Joi3.string().valid(...Object.values(AppServiceType2)).required(),
1387
+ serviceType: Joi3.string().valid(...Object.values(AppServiceType3)).required(),
1080
1388
  name: Joi3.string().required()
1081
1389
  });
1082
1390
  function MUnit(value) {
@@ -1208,7 +1516,7 @@ function useUnitRepository() {
1208
1516
  { $limit: limit }
1209
1517
  ]).toArray();
1210
1518
  const length = await collection.countDocuments(query);
1211
- const data = paginate2(items, page, limit, length);
1519
+ const data = paginate3(items, page, limit, length);
1212
1520
  setCache(cacheKey, data, 15 * 60).then(() => {
1213
1521
  logger7.info(`Cache set for key: ${cacheKey}`);
1214
1522
  }).catch((err) => {
@@ -1497,7 +1805,7 @@ function useAreaService() {
1497
1805
  // src/controllers/hygiene-area.controller.ts
1498
1806
  import Joi4 from "joi";
1499
1807
  import { BadRequestError as BadRequestError8, logger as logger9 } from "@7365admin1/node-server-utils";
1500
- import { AppServiceType as AppServiceType3 } from "@7365admin1/core";
1808
+ import { AppServiceType as AppServiceType4 } from "@7365admin1/core";
1501
1809
 
1502
1810
  // src/utils/convert-excel.util.ts
1503
1811
  import { Readable } from "stream";
@@ -1562,7 +1870,7 @@ function useAreaController() {
1562
1870
  search: Joi4.string().optional().allow("", null),
1563
1871
  type: Joi4.string().valid("all", ...allowedTypes).optional().allow("", null),
1564
1872
  site: Joi4.string().hex().required(),
1565
- serviceType: Joi4.string().valid(...Object.values(AppServiceType3)).required()
1873
+ serviceType: Joi4.string().valid(...Object.values(AppServiceType4)).required()
1566
1874
  });
1567
1875
  const { error } = validation.validate(query);
1568
1876
  if (error) {
@@ -1671,7 +1979,7 @@ function useAreaController() {
1671
1979
  const query = { ...req.query, ...req.params };
1672
1980
  const validation = Joi4.object({
1673
1981
  site: Joi4.string().hex().required(),
1674
- serviceType: Joi4.string().valid(...Object.values(AppServiceType3)).required()
1982
+ serviceType: Joi4.string().valid(...Object.values(AppServiceType4)).required()
1675
1983
  });
1676
1984
  const { error, value } = validation.validate(query);
1677
1985
  if (error) {
@@ -1694,7 +2002,7 @@ function useAreaController() {
1694
2002
  const query = { ...req.query, ...req.params };
1695
2003
  const validation = Joi4.object({
1696
2004
  site: Joi4.string().hex().required(),
1697
- serviceType: Joi4.string().valid(...Object.values(AppServiceType3)).required()
2005
+ serviceType: Joi4.string().valid(...Object.values(AppServiceType4)).required()
1698
2006
  });
1699
2007
  const { error, value } = validation.validate(query);
1700
2008
  if (error) {
@@ -1977,7 +2285,7 @@ function useUnitService() {
1977
2285
  // src/controllers/hygiene-unit.controller.ts
1978
2286
  import Joi5 from "joi";
1979
2287
  import { BadRequestError as BadRequestError10, logger as logger12 } from "@7365admin1/node-server-utils";
1980
- import { AppServiceType as AppServiceType4 } from "@7365admin1/core";
2288
+ import { AppServiceType as AppServiceType5 } from "@7365admin1/core";
1981
2289
  function useUnitController() {
1982
2290
  const { createUnit: _createUnit, getUnits: _getUnits } = useUnitRepository();
1983
2291
  const {
@@ -2011,7 +2319,7 @@ function useUnitController() {
2011
2319
  limit: Joi5.number().min(1).optional().allow("", null),
2012
2320
  search: Joi5.string().optional().allow("", null),
2013
2321
  site: Joi5.string().hex().required(),
2014
- serviceType: Joi5.string().valid(...Object.values(AppServiceType4)).required()
2322
+ serviceType: Joi5.string().valid(...Object.values(AppServiceType5)).required()
2015
2323
  });
2016
2324
  const { error } = validation.validate(query);
2017
2325
  if (error) {
@@ -2092,7 +2400,7 @@ function useUnitController() {
2092
2400
  const query = { ...req.query, ...req.params };
2093
2401
  const validation = Joi5.object({
2094
2402
  site: Joi5.string().hex().required(),
2095
- serviceType: Joi5.string().valid(...Object.values(AppServiceType4)).required()
2403
+ serviceType: Joi5.string().valid(...Object.values(AppServiceType5)).required()
2096
2404
  });
2097
2405
  const { error, value } = validation.validate(query);
2098
2406
  if (error) {
@@ -2115,7 +2423,7 @@ function useUnitController() {
2115
2423
  const query = { ...req.query, ...req.params };
2116
2424
  const validation = Joi5.object({
2117
2425
  site: Joi5.string().hex().required(),
2118
- serviceType: Joi5.string().valid(...Object.values(AppServiceType4)).required()
2426
+ serviceType: Joi5.string().valid(...Object.values(AppServiceType5)).required()
2119
2427
  });
2120
2428
  const { error, value } = validation.validate(query);
2121
2429
  if (error) {
@@ -2161,11 +2469,11 @@ function useUnitController() {
2161
2469
  import Joi6 from "joi";
2162
2470
  import { ObjectId as ObjectId6 } from "mongodb";
2163
2471
  import { BadRequestError as BadRequestError11, logger as logger13 } from "@7365admin1/node-server-utils";
2164
- import { AppServiceType as AppServiceType5 } from "@7365admin1/core";
2472
+ import { AppServiceType as AppServiceType6 } from "@7365admin1/core";
2165
2473
  var parentChecklistSchema = Joi6.object({
2166
2474
  createdAt: Joi6.alternatives().try(Joi6.date(), Joi6.string()).optional().allow("", null),
2167
2475
  site: Joi6.string().hex().required(),
2168
- serviceType: Joi6.string().valid(...Object.values(AppServiceType5)).required()
2476
+ serviceType: Joi6.string().valid(...Object.values(AppServiceType6)).required()
2169
2477
  });
2170
2478
  function MParentChecklist(value) {
2171
2479
  const { error } = parentChecklistSchema.validate(value);
@@ -2194,13 +2502,13 @@ import { ObjectId as ObjectId7 } from "mongodb";
2194
2502
  import {
2195
2503
  useAtlas as useAtlas5,
2196
2504
  InternalServerError as InternalServerError4,
2197
- paginate as paginate3,
2505
+ paginate as paginate4,
2198
2506
  useCache as useCache4,
2199
2507
  logger as logger14,
2200
2508
  makeCacheKey as makeCacheKey4,
2201
2509
  BadRequestError as BadRequestError12
2202
2510
  } from "@7365admin1/node-server-utils";
2203
- import { AppServiceType as AppServiceType6 } from "@7365admin1/core";
2511
+ import { AppServiceType as AppServiceType7 } from "@7365admin1/core";
2204
2512
  function useParentChecklistRepo() {
2205
2513
  const db = useAtlas5.getDb();
2206
2514
  if (!db) {
@@ -2232,7 +2540,7 @@ function useParentChecklistRepo() {
2232
2540
  startOfDay.setUTCHours(0, 0, 0, 0);
2233
2541
  const endOfDay = new Date(currentDate);
2234
2542
  endOfDay.setUTCHours(23, 59, 59, 999);
2235
- const allServiceTypes = Object.values(AppServiceType6);
2543
+ const allServiceTypes = Object.values(AppServiceType7);
2236
2544
  const dateStr = currentDate.toISOString().split("T")[0];
2237
2545
  if (value.site) {
2238
2546
  let siteObjectId;
@@ -2456,7 +2764,7 @@ function useParentChecklistRepo() {
2456
2764
  );
2457
2765
  const items = await collection.aggregate(pipeline).toArray();
2458
2766
  const length = await collection.countDocuments(query);
2459
- const data = paginate3(items, page, limit, length);
2767
+ const data = paginate4(items, page, limit, length);
2460
2768
  setCache(cacheKey, data, 15 * 60).then(() => {
2461
2769
  logger14.info(`Cache set for key: ${cacheKey}`);
2462
2770
  }).catch((err) => {
@@ -2637,7 +2945,7 @@ function useParentChecklistRepo() {
2637
2945
  // src/controllers/hygiene-parent-checklist.controller.ts
2638
2946
  import Joi7 from "joi";
2639
2947
  import { BadRequestError as BadRequestError13, logger as logger15 } from "@7365admin1/node-server-utils";
2640
- import { AppServiceType as AppServiceType7 } from "@7365admin1/core";
2948
+ import { AppServiceType as AppServiceType8 } from "@7365admin1/core";
2641
2949
  function useParentChecklistController() {
2642
2950
  const {
2643
2951
  createParentChecklist: _createParentChecklist,
@@ -2648,7 +2956,7 @@ function useParentChecklistController() {
2648
2956
  const validation = Joi7.object({
2649
2957
  createdAt: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
2650
2958
  site: Joi7.string().hex().required(),
2651
- serviceType: Joi7.string().valid(...Object.values(AppServiceType7)).optional().allow("", null)
2959
+ serviceType: Joi7.string().valid(...Object.values(AppServiceType8)).optional().allow("", null)
2652
2960
  });
2653
2961
  const { error } = validation.validate(payload);
2654
2962
  if (error) {
@@ -2673,7 +2981,7 @@ function useParentChecklistController() {
2673
2981
  limit: Joi7.number().min(1).optional().allow("", null),
2674
2982
  search: Joi7.string().optional().allow("", null),
2675
2983
  site: Joi7.string().hex().required(),
2676
- serviceType: Joi7.string().valid(...Object.values(AppServiceType7)).required(),
2984
+ serviceType: Joi7.string().valid(...Object.values(AppServiceType8)).required(),
2677
2985
  startDate: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
2678
2986
  endDate: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
2679
2987
  status: Joi7.string().valid(...allowedStatus, "all").optional().allow("", null)
@@ -2721,11 +3029,11 @@ function useParentChecklistController() {
2721
3029
  import Joi8 from "joi";
2722
3030
  import { ObjectId as ObjectId8 } from "mongodb";
2723
3031
  import { BadRequestError as BadRequestError14, logger as logger16 } from "@7365admin1/node-server-utils";
2724
- import { AppServiceType as AppServiceType8 } from "@7365admin1/core";
3032
+ import { AppServiceType as AppServiceType9 } from "@7365admin1/core";
2725
3033
  var allowedChecklistStatus = ["open", "completed", "closed"];
2726
3034
  var areaChecklistSchema = Joi8.object({
2727
3035
  schedule: Joi8.string().hex().required(),
2728
- serviceType: Joi8.string().valid(...Object.values(AppServiceType8)).required(),
3036
+ serviceType: Joi8.string().valid(...Object.values(AppServiceType9)).required(),
2729
3037
  area: Joi8.string().hex().required(),
2730
3038
  name: Joi8.string().required(),
2731
3039
  type: Joi8.string().valid(...allowedTypes).required(),
@@ -2812,7 +3120,7 @@ import {
2812
3120
  InternalServerError as InternalServerError5,
2813
3121
  logger as logger17,
2814
3122
  makeCacheKey as makeCacheKey5,
2815
- paginate as paginate4,
3123
+ paginate as paginate5,
2816
3124
  useAtlas as useAtlas6,
2817
3125
  useCache as useCache5
2818
3126
  } from "@7365admin1/node-server-utils";
@@ -3003,7 +3311,7 @@ function useAreaChecklistRepo() {
3003
3311
  ];
3004
3312
  const items = await collection.aggregate(pipeline, { session }).toArray();
3005
3313
  const length = await collection.countDocuments(query, { session });
3006
- const data = paginate4(items, page, limit, length);
3314
+ const data = paginate5(items, page, limit, length);
3007
3315
  setCache(cacheKey, data, 15 * 60).then(() => {
3008
3316
  logger17.info(`Cache set for key: ${cacheKey}`);
3009
3317
  }).catch((err) => {
@@ -3111,7 +3419,7 @@ function useAreaChecklistRepo() {
3111
3419
  ];
3112
3420
  const items = await collection.aggregate(pipeline).toArray();
3113
3421
  const length = await collection.countDocuments(query);
3114
- const data = paginate4(items, page, limit, length);
3422
+ const data = paginate5(items, page, limit, length);
3115
3423
  setCache(cacheKey, data, 15 * 60).then(() => {
3116
3424
  logger17.info(`Cache set for key: ${cacheKey}`);
3117
3425
  }).catch((err) => {
@@ -3498,7 +3806,7 @@ function useAreaChecklistRepo() {
3498
3806
  collection.aggregate(countPipeline, { session }).toArray()
3499
3807
  ]);
3500
3808
  const length = countResult.length > 0 ? countResult[0].total : 0;
3501
- const data = paginate4(items, page, limit, length);
3809
+ const data = paginate5(items, page, limit, length);
3502
3810
  setCache(cacheKey, data, 15 * 60).then(() => {
3503
3811
  logger17.info(`Cache set for key: ${cacheKey}`);
3504
3812
  }).catch((err) => {
@@ -4177,7 +4485,7 @@ import {
4177
4485
  InternalServerError as InternalServerError7,
4178
4486
  logger as logger20
4179
4487
  } from "@7365admin1/node-server-utils";
4180
- import { AppServiceType as AppServiceType9 } from "@7365admin1/core";
4488
+ import { AppServiceType as AppServiceType10 } from "@7365admin1/core";
4181
4489
 
4182
4490
  // src/services/hygiene-checklist-pdf.service.ts
4183
4491
  import { launch } from "puppeteer";
@@ -4444,7 +4752,7 @@ function useAreaChecklistController() {
4444
4752
  type: Joi9.string().valid(...allowedTypes, "all").optional().allow("", null),
4445
4753
  status: Joi9.string().valid(...allowedStatus, "all").optional().allow("", null),
4446
4754
  schedule: Joi9.string().hex().required(),
4447
- serviceType: Joi9.string().valid(...Object.values(AppServiceType9)).required()
4755
+ serviceType: Joi9.string().valid(...Object.values(AppServiceType10)).required()
4448
4756
  });
4449
4757
  const { error } = validation.validate(query);
4450
4758
  if (error) {
@@ -4544,7 +4852,7 @@ function useAreaChecklistController() {
4544
4852
  page: Joi9.number().min(1).optional().allow("", null),
4545
4853
  limit: Joi9.number().min(1).optional().allow("", null),
4546
4854
  search: Joi9.string().optional().allow("", null),
4547
- serviceType: Joi9.string().valid(...Object.values(AppServiceType9)).required(),
4855
+ serviceType: Joi9.string().valid(...Object.values(AppServiceType10)).required(),
4548
4856
  id: Joi9.string().hex().required()
4549
4857
  });
4550
4858
  const { error } = validation.validate(query);
@@ -4673,10 +4981,10 @@ function useAreaChecklistController() {
4673
4981
  import Joi10 from "joi";
4674
4982
  import { ObjectId as ObjectId12 } from "mongodb";
4675
4983
  import { BadRequestError as BadRequestError17, logger as logger21 } from "@7365admin1/node-server-utils";
4676
- import { AppServiceType as AppServiceType10 } from "@7365admin1/core";
4984
+ import { AppServiceType as AppServiceType11 } from "@7365admin1/core";
4677
4985
  var supplySchema = Joi10.object({
4678
4986
  site: Joi10.string().hex().required(),
4679
- serviceType: Joi10.string().valid(...Object.values(AppServiceType10)).required(),
4987
+ serviceType: Joi10.string().valid(...Object.values(AppServiceType11)).required(),
4680
4988
  name: Joi10.string().required(),
4681
4989
  unitOfMeasurement: Joi10.string().required()
4682
4990
  });
@@ -4711,7 +5019,7 @@ import { ObjectId as ObjectId13 } from "mongodb";
4711
5019
  import {
4712
5020
  useAtlas as useAtlas9,
4713
5021
  InternalServerError as InternalServerError8,
4714
- paginate as paginate5,
5022
+ paginate as paginate6,
4715
5023
  BadRequestError as BadRequestError18,
4716
5024
  useCache as useCache6,
4717
5025
  logger as logger22,
@@ -4829,7 +5137,7 @@ function useSupplyRepository() {
4829
5137
  { $limit: limit }
4830
5138
  ]).toArray();
4831
5139
  const length = await collection.countDocuments(query);
4832
- const data = paginate5(items, page, limit, length);
5140
+ const data = paginate6(items, page, limit, length);
4833
5141
  setCache(cacheKey, data, 15 * 60).then(() => {
4834
5142
  logger22.info(`Cache set for key: ${cacheKey}`);
4835
5143
  }).catch((err) => {
@@ -4967,7 +5275,7 @@ function useSupplyRepository() {
4967
5275
  // src/controllers/hygiene-supply.controller.ts
4968
5276
  import Joi11 from "joi";
4969
5277
  import { BadRequestError as BadRequestError19, logger as logger23 } from "@7365admin1/node-server-utils";
4970
- import { AppServiceType as AppServiceType11 } from "@7365admin1/core";
5278
+ import { AppServiceType as AppServiceType12 } from "@7365admin1/core";
4971
5279
  function useSupplyController() {
4972
5280
  const {
4973
5281
  createSupply: _createSupply,
@@ -5001,7 +5309,7 @@ function useSupplyController() {
5001
5309
  limit: Joi11.number().min(1).optional().allow("", null),
5002
5310
  search: Joi11.string().optional().allow("", null),
5003
5311
  site: Joi11.string().hex().required(),
5004
- serviceType: Joi11.string().valid(...Object.values(AppServiceType11)).required()
5312
+ serviceType: Joi11.string().valid(...Object.values(AppServiceType12)).required()
5005
5313
  });
5006
5314
  const { error } = validation.validate(query);
5007
5315
  if (error) {
@@ -5106,10 +5414,10 @@ function useSupplyController() {
5106
5414
  import Joi12 from "joi";
5107
5415
  import { ObjectId as ObjectId14 } from "mongodb";
5108
5416
  import { BadRequestError as BadRequestError20, logger as logger24 } from "@7365admin1/node-server-utils";
5109
- import { AppServiceType as AppServiceType12 } from "@7365admin1/core";
5417
+ import { AppServiceType as AppServiceType13 } from "@7365admin1/core";
5110
5418
  var stockSchema = Joi12.object({
5111
5419
  site: Joi12.string().hex().required(),
5112
- serviceType: Joi12.string().valid(...Object.values(AppServiceType12)).required(),
5420
+ serviceType: Joi12.string().valid(...Object.values(AppServiceType13)).required(),
5113
5421
  supply: Joi12.string().hex().required(),
5114
5422
  in: Joi12.number().min(0).optional(),
5115
5423
  out: Joi12.number().min(0).optional(),
@@ -5160,7 +5468,7 @@ import {
5160
5468
  useCache as useCache7,
5161
5469
  logger as logger25,
5162
5470
  makeCacheKey as makeCacheKey7,
5163
- paginate as paginate6
5471
+ paginate as paginate7
5164
5472
  } from "@7365admin1/node-server-utils";
5165
5473
  function useStockRepository() {
5166
5474
  const db = useAtlas10.getDb();
@@ -5268,7 +5576,7 @@ function useStockRepository() {
5268
5576
  { $limit: limit }
5269
5577
  ]).toArray();
5270
5578
  const length = await collection.countDocuments(query);
5271
- const data = paginate6(items, page, limit, length);
5579
+ const data = paginate7(items, page, limit, length);
5272
5580
  setCache(cacheKey, data, 15 * 60).then(() => {
5273
5581
  logger25.info(`Cache set for key: ${cacheKey}`);
5274
5582
  }).catch((err) => {
@@ -5343,7 +5651,7 @@ function useStockService() {
5343
5651
  // src/controllers/hygiene-stock.controller.ts
5344
5652
  import Joi13 from "joi";
5345
5653
  import { BadRequestError as BadRequestError23, logger as logger26 } from "@7365admin1/node-server-utils";
5346
- import { AppServiceType as AppServiceType13 } from "@7365admin1/core";
5654
+ import { AppServiceType as AppServiceType14 } from "@7365admin1/core";
5347
5655
  function useStockController() {
5348
5656
  const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
5349
5657
  const { createStock: _createStock } = useStockService();
@@ -5351,7 +5659,7 @@ function useStockController() {
5351
5659
  const payload = { ...req.body, ...req.params };
5352
5660
  const validation = Joi13.object({
5353
5661
  site: Joi13.string().hex().required(),
5354
- serviceType: Joi13.string().valid(...Object.values(AppServiceType13)).required(),
5662
+ serviceType: Joi13.string().valid(...Object.values(AppServiceType14)).required(),
5355
5663
  supply: Joi13.string().hex().required(),
5356
5664
  qty: Joi13.number().min(0).required(),
5357
5665
  remarks: Joi13.string().optional().allow("", null)
@@ -5379,7 +5687,7 @@ function useStockController() {
5379
5687
  limit: Joi13.number().min(1).optional().allow("", null),
5380
5688
  search: Joi13.string().optional().allow("", null),
5381
5689
  site: Joi13.string().hex().required(),
5382
- serviceType: Joi13.string().valid(...Object.values(AppServiceType13)).required(),
5690
+ serviceType: Joi13.string().valid(...Object.values(AppServiceType14)).required(),
5383
5691
  supply: Joi13.string().hex().required()
5384
5692
  });
5385
5693
  const { error } = validation.validate(query);
@@ -5421,11 +5729,11 @@ function useStockController() {
5421
5729
  import Joi14 from "joi";
5422
5730
  import { ObjectId as ObjectId16 } from "mongodb";
5423
5731
  import { BadRequestError as BadRequestError24, logger as logger27 } from "@7365admin1/node-server-utils";
5424
- import { AppServiceType as AppServiceType14 } from "@7365admin1/core";
5732
+ import { AppServiceType as AppServiceType15 } from "@7365admin1/core";
5425
5733
  var allowedCheckOutItemStatus = ["pending", "completed"];
5426
5734
  var checkOutItemSchema = Joi14.object({
5427
5735
  site: Joi14.string().hex().required(),
5428
- serviceType: Joi14.string().valid(...Object.values(AppServiceType14)).required(),
5736
+ serviceType: Joi14.string().valid(...Object.values(AppServiceType15)).required(),
5429
5737
  supply: Joi14.string().hex().required(),
5430
5738
  supplyName: Joi14.string().required(),
5431
5739
  qty: Joi14.number().min(0).required(),
@@ -5477,7 +5785,7 @@ import {
5477
5785
  useCache as useCache8,
5478
5786
  logger as logger28,
5479
5787
  makeCacheKey as makeCacheKey8,
5480
- paginate as paginate7,
5788
+ paginate as paginate8,
5481
5789
  BadRequestError as BadRequestError25,
5482
5790
  NotFoundError as NotFoundError6
5483
5791
  } from "@7365admin1/node-server-utils";
@@ -5636,7 +5944,7 @@ function useCheckOutItemRepository() {
5636
5944
  { $limit: limit }
5637
5945
  ]).toArray();
5638
5946
  const length = await collection.countDocuments(query);
5639
- const data = paginate7(items, page, limit, length);
5947
+ const data = paginate8(items, page, limit, length);
5640
5948
  setCache(cacheKey, data, 15 * 60).then(() => {
5641
5949
  logger28.info(`Cache set for key: ${cacheKey}`);
5642
5950
  }).catch((err) => {
@@ -5859,7 +6167,7 @@ function useCheckOutItemService() {
5859
6167
  // src/controllers/hygiene-checkout-item.controller.ts
5860
6168
  import Joi15 from "joi";
5861
6169
  import { BadRequestError as BadRequestError27, logger as logger29 } from "@7365admin1/node-server-utils";
5862
- import { AppServiceType as AppServiceType15 } from "@7365admin1/core";
6170
+ import { AppServiceType as AppServiceType16 } from "@7365admin1/core";
5863
6171
  function useCheckOutItemController() {
5864
6172
  const {
5865
6173
  getCheckOutItems: _getCheckOutItems,
@@ -5882,7 +6190,7 @@ function useCheckOutItemController() {
5882
6190
  };
5883
6191
  const validation = Joi15.object({
5884
6192
  site: Joi15.string().hex().required(),
5885
- serviceType: Joi15.string().valid(...Object.values(AppServiceType15)).required(),
6193
+ serviceType: Joi15.string().valid(...Object.values(AppServiceType16)).required(),
5886
6194
  supply: Joi15.string().hex().required(),
5887
6195
  qty: Joi15.number().min(0).required(),
5888
6196
  attachment: Joi15.array().items(Joi15.string()).optional().allow(null),
@@ -5917,7 +6225,7 @@ function useCheckOutItemController() {
5917
6225
  };
5918
6226
  const validation = Joi15.object({
5919
6227
  site: Joi15.string().hex().required(),
5920
- serviceType: Joi15.string().valid(...Object.values(AppServiceType15)).required(),
6228
+ serviceType: Joi15.string().valid(...Object.values(AppServiceType16)).required(),
5921
6229
  createdBy: Joi15.string().hex().required(),
5922
6230
  items: Joi15.array().items(
5923
6231
  Joi15.object({
@@ -5950,7 +6258,7 @@ function useCheckOutItemController() {
5950
6258
  limit: Joi15.number().min(1).optional().allow("", null),
5951
6259
  search: Joi15.string().optional().allow("", null),
5952
6260
  site: Joi15.string().hex().required(),
5953
- serviceType: Joi15.string().valid(...Object.values(AppServiceType15)).required()
6261
+ serviceType: Joi15.string().valid(...Object.values(AppServiceType16)).required()
5954
6262
  });
5955
6263
  const { error } = validation.validate(query);
5956
6264
  if (error) {
@@ -6008,12 +6316,12 @@ function useCheckOutItemController() {
6008
6316
 
6009
6317
  // src/models/hygiene-schedule-task.model.ts
6010
6318
  import { BadRequestError as BadRequestError28, logger as logger30 } from "@7365admin1/node-server-utils";
6011
- import { AppServiceType as AppServiceType16 } from "@7365admin1/core";
6319
+ import { AppServiceType as AppServiceType17 } from "@7365admin1/core";
6012
6320
  import Joi16 from "joi";
6013
6321
  import { ObjectId as ObjectId18 } from "mongodb";
6014
6322
  var scheduleTaskSchema = Joi16.object({
6015
6323
  site: Joi16.string().hex().required(),
6016
- serviceType: Joi16.string().valid(...Object.values(AppServiceType16)).required(),
6324
+ serviceType: Joi16.string().valid(...Object.values(AppServiceType17)).required(),
6017
6325
  title: Joi16.string().required(),
6018
6326
  time: Joi16.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).required(),
6019
6327
  dates: Joi16.array().min(1).items(
@@ -6072,7 +6380,7 @@ import { ObjectId as ObjectId19 } from "mongodb";
6072
6380
  import {
6073
6381
  useAtlas as useAtlas14,
6074
6382
  InternalServerError as InternalServerError11,
6075
- paginate as paginate8,
6383
+ paginate as paginate9,
6076
6384
  BadRequestError as BadRequestError29,
6077
6385
  useCache as useCache9,
6078
6386
  logger as logger31,
@@ -6175,7 +6483,7 @@ function useScheduleTaskRepository() {
6175
6483
  { $limit: limit }
6176
6484
  ]).toArray();
6177
6485
  const length = await collection.countDocuments(query);
6178
- const data = paginate8(items, page, limit, length);
6486
+ const data = paginate9(items, page, limit, length);
6179
6487
  setCache(cacheKey, data, 15 * 60).then(() => {
6180
6488
  logger31.info(`Cache set for key: ${cacheKey}`);
6181
6489
  }).catch((err) => {
@@ -6628,7 +6936,7 @@ function useScheduleTaskService() {
6628
6936
  // src/controllers/hygiene-schedule-task.controller.ts
6629
6937
  import Joi17 from "joi";
6630
6938
  import { BadRequestError as BadRequestError30, logger as logger33 } from "@7365admin1/node-server-utils";
6631
- import { AppServiceType as AppServiceType17 } from "@7365admin1/core";
6939
+ import { AppServiceType as AppServiceType18 } from "@7365admin1/core";
6632
6940
  function useScheduleTaskController() {
6633
6941
  const {
6634
6942
  createScheduleTask: _createScheduleTask,
@@ -6662,7 +6970,7 @@ function useScheduleTaskController() {
6662
6970
  limit: Joi17.number().min(1).optional().allow("", null),
6663
6971
  search: Joi17.string().optional().allow("", null),
6664
6972
  site: Joi17.string().hex().required(),
6665
- serviceType: Joi17.string().valid(...Object.values(AppServiceType17)).required()
6973
+ serviceType: Joi17.string().valid(...Object.values(AppServiceType18)).required()
6666
6974
  });
6667
6975
  const { error } = validation.validate(query);
6668
6976
  if (error) {