@7365admin1/module-hygiene 4.21.0 → 4.23.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);
@@ -2191,16 +2499,17 @@ function MParentChecklist(value) {
2191
2499
 
2192
2500
  // src/repositories/hygiene-parent-checklist.repository.ts
2193
2501
  import { ObjectId as ObjectId7 } from "mongodb";
2502
+ import moment2 from "moment-timezone";
2194
2503
  import {
2195
2504
  useAtlas as useAtlas5,
2196
2505
  InternalServerError as InternalServerError4,
2197
- paginate as paginate3,
2506
+ paginate as paginate4,
2198
2507
  useCache as useCache4,
2199
2508
  logger as logger14,
2200
2509
  makeCacheKey as makeCacheKey4,
2201
2510
  BadRequestError as BadRequestError12
2202
2511
  } from "@7365admin1/node-server-utils";
2203
- import { AppServiceType as AppServiceType6 } from "@7365admin1/core";
2512
+ import { AppServiceType as AppServiceType7 } from "@7365admin1/core";
2204
2513
  function useParentChecklistRepo() {
2205
2514
  const db = useAtlas5.getDb();
2206
2515
  if (!db) {
@@ -2228,11 +2537,9 @@ function useParentChecklistRepo() {
2228
2537
  async function createParentChecklist(value, session) {
2229
2538
  try {
2230
2539
  const currentDate = value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date();
2231
- const startOfDay = new Date(currentDate);
2232
- startOfDay.setUTCHours(0, 0, 0, 0);
2233
- const endOfDay = new Date(currentDate);
2234
- endOfDay.setUTCHours(23, 59, 59, 999);
2235
- const allServiceTypes = Object.values(AppServiceType6);
2540
+ const startOfDay = moment2(currentDate).tz("Asia/Singapore").startOf("day").toDate();
2541
+ const endOfDay = moment2(currentDate).tz("Asia/Singapore").endOf("day").toDate();
2542
+ const allServiceTypes = Object.values(AppServiceType7);
2236
2543
  const dateStr = currentDate.toISOString().split("T")[0];
2237
2544
  if (value.site) {
2238
2545
  let siteObjectId;
@@ -2456,7 +2763,7 @@ function useParentChecklistRepo() {
2456
2763
  );
2457
2764
  const items = await collection.aggregate(pipeline).toArray();
2458
2765
  const length = await collection.countDocuments(query);
2459
- const data = paginate3(items, page, limit, length);
2766
+ const data = paginate4(items, page, limit, length);
2460
2767
  setCache(cacheKey, data, 15 * 60).then(() => {
2461
2768
  logger14.info(`Cache set for key: ${cacheKey}`);
2462
2769
  }).catch((err) => {
@@ -2582,11 +2889,8 @@ function useParentChecklistRepo() {
2582
2889
  }
2583
2890
  }
2584
2891
  async function getTodayParentChecklists() {
2585
- const now = /* @__PURE__ */ new Date();
2586
- const start = new Date(now);
2587
- start.setUTCHours(0, 0, 0, 0);
2588
- const end = new Date(now);
2589
- end.setUTCHours(23, 59, 59, 999);
2892
+ const start = moment2().tz("Asia/Singapore").startOf("day").toDate();
2893
+ const end = moment2().tz("Asia/Singapore").endOf("day").toDate();
2590
2894
  try {
2591
2895
  const items = await collection.find(
2592
2896
  { createdAt: { $gte: start, $lte: end } },
@@ -2599,11 +2903,8 @@ function useParentChecklistRepo() {
2599
2903
  }
2600
2904
  }
2601
2905
  async function getTodayParentChecklistsForAreaGen() {
2602
- const now = /* @__PURE__ */ new Date();
2603
- const start = new Date(now);
2604
- start.setUTCHours(0, 0, 0, 0);
2605
- const end = new Date(now);
2606
- end.setUTCHours(23, 59, 59, 999);
2906
+ const start = moment2().tz("Asia/Singapore").startOf("day").toDate();
2907
+ const end = moment2().tz("Asia/Singapore").endOf("day").toDate();
2607
2908
  try {
2608
2909
  const items = await collection.find(
2609
2910
  {
@@ -2637,7 +2938,7 @@ function useParentChecklistRepo() {
2637
2938
  // src/controllers/hygiene-parent-checklist.controller.ts
2638
2939
  import Joi7 from "joi";
2639
2940
  import { BadRequestError as BadRequestError13, logger as logger15 } from "@7365admin1/node-server-utils";
2640
- import { AppServiceType as AppServiceType7 } from "@7365admin1/core";
2941
+ import { AppServiceType as AppServiceType8 } from "@7365admin1/core";
2641
2942
  function useParentChecklistController() {
2642
2943
  const {
2643
2944
  createParentChecklist: _createParentChecklist,
@@ -2648,7 +2949,7 @@ function useParentChecklistController() {
2648
2949
  const validation = Joi7.object({
2649
2950
  createdAt: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
2650
2951
  site: Joi7.string().hex().required(),
2651
- serviceType: Joi7.string().valid(...Object.values(AppServiceType7)).optional().allow("", null)
2952
+ serviceType: Joi7.string().valid(...Object.values(AppServiceType8)).optional().allow("", null)
2652
2953
  });
2653
2954
  const { error } = validation.validate(payload);
2654
2955
  if (error) {
@@ -2673,7 +2974,7 @@ function useParentChecklistController() {
2673
2974
  limit: Joi7.number().min(1).optional().allow("", null),
2674
2975
  search: Joi7.string().optional().allow("", null),
2675
2976
  site: Joi7.string().hex().required(),
2676
- serviceType: Joi7.string().valid(...Object.values(AppServiceType7)).required(),
2977
+ serviceType: Joi7.string().valid(...Object.values(AppServiceType8)).required(),
2677
2978
  startDate: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
2678
2979
  endDate: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
2679
2980
  status: Joi7.string().valid(...allowedStatus, "all").optional().allow("", null)
@@ -2721,11 +3022,11 @@ function useParentChecklistController() {
2721
3022
  import Joi8 from "joi";
2722
3023
  import { ObjectId as ObjectId8 } from "mongodb";
2723
3024
  import { BadRequestError as BadRequestError14, logger as logger16 } from "@7365admin1/node-server-utils";
2724
- import { AppServiceType as AppServiceType8 } from "@7365admin1/core";
3025
+ import { AppServiceType as AppServiceType9 } from "@7365admin1/core";
2725
3026
  var allowedChecklistStatus = ["open", "completed", "closed"];
2726
3027
  var areaChecklistSchema = Joi8.object({
2727
3028
  schedule: Joi8.string().hex().required(),
2728
- serviceType: Joi8.string().valid(...Object.values(AppServiceType8)).required(),
3029
+ serviceType: Joi8.string().valid(...Object.values(AppServiceType9)).required(),
2729
3030
  area: Joi8.string().hex().required(),
2730
3031
  name: Joi8.string().required(),
2731
3032
  type: Joi8.string().valid(...allowedTypes).required(),
@@ -2812,7 +3113,7 @@ import {
2812
3113
  InternalServerError as InternalServerError5,
2813
3114
  logger as logger17,
2814
3115
  makeCacheKey as makeCacheKey5,
2815
- paginate as paginate4,
3116
+ paginate as paginate5,
2816
3117
  useAtlas as useAtlas6,
2817
3118
  useCache as useCache5
2818
3119
  } from "@7365admin1/node-server-utils";
@@ -3003,7 +3304,7 @@ function useAreaChecklistRepo() {
3003
3304
  ];
3004
3305
  const items = await collection.aggregate(pipeline, { session }).toArray();
3005
3306
  const length = await collection.countDocuments(query, { session });
3006
- const data = paginate4(items, page, limit, length);
3307
+ const data = paginate5(items, page, limit, length);
3007
3308
  setCache(cacheKey, data, 15 * 60).then(() => {
3008
3309
  logger17.info(`Cache set for key: ${cacheKey}`);
3009
3310
  }).catch((err) => {
@@ -3111,7 +3412,7 @@ function useAreaChecklistRepo() {
3111
3412
  ];
3112
3413
  const items = await collection.aggregate(pipeline).toArray();
3113
3414
  const length = await collection.countDocuments(query);
3114
- const data = paginate4(items, page, limit, length);
3415
+ const data = paginate5(items, page, limit, length);
3115
3416
  setCache(cacheKey, data, 15 * 60).then(() => {
3116
3417
  logger17.info(`Cache set for key: ${cacheKey}`);
3117
3418
  }).catch((err) => {
@@ -3498,7 +3799,7 @@ function useAreaChecklistRepo() {
3498
3799
  collection.aggregate(countPipeline, { session }).toArray()
3499
3800
  ]);
3500
3801
  const length = countResult.length > 0 ? countResult[0].total : 0;
3501
- const data = paginate4(items, page, limit, length);
3802
+ const data = paginate5(items, page, limit, length);
3502
3803
  setCache(cacheKey, data, 15 * 60).then(() => {
3503
3804
  logger17.info(`Cache set for key: ${cacheKey}`);
3504
3805
  }).catch((err) => {
@@ -4177,7 +4478,7 @@ import {
4177
4478
  InternalServerError as InternalServerError7,
4178
4479
  logger as logger20
4179
4480
  } from "@7365admin1/node-server-utils";
4180
- import { AppServiceType as AppServiceType9 } from "@7365admin1/core";
4481
+ import { AppServiceType as AppServiceType10 } from "@7365admin1/core";
4181
4482
 
4182
4483
  // src/services/hygiene-checklist-pdf.service.ts
4183
4484
  import { launch } from "puppeteer";
@@ -4444,7 +4745,7 @@ function useAreaChecklistController() {
4444
4745
  type: Joi9.string().valid(...allowedTypes, "all").optional().allow("", null),
4445
4746
  status: Joi9.string().valid(...allowedStatus, "all").optional().allow("", null),
4446
4747
  schedule: Joi9.string().hex().required(),
4447
- serviceType: Joi9.string().valid(...Object.values(AppServiceType9)).required()
4748
+ serviceType: Joi9.string().valid(...Object.values(AppServiceType10)).required()
4448
4749
  });
4449
4750
  const { error } = validation.validate(query);
4450
4751
  if (error) {
@@ -4544,7 +4845,7 @@ function useAreaChecklistController() {
4544
4845
  page: Joi9.number().min(1).optional().allow("", null),
4545
4846
  limit: Joi9.number().min(1).optional().allow("", null),
4546
4847
  search: Joi9.string().optional().allow("", null),
4547
- serviceType: Joi9.string().valid(...Object.values(AppServiceType9)).required(),
4848
+ serviceType: Joi9.string().valid(...Object.values(AppServiceType10)).required(),
4548
4849
  id: Joi9.string().hex().required()
4549
4850
  });
4550
4851
  const { error } = validation.validate(query);
@@ -4673,12 +4974,13 @@ function useAreaChecklistController() {
4673
4974
  import Joi10 from "joi";
4674
4975
  import { ObjectId as ObjectId12 } from "mongodb";
4675
4976
  import { BadRequestError as BadRequestError17, logger as logger21 } from "@7365admin1/node-server-utils";
4676
- import { AppServiceType as AppServiceType10 } from "@7365admin1/core";
4977
+ import { AppServiceType as AppServiceType11 } from "@7365admin1/core";
4677
4978
  var supplySchema = Joi10.object({
4678
4979
  site: Joi10.string().hex().required(),
4679
- serviceType: Joi10.string().valid(...Object.values(AppServiceType10)).required(),
4980
+ serviceType: Joi10.string().valid(...Object.values(AppServiceType11)).required(),
4680
4981
  name: Joi10.string().required(),
4681
- unitOfMeasurement: Joi10.string().required()
4982
+ unitOfMeasurement: Joi10.string().required(),
4983
+ attachment: Joi10.string().allow(null, "").optional()
4682
4984
  });
4683
4985
  function MSupply(value) {
4684
4986
  const { error } = supplySchema.validate(value);
@@ -4699,6 +5001,7 @@ function MSupply(value) {
4699
5001
  name: value.name,
4700
5002
  unitOfMeasurement: value.unitOfMeasurement,
4701
5003
  qty: 0,
5004
+ attachment: value.attachment,
4702
5005
  status: "active",
4703
5006
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4704
5007
  updatedAt: "",
@@ -4711,7 +5014,7 @@ import { ObjectId as ObjectId13 } from "mongodb";
4711
5014
  import {
4712
5015
  useAtlas as useAtlas9,
4713
5016
  InternalServerError as InternalServerError8,
4714
- paginate as paginate5,
5017
+ paginate as paginate6,
4715
5018
  BadRequestError as BadRequestError18,
4716
5019
  useCache as useCache6,
4717
5020
  logger as logger22,
@@ -4819,6 +5122,7 @@ function useSupplyRepository() {
4819
5122
  { $match: query },
4820
5123
  {
4821
5124
  $project: {
5125
+ attachment: 1,
4822
5126
  name: 1,
4823
5127
  qty: 1,
4824
5128
  status: 1
@@ -4829,7 +5133,7 @@ function useSupplyRepository() {
4829
5133
  { $limit: limit }
4830
5134
  ]).toArray();
4831
5135
  const length = await collection.countDocuments(query);
4832
- const data = paginate5(items, page, limit, length);
5136
+ const data = paginate6(items, page, limit, length);
4833
5137
  setCache(cacheKey, data, 15 * 60).then(() => {
4834
5138
  logger22.info(`Cache set for key: ${cacheKey}`);
4835
5139
  }).catch((err) => {
@@ -4867,6 +5171,7 @@ function useSupplyRepository() {
4867
5171
  { $match: query },
4868
5172
  {
4869
5173
  $project: {
5174
+ attachment: 1,
4870
5175
  name: 1,
4871
5176
  unitOfMeasurement: 1,
4872
5177
  qty: 1
@@ -4967,7 +5272,7 @@ function useSupplyRepository() {
4967
5272
  // src/controllers/hygiene-supply.controller.ts
4968
5273
  import Joi11 from "joi";
4969
5274
  import { BadRequestError as BadRequestError19, logger as logger23 } from "@7365admin1/node-server-utils";
4970
- import { AppServiceType as AppServiceType11 } from "@7365admin1/core";
5275
+ import { AppServiceType as AppServiceType12 } from "@7365admin1/core";
4971
5276
  function useSupplyController() {
4972
5277
  const {
4973
5278
  createSupply: _createSupply,
@@ -5001,7 +5306,7 @@ function useSupplyController() {
5001
5306
  limit: Joi11.number().min(1).optional().allow("", null),
5002
5307
  search: Joi11.string().optional().allow("", null),
5003
5308
  site: Joi11.string().hex().required(),
5004
- serviceType: Joi11.string().valid(...Object.values(AppServiceType11)).required()
5309
+ serviceType: Joi11.string().valid(...Object.values(AppServiceType12)).required()
5005
5310
  });
5006
5311
  const { error } = validation.validate(query);
5007
5312
  if (error) {
@@ -5055,7 +5360,8 @@ function useSupplyController() {
5055
5360
  id: Joi11.string().hex().required(),
5056
5361
  name: Joi11.string().optional().allow("", null),
5057
5362
  unitOfMeasurement: Joi11.string().optional().allow("", null),
5058
- qty: Joi11.number().min(0).optional().allow("", null)
5363
+ qty: Joi11.number().min(0).optional().allow("", null),
5364
+ attachment: Joi11.string().optional().allow("", null)
5059
5365
  });
5060
5366
  const { error } = validation.validate(payload);
5061
5367
  if (error) {
@@ -5106,10 +5412,10 @@ function useSupplyController() {
5106
5412
  import Joi12 from "joi";
5107
5413
  import { ObjectId as ObjectId14 } from "mongodb";
5108
5414
  import { BadRequestError as BadRequestError20, logger as logger24 } from "@7365admin1/node-server-utils";
5109
- import { AppServiceType as AppServiceType12 } from "@7365admin1/core";
5415
+ import { AppServiceType as AppServiceType13 } from "@7365admin1/core";
5110
5416
  var stockSchema = Joi12.object({
5111
5417
  site: Joi12.string().hex().required(),
5112
- serviceType: Joi12.string().valid(...Object.values(AppServiceType12)).required(),
5418
+ serviceType: Joi12.string().valid(...Object.values(AppServiceType13)).required(),
5113
5419
  supply: Joi12.string().hex().required(),
5114
5420
  in: Joi12.number().min(0).optional(),
5115
5421
  out: Joi12.number().min(0).optional(),
@@ -5160,7 +5466,7 @@ import {
5160
5466
  useCache as useCache7,
5161
5467
  logger as logger25,
5162
5468
  makeCacheKey as makeCacheKey7,
5163
- paginate as paginate6
5469
+ paginate as paginate7
5164
5470
  } from "@7365admin1/node-server-utils";
5165
5471
  function useStockRepository() {
5166
5472
  const db = useAtlas10.getDb();
@@ -5268,7 +5574,7 @@ function useStockRepository() {
5268
5574
  { $limit: limit }
5269
5575
  ]).toArray();
5270
5576
  const length = await collection.countDocuments(query);
5271
- const data = paginate6(items, page, limit, length);
5577
+ const data = paginate7(items, page, limit, length);
5272
5578
  setCache(cacheKey, data, 15 * 60).then(() => {
5273
5579
  logger25.info(`Cache set for key: ${cacheKey}`);
5274
5580
  }).catch((err) => {
@@ -5343,7 +5649,7 @@ function useStockService() {
5343
5649
  // src/controllers/hygiene-stock.controller.ts
5344
5650
  import Joi13 from "joi";
5345
5651
  import { BadRequestError as BadRequestError23, logger as logger26 } from "@7365admin1/node-server-utils";
5346
- import { AppServiceType as AppServiceType13 } from "@7365admin1/core";
5652
+ import { AppServiceType as AppServiceType14 } from "@7365admin1/core";
5347
5653
  function useStockController() {
5348
5654
  const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
5349
5655
  const { createStock: _createStock } = useStockService();
@@ -5351,7 +5657,7 @@ function useStockController() {
5351
5657
  const payload = { ...req.body, ...req.params };
5352
5658
  const validation = Joi13.object({
5353
5659
  site: Joi13.string().hex().required(),
5354
- serviceType: Joi13.string().valid(...Object.values(AppServiceType13)).required(),
5660
+ serviceType: Joi13.string().valid(...Object.values(AppServiceType14)).required(),
5355
5661
  supply: Joi13.string().hex().required(),
5356
5662
  qty: Joi13.number().min(0).required(),
5357
5663
  remarks: Joi13.string().optional().allow("", null)
@@ -5379,7 +5685,7 @@ function useStockController() {
5379
5685
  limit: Joi13.number().min(1).optional().allow("", null),
5380
5686
  search: Joi13.string().optional().allow("", null),
5381
5687
  site: Joi13.string().hex().required(),
5382
- serviceType: Joi13.string().valid(...Object.values(AppServiceType13)).required(),
5688
+ serviceType: Joi13.string().valid(...Object.values(AppServiceType14)).required(),
5383
5689
  supply: Joi13.string().hex().required()
5384
5690
  });
5385
5691
  const { error } = validation.validate(query);
@@ -5421,11 +5727,11 @@ function useStockController() {
5421
5727
  import Joi14 from "joi";
5422
5728
  import { ObjectId as ObjectId16 } from "mongodb";
5423
5729
  import { BadRequestError as BadRequestError24, logger as logger27 } from "@7365admin1/node-server-utils";
5424
- import { AppServiceType as AppServiceType14 } from "@7365admin1/core";
5730
+ import { AppServiceType as AppServiceType15 } from "@7365admin1/core";
5425
5731
  var allowedCheckOutItemStatus = ["pending", "completed"];
5426
5732
  var checkOutItemSchema = Joi14.object({
5427
5733
  site: Joi14.string().hex().required(),
5428
- serviceType: Joi14.string().valid(...Object.values(AppServiceType14)).required(),
5734
+ serviceType: Joi14.string().valid(...Object.values(AppServiceType15)).required(),
5429
5735
  supply: Joi14.string().hex().required(),
5430
5736
  supplyName: Joi14.string().required(),
5431
5737
  qty: Joi14.number().min(0).required(),
@@ -5477,7 +5783,7 @@ import {
5477
5783
  useCache as useCache8,
5478
5784
  logger as logger28,
5479
5785
  makeCacheKey as makeCacheKey8,
5480
- paginate as paginate7,
5786
+ paginate as paginate8,
5481
5787
  BadRequestError as BadRequestError25,
5482
5788
  NotFoundError as NotFoundError6
5483
5789
  } from "@7365admin1/node-server-utils";
@@ -5636,7 +5942,7 @@ function useCheckOutItemRepository() {
5636
5942
  { $limit: limit }
5637
5943
  ]).toArray();
5638
5944
  const length = await collection.countDocuments(query);
5639
- const data = paginate7(items, page, limit, length);
5945
+ const data = paginate8(items, page, limit, length);
5640
5946
  setCache(cacheKey, data, 15 * 60).then(() => {
5641
5947
  logger28.info(`Cache set for key: ${cacheKey}`);
5642
5948
  }).catch((err) => {
@@ -5859,7 +6165,7 @@ function useCheckOutItemService() {
5859
6165
  // src/controllers/hygiene-checkout-item.controller.ts
5860
6166
  import Joi15 from "joi";
5861
6167
  import { BadRequestError as BadRequestError27, logger as logger29 } from "@7365admin1/node-server-utils";
5862
- import { AppServiceType as AppServiceType15 } from "@7365admin1/core";
6168
+ import { AppServiceType as AppServiceType16 } from "@7365admin1/core";
5863
6169
  function useCheckOutItemController() {
5864
6170
  const {
5865
6171
  getCheckOutItems: _getCheckOutItems,
@@ -5882,7 +6188,7 @@ function useCheckOutItemController() {
5882
6188
  };
5883
6189
  const validation = Joi15.object({
5884
6190
  site: Joi15.string().hex().required(),
5885
- serviceType: Joi15.string().valid(...Object.values(AppServiceType15)).required(),
6191
+ serviceType: Joi15.string().valid(...Object.values(AppServiceType16)).required(),
5886
6192
  supply: Joi15.string().hex().required(),
5887
6193
  qty: Joi15.number().min(0).required(),
5888
6194
  attachment: Joi15.array().items(Joi15.string()).optional().allow(null),
@@ -5917,7 +6223,7 @@ function useCheckOutItemController() {
5917
6223
  };
5918
6224
  const validation = Joi15.object({
5919
6225
  site: Joi15.string().hex().required(),
5920
- serviceType: Joi15.string().valid(...Object.values(AppServiceType15)).required(),
6226
+ serviceType: Joi15.string().valid(...Object.values(AppServiceType16)).required(),
5921
6227
  createdBy: Joi15.string().hex().required(),
5922
6228
  items: Joi15.array().items(
5923
6229
  Joi15.object({
@@ -5950,7 +6256,7 @@ function useCheckOutItemController() {
5950
6256
  limit: Joi15.number().min(1).optional().allow("", null),
5951
6257
  search: Joi15.string().optional().allow("", null),
5952
6258
  site: Joi15.string().hex().required(),
5953
- serviceType: Joi15.string().valid(...Object.values(AppServiceType15)).required()
6259
+ serviceType: Joi15.string().valid(...Object.values(AppServiceType16)).required()
5954
6260
  });
5955
6261
  const { error } = validation.validate(query);
5956
6262
  if (error) {
@@ -6008,12 +6314,12 @@ function useCheckOutItemController() {
6008
6314
 
6009
6315
  // src/models/hygiene-schedule-task.model.ts
6010
6316
  import { BadRequestError as BadRequestError28, logger as logger30 } from "@7365admin1/node-server-utils";
6011
- import { AppServiceType as AppServiceType16 } from "@7365admin1/core";
6317
+ import { AppServiceType as AppServiceType17 } from "@7365admin1/core";
6012
6318
  import Joi16 from "joi";
6013
6319
  import { ObjectId as ObjectId18 } from "mongodb";
6014
6320
  var scheduleTaskSchema = Joi16.object({
6015
6321
  site: Joi16.string().hex().required(),
6016
- serviceType: Joi16.string().valid(...Object.values(AppServiceType16)).required(),
6322
+ serviceType: Joi16.string().valid(...Object.values(AppServiceType17)).required(),
6017
6323
  title: Joi16.string().required(),
6018
6324
  time: Joi16.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).required(),
6019
6325
  dates: Joi16.array().min(1).items(
@@ -6072,7 +6378,7 @@ import { ObjectId as ObjectId19 } from "mongodb";
6072
6378
  import {
6073
6379
  useAtlas as useAtlas14,
6074
6380
  InternalServerError as InternalServerError11,
6075
- paginate as paginate8,
6381
+ paginate as paginate9,
6076
6382
  BadRequestError as BadRequestError29,
6077
6383
  useCache as useCache9,
6078
6384
  logger as logger31,
@@ -6175,7 +6481,7 @@ function useScheduleTaskRepository() {
6175
6481
  { $limit: limit }
6176
6482
  ]).toArray();
6177
6483
  const length = await collection.countDocuments(query);
6178
- const data = paginate8(items, page, limit, length);
6484
+ const data = paginate9(items, page, limit, length);
6179
6485
  setCache(cacheKey, data, 15 * 60).then(() => {
6180
6486
  logger31.info(`Cache set for key: ${cacheKey}`);
6181
6487
  }).catch((err) => {
@@ -6628,7 +6934,7 @@ function useScheduleTaskService() {
6628
6934
  // src/controllers/hygiene-schedule-task.controller.ts
6629
6935
  import Joi17 from "joi";
6630
6936
  import { BadRequestError as BadRequestError30, logger as logger33 } from "@7365admin1/node-server-utils";
6631
- import { AppServiceType as AppServiceType17 } from "@7365admin1/core";
6937
+ import { AppServiceType as AppServiceType18 } from "@7365admin1/core";
6632
6938
  function useScheduleTaskController() {
6633
6939
  const {
6634
6940
  createScheduleTask: _createScheduleTask,
@@ -6662,7 +6968,7 @@ function useScheduleTaskController() {
6662
6968
  limit: Joi17.number().min(1).optional().allow("", null),
6663
6969
  search: Joi17.string().optional().allow("", null),
6664
6970
  site: Joi17.string().hex().required(),
6665
- serviceType: Joi17.string().valid(...Object.values(AppServiceType17)).required()
6971
+ serviceType: Joi17.string().valid(...Object.values(AppServiceType18)).required()
6666
6972
  });
6667
6973
  const { error } = validation.validate(query);
6668
6974
  if (error) {