@iservice365/module-hygiene 0.1.2 → 0.2.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.js CHANGED
@@ -33,32 +33,21 @@ __export(src_exports, {
33
33
  MArea: () => MArea,
34
34
  MAreaChecklist: () => MAreaChecklist,
35
35
  MParentChecklist: () => MParentChecklist,
36
- MScheduleTaskArea: () => MScheduleTaskArea,
37
- MToiletLocation: () => MToiletLocation,
38
36
  MUnit: () => MUnit,
39
37
  MUnitChecklist: () => MUnitChecklist,
40
- allowedStatus: () => allowedStatus,
41
- allowedTypes: () => allowedTypes,
38
+ allowedChecklistStatus: () => allowedChecklistStatus,
42
39
  areaChecklistSchema: () => areaChecklistSchema,
43
40
  areaSchema: () => areaSchema,
44
41
  parentChecklistSchema: () => parentChecklistSchema,
45
- scheduleTaskAreaSchema: () => scheduleTaskAreaSchema,
46
- toiletLocationSchema: () => toiletLocationSchema,
47
42
  unitChecklistSchema: () => unitChecklistSchema,
48
43
  unitSchema: () => unitSchema,
49
44
  useAreaChecklistController: () => useAreaChecklistController,
50
45
  useAreaChecklistRepo: () => useAreaChecklistRepo,
51
46
  useAreaController: () => useAreaController,
52
- useAreaRepository: () => useAreaRepository,
47
+ useAreaRepo: () => useAreaRepo,
53
48
  useAreaService: () => useAreaService,
54
49
  useParentChecklistController: () => useParentChecklistController,
55
50
  useParentChecklistRepo: () => useParentChecklistRepo,
56
- useScheduleTaskAreaController: () => useScheduleTaskAreaController,
57
- useScheduleTaskAreaRepository: () => useScheduleTaskAreaRepository,
58
- useScheduleTaskAreaService: () => useScheduleTaskAreaService,
59
- useToiletLocationController: () => useToiletLocationController,
60
- useToiletLocationRepository: () => useToiletLocationRepository,
61
- useToiletLocationService: () => useToiletLocationService,
62
51
  useUnitChecklistController: () => useUnitChecklistController,
63
52
  useUnitChecklistRepo: () => useUnitChecklistRepo,
64
53
  useUnitController: () => useUnitController,
@@ -71,16 +60,25 @@ module.exports = __toCommonJS(src_exports);
71
60
  var import_node_server_utils = require("@iservice365/node-server-utils");
72
61
  var import_joi = __toESM(require("joi"));
73
62
  var import_mongodb = require("mongodb");
63
+
64
+ // src/models/hygiene-base.model.ts
65
+ var allowedTypes = ["common", "toilet"];
66
+ var allowedStatus = ["ready", "ongoing", "completed"];
67
+
68
+ // src/models/hygiene-area.model.ts
74
69
  var areaSchema = import_joi.default.object({
75
- name: import_joi.default.string().required(),
76
70
  site: import_joi.default.string().hex().required(),
77
- createdBy: import_joi.default.string().hex().required(),
78
- checklist: import_joi.default.array().items(
71
+ name: import_joi.default.string().required(),
72
+ type: import_joi.default.string().valid(...allowedTypes).required(),
73
+ set: import_joi.default.number().min(0).optional(),
74
+ units: import_joi.default.array().items(
79
75
  import_joi.default.object({
80
- _id: import_joi.default.string().hex().required(),
76
+ unit: import_joi.default.string().hex().required(),
81
77
  name: import_joi.default.string().required()
82
- })
83
- ).optional()
78
+ }).optional()
79
+ ).min(1).unique("unit", { ignoreUndefined: true }).messages({
80
+ "array.unique": "Duplicate area units are not allowed"
81
+ })
84
82
  });
85
83
  function MArea(value) {
86
84
  const { error } = areaSchema.validate(value);
@@ -95,56 +93,58 @@ function MArea(value) {
95
93
  throw new import_node_server_utils.BadRequestError("Invalid site ID format.");
96
94
  }
97
95
  }
98
- if (value.createdBy) {
99
- try {
100
- value.createdBy = new import_mongodb.ObjectId(value.createdBy);
101
- } catch (error2) {
102
- throw new import_node_server_utils.BadRequestError("Invalid createdBy ID format.");
103
- }
104
- }
105
- if (value.checklist && Array.isArray(value.checklist)) {
106
- value.checklist = value.checklist.map((item) => {
96
+ if (value.units && Array.isArray(value.units)) {
97
+ value.units = value.units.map((item) => {
107
98
  try {
108
99
  return {
109
100
  ...item,
110
- _id: new import_mongodb.ObjectId(item._id)
101
+ unit: new import_mongodb.ObjectId(item.unit)
111
102
  };
112
103
  } catch (error2) {
113
- throw new import_node_server_utils.BadRequestError(
114
- `Invalid checklist item ID format: ${item._id}`
115
- );
104
+ throw new import_node_server_utils.BadRequestError(`Invalid unit ID format: ${item.unit}`);
116
105
  }
117
106
  });
118
107
  }
119
108
  return {
120
- name: value.name,
121
109
  site: value.site,
122
- createdBy: value.createdBy,
123
- checklist: value.checklist,
124
- status: value.status ?? "active",
110
+ name: value.name,
111
+ type: value.type,
112
+ set: value.set ?? 0,
113
+ units: value.units ?? [],
114
+ status: "active",
125
115
  createdAt: /* @__PURE__ */ new Date(),
126
- updatedAt: value.updatedAt ?? "",
127
- deletedAt: value.deletedAt ?? ""
116
+ updatedAt: "",
117
+ deletedAt: ""
128
118
  };
129
119
  }
130
120
 
131
121
  // src/repositories/hygiene-area.repository.ts
132
122
  var import_mongodb2 = require("mongodb");
133
123
  var import_node_server_utils2 = require("@iservice365/node-server-utils");
134
- function useAreaRepository() {
124
+
125
+ // src/utils/capitalize-text.ts
126
+ function capitalizeText(text) {
127
+ if (!text)
128
+ return "";
129
+ return text.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
130
+ }
131
+
132
+ // src/repositories/hygiene-area.repository.ts
133
+ function useAreaRepo() {
135
134
  const db = import_node_server_utils2.useAtlas.getDb();
136
135
  if (!db) {
137
136
  throw new import_node_server_utils2.InternalServerError("Unable to connect to server.");
138
137
  }
139
- const namespace_collection = "hygiene-areas";
138
+ const namespace_collection = "site.cleaning.areas";
140
139
  const collection = db.collection(namespace_collection);
141
140
  const { delNamespace, setCache, getCache } = (0, import_node_server_utils2.useCache)(namespace_collection);
142
141
  async function createIndex() {
143
142
  try {
144
143
  await collection.createIndexes([
145
144
  { key: { site: 1 } },
146
- { key: { createdBy: 1 } },
147
- { key: { status: 1 } }
145
+ { key: { type: 1 } },
146
+ { key: { status: 1 } },
147
+ { key: { "units.unit": 1 } }
148
148
  ]);
149
149
  } catch (error) {
150
150
  throw new import_node_server_utils2.InternalServerError("Failed to create index on hygiene area.");
@@ -162,7 +162,7 @@ function useAreaRepository() {
162
162
  async function createUniqueIndex() {
163
163
  try {
164
164
  await collection.createIndex(
165
- { name: 1, site: 1, deletedAt: 1 },
165
+ { site: 1, name: 1, type: 1, deletedAt: 1 },
166
166
  { unique: true }
167
167
  );
168
168
  } catch (error) {
@@ -187,7 +187,9 @@ function useAreaRepository() {
187
187
  } catch (error) {
188
188
  const isDuplicated = error.message.includes("duplicate");
189
189
  if (isDuplicated) {
190
- throw new import_node_server_utils2.BadRequestError("Area already exists.");
190
+ throw new import_node_server_utils2.BadRequestError(
191
+ `${capitalizeText(value.type)} area already exists.`
192
+ );
191
193
  }
192
194
  throw error;
193
195
  }
@@ -196,9 +198,7 @@ function useAreaRepository() {
196
198
  page = 1,
197
199
  limit = 10,
198
200
  search = "",
199
- startDate = "",
200
- endDate = "",
201
- site = ""
201
+ site
202
202
  }) {
203
203
  page = page > 0 ? page - 1 : 0;
204
204
  const query = {
@@ -208,32 +208,17 @@ function useAreaRepository() {
208
208
  page,
209
209
  limit
210
210
  };
211
- if (site) {
212
- try {
213
- site = new import_mongodb2.ObjectId(site);
214
- cacheOptions.site = site.toString();
215
- } catch (error) {
216
- throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
217
- }
211
+ try {
212
+ site = new import_mongodb2.ObjectId(site);
213
+ query.site = site;
214
+ cacheOptions.site = site.toString();
215
+ } catch (error) {
216
+ throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
218
217
  }
219
218
  if (search) {
220
219
  query.$or = [{ name: { $regex: search, $options: "i" } }];
221
220
  cacheOptions.search = search;
222
221
  }
223
- if (startDate && endDate) {
224
- query.createdAt = {
225
- $gte: new Date(startDate),
226
- $lte: new Date(endDate)
227
- };
228
- cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
229
- cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
230
- } else if (startDate) {
231
- query.createdAt = { $gte: new Date(startDate) };
232
- cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
233
- } else if (endDate) {
234
- query.createdAt = { $lte: new Date(endDate) };
235
- cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
236
- }
237
222
  const cacheKey = (0, import_node_server_utils2.makeCacheKey)(namespace_collection, cacheOptions);
238
223
  const cachedData = await getCache(cacheKey);
239
224
  if (cachedData) {
@@ -243,45 +228,11 @@ function useAreaRepository() {
243
228
  try {
244
229
  const items = await collection.aggregate([
245
230
  { $match: query },
246
- {
247
- $lookup: {
248
- from: "sites",
249
- localField: "site",
250
- foreignField: "_id",
251
- pipeline: [{ $project: { name: 1 } }],
252
- as: "site"
253
- }
254
- },
255
- {
256
- $unwind: {
257
- path: "$site",
258
- preserveNullAndEmptyArrays: true
259
- }
260
- },
261
- {
262
- $lookup: {
263
- from: "users",
264
- localField: "createdBy",
265
- foreignField: "_id",
266
- pipeline: [{ $project: { name: 1 } }],
267
- as: "createdBy"
268
- }
269
- },
270
- {
271
- $unwind: {
272
- path: "$createdBy",
273
- preserveNullAndEmptyArrays: true
274
- }
275
- },
276
231
  {
277
232
  $project: {
278
233
  name: 1,
279
- site: "$site._id",
280
- siteName: "$site.name",
281
- createdByName: "$createdBy.name",
282
- checklist: 1,
283
- status: 1,
284
- createdAt: 1
234
+ type: 1,
235
+ set: 1
285
236
  }
286
237
  },
287
238
  { $sort: { _id: -1 } },
@@ -300,6 +251,47 @@ function useAreaRepository() {
300
251
  throw error;
301
252
  }
302
253
  }
254
+ async function getAreasForChecklist({
255
+ site,
256
+ type
257
+ }) {
258
+ const query = { type, status: { $ne: "deleted" } };
259
+ const cacheOptions = { type };
260
+ try {
261
+ site = new import_mongodb2.ObjectId(site);
262
+ query.site = site;
263
+ cacheOptions.site = site.toString();
264
+ } catch (error) {
265
+ throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
266
+ }
267
+ const cacheKey = (0, import_node_server_utils2.makeCacheKey)(namespace_collection, cacheOptions);
268
+ const cachedData = await getCache(cacheKey);
269
+ if (cachedData) {
270
+ import_node_server_utils2.logger.info(`Cache hit for key: ${cacheKey}`);
271
+ return cachedData;
272
+ }
273
+ try {
274
+ const items = await collection.aggregate([
275
+ { $match: query },
276
+ {
277
+ $project: {
278
+ name: 1,
279
+ set: 1,
280
+ units: 1
281
+ }
282
+ },
283
+ { $sort: { _id: -1 } }
284
+ ]).toArray();
285
+ setCache(cacheKey, items, 15 * 60).then(() => {
286
+ import_node_server_utils2.logger.info(`Cache set for key: ${cacheKey}`);
287
+ }).catch((err) => {
288
+ import_node_server_utils2.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
289
+ });
290
+ return items;
291
+ } catch (error) {
292
+ throw error;
293
+ }
294
+ }
303
295
  async function getAreaById(_id) {
304
296
  try {
305
297
  _id = new import_mongodb2.ObjectId(_id);
@@ -324,11 +316,12 @@ function useAreaRepository() {
324
316
  {
325
317
  $project: {
326
318
  name: 1,
327
- checklist: 1
319
+ set: 1,
320
+ units: 1
328
321
  }
329
322
  }
330
323
  ]).toArray();
331
- if (!data || !data.length) {
324
+ if (!data || data.length === 0) {
332
325
  throw new import_node_server_utils2.NotFoundError("Area not found.");
333
326
  }
334
327
  setCache(cacheKey, data[0], 15 * 60).then(() => {
@@ -341,22 +334,6 @@ function useAreaRepository() {
341
334
  throw error;
342
335
  }
343
336
  }
344
- async function getAreaByName(name, site) {
345
- try {
346
- if (site)
347
- site = new import_mongodb2.ObjectId(site);
348
- } catch (error) {
349
- throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
350
- }
351
- try {
352
- return await collection.findOne({
353
- name: { $regex: new RegExp(`^${name}$`, "i") },
354
- ...site && { site }
355
- });
356
- } catch (error) {
357
- throw new import_node_server_utils2.BadRequestError("Unable to fetch area by name.");
358
- }
359
- }
360
337
  async function updateArea(_id, value) {
361
338
  try {
362
339
  _id = new import_mongodb2.ObjectId(_id);
@@ -364,7 +341,30 @@ function useAreaRepository() {
364
341
  throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
365
342
  }
366
343
  try {
367
- const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
344
+ const updateValue = {
345
+ updatedAt: /* @__PURE__ */ new Date()
346
+ };
347
+ if (value.name !== void 0) {
348
+ updateValue.name = value.name;
349
+ }
350
+ if (value.type !== void 0) {
351
+ updateValue.type = value.type;
352
+ }
353
+ if (value.set !== void 0) {
354
+ updateValue.set = value.set;
355
+ }
356
+ if (value.units && Array.isArray(value.units)) {
357
+ updateValue.units = value.units.map((item) => {
358
+ try {
359
+ return {
360
+ ...item,
361
+ unit: new import_mongodb2.ObjectId(item.unit)
362
+ };
363
+ } catch (error) {
364
+ throw new import_node_server_utils2.BadRequestError(`Invalid unit ID format: ${item.unit}`);
365
+ }
366
+ });
367
+ }
368
368
  const res = await collection.updateOne({ _id }, { $set: updateValue });
369
369
  if (res.modifiedCount === 0) {
370
370
  throw new import_node_server_utils2.InternalServerError("Unable to update cleaning area.");
@@ -392,17 +392,15 @@ function useAreaRepository() {
392
392
  } catch (error) {
393
393
  throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
394
394
  }
395
- if (value.checklist && Array.isArray(value.checklist)) {
396
- value.checklist = value.checklist.map((item) => {
395
+ if (value.units && Array.isArray(value.units)) {
396
+ value.units = value.units.map((item) => {
397
397
  try {
398
398
  return {
399
399
  ...item,
400
- _id: new import_mongodb2.ObjectId(item._id)
400
+ unit: new import_mongodb2.ObjectId(item.unit)
401
401
  };
402
402
  } catch (error) {
403
- throw new import_node_server_utils2.BadRequestError(
404
- `Invalid checklist item ID format: ${item._id}`
405
- );
403
+ throw new import_node_server_utils2.BadRequestError(`Invalid unit ID format: ${item.unit}`);
406
404
  }
407
405
  });
408
406
  }
@@ -464,8 +462,8 @@ function useAreaRepository() {
464
462
  createUniqueIndex,
465
463
  createArea,
466
464
  getAreas,
465
+ getAreasForChecklist,
467
466
  getAreaById,
468
- getAreaByName,
469
467
  updateArea,
470
468
  updateAreaChecklist,
471
469
  deleteArea
@@ -475,10 +473,9 @@ function useAreaRepository() {
475
473
  // src/services/hygiene-area.service.ts
476
474
  var import_node_server_utils3 = require("@iservice365/node-server-utils");
477
475
  function useAreaService() {
478
- const { createArea: _createArea } = useAreaRepository();
479
- async function uploadByFile({
476
+ const { createArea: _createArea } = useAreaRepo();
477
+ async function importArea({
480
478
  dataJson,
481
- createdBy,
482
479
  site
483
480
  }) {
484
481
  let dataArray;
@@ -490,49 +487,101 @@ function useAreaService() {
490
487
  if (!dataArray || dataArray.length === 0) {
491
488
  throw new import_node_server_utils3.NotFoundError("No data found in the uploaded file");
492
489
  }
493
- const session = import_node_server_utils3.useAtlas.getClient()?.startSession();
494
490
  const insertedAreaIds = [];
495
- try {
496
- session?.startTransaction();
497
- for (const row of dataArray) {
498
- if (!row?.AREA_NAME) {
499
- import_node_server_utils3.logger.warn("Skipping row with missing AREA_NAME:", row);
491
+ const duplicateAreas = [];
492
+ const failedAreas = [];
493
+ const skippedRows = [];
494
+ try {
495
+ for (let i = 0; i < dataArray.length; i++) {
496
+ const row = dataArray[i];
497
+ if (!row?.TYPE) {
498
+ import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with missing TYPE:`, row);
499
+ skippedRows.push(i + 1);
500
+ continue;
501
+ }
502
+ const areaType = String(row.TYPE).trim();
503
+ if (!areaType) {
504
+ import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with empty area type`);
505
+ skippedRows.push(i + 1);
506
+ continue;
507
+ }
508
+ if (!row?.NAME) {
509
+ import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with missing NAME:`, row);
510
+ skippedRows.push(i + 1);
511
+ continue;
512
+ }
513
+ const areaName = String(row.NAME).trim();
514
+ if (!areaName) {
515
+ import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with empty ${areaType} area name`);
516
+ skippedRows.push(i + 1);
500
517
  continue;
501
518
  }
502
519
  try {
503
- const insertedId = await _createArea(
504
- {
505
- name: String(row.AREA_NAME).trim(),
506
- site,
507
- createdBy
508
- },
509
- session
510
- );
520
+ const insertedId = await _createArea({
521
+ type: areaType,
522
+ name: areaName,
523
+ site
524
+ });
511
525
  insertedAreaIds.push(insertedId);
526
+ import_node_server_utils3.logger.info(`Successfully created ${areaType} area: ${areaName}`);
512
527
  } catch (error) {
513
528
  import_node_server_utils3.logger.error(
514
- `Error creating area "${row.AREA_NAME}":`,
515
- error.message
529
+ `Error creating ${areaType} area "${areaName}": ${error.message}`
516
530
  );
517
- continue;
531
+ if (error.message.includes("duplicate")) {
532
+ duplicateAreas.push(areaName);
533
+ } else {
534
+ failedAreas.push(areaName);
535
+ }
518
536
  }
519
537
  }
520
- await session?.commitTransaction();
521
- import_node_server_utils3.logger.info(`Successfully uploaded ${insertedAreaIds.length} areas`);
522
- return {
523
- message: `Successfully uploaded ${insertedAreaIds.length} areas`
524
- };
538
+ let message = `Upload completed: ${insertedAreaIds.length} areas successfully created`;
539
+ if (duplicateAreas.length > 0) {
540
+ message += `, ${duplicateAreas.length} areas skipped (already exist)`;
541
+ }
542
+ if (failedAreas.length > 0) {
543
+ message += `, ${failedAreas.length} areas failed`;
544
+ }
545
+ if (skippedRows.length > 0) {
546
+ message += `, ${skippedRows.length} rows skipped (invalid data)`;
547
+ }
548
+ import_node_server_utils3.logger.info(message);
549
+ if (insertedAreaIds.length === 0) {
550
+ if (duplicateAreas.length > 0 && failedAreas.length === 0) {
551
+ throw new import_node_server_utils3.BadRequestError(
552
+ `No new areas were created. All ${duplicateAreas.length} areas already exist in the system: ${duplicateAreas.join(", ")}`
553
+ );
554
+ } else if (failedAreas.length > 0) {
555
+ throw new import_node_server_utils3.BadRequestError(
556
+ `No areas were created. Please check your data format and ensure area names are valid.`
557
+ );
558
+ } else if (skippedRows.length > 0) {
559
+ throw new import_node_server_utils3.BadRequestError(
560
+ `No areas were created. All rows contained invalid or missing area names.`
561
+ );
562
+ }
563
+ }
564
+ return { message };
525
565
  } catch (error) {
526
- await session?.abortTransaction();
527
566
  import_node_server_utils3.logger.error("Error while uploading area information", error);
528
- throw error;
529
- } finally {
530
- session?.endSession();
567
+ if (error instanceof import_node_server_utils3.BadRequestError) {
568
+ throw error;
569
+ } else if (error.message.includes("duplicate")) {
570
+ throw new import_node_server_utils3.BadRequestError(
571
+ `Upload failed due to duplicate area names. Please ensure all area names are unique.`
572
+ );
573
+ } else if (error.message.includes("validation")) {
574
+ throw new import_node_server_utils3.BadRequestError(
575
+ "Upload failed due to invalid data format. Please check that all required fields are properly filled."
576
+ );
577
+ } else {
578
+ throw new import_node_server_utils3.BadRequestError(
579
+ `Upload failed: ${error.message || "Please check your data format and try again."}`
580
+ );
581
+ }
531
582
  }
532
583
  }
533
- return {
534
- uploadByFile
535
- };
584
+ return { importArea };
536
585
  }
537
586
 
538
587
  // src/controllers/hygiene-area.controller.ts
@@ -570,20 +619,15 @@ function convertBufferFile(bufferFile) {
570
619
  function useAreaController() {
571
620
  const {
572
621
  createArea: _createArea,
573
- getAreas: _getAll,
622
+ getAreas: _getAreas,
574
623
  getAreaById: _getAreaById,
575
624
  updateArea: _updateArea,
576
625
  updateAreaChecklist: _updateAreaChecklist,
577
626
  deleteArea: _deleteById
578
- } = useAreaRepository();
579
- const { uploadByFile: _uploadByFile } = useAreaService();
627
+ } = useAreaRepo();
628
+ const { importArea: _importArea } = useAreaService();
580
629
  async function createArea(req, res, next) {
581
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
582
- (acc, [key, value]) => ({ ...acc, [key]: value }),
583
- {}
584
- ) : {};
585
- const createdBy = cookies["user"] || "";
586
- const payload = { ...req.body, createdBy };
630
+ const payload = { ...req.body, ...req.params };
587
631
  const { error } = areaSchema.validate(payload);
588
632
  if (error) {
589
633
  import_node_server_utils4.logger.log({ level: "error", message: error.message });
@@ -600,35 +644,30 @@ function useAreaController() {
600
644
  return;
601
645
  }
602
646
  }
603
- async function getAll(req, res, next) {
604
- const query = req.query;
647
+ async function getAreas(req, res, next) {
648
+ const query = { ...req.query, ...req.params };
605
649
  const validation = import_joi2.default.object({
606
650
  page: import_joi2.default.number().min(1).optional().allow("", null),
607
651
  limit: import_joi2.default.number().min(1).optional().allow("", null),
608
652
  search: import_joi2.default.string().optional().allow("", null),
609
- startDate: import_joi2.default.alternatives().try(import_joi2.default.date(), import_joi2.default.string()).optional().allow("", null),
610
- endDate: import_joi2.default.alternatives().try(import_joi2.default.date(), import_joi2.default.string()).optional().allow("", null),
611
- site: import_joi2.default.string().hex().optional().allow("", null)
653
+ site: import_joi2.default.string().hex().required()
612
654
  });
613
655
  const { error } = validation.validate(query);
614
656
  if (error) {
657
+ import_node_server_utils4.logger.log({ level: "error", message: error.message });
615
658
  next(new import_node_server_utils4.BadRequestError(error.message));
616
659
  return;
617
660
  }
618
661
  const page = parseInt(req.query.page) ?? 1;
619
662
  const limit = parseInt(req.query.limit) ?? 20;
620
663
  const search = req.query.search ?? "";
621
- const site = req.query.site ?? "";
622
- const startDate = req.query.startDate ?? "";
623
- const endDate = req.query.endDate ?? "";
664
+ const site = req.params.site ?? "";
624
665
  try {
625
- const data = await _getAll({
666
+ const data = await _getAreas({
626
667
  page,
627
668
  limit,
628
669
  search,
629
- site,
630
- startDate,
631
- endDate
670
+ site
632
671
  });
633
672
  res.json(data);
634
673
  return;
@@ -660,7 +699,17 @@ function useAreaController() {
660
699
  const payload = { id: req.params.id, ...req.body };
661
700
  const schema = import_joi2.default.object({
662
701
  id: import_joi2.default.string().hex().required(),
663
- name: import_joi2.default.string().required()
702
+ name: import_joi2.default.string().optional().allow("", null),
703
+ type: import_joi2.default.string().optional().allow("", null, ...allowedTypes),
704
+ set: import_joi2.default.number().min(0).optional(),
705
+ units: import_joi2.default.array().items(
706
+ import_joi2.default.object({
707
+ unit: import_joi2.default.string().hex().required(),
708
+ name: import_joi2.default.string().required()
709
+ }).required()
710
+ ).min(1).unique("unit", { ignoreUndefined: true }).optional().messages({
711
+ "array.unique": "Duplicate area units are not allowed"
712
+ })
664
713
  });
665
714
  const { error } = schema.validate(payload);
666
715
  if (error) {
@@ -683,13 +732,13 @@ function useAreaController() {
683
732
  const payload = { id: req.params.id, ...req.body };
684
733
  const schema = import_joi2.default.object({
685
734
  id: import_joi2.default.string().hex().required(),
686
- checklist: import_joi2.default.array().items(
735
+ units: import_joi2.default.array().items(
687
736
  import_joi2.default.object({
688
- _id: import_joi2.default.string().hex().required(),
737
+ unit: import_joi2.default.string().hex().required(),
689
738
  name: import_joi2.default.string().required()
690
739
  }).required()
691
- ).min(1).unique("_id", { ignoreUndefined: true }).messages({
692
- "array.unique": "Duplicate checklist items are not allowed"
740
+ ).min(1).unique("unit", { ignoreUndefined: true }).messages({
741
+ "array.unique": "Duplicate area units are not allowed"
693
742
  })
694
743
  });
695
744
  const { error } = schema.validate(payload);
@@ -711,10 +760,8 @@ function useAreaController() {
711
760
  }
712
761
  async function deleteArea(req, res, next) {
713
762
  const id = req.params.id;
714
- const validation = import_joi2.default.object({
715
- id: import_joi2.default.string().hex().required()
716
- });
717
- const { error } = validation.validate({ id });
763
+ const validation = import_joi2.default.string().hex().required();
764
+ const { error } = validation.validate(id);
718
765
  if (error) {
719
766
  import_node_server_utils4.logger.log({ level: "error", message: error.message });
720
767
  next(new import_node_server_utils4.BadRequestError(error.message));
@@ -730,22 +777,14 @@ function useAreaController() {
730
777
  return;
731
778
  }
732
779
  }
733
- async function uploadByFile(req, res, next) {
780
+ async function importArea(req, res, next) {
734
781
  if (!req.file) {
735
782
  next(new import_node_server_utils4.BadRequestError("File is required!"));
736
783
  return;
737
784
  }
738
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
739
- (acc, [key, value]) => ({ ...acc, [key]: value }),
740
- {}
741
- ) : {};
742
- const createdBy = cookies["user"] || "";
743
- const { site } = req.body;
744
- const schema = import_joi2.default.object({
745
- site: import_joi2.default.string().hex().optional().allow("", null),
746
- createdBy: import_joi2.default.string().hex().required()
747
- });
748
- const { error } = schema.validate({ site, createdBy });
785
+ const { site } = req.params;
786
+ const schema = import_joi2.default.string().hex().required();
787
+ const { error } = schema.validate(site);
749
788
  if (error) {
750
789
  import_node_server_utils4.logger.log({ level: "error", message: error.message });
751
790
  next(new import_node_server_utils4.BadRequestError(error.message));
@@ -754,7 +793,7 @@ function useAreaController() {
754
793
  try {
755
794
  const xlsData = await convertBufferFile(req.file.buffer);
756
795
  const dataJson = JSON.stringify(xlsData);
757
- const result = await _uploadByFile({ dataJson, createdBy, site });
796
+ const result = await _importArea({ dataJson, site });
758
797
  return res.status(201).json(result);
759
798
  } catch (error2) {
760
799
  import_node_server_utils4.logger.log({ level: "error", message: error2.message });
@@ -764,35 +803,27 @@ function useAreaController() {
764
803
  }
765
804
  return {
766
805
  createArea,
767
- getAll,
806
+ getAreas,
768
807
  getAreaById,
769
808
  updateArea,
770
809
  updateAreaChecklist,
771
810
  deleteArea,
772
- uploadByFile
811
+ importArea
773
812
  };
774
813
  }
775
814
 
776
- // src/models/hygiene-toilet-location.model.ts
815
+ // src/models/hygiene-unit.model.ts
777
816
  var import_node_server_utils5 = require("@iservice365/node-server-utils");
778
817
  var import_joi3 = __toESM(require("joi"));
779
818
  var import_mongodb3 = require("mongodb");
780
- var toiletLocationSchema = import_joi3.default.object({
781
- name: import_joi3.default.string().required(),
819
+ var unitSchema = import_joi3.default.object({
782
820
  site: import_joi3.default.string().hex().required(),
783
- createdBy: import_joi3.default.string().hex().required(),
784
- checklist: import_joi3.default.array().items(
785
- import_joi3.default.object({
786
- _id: import_joi3.default.string().hex().required(),
787
- name: import_joi3.default.string().required()
788
- })
789
- ).optional(),
790
- updatedAt: import_joi3.default.date().optional().allow("", null),
791
- status: import_joi3.default.string().allow("", null).optional()
821
+ name: import_joi3.default.string().required()
792
822
  });
793
- function MToiletLocation(value) {
794
- const { error } = toiletLocationSchema.validate(value);
823
+ function MUnit(value) {
824
+ const { error } = unitSchema.validate(value);
795
825
  if (error) {
826
+ import_node_server_utils5.logger.info(`Hygiene Unit Model: ${error.message}`);
796
827
  throw new import_node_server_utils5.BadRequestError(error.message);
797
828
  }
798
829
  if (value.site) {
@@ -802,75 +833,64 @@ function MToiletLocation(value) {
802
833
  throw new import_node_server_utils5.BadRequestError("Invalid site ID format.");
803
834
  }
804
835
  }
805
- if (value.createdBy) {
806
- try {
807
- value.createdBy = new import_mongodb3.ObjectId(value.createdBy);
808
- } catch (error2) {
809
- throw new import_node_server_utils5.BadRequestError("Invalid createdBy ID format.");
810
- }
811
- }
812
- if (value.checklist && Array.isArray(value.checklist)) {
813
- value.checklist = value.checklist.map((item) => {
814
- try {
815
- return {
816
- ...item,
817
- _id: new import_mongodb3.ObjectId(item._id)
818
- };
819
- } catch (error2) {
820
- throw new import_node_server_utils5.BadRequestError(
821
- `Invalid checklist item ID format: ${item._id}`
822
- );
823
- }
824
- });
825
- }
826
836
  return {
827
- name: value.name,
828
837
  site: value.site,
829
- createdBy: value.createdBy,
830
- checklist: value.checklist,
831
- status: value.status ?? "",
838
+ name: value.name,
832
839
  createdAt: /* @__PURE__ */ new Date(),
833
- updatedAt: value.updatedAt ?? "",
834
- deletedAt: value.deletedAt ?? ""
840
+ status: "active",
841
+ updatedAt: "",
842
+ deletedAt: ""
835
843
  };
836
844
  }
837
845
 
838
- // src/repositories/hygiene-toilet-location.repository.ts
846
+ // src/services/hygiene-unit.service.ts
847
+ var import_node_server_utils7 = require("@iservice365/node-server-utils");
848
+
849
+ // src/repositories/hygiene-unit.repository.ts
839
850
  var import_mongodb4 = require("mongodb");
840
851
  var import_node_server_utils6 = require("@iservice365/node-server-utils");
841
- function useToiletLocationRepository() {
852
+ function useUnitRepository() {
842
853
  const db = import_node_server_utils6.useAtlas.getDb();
843
854
  if (!db) {
844
855
  throw new import_node_server_utils6.InternalServerError("Unable to connect to server.");
845
856
  }
846
- const namespace_collection = "hygiene-toilet-locations";
857
+ const namespace_collection = "site.cleaning.area.unit";
847
858
  const collection = db.collection(namespace_collection);
848
- const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils6.useCache)(namespace_collection);
849
- async function createIndexes() {
859
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils6.useCache)(namespace_collection);
860
+ async function createIndex() {
850
861
  try {
851
862
  await collection.createIndexes([
852
863
  { key: { site: 1 } },
853
- { key: { name: "text" } }
864
+ { key: { status: 1 } }
854
865
  ]);
855
866
  } catch (error) {
856
- throw new import_node_server_utils6.InternalServerError("Failed to create index on site.");
867
+ throw new import_node_server_utils6.InternalServerError("Failed to create index on hygiene unit.");
868
+ }
869
+ }
870
+ async function createTextIndex() {
871
+ try {
872
+ await collection.createIndex({ name: "text" });
873
+ } catch (error) {
874
+ throw new import_node_server_utils6.InternalServerError(
875
+ "Failed to create text index on hygiene unit."
876
+ );
857
877
  }
858
878
  }
859
879
  async function createUniqueIndex() {
860
880
  try {
861
881
  await collection.createIndex(
862
- { name: 1, site: 1, deletedAt: 1 },
882
+ { site: 1, name: 1, deletedAt: 1 },
863
883
  { unique: true }
864
884
  );
865
885
  } catch (error) {
866
886
  throw new import_node_server_utils6.InternalServerError(
867
- "Failed to create unique index on hygiene area."
887
+ "Failed to create unique index on hygiene unit."
868
888
  );
869
889
  }
870
890
  }
871
- async function create(value, session) {
891
+ async function createUnit(value, session) {
872
892
  try {
873
- value = MToiletLocation(value);
893
+ value = MUnit(value);
874
894
  const res = await collection.insertOne(value, { session });
875
895
  delNamespace().then(() => {
876
896
  import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
@@ -884,190 +904,46 @@ function useToiletLocationRepository() {
884
904
  } catch (error) {
885
905
  const isDuplicated = error.message.includes("duplicate");
886
906
  if (isDuplicated) {
887
- throw new import_node_server_utils6.BadRequestError("Toilet location already exists.");
907
+ throw new import_node_server_utils6.BadRequestError("Unit already exists.");
888
908
  }
889
909
  throw error;
890
910
  }
891
911
  }
892
- async function updateToiletLocation(_id, value) {
912
+ async function getUnits({
913
+ page = 1,
914
+ limit = 10,
915
+ search = "",
916
+ site
917
+ }) {
918
+ page = page > 0 ? page - 1 : 0;
919
+ const query = {
920
+ status: { $ne: "deleted" }
921
+ };
922
+ const cacheOptions = {
923
+ page,
924
+ limit
925
+ };
893
926
  try {
894
- _id = new import_mongodb4.ObjectId(_id);
927
+ site = new import_mongodb4.ObjectId(site);
928
+ query.site = site;
929
+ cacheOptions.site = site.toString();
895
930
  } catch (error) {
896
- throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
897
- }
898
- if (value.checklist && Array.isArray(value.checklist)) {
899
- value.checklist = value.checklist.map((item) => {
900
- try {
901
- return {
902
- ...item,
903
- _id: new import_mongodb4.ObjectId(item._id)
904
- };
905
- } catch (error) {
906
- throw new import_node_server_utils6.BadRequestError(
907
- `Invalid checklist item ID format: ${item._id}`
908
- );
909
- }
910
- });
931
+ throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
911
932
  }
912
- try {
913
- const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
914
- const res = await collection.updateOne({ _id }, { $set: updateValue });
915
- if (res.modifiedCount === 0) {
916
- throw new import_node_server_utils6.InternalServerError("Unable to update toilet location.");
917
- }
918
- delNamespace().then(() => {
919
- import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
920
- }).catch((err) => {
921
- import_node_server_utils6.logger.error(
922
- `Failed to clear cache for namespace: ${namespace_collection}`,
923
- err
924
- );
925
- });
926
- return res.modifiedCount;
927
- } catch (error) {
928
- const isDuplicated = error.message.includes("duplicate");
929
- if (isDuplicated) {
930
- throw new import_node_server_utils6.BadRequestError("Toilet location already exists.");
931
- }
932
- throw error;
933
- }
934
- }
935
- async function deleteToiletLocation(_id, session) {
936
- try {
937
- _id = new import_mongodb4.ObjectId(_id);
938
- } catch (error) {
939
- throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
940
- }
941
- try {
942
- const updateValue = {
943
- status: "deleted",
944
- updatedAt: /* @__PURE__ */ new Date(),
945
- deletedAt: /* @__PURE__ */ new Date()
946
- };
947
- const res = await collection.updateOne(
948
- { _id },
949
- { $set: updateValue },
950
- { session }
951
- );
952
- if (res.modifiedCount === 0) {
953
- throw new import_node_server_utils6.InternalServerError("Unable to delete toilet location.");
954
- }
955
- delNamespace().then(() => {
956
- import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
957
- }).catch((err) => {
958
- import_node_server_utils6.logger.error(
959
- `Failed to clear cache for namespace: ${namespace_collection}`,
960
- err
961
- );
962
- });
963
- return res.modifiedCount;
964
- } catch (error) {
965
- throw error;
966
- }
967
- }
968
- async function getToiletLocations({
969
- page = 1,
970
- limit = 10,
971
- search = "",
972
- sort = {},
973
- startDate = "",
974
- endDate = "",
975
- site = ""
976
- }) {
977
- page = page > 0 ? page - 1 : 0;
978
- let dateFilter = {};
979
- try {
980
- site = new import_mongodb4.ObjectId(site);
981
- } catch (error) {
982
- throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
983
- }
984
- const query = {
985
- status: { $ne: "deleted" }
986
- };
987
- const cacheOptions = {
988
- site: site.toString()
989
- };
990
- sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
991
- cacheOptions.sort = JSON.stringify(sort);
992
933
  if (search) {
993
934
  query.$or = [{ name: { $regex: search, $options: "i" } }];
994
935
  cacheOptions.search = search;
995
936
  }
996
- delNamespace().then(() => {
997
- import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
998
- }).catch((err) => {
999
- import_node_server_utils6.logger.error(
1000
- `Failed to clear cache for namespace: ${namespace_collection}`,
1001
- err
1002
- );
1003
- });
1004
937
  const cacheKey = (0, import_node_server_utils6.makeCacheKey)(namespace_collection, cacheOptions);
1005
938
  const cachedData = await getCache(cacheKey);
1006
939
  if (cachedData) {
1007
940
  import_node_server_utils6.logger.info(`Cache hit for key: ${cacheKey}`);
1008
941
  return cachedData;
1009
942
  }
1010
- if (startDate && endDate) {
1011
- dateFilter = {
1012
- createdAt: {
1013
- $gte: new Date(startDate),
1014
- $lte: new Date(endDate)
1015
- }
1016
- };
1017
- } else if (startDate) {
1018
- dateFilter = { createdAt: { $gte: new Date(startDate) } };
1019
- } else if (endDate) {
1020
- dateFilter = { createdAt: { $lte: new Date(endDate) } };
1021
- }
1022
943
  try {
1023
944
  const items = await collection.aggregate([
1024
- {
1025
- $match: {
1026
- ...dateFilter,
1027
- ...query
1028
- }
1029
- },
1030
- {
1031
- $lookup: {
1032
- from: "sites",
1033
- localField: "site",
1034
- foreignField: "_id",
1035
- pipeline: [{ $project: { name: 1 } }],
1036
- as: "site"
1037
- }
1038
- },
1039
- {
1040
- $unwind: {
1041
- path: "$site",
1042
- preserveNullAndEmptyArrays: true
1043
- }
1044
- },
1045
- {
1046
- $lookup: {
1047
- from: "users",
1048
- localField: "createdBy",
1049
- foreignField: "_id",
1050
- pipeline: [{ $project: { name: 1 } }],
1051
- as: "createdBy"
1052
- }
1053
- },
1054
- {
1055
- $unwind: {
1056
- path: "$createdBy",
1057
- preserveNullAndEmptyArrays: true
1058
- }
1059
- },
1060
- {
1061
- $project: {
1062
- name: 1,
1063
- site: "$site._id",
1064
- siteName: "$site.name",
1065
- createdByName: "$createdBy.name",
1066
- checklist: 1,
1067
- status: 1,
1068
- createdAt: 1
1069
- }
1070
- },
945
+ { $match: query },
946
+ { $project: { name: 1 } },
1071
947
  { $sort: { _id: -1 } },
1072
948
  { $skip: page * limit },
1073
949
  { $limit: limit }
@@ -1084,47 +960,17 @@ function useToiletLocationRepository() {
1084
960
  throw error;
1085
961
  }
1086
962
  }
1087
- async function getToiletLocationByName(name, site) {
1088
- try {
1089
- if (site)
1090
- site = new import_mongodb4.ObjectId(site);
1091
- } catch (error) {
1092
- throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
1093
- }
1094
- try {
1095
- return await collection.findOne({
1096
- name: { $regex: new RegExp(`^${name}$`, "i") },
1097
- ...site && { site }
1098
- });
1099
- } catch (error) {
1100
- throw new import_node_server_utils6.BadRequestError("Unable to fetch toilet location by name.");
1101
- }
1102
- }
1103
- async function updateToiletLocationChecklist(_id, value) {
963
+ async function updateUnit(_id, value) {
1104
964
  try {
1105
965
  _id = new import_mongodb4.ObjectId(_id);
1106
966
  } catch (error) {
1107
- throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
1108
- }
1109
- if (value.checklist && Array.isArray(value.checklist)) {
1110
- value.checklist = value.checklist.map((item) => {
1111
- try {
1112
- return {
1113
- ...item,
1114
- _id: new import_mongodb4.ObjectId(item._id)
1115
- };
1116
- } catch (error) {
1117
- throw new import_node_server_utils6.BadRequestError(
1118
- `Invalid checklist item ID format: ${item._id}`
1119
- );
1120
- }
1121
- });
967
+ throw new import_node_server_utils6.BadRequestError("Invalid unit ID format.");
1122
968
  }
1123
969
  try {
1124
970
  const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
1125
971
  const res = await collection.updateOne({ _id }, { $set: updateValue });
1126
972
  if (res.modifiedCount === 0) {
1127
- throw new import_node_server_utils6.InternalServerError("Unable to update toilet location.");
973
+ throw new import_node_server_utils6.InternalServerError("Unable to update cleaning unit.");
1128
974
  }
1129
975
  delNamespace().then(() => {
1130
976
  import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
@@ -1136,70 +982,62 @@ function useToiletLocationRepository() {
1136
982
  });
1137
983
  return res.modifiedCount;
1138
984
  } catch (error) {
985
+ const isDuplicated = error.message.includes("duplicate");
986
+ if (isDuplicated) {
987
+ throw new import_node_server_utils6.BadRequestError("Area already exists.");
988
+ }
1139
989
  throw error;
1140
990
  }
1141
991
  }
1142
- async function getToiletLocationById(_id) {
992
+ async function deleteUnit(_id, session) {
1143
993
  try {
1144
994
  _id = new import_mongodb4.ObjectId(_id);
1145
995
  } catch (error) {
1146
- throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
1147
- }
1148
- const query = {
1149
- _id,
1150
- status: { $ne: "deleted" }
1151
- };
1152
- const cacheKey = (0, import_node_server_utils6.makeCacheKey)(namespace_collection, {
1153
- _id: _id.toString()
1154
- });
1155
- const cachedData = await getCache(cacheKey);
1156
- if (cachedData) {
1157
- import_node_server_utils6.logger.info(`Cache hit for key: ${cacheKey}`);
1158
- return cachedData;
996
+ throw new import_node_server_utils6.BadRequestError("Invalid unit ID format.");
1159
997
  }
1160
998
  try {
1161
- const data = await collection.aggregate([
1162
- { $match: query },
1163
- {
1164
- $project: {
1165
- name: 1,
1166
- checklist: 1
1167
- }
1168
- }
1169
- ]).toArray();
1170
- if (!data || !data.length) {
1171
- throw new import_node_server_utils6.NotFoundError("Area not found.");
999
+ const updateValue = {
1000
+ status: "deleted",
1001
+ updatedAt: /* @__PURE__ */ new Date(),
1002
+ deletedAt: /* @__PURE__ */ new Date()
1003
+ };
1004
+ const res = await collection.updateOne(
1005
+ { _id },
1006
+ { $set: updateValue },
1007
+ { session }
1008
+ );
1009
+ if (res.modifiedCount === 0) {
1010
+ throw new import_node_server_utils6.InternalServerError("Unable to delete unit.");
1172
1011
  }
1173
- setCache(cacheKey, data[0], 15 * 60).then(() => {
1174
- import_node_server_utils6.logger.info(`Cache set for key: ${cacheKey}`);
1012
+ delNamespace().then(() => {
1013
+ import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
1175
1014
  }).catch((err) => {
1176
- import_node_server_utils6.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
1015
+ import_node_server_utils6.logger.error(
1016
+ `Failed to clear cache for namespace: ${namespace_collection}`,
1017
+ err
1018
+ );
1177
1019
  });
1178
- return data[0];
1020
+ return res.modifiedCount;
1179
1021
  } catch (error) {
1180
1022
  throw error;
1181
1023
  }
1182
1024
  }
1183
1025
  return {
1184
- createIndexes,
1026
+ createIndex,
1027
+ createTextIndex,
1185
1028
  createUniqueIndex,
1186
- getToiletLocations,
1187
- create,
1188
- updateToiletLocation,
1189
- deleteToiletLocation,
1190
- getToiletLocationByName,
1191
- getToiletLocationById,
1192
- updateToiletLocationChecklist
1029
+ createUnit,
1030
+ getUnits,
1031
+ updateUnit,
1032
+ deleteUnit
1193
1033
  };
1194
1034
  }
1195
1035
 
1196
- // src/services/hygiene-toilet-location.service.ts
1197
- var import_node_server_utils7 = require("@iservice365/node-server-utils");
1198
- function useToiletLocationService() {
1199
- const { create: _createToilet } = useToiletLocationRepository();
1200
- async function uploadByFile({
1036
+ // src/services/hygiene-unit.service.ts
1037
+ function useUnitService() {
1038
+ const { createUnit: _createUnit } = useUnitRepository();
1039
+ async function importUnit({
1201
1040
  dataJson,
1202
- createdBy,
1203
1041
  site
1204
1042
  }) {
1205
1043
  let dataArray;
@@ -1211,146 +1049,158 @@ function useToiletLocationService() {
1211
1049
  if (!dataArray || dataArray.length === 0) {
1212
1050
  throw new import_node_server_utils7.NotFoundError("No data found in the uploaded file");
1213
1051
  }
1214
- const session = import_node_server_utils7.useAtlas.getClient()?.startSession();
1215
- const insertedAreaIds = [];
1216
- try {
1217
- session?.startTransaction();
1218
- for (const row of dataArray) {
1219
- if (!row?.AREA_NAME) {
1220
- import_node_server_utils7.logger.warn("Skipping row with missing TOILET NAME:", row);
1052
+ const insertedUnitIds = [];
1053
+ const duplicateUnits = [];
1054
+ const failedUnits = [];
1055
+ const skippedRows = [];
1056
+ try {
1057
+ for (let i = 0; i < dataArray.length; i++) {
1058
+ const row = dataArray[i];
1059
+ if (!row?.NAME) {
1060
+ import_node_server_utils7.logger.warn(`Skipping row ${i + 1} with missing NAME:`, row);
1061
+ skippedRows.push(i + 1);
1062
+ continue;
1063
+ }
1064
+ const unitName = String(row.NAME).trim();
1065
+ if (!unitName) {
1066
+ import_node_server_utils7.logger.warn(`Skipping row ${i + 1} with empty unit name`);
1067
+ skippedRows.push(i + 1);
1221
1068
  continue;
1222
1069
  }
1223
1070
  try {
1224
- const insertedId = await _createToilet(
1225
- {
1226
- name: String(row.TOILET_NAME).trim(),
1227
- site,
1228
- createdBy
1229
- },
1230
- session
1231
- );
1232
- insertedAreaIds.push(insertedId);
1071
+ const insertedId = await _createUnit({
1072
+ name: unitName,
1073
+ site
1074
+ });
1075
+ insertedUnitIds.push(insertedId);
1076
+ import_node_server_utils7.logger.info(`Successfully created unit: ${unitName}`);
1233
1077
  } catch (error) {
1234
- import_node_server_utils7.logger.error(
1235
- `Error creating area "${row.AREA_NAME}":`,
1236
- error.message
1078
+ import_node_server_utils7.logger.error(`Error creating unit "${unitName}": ${error.message}`);
1079
+ if (error.message.includes("Unit already exists")) {
1080
+ duplicateUnits.push(unitName);
1081
+ } else {
1082
+ failedUnits.push(unitName);
1083
+ }
1084
+ }
1085
+ }
1086
+ let message = `Upload completed: ${insertedUnitIds.length} units successfully created`;
1087
+ if (duplicateUnits.length > 0) {
1088
+ message += `, ${duplicateUnits.length} units skipped (already exist)`;
1089
+ }
1090
+ if (failedUnits.length > 0) {
1091
+ message += `, ${failedUnits.length} units failed`;
1092
+ }
1093
+ if (skippedRows.length > 0) {
1094
+ message += `, ${skippedRows.length} rows skipped (invalid data)`;
1095
+ }
1096
+ import_node_server_utils7.logger.info(message);
1097
+ if (insertedUnitIds.length === 0) {
1098
+ if (duplicateUnits.length > 0 && failedUnits.length === 0) {
1099
+ throw new import_node_server_utils7.BadRequestError(
1100
+ `No new units were created. All ${duplicateUnits.length} units already exist in the system: ${duplicateUnits.join(", ")}`
1101
+ );
1102
+ } else if (failedUnits.length > 0) {
1103
+ throw new import_node_server_utils7.BadRequestError(
1104
+ `No units were created. Please check your data format and ensure unit names are valid.`
1105
+ );
1106
+ } else if (skippedRows.length > 0) {
1107
+ throw new import_node_server_utils7.BadRequestError(
1108
+ `No units were created. All rows contained invalid or missing unit names.`
1237
1109
  );
1238
- continue;
1239
1110
  }
1240
1111
  }
1241
- await session?.commitTransaction();
1242
- import_node_server_utils7.logger.info(`Successfully uploaded ${insertedAreaIds.length} areas`);
1243
- return {
1244
- message: `Successfully uploaded ${insertedAreaIds.length} areas`
1245
- };
1246
- } catch (error) {
1247
- await session?.abortTransaction();
1248
- import_node_server_utils7.logger.error("Error while uploading area information", error);
1249
- throw error;
1250
- } finally {
1251
- session?.endSession();
1112
+ return { message };
1113
+ } catch (error) {
1114
+ import_node_server_utils7.logger.error("Error while uploading unit information", error);
1115
+ if (error instanceof import_node_server_utils7.BadRequestError) {
1116
+ throw error;
1117
+ } else if (error.message.includes("duplicate")) {
1118
+ throw new import_node_server_utils7.BadRequestError(
1119
+ "Upload failed due to duplicate unit names. Please ensure all unit names are unique."
1120
+ );
1121
+ } else if (error.message.includes("validation")) {
1122
+ throw new import_node_server_utils7.BadRequestError(
1123
+ "Upload failed due to invalid data format. Please check that all required fields are properly filled."
1124
+ );
1125
+ } else {
1126
+ throw new import_node_server_utils7.BadRequestError(
1127
+ `Upload failed: ${error.message || "Please check your data format and try again."}`
1128
+ );
1129
+ }
1252
1130
  }
1253
1131
  }
1254
- return {
1255
- uploadByFile
1256
- };
1132
+ return { importUnit };
1257
1133
  }
1258
1134
 
1259
- // src/controllers/hygiene-toilet-location.controller.ts
1260
- var import_joi4 = __toESM(require("joi"));
1135
+ // src/controllers/hygiene-unit.controller.ts
1261
1136
  var import_node_server_utils8 = require("@iservice365/node-server-utils");
1262
- function useToiletLocationController() {
1263
- const { uploadByFile: _uploadByFile } = useToiletLocationService();
1137
+ var import_joi4 = __toESM(require("joi"));
1138
+ function useUnitController() {
1264
1139
  const {
1265
- create: _createToiletLocation,
1266
- updateToiletLocation: _updateToiletLocation,
1267
- updateToiletLocationChecklist: _updateToiletLocationChecklist,
1268
- getToiletLocationById: _getToiletLocationById,
1269
- getToiletLocations: _getAll,
1270
- deleteToiletLocation: _deleteById
1271
- } = useToiletLocationRepository();
1272
- async function getAll(req, res, next) {
1273
- const query = req.query;
1140
+ createUnit: _createUnit,
1141
+ getUnits: _getUnits,
1142
+ updateUnit: _updateUnit,
1143
+ deleteUnit: _deleteUnit
1144
+ } = useUnitRepository();
1145
+ const { importUnit: _importUnit } = useUnitService();
1146
+ async function createUnit(req, res, next) {
1147
+ const payload = { ...req.body, ...req.params };
1148
+ const { error } = unitSchema.validate(payload);
1149
+ if (error) {
1150
+ import_node_server_utils8.logger.log({ level: "error", message: error.message });
1151
+ next(new import_node_server_utils8.BadRequestError(error.message));
1152
+ return;
1153
+ }
1154
+ try {
1155
+ const id = await _createUnit(payload);
1156
+ res.status(201).json({ message: "Unit created successfully.", id });
1157
+ return;
1158
+ } catch (error2) {
1159
+ import_node_server_utils8.logger.log({ level: "error", message: error2.message });
1160
+ next(error2);
1161
+ return;
1162
+ }
1163
+ }
1164
+ async function getUnits(req, res, next) {
1165
+ const query = { ...req.query, ...req.params };
1274
1166
  const validation = import_joi4.default.object({
1275
1167
  page: import_joi4.default.number().min(1).optional().allow("", null),
1276
1168
  limit: import_joi4.default.number().min(1).optional().allow("", null),
1277
1169
  search: import_joi4.default.string().optional().allow("", null),
1278
- site: import_joi4.default.string().hex().optional().allow("", null)
1170
+ site: import_joi4.default.string().hex().required()
1279
1171
  });
1280
1172
  const { error } = validation.validate(query);
1281
1173
  if (error) {
1174
+ import_node_server_utils8.logger.log({ level: "error", message: error.message });
1282
1175
  next(new import_node_server_utils8.BadRequestError(error.message));
1283
1176
  return;
1284
1177
  }
1285
1178
  const page = parseInt(req.query.page) ?? 1;
1286
- let limit = parseInt(req.query.limit) ?? 20;
1287
- limit = isNaN(limit) ? 20 : limit;
1288
- const sort = req.query.sort ? String(req.query.sort).split(",") : "";
1289
- const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
1290
- const sortObj = {};
1291
- if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
1292
- sort.forEach((field, index) => {
1293
- sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
1294
- });
1295
- }
1296
- const site = req.query.site ?? "";
1179
+ const limit = parseInt(req.query.limit) ?? 20;
1297
1180
  const search = req.query.search ?? "";
1181
+ const site = req.params.site ?? "";
1298
1182
  try {
1299
- const buildings = await _getAll({
1183
+ const data = await _getUnits({
1300
1184
  page,
1301
1185
  limit,
1302
- sort: sortObj,
1303
- site,
1304
- search
1186
+ search,
1187
+ site
1305
1188
  });
1306
- res.json(buildings);
1189
+ res.json(data);
1307
1190
  return;
1308
1191
  } catch (error2) {
1192
+ import_node_server_utils8.logger.log({ level: "error", message: error2.message });
1309
1193
  next(error2);
1310
- }
1311
- }
1312
- async function createToiletLocation(req, res, next) {
1313
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
1314
- (acc, [key, value]) => ({ ...acc, [key]: value }),
1315
- {}
1316
- ) : {};
1317
- const createdBy = cookies["user"] || "";
1318
- const payload = { ...req.body, createdBy };
1319
- const schema = import_joi4.default.object({
1320
- name: import_joi4.default.string().required(),
1321
- site: import_joi4.default.string().hex().optional().allow("", null),
1322
- status: import_joi4.default.string().optional().allow("", null),
1323
- createdBy: import_joi4.default.string().hex().optional().allow("", null)
1324
- });
1325
- const { error } = schema.validate(payload);
1326
- if (error) {
1327
- next(new import_node_server_utils8.BadRequestError(error.message));
1328
- import_node_server_utils8.logger.info(`Controller: ${error.message}`);
1329
- return;
1330
- }
1331
- try {
1332
- const result = await _createToiletLocation(payload);
1333
- res.status(201).json(result);
1334
1194
  return;
1335
- } catch (error2) {
1336
- next(error2);
1337
1195
  }
1338
1196
  }
1339
- async function updateToiletLocation(req, res, next) {
1197
+ async function updateUnit(req, res, next) {
1340
1198
  const payload = { id: req.params.id, ...req.body };
1341
- const schema = import_joi4.default.object({
1199
+ const validation = import_joi4.default.object({
1342
1200
  id: import_joi4.default.string().hex().required(),
1343
- name: import_joi4.default.string().required(),
1344
- checklist: import_joi4.default.array().items(
1345
- import_joi4.default.object({
1346
- _id: import_joi4.default.string().hex().required(),
1347
- name: import_joi4.default.string().required()
1348
- }).optional()
1349
- ),
1350
- site: import_joi4.default.string().hex().optional().allow("", null),
1351
- status: import_joi4.default.string().optional().allow("", null)
1201
+ name: import_joi4.default.string().required()
1352
1202
  });
1353
- const { error } = schema.validate(payload);
1203
+ const { error } = validation.validate(payload);
1354
1204
  if (error) {
1355
1205
  import_node_server_utils8.logger.log({ level: "error", message: error.message });
1356
1206
  next(new import_node_server_utils8.BadRequestError(error.message));
@@ -1358,74 +1208,29 @@ function useToiletLocationController() {
1358
1208
  }
1359
1209
  try {
1360
1210
  const { id, ...value } = payload;
1361
- await _updateToiletLocation(id, value);
1362
- res.status(201).json({ message: "Toilet location updated successfully." });
1211
+ await _updateUnit(id, value);
1212
+ res.json({ message: "Unit updated successfully." });
1363
1213
  return;
1364
1214
  } catch (error2) {
1365
1215
  import_node_server_utils8.logger.log({ level: "error", message: error2.message });
1366
1216
  next(error2);
1217
+ return;
1367
1218
  }
1368
1219
  }
1369
- async function deleteToiletLocation(req, res, next) {
1220
+ async function deleteUnit(req, res, next) {
1370
1221
  const id = req.params.id;
1371
1222
  const validation = import_joi4.default.object({
1372
1223
  id: import_joi4.default.string().hex().required()
1373
1224
  });
1374
1225
  const { error } = validation.validate({ id });
1375
- if (error) {
1376
- next(new import_node_server_utils8.BadRequestError(error.message));
1377
- return;
1378
- }
1379
- try {
1380
- const message = await _deleteById(id);
1381
- res.json(message);
1382
- return;
1383
- } catch (error2) {
1384
- next(error2);
1385
- }
1386
- }
1387
- async function updateToiletLocationChecklist(req, res, next) {
1388
- const payload = { id: req.params.id, ...req.body };
1389
- const schema = import_joi4.default.object({
1390
- id: import_joi4.default.string().hex().required(),
1391
- checklist: import_joi4.default.array().items(
1392
- import_joi4.default.object({
1393
- _id: import_joi4.default.string().hex().required(),
1394
- name: import_joi4.default.string().required()
1395
- }).required()
1396
- ).min(1).unique("_id", { ignoreUndefined: true }).messages({
1397
- "array.unique": "Duplicate checklist items are not allowed"
1398
- })
1399
- });
1400
- const { error } = schema.validate(payload);
1401
- if (error) {
1402
- import_node_server_utils8.logger.log({ level: "error", message: error.message });
1403
- next(new import_node_server_utils8.BadRequestError(error.message));
1404
- return;
1405
- }
1406
- try {
1407
- const { id, ...value } = payload;
1408
- await _updateToiletLocationChecklist(id, value);
1409
- res.json({ message: "Toilet location updated successfully." });
1410
- return;
1411
- } catch (error2) {
1412
- import_node_server_utils8.logger.log({ level: "error", message: error2.message });
1413
- next(error2);
1414
- return;
1415
- }
1416
- }
1417
- async function getToiletLocationById(req, res, next) {
1418
- const validation = import_joi4.default.string().hex().required();
1419
- const _id = req.params.id;
1420
- const { error } = validation.validate(_id);
1421
1226
  if (error) {
1422
1227
  import_node_server_utils8.logger.log({ level: "error", message: error.message });
1423
1228
  next(new import_node_server_utils8.BadRequestError(error.message));
1424
1229
  return;
1425
1230
  }
1426
1231
  try {
1427
- const data = await _getToiletLocationById(_id);
1428
- res.json(data);
1232
+ await _deleteUnit(id);
1233
+ res.json({ message: "Unit deleted successfully." });
1429
1234
  return;
1430
1235
  } catch (error2) {
1431
1236
  import_node_server_utils8.logger.log({ level: "error", message: error2.message });
@@ -1433,22 +1238,14 @@ function useToiletLocationController() {
1433
1238
  return;
1434
1239
  }
1435
1240
  }
1436
- async function uploadByFile(req, res, next) {
1241
+ async function importUnit(req, res, next) {
1437
1242
  if (!req.file) {
1438
1243
  next(new import_node_server_utils8.BadRequestError("File is required!"));
1439
1244
  return;
1440
1245
  }
1441
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
1442
- (acc, [key, value]) => ({ ...acc, [key]: value }),
1443
- {}
1444
- ) : {};
1445
- const createdBy = cookies["user"] || "";
1446
- const { site } = req.body;
1447
- const schema = import_joi4.default.object({
1448
- site: import_joi4.default.string().hex().optional().allow("", null),
1449
- createdBy: import_joi4.default.string().hex().required()
1450
- });
1451
- const { error } = schema.validate({ site, createdBy });
1246
+ const { site } = req.params;
1247
+ const validation = import_joi4.default.string().hex().required();
1248
+ const { error } = validation.validate(site);
1452
1249
  if (error) {
1453
1250
  import_node_server_utils8.logger.log({ level: "error", message: error.message });
1454
1251
  next(new import_node_server_utils8.BadRequestError(error.message));
@@ -1457,7 +1254,7 @@ function useToiletLocationController() {
1457
1254
  try {
1458
1255
  const xlsData = await convertBufferFile(req.file.buffer);
1459
1256
  const dataJson = JSON.stringify(xlsData);
1460
- const result = await _uploadByFile({ dataJson, createdBy, site });
1257
+ const result = await _importUnit({ dataJson, site });
1461
1258
  return res.status(201).json(result);
1462
1259
  } catch (error2) {
1463
1260
  import_node_server_utils8.logger.log({ level: "error", message: error2.message });
@@ -1466,13 +1263,11 @@ function useToiletLocationController() {
1466
1263
  }
1467
1264
  }
1468
1265
  return {
1469
- getAll,
1470
- createToiletLocation,
1471
- updateToiletLocation,
1472
- deleteToiletLocation,
1473
- updateToiletLocationChecklist,
1474
- getToiletLocationById,
1475
- uploadByFile
1266
+ createUnit,
1267
+ getUnits,
1268
+ updateUnit,
1269
+ deleteUnit,
1270
+ importUnit
1476
1271
  };
1477
1272
  }
1478
1273
 
@@ -1480,22 +1275,9 @@ function useToiletLocationController() {
1480
1275
  var import_node_server_utils9 = require("@iservice365/node-server-utils");
1481
1276
  var import_joi5 = __toESM(require("joi"));
1482
1277
  var import_mongodb5 = require("mongodb");
1483
- var allowedTypes = ["cleaner", "toilet"];
1484
- var allowedStatus = [
1485
- "To Do",
1486
- "Pending",
1487
- "In Progress",
1488
- "Completed",
1489
- "Expired"
1490
- ];
1491
1278
  var parentChecklistSchema = import_joi5.default.object({
1492
- date: import_joi5.default.date().required(),
1493
- status: import_joi5.default.array().items(
1494
- import_joi5.default.object({
1495
- type: import_joi5.default.string().required().valid(...allowedTypes),
1496
- site: import_joi5.default.string().hex().required()
1497
- })
1498
- ).optional()
1279
+ createdAt: import_joi5.default.alternatives().try(import_joi5.default.date(), import_joi5.default.string()).optional().allow("", null),
1280
+ site: import_joi5.default.string().hex().required()
1499
1281
  });
1500
1282
  function MParentChecklist(value) {
1501
1283
  const { error } = parentChecklistSchema.validate(value);
@@ -1503,26 +1285,17 @@ function MParentChecklist(value) {
1503
1285
  import_node_server_utils9.logger.info(`Hygiene Parent Checklist Model: ${error.message}`);
1504
1286
  throw new import_node_server_utils9.BadRequestError(error.message);
1505
1287
  }
1506
- if (value.status && Array.isArray(value.status)) {
1507
- value.status = value.status.map((item) => {
1508
- try {
1509
- return {
1510
- ...item,
1511
- site: new import_mongodb5.ObjectId(item.site),
1512
- status: item.status || "To Do",
1513
- completedAt: item.completedAt || ""
1514
- };
1515
- } catch (error2) {
1516
- throw new import_node_server_utils9.BadRequestError(
1517
- `Invalid status site ID format: ${item.site}`
1518
- );
1519
- }
1520
- });
1288
+ if (value.site) {
1289
+ try {
1290
+ value.site = new import_mongodb5.ObjectId(value.site);
1291
+ } catch (error2) {
1292
+ throw new import_node_server_utils9.BadRequestError(`Invalid site ID format: ${value.site}`);
1293
+ }
1521
1294
  }
1522
1295
  return {
1523
- date: new Date(value.date),
1524
- status: value.status,
1525
- createdAt: /* @__PURE__ */ new Date(),
1296
+ site: value.site,
1297
+ status: "ready",
1298
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
1526
1299
  updatedAt: value.updatedAt ?? ""
1527
1300
  };
1528
1301
  }
@@ -1535,14 +1308,17 @@ function useParentChecklistRepo() {
1535
1308
  if (!db) {
1536
1309
  throw new import_node_server_utils10.InternalServerError("Unable to connect to server.");
1537
1310
  }
1538
- const namespace_collection = "hygiene-parent-checklist";
1311
+ const namespace_collection = "site.cleaning.schedules";
1312
+ const site_collection = "sites";
1539
1313
  const collection = db.collection(namespace_collection);
1314
+ const siteCollection = db.collection(site_collection);
1540
1315
  const { delNamespace, setCache, getCache } = (0, import_node_server_utils10.useCache)(namespace_collection);
1541
1316
  async function createIndex() {
1542
1317
  try {
1543
1318
  await collection.createIndexes([
1544
- { key: { date: 1 } },
1545
- { key: { "status.type": 1, "status.site": 1 } }
1319
+ { key: { createdAt: 1 } },
1320
+ { key: { site: 1 } },
1321
+ { key: { status: 1 } }
1546
1322
  ]);
1547
1323
  } catch (error) {
1548
1324
  throw new import_node_server_utils10.InternalServerError(
@@ -1552,13 +1328,13 @@ function useParentChecklistRepo() {
1552
1328
  }
1553
1329
  async function createParentChecklist(value, session) {
1554
1330
  try {
1555
- const currentDate = value.date ? new Date(value.date) : /* @__PURE__ */ new Date();
1331
+ const currentDate = value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date();
1556
1332
  const startOfDay = new Date(currentDate);
1557
1333
  startOfDay.setUTCHours(0, 0, 0, 0);
1558
1334
  const endOfDay = new Date(currentDate);
1559
1335
  endOfDay.setUTCHours(23, 59, 59, 999);
1560
1336
  const existingChecklist = await collection.findOne({
1561
- date: {
1337
+ createdAt: {
1562
1338
  $gte: startOfDay,
1563
1339
  $lte: endOfDay
1564
1340
  }
@@ -1568,8 +1344,25 @@ function useParentChecklistRepo() {
1568
1344
  import_node_server_utils10.logger.info(`Parent checklist already exists for today: ${dateStr2}`);
1569
1345
  return existingChecklist._id;
1570
1346
  }
1571
- const processedValue = MParentChecklist(value);
1572
- const result = await collection.insertOne(processedValue, { session });
1347
+ const siteIds = await getHygieneSiteIds();
1348
+ if (!Array.isArray(siteIds)) {
1349
+ import_node_server_utils10.logger.error("getHygieneSiteIds returned non-array value:", siteIds);
1350
+ throw new import_node_server_utils10.InternalServerError("Failed to retrieve site IDs");
1351
+ }
1352
+ if (siteIds.length === 0) {
1353
+ import_node_server_utils10.logger.warn("No sites found for creating parent checklist");
1354
+ throw new import_node_server_utils10.BadRequestError("No sites available for checklist creation");
1355
+ }
1356
+ const checklistDocs = [];
1357
+ for (const site of siteIds) {
1358
+ checklistDocs.push(
1359
+ MParentChecklist({
1360
+ site,
1361
+ createdAt: currentDate
1362
+ })
1363
+ );
1364
+ }
1365
+ const result = await collection.insertMany(checklistDocs, { session });
1573
1366
  delNamespace().then(() => {
1574
1367
  import_node_server_utils10.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
1575
1368
  }).catch((err) => {
@@ -1580,9 +1373,9 @@ function useParentChecklistRepo() {
1580
1373
  });
1581
1374
  const dateStr = currentDate.toISOString().split("T")[0];
1582
1375
  import_node_server_utils10.logger.info(
1583
- `Created new parent checklist ${result.insertedId} for today: ${dateStr}`
1376
+ `Created ${Object.keys(result.insertedIds).length} parent checklists for today: ${dateStr}`
1584
1377
  );
1585
- return result.insertedId;
1378
+ return Object.values(result.insertedIds);
1586
1379
  } catch (error) {
1587
1380
  import_node_server_utils10.logger.error("Failed to create daily parent checklist", error);
1588
1381
  throw error;
@@ -1593,7 +1386,6 @@ function useParentChecklistRepo() {
1593
1386
  limit = 10,
1594
1387
  search = "",
1595
1388
  site,
1596
- type,
1597
1389
  startDate = "",
1598
1390
  endDate = ""
1599
1391
  }) {
@@ -1605,19 +1397,13 @@ function useParentChecklistRepo() {
1605
1397
  };
1606
1398
  try {
1607
1399
  site = new import_mongodb6.ObjectId(site);
1400
+ query.site = site;
1608
1401
  cacheOptions.site = site.toString();
1609
1402
  } catch (error) {
1610
1403
  throw new import_node_server_utils10.BadRequestError("Invalid site ID format.");
1611
1404
  }
1612
- cacheOptions.type = type;
1613
- query.status = {
1614
- $elemMatch: {
1615
- site: new import_mongodb6.ObjectId(site),
1616
- type
1617
- }
1618
- };
1619
1405
  if (search) {
1620
- query.$or = [{ name: { $regex: search, $options: "i" } }];
1406
+ query.$text = { $search: search };
1621
1407
  cacheOptions.search = search;
1622
1408
  }
1623
1409
  if (startDate && endDate) {
@@ -1642,35 +1428,24 @@ function useParentChecklistRepo() {
1642
1428
  }
1643
1429
  try {
1644
1430
  const pipeline = [{ $match: query }];
1645
- const filterConditions = [];
1646
- filterConditions.push({ $eq: ["$$this.site", new import_mongodb6.ObjectId(site)] });
1647
- filterConditions.push({ $eq: ["$$this.type", type] });
1648
- pipeline.push({
1649
- $addFields: {
1650
- filteredStatus: {
1651
- $filter: {
1652
- input: "$status",
1653
- cond: { $and: filterConditions }
1654
- }
1655
- }
1656
- }
1657
- });
1658
- pipeline.push({
1659
- $match: {
1660
- filteredStatus: { $ne: [] }
1661
- }
1662
- });
1663
- pipeline.push({
1664
- $addFields: {
1665
- statusObj: { $arrayElemAt: ["$filteredStatus", 0] }
1666
- }
1667
- });
1668
1431
  pipeline.push({
1669
1432
  $project: {
1670
1433
  _id: 1,
1671
- date: 1,
1672
- status: "$statusObj.status",
1673
- completedAt: "$statusObj.completedAt",
1434
+ site: 1,
1435
+ status: {
1436
+ $switch: {
1437
+ branches: [
1438
+ { case: { $eq: ["$status", "ready"] }, then: "Ready" },
1439
+ {
1440
+ case: { $eq: ["$status", "ongoing"] },
1441
+ then: "Ongoing"
1442
+ },
1443
+ { case: { $eq: ["$status", "completed"] }, then: "Completed" }
1444
+ ],
1445
+ default: "$status"
1446
+ }
1447
+ },
1448
+ completedAt: 1,
1674
1449
  createdAt: 1
1675
1450
  }
1676
1451
  });
@@ -1692,10 +1467,10 @@ function useParentChecklistRepo() {
1692
1467
  throw error;
1693
1468
  }
1694
1469
  }
1695
- async function updateParentChecklistStatuses(date) {
1470
+ async function updateParentChecklistStatuses(createdAt) {
1696
1471
  try {
1697
1472
  const currentDate = /* @__PURE__ */ new Date();
1698
- const dateToUpdate = date || new Date(currentDate.getTime() - 24 * 60 * 60 * 1e3);
1473
+ const dateToUpdate = createdAt || new Date(currentDate.getTime() - 24 * 60 * 60 * 1e3);
1699
1474
  const startOfDay = new Date(dateToUpdate);
1700
1475
  startOfDay.setUTCHours(0, 0, 0, 0);
1701
1476
  const endOfDay = new Date(dateToUpdate);
@@ -1714,38 +1489,32 @@ function useParentChecklistRepo() {
1714
1489
  },
1715
1490
  {
1716
1491
  $lookup: {
1717
- from: "hygiene-checklist.areas",
1718
- localField: "_id",
1719
- foreignField: "parentChecklist",
1492
+ from: "site.cleaning.schedule.areas",
1493
+ let: { parentId: "$_id" },
1720
1494
  pipeline: [
1495
+ {
1496
+ $match: {
1497
+ $expr: { $eq: ["$parentChecklist", "$$parentId"] }
1498
+ }
1499
+ },
1721
1500
  {
1722
1501
  $group: {
1723
1502
  _id: {
1724
- site: "$site",
1725
- type: "$type"
1503
+ parentChecklist: "$parentChecklist"
1726
1504
  },
1727
1505
  completedCount: {
1728
1506
  $sum: {
1729
- $cond: [{ $eq: ["$status", "Completed"] }, 1, 0]
1507
+ $cond: [{ $eq: ["$status", "completed"] }, 1, 0]
1730
1508
  }
1731
1509
  },
1732
- inProgressCount: {
1510
+ ongoingCount: {
1733
1511
  $sum: {
1734
- $cond: [{ $eq: ["$status", "In Progress"] }, 1, 0]
1512
+ $cond: [{ $eq: ["$status", "ongoing"] }, 1, 0]
1735
1513
  }
1736
1514
  },
1737
- toDoCount: {
1515
+ readyCount: {
1738
1516
  $sum: {
1739
- $cond: [
1740
- {
1741
- $or: [
1742
- { $eq: ["$status", "To Do"] },
1743
- { $eq: ["$status", "Pending"] }
1744
- ]
1745
- },
1746
- 1,
1747
- 0
1748
- ]
1517
+ $cond: [{ $eq: ["$status", "ready"] }, 1, 0]
1749
1518
  }
1750
1519
  },
1751
1520
  totalCount: { $sum: 1 }
@@ -1758,21 +1527,21 @@ function useParentChecklistRepo() {
1758
1527
  if: {
1759
1528
  $and: [
1760
1529
  { $gt: ["$completedCount", 0] },
1761
- { $eq: ["$inProgressCount", 0] },
1762
- { $eq: ["$toDoCount", 0] }
1530
+ { $eq: ["$ongoingCount", 0] },
1531
+ { $eq: ["$readyCount", 0] }
1763
1532
  ]
1764
1533
  },
1765
- then: "Completed",
1534
+ then: "completed",
1766
1535
  else: {
1767
1536
  $cond: {
1768
1537
  if: {
1769
1538
  $and: [
1770
1539
  { $eq: ["$completedCount", 0] },
1771
- { $eq: ["$inProgressCount", 0] }
1540
+ { $eq: ["$ongoingCount", 0] }
1772
1541
  ]
1773
1542
  },
1774
- then: "Expired",
1775
- else: "In Progress"
1543
+ then: "expired",
1544
+ else: "ongoing"
1776
1545
  }
1777
1546
  }
1778
1547
  }
@@ -1782,8 +1551,8 @@ function useParentChecklistRepo() {
1782
1551
  if: {
1783
1552
  $and: [
1784
1553
  { $gt: ["$completedCount", 0] },
1785
- { $eq: ["$inProgressCount", 0] },
1786
- { $eq: ["$toDoCount", 0] }
1554
+ { $eq: ["$ongoingCount", 0] },
1555
+ { $eq: ["$readyCount", 0] }
1787
1556
  ]
1788
1557
  },
1789
1558
  then: /* @__PURE__ */ new Date(),
@@ -1796,27 +1565,21 @@ function useParentChecklistRepo() {
1796
1565
  as: "areaStats"
1797
1566
  }
1798
1567
  },
1568
+ {
1569
+ $match: {
1570
+ "areaStats.0": { $exists: true }
1571
+ }
1572
+ },
1799
1573
  {
1800
1574
  $addFields: {
1801
- newStatus: {
1802
- $map: {
1803
- input: "$areaStats",
1804
- as: "stat",
1805
- in: {
1806
- site: "$$stat._id.site",
1807
- type: "$$stat._id.type",
1808
- status: "$$stat.finalStatus",
1809
- completedAt: "$$stat.completedAt"
1810
- }
1811
- }
1812
- }
1575
+ areaData: { $arrayElemAt: ["$areaStats", 0] }
1813
1576
  }
1814
1577
  },
1815
- { $match: { newStatus: { $ne: [] } } },
1816
1578
  {
1817
1579
  $project: {
1818
1580
  _id: 1,
1819
- newStatus: 1
1581
+ newStatus: "$areaData.finalStatus",
1582
+ completedAt: "$areaData.completedAt"
1820
1583
  }
1821
1584
  }
1822
1585
  ]).toArray();
@@ -1830,9 +1593,8 @@ function useParentChecklistRepo() {
1830
1593
  return null;
1831
1594
  }
1832
1595
  const bulkOps = statusUpdates.map((update) => {
1833
- const statusTypes = update.newStatus.map((s) => `${s.type}(${s.status})`).join(", ");
1834
1596
  import_node_server_utils10.logger.info(
1835
- `Updating parent checklist ${update._id} with ${update.newStatus.length} status entries: [${statusTypes}]`
1597
+ `Updating parent checklist ${update._id} with status: ${update.newStatus}`
1836
1598
  );
1837
1599
  return {
1838
1600
  updateOne: {
@@ -1840,6 +1602,7 @@ function useParentChecklistRepo() {
1840
1602
  update: {
1841
1603
  $set: {
1842
1604
  status: update.newStatus,
1605
+ completedAt: update.completedAt,
1843
1606
  updatedAt: /* @__PURE__ */ new Date()
1844
1607
  }
1845
1608
  }
@@ -1865,6 +1628,36 @@ function useParentChecklistRepo() {
1865
1628
  throw error;
1866
1629
  }
1867
1630
  }
1631
+ async function getHygieneSiteIds() {
1632
+ const query = {
1633
+ status: { $ne: "deleted" }
1634
+ };
1635
+ const cacheKey = (0, import_node_server_utils10.makeCacheKey)(site_collection, { tag: "site-ids" });
1636
+ const cachedData = await getCache(cacheKey);
1637
+ if (cachedData && Array.isArray(cachedData)) {
1638
+ import_node_server_utils10.logger.info(`Cache hit for key: ${cacheKey}`);
1639
+ return cachedData;
1640
+ }
1641
+ try {
1642
+ const items = await siteCollection.aggregate([
1643
+ { $match: query },
1644
+ { $project: { _id: 1 } },
1645
+ { $sort: { _id: -1 } }
1646
+ ]).toArray();
1647
+ const siteIds = items.map((item) => item._id.toString());
1648
+ if (siteIds.length > 0) {
1649
+ setCache(cacheKey, siteIds, 15 * 60).then(() => {
1650
+ import_node_server_utils10.logger.info(`Cache set for key: ${cacheKey}`);
1651
+ }).catch((err) => {
1652
+ import_node_server_utils10.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
1653
+ });
1654
+ }
1655
+ return siteIds;
1656
+ } catch (error) {
1657
+ import_node_server_utils10.logger.error("Failed to get hygiene site IDs", error);
1658
+ throw error;
1659
+ }
1660
+ }
1868
1661
  return {
1869
1662
  createIndex,
1870
1663
  createParentChecklist,
@@ -1906,7 +1699,6 @@ function useParentChecklistController() {
1906
1699
  limit: import_joi6.default.number().min(1).optional().allow("", null),
1907
1700
  search: import_joi6.default.string().optional().allow("", null),
1908
1701
  site: import_joi6.default.string().hex().required(),
1909
- type: import_joi6.default.string().required().valid(...allowedTypes),
1910
1702
  startDate: import_joi6.default.alternatives().try(import_joi6.default.date(), import_joi6.default.string()).optional().allow("", null),
1911
1703
  endDate: import_joi6.default.alternatives().try(import_joi6.default.date(), import_joi6.default.string()).optional().allow("", null)
1912
1704
  });
@@ -1916,1299 +1708,119 @@ function useParentChecklistController() {
1916
1708
  next(new import_node_server_utils11.BadRequestError(error.message));
1917
1709
  return;
1918
1710
  }
1919
- const page = parseInt(req.query.page) ?? 1;
1920
- const limit = parseInt(req.query.limit) ?? 20;
1921
- const search = req.query.search ?? "";
1922
- const site = req.params.site ?? "";
1923
- const type = req.params.type ?? "";
1924
- const startDate = req.query.startDate ?? "";
1925
- const endDate = req.query.endDate ?? "";
1926
- try {
1927
- const data = await _getAllParentChecklist({
1928
- page,
1929
- limit,
1930
- search,
1931
- site,
1932
- type,
1933
- startDate,
1934
- endDate
1935
- });
1936
- res.json(data);
1937
- return;
1938
- } catch (error2) {
1939
- import_node_server_utils11.logger.log({ level: "error", message: error2.message });
1940
- next(error2);
1941
- return;
1942
- }
1943
- }
1944
- return {
1945
- createParentChecklist,
1946
- getAllParentChecklist
1947
- };
1948
- }
1949
-
1950
- // src/models/hygiene-unit.model.ts
1951
- var import_node_server_utils12 = require("@iservice365/node-server-utils");
1952
- var import_joi7 = __toESM(require("joi"));
1953
- var import_mongodb7 = require("mongodb");
1954
- var unitSchema = import_joi7.default.object({
1955
- name: import_joi7.default.string().required(),
1956
- site: import_joi7.default.string().hex().required(),
1957
- createdBy: import_joi7.default.string().hex().required()
1958
- });
1959
- function MUnit(value) {
1960
- const { error } = unitSchema.validate(value);
1961
- if (error) {
1962
- import_node_server_utils12.logger.info(`Hygiene Unit Model: ${error.message}`);
1963
- throw new import_node_server_utils12.BadRequestError(error.message);
1964
- }
1965
- if (value.site) {
1966
- try {
1967
- value.site = new import_mongodb7.ObjectId(value.site);
1968
- } catch (error2) {
1969
- throw new import_node_server_utils12.BadRequestError("Invalid site ID format.");
1970
- }
1971
- }
1972
- if (value.createdBy) {
1973
- try {
1974
- value.createdBy = new import_mongodb7.ObjectId(value.createdBy);
1975
- } catch (error2) {
1976
- throw new import_node_server_utils12.BadRequestError("Invalid createdBy ID format.");
1977
- }
1978
- }
1979
- return {
1980
- name: value.name,
1981
- createdBy: value.createdBy,
1982
- site: value.site,
1983
- status: "active",
1984
- createdAt: /* @__PURE__ */ new Date(),
1985
- updatedAt: value.updatedAt ?? "",
1986
- deletedAt: value.deletedAt ?? ""
1987
- };
1988
- }
1989
-
1990
- // src/services/hygiene-unit.service.ts
1991
- var import_node_server_utils14 = require("@iservice365/node-server-utils");
1992
-
1993
- // src/repositories/hygiene-unit.repository.ts
1994
- var import_mongodb8 = require("mongodb");
1995
- var import_node_server_utils13 = require("@iservice365/node-server-utils");
1996
- function useUnitRepository() {
1997
- const db = import_node_server_utils13.useAtlas.getDb();
1998
- if (!db) {
1999
- throw new import_node_server_utils13.InternalServerError("Unable to connect to server.");
2000
- }
2001
- const namespace_collection = "hygiene-units";
2002
- const collection = db.collection(namespace_collection);
2003
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils13.useCache)(namespace_collection);
2004
- async function createIndex() {
2005
- try {
2006
- await collection.createIndexes([
2007
- { key: { site: 1 } },
2008
- { key: { createdBy: 1 } },
2009
- { key: { status: 1 } }
2010
- ]);
2011
- } catch (error) {
2012
- throw new import_node_server_utils13.InternalServerError("Failed to create index on hygiene unit.");
2013
- }
2014
- }
2015
- async function createTextIndex() {
2016
- try {
2017
- await collection.createIndex({ name: "text" });
2018
- } catch (error) {
2019
- throw new import_node_server_utils13.InternalServerError(
2020
- "Failed to create text index on hygiene unit."
2021
- );
2022
- }
2023
- }
2024
- async function createUniqueIndex() {
2025
- try {
2026
- await collection.createIndex(
2027
- { name: 1, site: 1, deletedAt: 1 },
2028
- { unique: true }
2029
- );
2030
- } catch (error) {
2031
- throw new import_node_server_utils13.InternalServerError(
2032
- "Failed to create unique index on hygiene unit."
2033
- );
2034
- }
2035
- }
2036
- async function createUnit(value, session) {
2037
- try {
2038
- value = MUnit(value);
2039
- const res = await collection.insertOne(value, { session });
2040
- delNamespace().then(() => {
2041
- import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2042
- }).catch((err) => {
2043
- import_node_server_utils13.logger.error(
2044
- `Failed to clear cache for namespace: ${namespace_collection}`,
2045
- err
2046
- );
2047
- });
2048
- return res.insertedId;
2049
- } catch (error) {
2050
- const isDuplicated = error.message.includes("duplicate");
2051
- if (isDuplicated) {
2052
- throw new import_node_server_utils13.BadRequestError("Unit already exists.");
2053
- }
2054
- throw error;
2055
- }
2056
- }
2057
- async function getUnits({
2058
- page = 1,
2059
- limit = 10,
2060
- search = "",
2061
- startDate = "",
2062
- endDate = "",
2063
- site = ""
2064
- }) {
2065
- page = page > 0 ? page - 1 : 0;
2066
- try {
2067
- site = new import_mongodb8.ObjectId(site);
2068
- } catch (error) {
2069
- throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
2070
- }
2071
- const query = {
2072
- status: { $ne: "deleted" },
2073
- site
2074
- };
2075
- const cacheOptions = {
2076
- page,
2077
- limit,
2078
- site: site.toString()
2079
- };
2080
- if (search) {
2081
- query.$or = [{ name: { $regex: search, $options: "i" } }];
2082
- cacheOptions.search = search;
2083
- }
2084
- if (startDate && endDate) {
2085
- query.createdAt = {
2086
- $gte: new Date(startDate),
2087
- $lte: new Date(endDate)
2088
- };
2089
- cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
2090
- cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
2091
- } else if (startDate) {
2092
- query.createdAt = { $gte: new Date(startDate) };
2093
- cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
2094
- } else if (endDate) {
2095
- query.createdAt = { $lte: new Date(endDate) };
2096
- cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
2097
- }
2098
- const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
2099
- const cachedData = await getCache(cacheKey);
2100
- if (cachedData) {
2101
- import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
2102
- return cachedData;
2103
- }
2104
- try {
2105
- const items = await collection.aggregate([
2106
- { $match: query },
2107
- {
2108
- $lookup: {
2109
- from: "sites",
2110
- localField: "site",
2111
- foreignField: "_id",
2112
- pipeline: [{ $project: { name: 1 } }],
2113
- as: "site"
2114
- }
2115
- },
2116
- {
2117
- $unwind: {
2118
- path: "$site",
2119
- preserveNullAndEmptyArrays: true
2120
- }
2121
- },
2122
- {
2123
- $lookup: {
2124
- from: "users",
2125
- localField: "createdBy",
2126
- foreignField: "_id",
2127
- pipeline: [{ $project: { name: 1 } }],
2128
- as: "createdBy"
2129
- }
2130
- },
2131
- {
2132
- $unwind: {
2133
- path: "$createdBy",
2134
- preserveNullAndEmptyArrays: true
2135
- }
2136
- },
2137
- {
2138
- $project: {
2139
- name: 1,
2140
- site: "$site._id",
2141
- siteName: "$site.name",
2142
- createdByName: "$createdBy.name",
2143
- checklist: 1,
2144
- status: 1,
2145
- createdAt: 1
2146
- }
2147
- },
2148
- { $sort: { _id: -1 } },
2149
- { $skip: page * limit },
2150
- { $limit: limit }
2151
- ]).toArray();
2152
- const length = await collection.countDocuments(query);
2153
- const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
2154
- setCache(cacheKey, data, 15 * 60).then(() => {
2155
- import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
2156
- }).catch((err) => {
2157
- import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2158
- });
2159
- return data;
2160
- } catch (error) {
2161
- throw error;
2162
- }
2163
- }
2164
- async function getUnitByName(name, site) {
2165
- try {
2166
- if (site)
2167
- site = new import_mongodb8.ObjectId(site);
2168
- } catch (error) {
2169
- throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
2170
- }
2171
- try {
2172
- return await collection.findOne({
2173
- name: { $regex: new RegExp(`^${name}$`, "i") },
2174
- ...site && { site }
2175
- });
2176
- } catch (error) {
2177
- throw new import_node_server_utils13.BadRequestError("Unable to fetch unit by name.");
2178
- }
2179
- }
2180
- async function getUnitById(id, site) {
2181
- try {
2182
- id = typeof id === "string" ? new import_mongodb8.ObjectId(id) : id;
2183
- } catch (error) {
2184
- throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
2185
- }
2186
- try {
2187
- if (site)
2188
- site = new import_mongodb8.ObjectId(site);
2189
- } catch (error) {
2190
- throw new import_node_server_utils13.BadRequestError(
2191
- "Unable to fetch unit by ID, Invalid site ID format."
2192
- );
2193
- }
2194
- try {
2195
- return await collection.findOne({ _id: id, ...site && { site } });
2196
- } catch (error) {
2197
- throw new import_node_server_utils13.BadRequestError("Unable to fetch unit by id.");
2198
- }
2199
- }
2200
- async function updateUnit(_id, value) {
2201
- try {
2202
- _id = new import_mongodb8.ObjectId(_id);
2203
- } catch (error) {
2204
- throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
2205
- }
2206
- try {
2207
- const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
2208
- const res = await collection.updateOne({ _id }, { $set: updateValue });
2209
- if (res.modifiedCount === 0) {
2210
- throw new import_node_server_utils13.InternalServerError("Unable to update cleaning unit.");
2211
- }
2212
- delNamespace().then(() => {
2213
- import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2214
- }).catch((err) => {
2215
- import_node_server_utils13.logger.error(
2216
- `Failed to clear cache for namespace: ${namespace_collection}`,
2217
- err
2218
- );
2219
- });
2220
- return res.modifiedCount;
2221
- } catch (error) {
2222
- const isDuplicated = error.message.includes("duplicate");
2223
- if (isDuplicated) {
2224
- throw new import_node_server_utils13.BadRequestError("Area already exists.");
2225
- }
2226
- throw error;
2227
- }
2228
- }
2229
- async function deleteUnit(_id, session) {
2230
- try {
2231
- _id = new import_mongodb8.ObjectId(_id);
2232
- } catch (error) {
2233
- throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
2234
- }
2235
- try {
2236
- const updateValue = {
2237
- status: "deleted",
2238
- updatedAt: /* @__PURE__ */ new Date(),
2239
- deletedAt: /* @__PURE__ */ new Date()
2240
- };
2241
- const res = await collection.updateOne(
2242
- { _id },
2243
- { $set: updateValue },
2244
- { session }
2245
- );
2246
- if (res.modifiedCount === 0) {
2247
- throw new import_node_server_utils13.InternalServerError("Unable to delete unit.");
2248
- }
2249
- delNamespace().then(() => {
2250
- import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2251
- }).catch((err) => {
2252
- import_node_server_utils13.logger.error(
2253
- `Failed to clear cache for namespace: ${namespace_collection}`,
2254
- err
2255
- );
2256
- });
2257
- return res.modifiedCount;
2258
- } catch (error) {
2259
- throw error;
2260
- }
2261
- }
2262
- return {
2263
- createIndex,
2264
- createTextIndex,
2265
- createUniqueIndex,
2266
- createUnit,
2267
- getUnits,
2268
- getUnitByName,
2269
- getUnitById,
2270
- updateUnit,
2271
- deleteUnit
2272
- };
2273
- }
2274
-
2275
- // src/services/hygiene-unit.service.ts
2276
- function useUnitService() {
2277
- const { createUnit: _createUnit } = useUnitRepository();
2278
- async function uploadByFile({
2279
- dataJson,
2280
- createdBy,
2281
- site
2282
- }) {
2283
- let dataArray;
2284
- try {
2285
- dataArray = JSON.parse(dataJson);
2286
- } catch (error) {
2287
- throw new import_node_server_utils14.BadRequestError("Invalid JSON format for data in excel");
2288
- }
2289
- if (!dataArray || dataArray.length === 0) {
2290
- throw new import_node_server_utils14.NotFoundError("No data found in the uploaded file");
2291
- }
2292
- const session = import_node_server_utils14.useAtlas.getClient()?.startSession();
2293
- const insertedUnitIds = [];
2294
- try {
2295
- session?.startTransaction();
2296
- for (const row of dataArray) {
2297
- if (!row?.UNIT_NAME) {
2298
- import_node_server_utils14.logger.warn("Skipping row with missing UNIT_NAME:", row);
2299
- continue;
2300
- }
2301
- try {
2302
- const insertedId = await _createUnit(
2303
- {
2304
- name: String(row.UNIT_NAME).trim(),
2305
- site,
2306
- createdBy
2307
- },
2308
- session
2309
- );
2310
- insertedUnitIds.push(insertedId);
2311
- } catch (error) {
2312
- import_node_server_utils14.logger.error(
2313
- `Error creating unit "${row.UNIT_NAME}":`,
2314
- error.message
2315
- );
2316
- continue;
2317
- }
2318
- }
2319
- await session?.commitTransaction();
2320
- import_node_server_utils14.logger.info(`Successfully uploaded ${insertedUnitIds.length} units`);
2321
- return {
2322
- message: `Successfully uploaded ${insertedUnitIds.length} units`
2323
- };
2324
- } catch (error) {
2325
- await session?.abortTransaction();
2326
- import_node_server_utils14.logger.error("Error while uploading unit information", error);
2327
- throw error;
2328
- } finally {
2329
- session?.endSession();
2330
- }
2331
- }
2332
- return {
2333
- uploadByFile
2334
- };
2335
- }
2336
-
2337
- // src/controllers/hygiene-unit.controller.ts
2338
- var import_node_server_utils15 = require("@iservice365/node-server-utils");
2339
- var import_joi8 = __toESM(require("joi"));
2340
- function useUnitController() {
2341
- const {
2342
- createUnit: _createUnit,
2343
- getUnits: _getUnits,
2344
- updateUnit: _updateUnit,
2345
- deleteUnit: _deleteUnit
2346
- } = useUnitRepository();
2347
- const { uploadByFile: _uploadByFile } = useUnitService();
2348
- async function createUnit(req, res, next) {
2349
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
2350
- (acc, [key, value]) => ({ ...acc, [key]: value }),
2351
- {}
2352
- ) : {};
2353
- const createdBy = cookies["user"] || "";
2354
- const payload = { ...req.body, createdBy };
2355
- const { error } = unitSchema.validate(payload);
2356
- if (error) {
2357
- import_node_server_utils15.logger.log({ level: "error", message: error.message });
2358
- next(new import_node_server_utils15.BadRequestError(error.message));
2359
- return;
2360
- }
2361
- try {
2362
- const id = await _createUnit(payload);
2363
- res.status(201).json({ message: "Unit created successfully.", id });
2364
- return;
2365
- } catch (error2) {
2366
- import_node_server_utils15.logger.log({ level: "error", message: error2.message });
2367
- next(error2);
2368
- return;
2369
- }
2370
- }
2371
- async function getAll(req, res, next) {
2372
- const query = req.query;
2373
- const validation = import_joi8.default.object({
2374
- page: import_joi8.default.number().min(1).optional().allow("", null),
2375
- limit: import_joi8.default.number().min(1).optional().allow("", null),
2376
- search: import_joi8.default.string().optional().allow("", null),
2377
- startDate: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
2378
- endDate: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
2379
- site: import_joi8.default.string().hex().optional().allow("", null)
2380
- });
2381
- const { error } = validation.validate(query);
2382
- if (error) {
2383
- import_node_server_utils15.logger.log({ level: "error", message: error.message });
2384
- next(new import_node_server_utils15.BadRequestError(error.message));
2385
- return;
2386
- }
2387
- const page = parseInt(req.query.page) ?? 1;
2388
- const limit = parseInt(req.query.limit) ?? 20;
2389
- const search = req.query.search ?? "";
2390
- const site = req.query.site ?? "";
2391
- const startDate = req.query.startDate ?? "";
2392
- const endDate = req.query.endDate ?? "";
2393
- try {
2394
- const data = await _getUnits({
2395
- page,
2396
- limit,
2397
- search,
2398
- site,
2399
- startDate,
2400
- endDate
2401
- });
2402
- res.json(data);
2403
- return;
2404
- } catch (error2) {
2405
- import_node_server_utils15.logger.log({ level: "error", message: error2.message });
2406
- next(error2);
2407
- return;
2408
- }
2409
- }
2410
- async function updateUnit(req, res, next) {
2411
- const payload = { id: req.params.id, ...req.body };
2412
- const schema = import_joi8.default.object({
2413
- id: import_joi8.default.string().hex().required(),
2414
- name: import_joi8.default.string().required()
2415
- });
2416
- const { error } = schema.validate(payload);
2417
- if (error) {
2418
- import_node_server_utils15.logger.log({ level: "error", message: error.message });
2419
- next(new import_node_server_utils15.BadRequestError(error.message));
2420
- return;
2421
- }
2422
- try {
2423
- const { id, ...value } = payload;
2424
- await _updateUnit(id, value);
2425
- res.json({ message: "Unit updated successfully." });
2426
- return;
2427
- } catch (error2) {
2428
- import_node_server_utils15.logger.log({ level: "error", message: error2.message });
2429
- next(error2);
2430
- return;
2431
- }
2432
- }
2433
- async function deleteUnit(req, res, next) {
2434
- const id = req.params.id;
2435
- const validation = import_joi8.default.object({
2436
- id: import_joi8.default.string().hex().required()
2437
- });
2438
- const { error } = validation.validate({ id });
2439
- if (error) {
2440
- import_node_server_utils15.logger.log({ level: "error", message: error.message });
2441
- next(new import_node_server_utils15.BadRequestError(error.message));
2442
- return;
2443
- }
2444
- try {
2445
- await _deleteUnit(id);
2446
- res.json({ message: "Unit deleted successfully." });
2447
- return;
2448
- } catch (error2) {
2449
- import_node_server_utils15.logger.log({ level: "error", message: error2.message });
2450
- next(error2);
2451
- return;
2452
- }
2453
- }
2454
- async function uploadByFile(req, res, next) {
2455
- if (!req.file) {
2456
- next(new import_node_server_utils15.BadRequestError("File is required!"));
2457
- return;
2458
- }
2459
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
2460
- (acc, [key, value]) => ({ ...acc, [key]: value }),
2461
- {}
2462
- ) : {};
2463
- const createdBy = cookies["user"] || "";
2464
- const { site } = req.body;
2465
- const schema = import_joi8.default.object({
2466
- site: import_joi8.default.string().hex().optional().allow("", null),
2467
- createdBy: import_joi8.default.string().hex().required()
2468
- });
2469
- const { error } = schema.validate({ site, createdBy });
2470
- if (error) {
2471
- import_node_server_utils15.logger.log({ level: "error", message: error.message });
2472
- next(new import_node_server_utils15.BadRequestError(error.message));
2473
- return;
2474
- }
2475
- try {
2476
- const xlsData = await convertBufferFile(req.file.buffer);
2477
- const dataJson = JSON.stringify(xlsData);
2478
- const result = await _uploadByFile({ dataJson, createdBy, site });
2479
- return res.status(201).json(result);
2480
- } catch (error2) {
2481
- import_node_server_utils15.logger.log({ level: "error", message: error2.message });
2482
- next(error2);
2483
- return;
2484
- }
2485
- }
2486
- return {
2487
- createUnit,
2488
- getAll,
2489
- updateUnit,
2490
- deleteUnit,
2491
- uploadByFile
2492
- };
2493
- }
2494
-
2495
- // src/models/hygiene-schedule-task-area.model.ts
2496
- var import_node_server_utils16 = require("@iservice365/node-server-utils");
2497
- var import_joi9 = __toESM(require("joi"));
2498
- var import_mongodb9 = require("mongodb");
2499
- var scheduleTaskAreaSchema = import_joi9.default.object({
2500
- name: import_joi9.default.string().required(),
2501
- site: import_joi9.default.string().hex().required(),
2502
- createdBy: import_joi9.default.string().hex().required(),
2503
- checklist: import_joi9.default.array().items(
2504
- import_joi9.default.object({
2505
- _id: import_joi9.default.string().hex().required(),
2506
- name: import_joi9.default.string().required()
2507
- })
2508
- ).optional(),
2509
- updatedAt: import_joi9.default.date().optional().allow("", null),
2510
- status: import_joi9.default.string().allow("", null).optional()
2511
- });
2512
- function MScheduleTaskArea(value) {
2513
- const { error } = scheduleTaskAreaSchema.validate(value);
2514
- if (error) {
2515
- throw new import_node_server_utils16.BadRequestError(error.message);
2516
- }
2517
- if (value.site) {
2518
- try {
2519
- value.site = new import_mongodb9.ObjectId(value.site);
2520
- } catch (error2) {
2521
- throw new import_node_server_utils16.BadRequestError("Invalid site ID format.");
2522
- }
2523
- }
2524
- if (value.createdBy) {
2525
- try {
2526
- value.createdBy = new import_mongodb9.ObjectId(value.createdBy);
2527
- } catch (error2) {
2528
- throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
2529
- }
2530
- }
2531
- if (value.checklist && Array.isArray(value.checklist)) {
2532
- value.checklist = value.checklist.map((item) => {
2533
- try {
2534
- return {
2535
- ...item,
2536
- _id: new import_mongodb9.ObjectId(item._id)
2537
- };
2538
- } catch (error2) {
2539
- throw new import_node_server_utils16.BadRequestError(
2540
- `Invalid checklist item ID format: ${item._id}`
2541
- );
2542
- }
2543
- });
2544
- }
2545
- return {
2546
- name: value.name,
2547
- site: value.site,
2548
- createdBy: value.createdBy,
2549
- checklist: value.checklist,
2550
- status: value.status ?? "",
2551
- createdAt: /* @__PURE__ */ new Date(),
2552
- updatedAt: value.updatedAt ?? "",
2553
- deletedAt: value.deletedAt ?? ""
2554
- };
2555
- }
2556
-
2557
- // src/repositories/hygiene-schedule-task-area.repository.ts
2558
- var import_mongodb10 = require("mongodb");
2559
- var import_node_server_utils17 = require("@iservice365/node-server-utils");
2560
- function useScheduleTaskAreaRepository() {
2561
- const db = import_node_server_utils17.useAtlas.getDb();
2562
- if (!db) {
2563
- throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
2564
- }
2565
- const namespace_collection = "hygiene-schedule-task-areas";
2566
- const collection = db.collection(namespace_collection);
2567
- const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
2568
- async function createIndexes() {
2569
- try {
2570
- await collection.createIndexes([
2571
- { key: { site: 1 } },
2572
- { key: { name: "text" } }
2573
- ]);
2574
- } catch (error) {
2575
- throw new import_node_server_utils17.InternalServerError("Failed to create index on site.");
2576
- }
2577
- }
2578
- async function createUniqueIndex() {
2579
- try {
2580
- await collection.createIndex(
2581
- { name: 1, site: 1, deletedAt: 1 },
2582
- { unique: true }
2583
- );
2584
- } catch (error) {
2585
- throw new import_node_server_utils17.InternalServerError(
2586
- "Failed to create unique index on hygiene area."
2587
- );
2588
- }
2589
- }
2590
- async function createScheduleTaskArea(value, session) {
2591
- try {
2592
- value = MScheduleTaskArea(value);
2593
- const res = await collection.insertOne(value, { session });
2594
- delNamespace().then(() => {
2595
- import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2596
- }).catch((err) => {
2597
- import_node_server_utils17.logger.error(
2598
- `Failed to clear cache for namespace: ${namespace_collection}`,
2599
- err
2600
- );
2601
- });
2602
- return res.insertedId;
2603
- } catch (error) {
2604
- const isDuplicated = error.message.includes("duplicate");
2605
- if (isDuplicated) {
2606
- throw new import_node_server_utils17.BadRequestError("Area already exists.");
2607
- }
2608
- throw error;
2609
- }
2610
- }
2611
- async function updateScheduleTaskArea(_id, params) {
2612
- try {
2613
- _id = new import_mongodb10.ObjectId(_id);
2614
- } catch (error) {
2615
- throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
2616
- }
2617
- try {
2618
- const updateValue = { ...params, updatedAt: /* @__PURE__ */ new Date() };
2619
- const res = await collection.updateOne({ _id }, { $set: updateValue });
2620
- if (res.modifiedCount === 0) {
2621
- throw new import_node_server_utils17.InternalServerError("Unable to update cleaning area.");
2622
- }
2623
- delNamespace().then(() => {
2624
- import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2625
- }).catch((err) => {
2626
- import_node_server_utils17.logger.error(
2627
- `Failed to clear cache for namespace: ${namespace_collection}`,
2628
- err
2629
- );
2630
- });
2631
- return res.modifiedCount;
2632
- } catch (error) {
2633
- const isDuplicated = error.message.includes("duplicate");
2634
- if (isDuplicated) {
2635
- throw new import_node_server_utils17.BadRequestError("Area already exists.");
2636
- }
2637
- throw error;
2638
- }
2639
- }
2640
- async function deleteScheduleTaskArea(_id, session) {
2641
- try {
2642
- _id = new import_mongodb10.ObjectId(_id);
2643
- } catch (error) {
2644
- throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
2645
- }
2646
- try {
2647
- const updateValue = {
2648
- status: "deleted",
2649
- updatedAt: /* @__PURE__ */ new Date(),
2650
- deletedAt: /* @__PURE__ */ new Date()
2651
- };
2652
- const res = await collection.updateOne(
2653
- { _id },
2654
- { $set: updateValue },
2655
- { session }
2656
- );
2657
- if (res.modifiedCount === 0) {
2658
- throw new import_node_server_utils17.InternalServerError("Unable to delete area.");
2659
- }
2660
- delNamespace().then(() => {
2661
- import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2662
- }).catch((err) => {
2663
- import_node_server_utils17.logger.error(
2664
- `Failed to clear cache for namespace: ${namespace_collection}`,
2665
- err
2666
- );
2667
- });
2668
- return res.modifiedCount;
2669
- } catch (error) {
2670
- throw error;
2671
- }
2672
- }
2673
- async function getScheduleTaskAreas({
2674
- page = 1,
2675
- limit = 10,
2676
- search = "",
2677
- startDate = "",
2678
- endDate = "",
2679
- site = ""
2680
- }) {
2681
- page = page > 0 ? page - 1 : 0;
2682
- const query = {
2683
- status: { $ne: "deleted" }
2684
- };
2685
- const cacheOptions = {
2686
- page,
2687
- limit
2688
- };
2689
- if (site) {
2690
- try {
2691
- site = new import_mongodb10.ObjectId(site);
2692
- cacheOptions.site = site.toString();
2693
- } catch (error) {
2694
- throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
2695
- }
2696
- }
2697
- if (search) {
2698
- query.$or = [{ name: { $regex: search, $options: "i" } }];
2699
- cacheOptions.search = search;
2700
- }
2701
- if (startDate && endDate) {
2702
- query.createdAt = {
2703
- $gte: new Date(startDate),
2704
- $lte: new Date(endDate)
2705
- };
2706
- cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
2707
- cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
2708
- } else if (startDate) {
2709
- query.createdAt = { $gte: new Date(startDate) };
2710
- cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
2711
- } else if (endDate) {
2712
- query.createdAt = { $lte: new Date(endDate) };
2713
- cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
2714
- }
2715
- const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
2716
- const cachedData = await getCache(cacheKey);
2717
- if (cachedData) {
2718
- import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
2719
- return cachedData;
2720
- }
2721
- try {
2722
- const items = await collection.aggregate([
2723
- {
2724
- $match: query
2725
- },
2726
- {
2727
- $lookup: {
2728
- from: "sites",
2729
- localField: "site",
2730
- foreignField: "_id",
2731
- pipeline: [{ $project: { name: 1 } }],
2732
- as: "site"
2733
- }
2734
- },
2735
- {
2736
- $unwind: {
2737
- path: "$site",
2738
- preserveNullAndEmptyArrays: true
2739
- }
2740
- },
2741
- {
2742
- $lookup: {
2743
- from: "users",
2744
- localField: "createdBy",
2745
- foreignField: "_id",
2746
- pipeline: [{ $project: { name: 1 } }],
2747
- as: "createdBy"
2748
- }
2749
- },
2750
- {
2751
- $unwind: {
2752
- path: "$createdBy",
2753
- preserveNullAndEmptyArrays: true
2754
- }
2755
- },
2756
- {
2757
- $project: {
2758
- name: 1,
2759
- site: "$site._id",
2760
- siteName: "$site.name",
2761
- createdByName: "$createdBy.name",
2762
- checklist: 1,
2763
- status: 1,
2764
- createdAt: 1
2765
- }
2766
- },
2767
- { $sort: { _id: -1 } },
2768
- { $skip: page * limit },
2769
- { $limit: limit }
2770
- ]).toArray();
2771
- const length = await collection.countDocuments(query);
2772
- const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
2773
- setCache(cacheKey, data, 15 * 60).then(() => {
2774
- import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
2775
- }).catch((err) => {
2776
- import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2777
- });
2778
- return data;
2779
- } catch (error) {
2780
- throw error;
2781
- }
2782
- }
2783
- async function getScheduleTaskAreaByName(name, site) {
2784
- try {
2785
- if (site)
2786
- site = new import_mongodb10.ObjectId(site);
2787
- } catch (error) {
2788
- throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
2789
- }
2790
- try {
2791
- return await collection.findOne({
2792
- name: { $regex: new RegExp(`^${name}$`, "i") },
2793
- ...site && { site }
2794
- });
2795
- } catch (error) {
2796
- throw new import_node_server_utils17.BadRequestError("Unable to fetch schedule task area by name.");
2797
- }
2798
- }
2799
- async function getScheduleTaskAreaById(id, site) {
2800
- try {
2801
- id = typeof id === "string" ? new import_mongodb10.ObjectId(id) : id;
2802
- } catch (error) {
2803
- throw new import_node_server_utils17.BadRequestError("Invalid unit ID format.");
2804
- }
2805
- try {
2806
- if (site)
2807
- site = new import_mongodb10.ObjectId(site);
2808
- } catch (error) {
2809
- throw new import_node_server_utils17.BadRequestError(
2810
- "Unable to fetch schedule task area by ID, Invalid site ID format."
2811
- );
2812
- }
2813
- try {
2814
- return await collection.findOne({ _id: id, ...site && { site } });
2815
- } catch (error) {
2816
- throw new import_node_server_utils17.BadRequestError("Unable to fetch schedule task area by id.");
2817
- }
2818
- }
2819
- async function getAreaById(_id) {
2820
- try {
2821
- _id = new import_mongodb10.ObjectId(_id);
2822
- } catch (error) {
2823
- throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
2824
- }
2825
- const query = {
2826
- _id,
2827
- status: { $ne: "deleted" }
2828
- };
2829
- const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, {
2830
- _id: _id.toString()
2831
- });
2832
- const cachedData = await getCache(cacheKey);
2833
- if (cachedData) {
2834
- import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
2835
- return cachedData;
2836
- }
2837
- try {
2838
- const data = await collection.aggregate([
2839
- { $match: query },
2840
- {
2841
- $project: {
2842
- name: 1,
2843
- checklist: 1
2844
- }
2845
- }
2846
- ]).toArray();
2847
- if (!data || !data.length) {
2848
- throw new import_node_server_utils17.NotFoundError("Area not found.");
2849
- }
2850
- setCache(cacheKey, data[0], 15 * 60).then(() => {
2851
- import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
2852
- }).catch((err) => {
2853
- import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2854
- });
2855
- return data[0];
2856
- } catch (error) {
2857
- throw error;
2858
- }
2859
- }
2860
- return {
2861
- createUniqueIndex,
2862
- createScheduleTaskArea,
2863
- updateScheduleTaskArea,
2864
- deleteScheduleTaskArea,
2865
- getScheduleTaskAreas,
2866
- createIndexes,
2867
- getScheduleTaskAreaByName,
2868
- getScheduleTaskAreaById,
2869
- getAreaById
2870
- };
2871
- }
2872
-
2873
- // src/services/hygiene-schedule-task-area.service.ts
2874
- var import_node_server_utils18 = require("@iservice365/node-server-utils");
2875
- function useScheduleTaskAreaService() {
2876
- const { createScheduleTaskArea: _create } = useScheduleTaskAreaRepository();
2877
- async function uploadByFile({
2878
- dataJson,
2879
- createdBy,
2880
- site
2881
- }) {
2882
- let dataArray;
2883
- try {
2884
- dataArray = JSON.parse(dataJson);
2885
- } catch (error) {
2886
- throw new import_node_server_utils18.BadRequestError("Invalid JSON format for data in excel");
2887
- }
2888
- if (!dataArray || dataArray.length === 0) {
2889
- throw new import_node_server_utils18.NotFoundError("No data found in the uploaded file");
2890
- }
2891
- const session = import_node_server_utils18.useAtlas.getClient()?.startSession();
2892
- const insertedAreaIds = [];
2893
- try {
2894
- session?.startTransaction();
2895
- for (const row of dataArray) {
2896
- if (!row?.AREA_NAME) {
2897
- import_node_server_utils18.logger.warn("Skipping row with missing AREA_NAME:", row);
2898
- continue;
2899
- }
2900
- try {
2901
- const insertedId = await _create(
2902
- {
2903
- name: String(row.AREA_NAME).trim(),
2904
- site,
2905
- createdBy
2906
- },
2907
- session
2908
- );
2909
- insertedAreaIds.push(insertedId);
2910
- } catch (error) {
2911
- import_node_server_utils18.logger.error(
2912
- `Error creating area "${row.AREA_NAME}":`,
2913
- error.message
2914
- );
2915
- continue;
2916
- }
2917
- }
2918
- await session?.commitTransaction();
2919
- import_node_server_utils18.logger.info(`Successfully uploaded ${insertedAreaIds.length} areas`);
2920
- return {
2921
- message: `Successfully uploaded ${insertedAreaIds.length} areas`
2922
- };
2923
- } catch (error) {
2924
- await session?.abortTransaction();
2925
- import_node_server_utils18.logger.error("Error while uploading area information", error);
2926
- throw error;
2927
- } finally {
2928
- session?.endSession();
2929
- }
2930
- }
2931
- return {
2932
- uploadByFile
2933
- };
2934
- }
2935
-
2936
- // src/controllers/hygiene-schedule-task-area.controller.ts
2937
- var import_node_server_utils19 = require("@iservice365/node-server-utils");
2938
- var import_joi10 = __toESM(require("joi"));
2939
- function useScheduleTaskAreaController() {
2940
- const { uploadByFile: _uploadByFile } = useScheduleTaskAreaService();
2941
- const {
2942
- getScheduleTaskAreas: _getAll,
2943
- createScheduleTaskArea: _createScheduleTaskArea,
2944
- updateScheduleTaskArea: _updateScheduleTaskArea,
2945
- deleteScheduleTaskArea: _deleteById,
2946
- getAreaById: _getAreaById
2947
- } = useScheduleTaskAreaRepository();
2948
- async function getAll(req, res, next) {
2949
- const query = req.query;
2950
- const validation = import_joi10.default.object({
2951
- page: import_joi10.default.number().min(1).optional().allow("", null),
2952
- limit: import_joi10.default.number().min(1).optional().allow("", null),
2953
- search: import_joi10.default.string().optional().allow("", null),
2954
- startDate: import_joi10.default.alternatives().try(import_joi10.default.date(), import_joi10.default.string()).optional().allow("", null),
2955
- endDate: import_joi10.default.alternatives().try(import_joi10.default.date(), import_joi10.default.string()).optional().allow("", null),
2956
- site: import_joi10.default.string().hex().optional().allow("", null)
2957
- });
2958
- const { error } = validation.validate(query);
2959
- if (error) {
2960
- next(new import_node_server_utils19.BadRequestError(error.message));
2961
- return;
2962
- }
2963
- const page = parseInt(req.query.page) ?? 1;
2964
- const limit = parseInt(req.query.limit) ?? 20;
2965
- const search = req.query.search ?? "";
2966
- const site = req.query.site ?? "";
2967
- const startDate = req.query.startDate ?? "";
2968
- const endDate = req.query.endDate ?? "";
2969
- try {
2970
- const data = await _getAll({
2971
- page,
2972
- limit,
2973
- search,
2974
- site,
2975
- startDate,
2976
- endDate
2977
- });
2978
- res.json(data);
2979
- return;
2980
- } catch (error2) {
2981
- next(error2);
2982
- return;
2983
- }
2984
- }
2985
- async function createScheduleTaskArea(req, res, next) {
2986
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
2987
- (acc, [key, value]) => ({ ...acc, [key]: value }),
2988
- {}
2989
- ) : {};
2990
- const createdBy = cookies["user"] || "";
2991
- const payload = { ...req.body, createdBy };
2992
- const { error } = scheduleTaskAreaSchema.validate(payload);
2993
- if (error) {
2994
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
2995
- next(new import_node_server_utils19.BadRequestError(error.message));
2996
- return;
2997
- }
2998
- try {
2999
- const id = await _createScheduleTaskArea(payload);
3000
- res.status(201).json({ message: "Area created successfully.", id });
3001
- return;
3002
- } catch (error2) {
3003
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
3004
- next(error2);
3005
- return;
3006
- }
3007
- }
3008
- async function updateScheduleTaskArea(req, res, next) {
3009
- const payload = { id: req.params.id, ...req.body };
3010
- const schema = import_joi10.default.object({
3011
- id: import_joi10.default.string().hex().required(),
3012
- name: import_joi10.default.string().required()
3013
- });
3014
- const { error } = schema.validate(payload);
3015
- if (error) {
3016
- next(new import_node_server_utils19.BadRequestError(error.message));
3017
- import_node_server_utils19.logger.info(`Controller: ${error.message}`);
3018
- return;
3019
- }
3020
- try {
3021
- const { id, ...value } = payload;
3022
- await _updateScheduleTaskArea(id, value);
3023
- res.json({ message: "Area updated successfully." });
3024
- return;
3025
- } catch (error2) {
3026
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
3027
- next(error2);
3028
- return;
3029
- }
3030
- }
3031
- async function deleteScheduleTaskArea(req, res, next) {
3032
- const id = req.params.id;
3033
- const validation = import_joi10.default.object({
3034
- id: import_joi10.default.string().hex().required()
3035
- });
3036
- const { error } = validation.validate({ id });
3037
- if (error) {
3038
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3039
- next(new import_node_server_utils19.BadRequestError(error.message));
3040
- return;
3041
- }
3042
- try {
3043
- await _deleteById(id);
3044
- res.json({ message: "Area deleted successfully." });
3045
- return;
3046
- } catch (error2) {
3047
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
3048
- next(error2);
3049
- return;
3050
- }
3051
- }
3052
- async function uploadByFile(req, res, next) {
3053
- if (!req.file) {
3054
- next(new import_node_server_utils19.BadRequestError("File is required!"));
3055
- return;
3056
- }
3057
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
3058
- (acc, [key, value]) => ({ ...acc, [key]: value }),
3059
- {}
3060
- ) : {};
3061
- const createdBy = cookies["user"] || "";
3062
- const { site } = req.body;
3063
- const schema = import_joi10.default.object({
3064
- site: import_joi10.default.string().hex().optional().allow("", null),
3065
- createdBy: import_joi10.default.string().hex().required()
3066
- });
3067
- const { error } = schema.validate({ site, createdBy });
3068
- if (error) {
3069
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3070
- next(new import_node_server_utils19.BadRequestError(error.message));
3071
- return;
3072
- }
3073
- try {
3074
- const xlsData = await convertBufferFile(req.file.buffer);
3075
- const dataJson = JSON.stringify(xlsData);
3076
- const result = await _uploadByFile({ dataJson, createdBy, site });
3077
- return res.status(201).json(result);
3078
- } catch (error2) {
3079
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
3080
- next(error2);
3081
- return;
3082
- }
3083
- }
3084
- async function getAreaById(req, res, next) {
3085
- const validation = import_joi10.default.string().hex().required();
3086
- const _id = req.params.id;
3087
- const { error } = validation.validate(_id);
3088
- if (error) {
3089
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3090
- next(new import_node_server_utils19.BadRequestError(error.message));
3091
- return;
3092
- }
1711
+ const page = parseInt(req.query.page) ?? 1;
1712
+ const limit = parseInt(req.query.limit) ?? 20;
1713
+ const search = req.query.search ?? "";
1714
+ const site = req.params.site ?? "";
1715
+ const startDate = req.query.startDate ?? "";
1716
+ const endDate = req.query.endDate ?? "";
3093
1717
  try {
3094
- const data = await _getAreaById(_id);
1718
+ const data = await _getAllParentChecklist({
1719
+ page,
1720
+ limit,
1721
+ search,
1722
+ site,
1723
+ startDate,
1724
+ endDate
1725
+ });
3095
1726
  res.json(data);
3096
1727
  return;
3097
1728
  } catch (error2) {
3098
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
1729
+ import_node_server_utils11.logger.log({ level: "error", message: error2.message });
3099
1730
  next(error2);
3100
1731
  return;
3101
1732
  }
3102
1733
  }
3103
1734
  return {
3104
- getAll,
3105
- getAreaById,
3106
- createScheduleTaskArea,
3107
- updateScheduleTaskArea,
3108
- deleteScheduleTaskArea,
3109
- uploadByFile
1735
+ createParentChecklist,
1736
+ getAllParentChecklist
3110
1737
  };
3111
1738
  }
3112
1739
 
3113
1740
  // src/models/hygiene-area-checklist.model.ts
3114
- var import_node_server_utils20 = require("@iservice365/node-server-utils");
3115
- var import_joi11 = __toESM(require("joi"));
3116
- var import_mongodb11 = require("mongodb");
3117
- var areaChecklistSchema = import_joi11.default.object({
3118
- type: import_joi11.default.string().required().valid(...allowedTypes),
3119
- site: import_joi11.default.string().hex().required(),
3120
- parentChecklist: import_joi11.default.string().hex().required(),
3121
- area: import_joi11.default.string().hex().required(),
3122
- name: import_joi11.default.string().optional().allow("", null),
3123
- createdBy: import_joi11.default.string().hex().optional().allow("", null)
1741
+ var import_node_server_utils12 = require("@iservice365/node-server-utils");
1742
+ var import_joi7 = __toESM(require("joi"));
1743
+ var import_mongodb7 = require("mongodb");
1744
+ var allowedChecklistStatus = ["ready", "completed"];
1745
+ var areaChecklistSchema = import_joi7.default.object({
1746
+ schedule: import_joi7.default.string().hex().required(),
1747
+ name: import_joi7.default.string().required(),
1748
+ type: import_joi7.default.string().valid(...allowedTypes).required(),
1749
+ checklist: import_joi7.default.array().items(
1750
+ import_joi7.default.object({
1751
+ set: import_joi7.default.number().min(0).required(),
1752
+ units: import_joi7.default.array().items(
1753
+ import_joi7.default.object({
1754
+ name: import_joi7.default.string().required()
1755
+ }).required()
1756
+ ).min(1).required()
1757
+ }).required()
1758
+ ).optional().default([])
3124
1759
  });
3125
1760
  function MAreaChecklist(value) {
3126
1761
  const { error } = areaChecklistSchema.validate(value);
3127
1762
  if (error) {
3128
- import_node_server_utils20.logger.info(`Hygiene Checklist Area Model: ${error.message}`);
3129
- throw new import_node_server_utils20.BadRequestError(error.message);
3130
- }
3131
- if (value.site) {
3132
- try {
3133
- value.site = new import_mongodb11.ObjectId(value.site);
3134
- } catch (error2) {
3135
- throw new import_node_server_utils20.BadRequestError("Invalid site ID format.");
3136
- }
3137
- }
3138
- if (value.parentChecklist) {
3139
- try {
3140
- value.parentChecklist = new import_mongodb11.ObjectId(value.parentChecklist);
3141
- } catch (error2) {
3142
- throw new import_node_server_utils20.BadRequestError("Invalid checklist ID format.");
3143
- }
3144
- }
3145
- if (value.area) {
3146
- try {
3147
- value.area = new import_mongodb11.ObjectId(value.area);
3148
- } catch (error2) {
3149
- throw new import_node_server_utils20.BadRequestError("Invalid area ID format.");
3150
- }
1763
+ import_node_server_utils12.logger.info(`Hygiene Checklist Area Model: ${error.message}`);
1764
+ throw new import_node_server_utils12.BadRequestError(error.message);
3151
1765
  }
3152
- if (value.createdBy) {
1766
+ if (value.schedule) {
3153
1767
  try {
3154
- value.createdBy = new import_mongodb11.ObjectId(value.createdBy);
1768
+ value.schedule = new import_mongodb7.ObjectId(value.schedule);
3155
1769
  } catch (error2) {
3156
- throw new import_node_server_utils20.BadRequestError("Invalid createdBy ID format.");
1770
+ throw new import_node_server_utils12.BadRequestError("Invalid schedule ID format.");
3157
1771
  }
3158
1772
  }
3159
- if (value.acceptedBy) {
3160
- try {
3161
- value.acceptedBy = new import_mongodb11.ObjectId(value.acceptedBy);
3162
- } catch (error2) {
3163
- throw new import_node_server_utils20.BadRequestError("Invalid acceptedBy ID format.");
3164
- }
1773
+ if (value.checklist && Array.isArray(value.checklist)) {
1774
+ value.checklist = value.checklist.map((checklistItem) => {
1775
+ return {
1776
+ set: checklistItem.set,
1777
+ units: checklistItem.units.map((unit) => ({
1778
+ name: unit.name,
1779
+ status: "ready",
1780
+ remarks: "",
1781
+ timestamp: ""
1782
+ }))
1783
+ };
1784
+ });
3165
1785
  }
3166
1786
  return {
1787
+ schedule: value.schedule,
1788
+ name: value.name,
3167
1789
  type: value.type,
3168
- site: value.site,
3169
- parentChecklist: value.parentChecklist,
3170
- area: value.area,
3171
- name: value.name ?? "",
3172
- status: value.status ?? "To Do",
3173
- createdBy: value.createdBy ?? "",
1790
+ checklist: value.checklist || [],
1791
+ status: "ready",
3174
1792
  createdAt: /* @__PURE__ */ new Date(),
3175
- acceptedBy: value.acceptedBy ?? "",
3176
- acceptedAt: value.acceptedAt ?? "",
3177
- startedAt: value.startedAt ?? "",
3178
- endedAt: value.endedAt ?? "",
3179
- signature: value.signature ?? "",
3180
- updatedAt: value.updatedAt ?? ""
1793
+ updatedAt: ""
3181
1794
  };
3182
1795
  }
3183
1796
 
3184
1797
  // src/repositories/hygiene-area-checklist.repository.ts
3185
- var import_node_server_utils21 = require("@iservice365/node-server-utils");
3186
- var import_mongodb12 = require("mongodb");
1798
+ var import_node_server_utils13 = require("@iservice365/node-server-utils");
1799
+ var import_mongodb8 = require("mongodb");
3187
1800
  function useAreaChecklistRepo() {
3188
- const db = import_node_server_utils21.useAtlas.getDb();
1801
+ const db = import_node_server_utils13.useAtlas.getDb();
3189
1802
  if (!db) {
3190
- throw new import_node_server_utils21.InternalServerError("Unable to connect to server.");
1803
+ throw new import_node_server_utils13.InternalServerError("Unable to connect to server.");
3191
1804
  }
3192
- const namespace_collection = "hygiene-checklist.areas";
3193
- const unit_checklist_collection = "hygiene-checklist.units";
1805
+ const namespace_collection = "site.cleaning.schedule.areas";
1806
+ const unit_checklist_collection = "site.cleaning.schedule.units";
3194
1807
  const collection = db.collection(namespace_collection);
3195
1808
  const unitChecklistCollection = db.collection(unit_checklist_collection);
3196
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils21.useCache)(namespace_collection);
3197
- const { delNamespace: delUnitNamespace } = (0, import_node_server_utils21.useCache)(
1809
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils13.useCache)(namespace_collection);
1810
+ const { delNamespace: delUnitNamespace } = (0, import_node_server_utils13.useCache)(
3198
1811
  unit_checklist_collection
3199
1812
  );
3200
1813
  async function createIndex() {
3201
1814
  try {
3202
1815
  await collection.createIndexes([
1816
+ { key: { schedule: 1 } },
3203
1817
  { key: { type: 1 } },
3204
- { key: { site: 1 } },
3205
- { key: { parentChecklist: 1 } },
3206
- { key: { area: 1 } },
1818
+ { key: { status: 1 } },
3207
1819
  { key: { createdAt: 1 } },
3208
1820
  { key: { acceptedBy: 1 } }
3209
1821
  ]);
3210
1822
  } catch (error) {
3211
- throw new import_node_server_utils21.InternalServerError(
1823
+ throw new import_node_server_utils13.InternalServerError(
3212
1824
  "Failed to create index on hygiene checklist area."
3213
1825
  );
3214
1826
  }
@@ -3217,16 +1829,14 @@ function useAreaChecklistRepo() {
3217
1829
  try {
3218
1830
  await collection.createIndex({ name: "text" });
3219
1831
  } catch (error) {
3220
- throw new import_node_server_utils21.InternalServerError(
1832
+ throw new import_node_server_utils13.InternalServerError(
3221
1833
  "Failed to create text index on hygiene checklist area."
3222
1834
  );
3223
1835
  }
3224
1836
  }
3225
1837
  async function createAreaChecklist(value, session) {
3226
1838
  try {
3227
- const siteId = new import_mongodb12.ObjectId(value.site);
3228
- const parentChecklistId = new import_mongodb12.ObjectId(value.parentChecklist);
3229
- const areaId = new import_mongodb12.ObjectId(value.area);
1839
+ const parentChecklistId = new import_mongodb8.ObjectId(value.schedule);
3230
1840
  const currentDate = /* @__PURE__ */ new Date();
3231
1841
  const startOfDay = new Date(currentDate);
3232
1842
  startOfDay.setUTCHours(0, 0, 0, 0);
@@ -3234,26 +1844,25 @@ function useAreaChecklistRepo() {
3234
1844
  endOfDay.setUTCHours(23, 59, 59, 999);
3235
1845
  const existingChecklist = await collection.findOne({
3236
1846
  type: value.type,
3237
- site: siteId,
3238
- parentChecklist: parentChecklistId,
3239
- area: areaId,
1847
+ schedule: parentChecklistId,
1848
+ name: value.name,
3240
1849
  createdAt: {
3241
1850
  $gte: startOfDay,
3242
1851
  $lte: endOfDay
3243
1852
  }
3244
1853
  });
3245
1854
  if (existingChecklist) {
3246
- import_node_server_utils21.logger.info(
3247
- `Area checklist already exists for area ${areaId} on ${currentDate.toISOString().split("T")[0]}`
1855
+ import_node_server_utils13.logger.info(
1856
+ `Area checklist already exists for area ${value.name} on ${currentDate.toISOString().split("T")[0]}`
3248
1857
  );
3249
1858
  return existingChecklist._id;
3250
1859
  }
3251
1860
  const processedValue = MAreaChecklist(value);
3252
1861
  const result = await collection.insertOne(processedValue, { session });
3253
1862
  delNamespace().then(() => {
3254
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
1863
+ import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3255
1864
  }).catch((err) => {
3256
- import_node_server_utils21.logger.error(
1865
+ import_node_server_utils13.logger.error(
3257
1866
  `Failed to clear cache for namespace: ${namespace_collection}`,
3258
1867
  err
3259
1868
  );
@@ -3267,62 +1876,62 @@ function useAreaChecklistRepo() {
3267
1876
  page = 1,
3268
1877
  limit = 10,
3269
1878
  search = "",
3270
- site,
3271
1879
  type,
3272
- parentChecklist
1880
+ schedule
3273
1881
  }) {
3274
1882
  page = page > 0 ? page - 1 : 0;
3275
- const query = { type };
1883
+ const query = {};
3276
1884
  const cacheOptions = {
3277
1885
  page,
3278
1886
  limit
3279
1887
  };
3280
1888
  try {
3281
- query.site = new import_mongodb12.ObjectId(site);
3282
- cacheOptions.site = site.toString();
1889
+ query.schedule = new import_mongodb8.ObjectId(schedule);
1890
+ cacheOptions.schedule = schedule.toString();
3283
1891
  } catch (error) {
3284
- throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
1892
+ throw new import_node_server_utils13.BadRequestError("Invalid parent checklist ID format.");
3285
1893
  }
3286
- try {
3287
- query.parentChecklist = new import_mongodb12.ObjectId(parentChecklist);
3288
- cacheOptions.parentChecklist = parentChecklist.toString();
3289
- } catch (error) {
3290
- throw new import_node_server_utils21.BadRequestError("Invalid parent checklist ID format.");
1894
+ if (type) {
1895
+ query.type = type;
1896
+ cacheOptions.type = type;
3291
1897
  }
3292
1898
  if (search) {
3293
1899
  query.$text = { $search: search };
3294
1900
  cacheOptions.search = search;
3295
1901
  }
3296
- const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, cacheOptions);
1902
+ const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
3297
1903
  const cachedData = await getCache(cacheKey);
3298
1904
  if (cachedData) {
3299
- import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
1905
+ import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
3300
1906
  return cachedData;
3301
1907
  }
3302
1908
  try {
3303
1909
  const pipeline = [
3304
1910
  { $match: query },
3305
- {
3306
- $lookup: {
3307
- from: "users",
3308
- localField: "acceptedBy",
3309
- foreignField: "_id",
3310
- pipeline: [{ $project: { name: 1 } }],
3311
- as: "acceptedBy"
3312
- }
3313
- },
3314
- {
3315
- $unwind: {
3316
- path: "$acceptedBy",
3317
- preserveNullAndEmptyArrays: true
3318
- }
3319
- },
3320
1911
  {
3321
1912
  $project: {
3322
1913
  name: 1,
3323
- acceptedByName: "$acceptedBy.name",
3324
- status: 1,
3325
- createdAt: 1
1914
+ status: {
1915
+ $switch: {
1916
+ branches: [
1917
+ { case: { $eq: ["$status", "ready"] }, then: "Ready" },
1918
+ { case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
1919
+ {
1920
+ case: { $eq: ["$status", "completed"] },
1921
+ then: "Completed"
1922
+ }
1923
+ ],
1924
+ default: "$status"
1925
+ }
1926
+ },
1927
+ type: 1,
1928
+ set: {
1929
+ $cond: {
1930
+ if: { $gt: [{ $size: { $ifNull: ["$checklist", []] } }, 0] },
1931
+ then: { $max: "$checklist.set" },
1932
+ else: 0
1933
+ }
1934
+ }
3326
1935
  }
3327
1936
  },
3328
1937
  { $sort: { _id: -1 } },
@@ -3331,11 +1940,11 @@ function useAreaChecklistRepo() {
3331
1940
  ];
3332
1941
  const items = await collection.aggregate(pipeline).toArray();
3333
1942
  const length = await collection.countDocuments(query);
3334
- const data = (0, import_node_server_utils21.paginate)(items, page, limit, length);
1943
+ const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
3335
1944
  setCache(cacheKey, data, 15 * 60).then(() => {
3336
- import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
1945
+ import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
3337
1946
  }).catch((err) => {
3338
- import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
1947
+ import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
3339
1948
  });
3340
1949
  return data;
3341
1950
  } catch (error) {
@@ -3348,7 +1957,7 @@ function useAreaChecklistRepo() {
3348
1957
  search = "",
3349
1958
  site,
3350
1959
  type,
3351
- parentChecklist,
1960
+ schedule,
3352
1961
  status,
3353
1962
  createdAt,
3354
1963
  user
@@ -3360,16 +1969,16 @@ function useAreaChecklistRepo() {
3360
1969
  limit
3361
1970
  };
3362
1971
  try {
3363
- query.site = new import_mongodb12.ObjectId(site);
1972
+ query.site = new import_mongodb8.ObjectId(site);
3364
1973
  cacheOptions.site = site.toString();
3365
1974
  } catch (error) {
3366
- throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
1975
+ throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
3367
1976
  }
3368
1977
  try {
3369
- query.parentChecklist = new import_mongodb12.ObjectId(parentChecklist);
3370
- cacheOptions.parentChecklist = parentChecklist.toString();
1978
+ query.schedule = new import_mongodb8.ObjectId(schedule);
1979
+ cacheOptions.schedule = schedule.toString();
3371
1980
  } catch (error) {
3372
- throw new import_node_server_utils21.BadRequestError("Invalid parent checklist ID format.");
1981
+ throw new import_node_server_utils13.BadRequestError("Invalid parent checklist ID format.");
3373
1982
  }
3374
1983
  if (search) {
3375
1984
  query.$text = { $search: search };
@@ -3386,20 +1995,20 @@ function useAreaChecklistRepo() {
3386
1995
  query.status = status;
3387
1996
  cacheOptions.status = status;
3388
1997
  } else {
3389
- query.status = { $in: ["In Progress", "Completed"] };
1998
+ query.status = { $in: ["ongoing", "completed"] };
3390
1999
  }
3391
2000
  if (user) {
3392
2001
  try {
3393
- query.acceptedBy = new import_mongodb12.ObjectId(user);
2002
+ query.acceptedBy = new import_mongodb8.ObjectId(user);
3394
2003
  cacheOptions.user = user.toString();
3395
2004
  } catch (error) {
3396
- throw new import_node_server_utils21.BadRequestError("Invalid user ID format.");
2005
+ throw new import_node_server_utils13.BadRequestError("Invalid user ID format.");
3397
2006
  }
3398
2007
  }
3399
- const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, cacheOptions);
2008
+ const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
3400
2009
  const cachedData = await getCache(cacheKey);
3401
2010
  if (cachedData) {
3402
- import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
2011
+ import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
3403
2012
  return cachedData;
3404
2013
  }
3405
2014
  try {
@@ -3428,9 +2037,21 @@ function useAreaChecklistRepo() {
3428
2037
  name: 1,
3429
2038
  createdAt: 1,
3430
2039
  acceptedByName: "$acceptedBy.name",
3431
- status: 1,
3432
- startedAt: 1,
3433
- endedAt: 1
2040
+ status: {
2041
+ $switch: {
2042
+ branches: [
2043
+ { case: { $eq: ["$status", "ready"] }, then: "Ready" },
2044
+ { case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
2045
+ {
2046
+ case: { $eq: ["$status", "completed"] },
2047
+ then: "Completed"
2048
+ }
2049
+ ],
2050
+ default: "$status"
2051
+ }
2052
+ },
2053
+ startedAt: "$acceptedAt",
2054
+ endedAt: "$completedAt"
3434
2055
  }
3435
2056
  },
3436
2057
  { $sort: { status: 1 } },
@@ -3439,11 +2060,11 @@ function useAreaChecklistRepo() {
3439
2060
  ];
3440
2061
  const items = await collection.aggregate(pipeline).toArray();
3441
2062
  const length = await collection.countDocuments(query);
3442
- const data = (0, import_node_server_utils21.paginate)(items, page, limit, length);
2063
+ const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
3443
2064
  setCache(cacheKey, data, 15 * 60).then(() => {
3444
- import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
2065
+ import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
3445
2066
  }).catch((err) => {
3446
- import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2067
+ import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
3447
2068
  });
3448
2069
  return data;
3449
2070
  } catch (error) {
@@ -3452,16 +2073,16 @@ function useAreaChecklistRepo() {
3452
2073
  }
3453
2074
  async function getAreaChecklistHistoryDetails(_id) {
3454
2075
  try {
3455
- _id = new import_mongodb12.ObjectId(_id);
2076
+ _id = new import_mongodb8.ObjectId(_id);
3456
2077
  } catch (error) {
3457
- throw new import_node_server_utils21.BadRequestError("Invalid area checklist ID format.");
2078
+ throw new import_node_server_utils13.BadRequestError("Invalid area checklist ID format.");
3458
2079
  }
3459
- const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, {
2080
+ const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, {
3460
2081
  _id: _id.toString()
3461
2082
  });
3462
2083
  const cachedData = await getCache(cacheKey);
3463
2084
  if (cachedData) {
3464
- import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
2085
+ import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
3465
2086
  return cachedData;
3466
2087
  }
3467
2088
  try {
@@ -3502,9 +2123,21 @@ function useAreaChecklistRepo() {
3502
2123
  name: 1,
3503
2124
  createdAt: 1,
3504
2125
  createdByName: "$createdBy.name",
3505
- startedAt: 1,
3506
- endedAt: 1,
3507
- status: 1,
2126
+ startedAt: "$acceptedAt",
2127
+ endedAt: "$completedAt",
2128
+ status: {
2129
+ $switch: {
2130
+ branches: [
2131
+ { case: { $eq: ["$status", "ready"] }, then: "Ready" },
2132
+ { case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
2133
+ {
2134
+ case: { $eq: ["$status", "completed"] },
2135
+ then: "Completed"
2136
+ }
2137
+ ],
2138
+ default: "$status"
2139
+ }
2140
+ },
3508
2141
  signature: 1,
3509
2142
  acceptedByName: "$acceptedBy.name"
3510
2143
  }
@@ -3527,16 +2160,16 @@ function useAreaChecklistRepo() {
3527
2160
  unitChecklistCollection.aggregate(unitPipeline).toArray()
3528
2161
  ]);
3529
2162
  if (!area.length) {
3530
- throw new import_node_server_utils21.BadRequestError("Area checklist not found.");
2163
+ throw new import_node_server_utils13.BadRequestError("Area checklist not found.");
3531
2164
  }
3532
2165
  const items = {
3533
2166
  area: area[0],
3534
2167
  units
3535
2168
  };
3536
2169
  setCache(cacheKey, items, 15 * 60).then(() => {
3537
- import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
2170
+ import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
3538
2171
  }).catch((err) => {
3539
- import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2172
+ import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
3540
2173
  });
3541
2174
  return items;
3542
2175
  } catch (error) {
@@ -3545,31 +2178,32 @@ function useAreaChecklistRepo() {
3545
2178
  }
3546
2179
  async function acceptAreaChecklist(_id, acceptedBy) {
3547
2180
  try {
3548
- _id = new import_mongodb12.ObjectId(_id);
2181
+ _id = new import_mongodb8.ObjectId(_id);
3549
2182
  } catch (error) {
3550
- throw new import_node_server_utils21.BadRequestError("Invalid area ID format.");
2183
+ throw new import_node_server_utils13.BadRequestError("Invalid area ID format.");
3551
2184
  }
3552
2185
  try {
3553
- acceptedBy = new import_mongodb12.ObjectId(acceptedBy);
2186
+ acceptedBy = new import_mongodb8.ObjectId(acceptedBy);
3554
2187
  } catch (error) {
3555
- throw new import_node_server_utils21.BadRequestError("Invalid acceptedBy ID format.");
2188
+ throw new import_node_server_utils13.BadRequestError("Invalid acceptedBy ID format.");
3556
2189
  }
3557
2190
  try {
3558
2191
  const now = /* @__PURE__ */ new Date();
3559
2192
  const updateValue = {
3560
- acceptedBy,
3561
- acceptedAt: now,
3562
- startedAt: now,
2193
+ metadata: {
2194
+ acceptedBy,
2195
+ acceptedAt: now
2196
+ },
3563
2197
  updatedAt: now
3564
2198
  };
3565
2199
  const res = await collection.updateOne({ _id }, { $set: updateValue });
3566
2200
  if (res.modifiedCount === 0) {
3567
- throw new import_node_server_utils21.InternalServerError("Unable to update cleaning area.");
2201
+ throw new import_node_server_utils13.InternalServerError("Unable to update cleaning area.");
3568
2202
  }
3569
2203
  delNamespace().then(() => {
3570
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2204
+ import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3571
2205
  }).catch((err) => {
3572
- import_node_server_utils21.logger.error(
2206
+ import_node_server_utils13.logger.error(
3573
2207
  `Failed to clear cache for namespace: ${namespace_collection}`,
3574
2208
  err
3575
2209
  );
@@ -3581,9 +2215,9 @@ function useAreaChecklistRepo() {
3581
2215
  }
3582
2216
  async function attachImageAreaChecklist(_id, attachments, session) {
3583
2217
  try {
3584
- _id = new import_mongodb12.ObjectId(_id);
2218
+ _id = new import_mongodb8.ObjectId(_id);
3585
2219
  } catch (error) {
3586
- throw new import_node_server_utils21.BadRequestError("Invalid area checklist ID format.");
2220
+ throw new import_node_server_utils13.BadRequestError("Invalid area checklist ID format.");
3587
2221
  }
3588
2222
  try {
3589
2223
  const now = /* @__PURE__ */ new Date();
@@ -3597,24 +2231,24 @@ function useAreaChecklistRepo() {
3597
2231
  { session }
3598
2232
  );
3599
2233
  if (res.modifiedCount === 0) {
3600
- throw new import_node_server_utils21.InternalServerError(
2234
+ throw new import_node_server_utils13.InternalServerError(
3601
2235
  "Unable to update cleaning area checklist."
3602
2236
  );
3603
2237
  }
3604
2238
  delNamespace().then(() => {
3605
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2239
+ import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3606
2240
  }).catch((err) => {
3607
- import_node_server_utils21.logger.error(
2241
+ import_node_server_utils13.logger.error(
3608
2242
  `Failed to clear cache for namespace: ${namespace_collection}`,
3609
2243
  err
3610
2244
  );
3611
2245
  });
3612
2246
  delUnitNamespace().then(() => {
3613
- import_node_server_utils21.logger.info(
2247
+ import_node_server_utils13.logger.info(
3614
2248
  `Cache cleared for namespace: ${unit_checklist_collection}`
3615
2249
  );
3616
2250
  }).catch((err) => {
3617
- import_node_server_utils21.logger.error(
2251
+ import_node_server_utils13.logger.error(
3618
2252
  `Failed to clear cache for namespace: ${unit_checklist_collection}`,
3619
2253
  err
3620
2254
  );
@@ -3626,26 +2260,28 @@ function useAreaChecklistRepo() {
3626
2260
  }
3627
2261
  async function submitAreaChecklist(_id, signature) {
3628
2262
  try {
3629
- _id = new import_mongodb12.ObjectId(_id);
2263
+ _id = new import_mongodb8.ObjectId(_id);
3630
2264
  } catch (error) {
3631
- throw new import_node_server_utils21.BadRequestError("Invalid area ID format.");
2265
+ throw new import_node_server_utils13.BadRequestError("Invalid area ID format.");
3632
2266
  }
3633
2267
  try {
3634
2268
  const now = /* @__PURE__ */ new Date();
3635
2269
  const updateValue = {
3636
- signature,
3637
- status: "In Progress",
3638
- endedAt: now,
2270
+ metadata: {
2271
+ signature,
2272
+ completedAt: now
2273
+ },
2274
+ status: "ongoing",
3639
2275
  updatedAt: now
3640
2276
  };
3641
2277
  const res = await collection.updateOne({ _id }, { $set: updateValue });
3642
2278
  if (res.modifiedCount === 0) {
3643
- throw new import_node_server_utils21.InternalServerError("Unable to update cleaning area.");
2279
+ throw new import_node_server_utils13.InternalServerError("Unable to update cleaning area.");
3644
2280
  }
3645
2281
  delNamespace().then(() => {
3646
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2282
+ import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3647
2283
  }).catch((err) => {
3648
- import_node_server_utils21.logger.error(
2284
+ import_node_server_utils13.logger.error(
3649
2285
  `Failed to clear cache for namespace: ${namespace_collection}`,
3650
2286
  err
3651
2287
  );
@@ -3657,26 +2293,28 @@ function useAreaChecklistRepo() {
3657
2293
  }
3658
2294
  async function completeAreaChecklist(_id, signature) {
3659
2295
  try {
3660
- _id = new import_mongodb12.ObjectId(_id);
2296
+ _id = new import_mongodb8.ObjectId(_id);
3661
2297
  } catch (error) {
3662
- throw new import_node_server_utils21.BadRequestError("Invalid area ID format.");
2298
+ throw new import_node_server_utils13.BadRequestError("Invalid area ID format.");
3663
2299
  }
3664
2300
  try {
3665
2301
  const now = /* @__PURE__ */ new Date();
3666
2302
  const updateValue = {
3667
- signature,
3668
- status: "Completed",
3669
- endedAt: now,
2303
+ metadata: {
2304
+ signature,
2305
+ completedAt: now
2306
+ },
2307
+ status: "completed",
3670
2308
  updatedAt: now
3671
2309
  };
3672
2310
  const res = await collection.updateOne({ _id }, { $set: updateValue });
3673
2311
  if (res.modifiedCount === 0) {
3674
- throw new import_node_server_utils21.InternalServerError("Unable to update cleaning area.");
2312
+ throw new import_node_server_utils13.InternalServerError("Unable to update cleaning area.");
3675
2313
  }
3676
2314
  delNamespace().then(() => {
3677
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2315
+ import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3678
2316
  }).catch((err) => {
3679
- import_node_server_utils21.logger.error(
2317
+ import_node_server_utils13.logger.error(
3680
2318
  `Failed to clear cache for namespace: ${namespace_collection}`,
3681
2319
  err
3682
2320
  );
@@ -3701,72 +2339,110 @@ function useAreaChecklistRepo() {
3701
2339
  }
3702
2340
 
3703
2341
  // src/controllers/hygiene-area-checklist.controller.ts
3704
- var import_node_server_utils23 = require("@iservice365/node-server-utils");
3705
- var import_joi12 = __toESM(require("joi"));
2342
+ var import_node_server_utils15 = require("@iservice365/node-server-utils");
2343
+ var import_joi8 = __toESM(require("joi"));
3706
2344
 
3707
2345
  // src/services/hygiene-area-checklist.service.ts
3708
- var import_node_server_utils22 = require("@iservice365/node-server-utils");
2346
+ var import_node_server_utils14 = require("@iservice365/node-server-utils");
3709
2347
  function useAreaChecklistService() {
3710
2348
  const { createAreaChecklist: _createAreaChecklist } = useAreaChecklistRepo();
3711
- const { getAreas } = useAreaRepository();
3712
- const { getToiletLocations } = useToiletLocationRepository();
2349
+ const { getAreasForChecklist } = useAreaRepo();
3713
2350
  async function createAreaChecklist(value) {
2351
+ const session = import_node_server_utils14.useAtlas.getClient()?.startSession();
3714
2352
  try {
2353
+ session?.startTransaction();
3715
2354
  const results = [];
3716
- if (value.type === "cleaner") {
3717
- const cleanerAreasResult = await getAreas({
3718
- site: value.site
3719
- });
3720
- const cleanerAreas = cleanerAreasResult.items || [];
3721
- if (cleanerAreas.length === 0) {
3722
- import_node_server_utils22.logger.warn(`No cleaner areas found for site: ${value.site}`);
3723
- return results;
3724
- }
3725
- for (const area of cleanerAreas) {
3726
- const checklistData = {
3727
- type: "cleaner",
3728
- site: value.site,
3729
- parentChecklist: value.parentChecklist,
3730
- area: area._id.toString(),
3731
- name: area.name,
3732
- createdBy: value.createdBy
3733
- };
3734
- const insertedId = await _createAreaChecklist(checklistData);
3735
- results.push(insertedId);
2355
+ let totalChecklistsCreated = 0;
2356
+ const BATCH_SIZE = 10;
2357
+ const commonAreasResult = await getAreasForChecklist({
2358
+ site: value.site,
2359
+ type: "common"
2360
+ });
2361
+ const commonAreas = commonAreasResult || [];
2362
+ if (commonAreas.length > 0) {
2363
+ for (let i = 0; i < commonAreas.length; i += BATCH_SIZE) {
2364
+ const batch = commonAreas.slice(i, i + BATCH_SIZE);
2365
+ const batchPromises = batch.map(async (area) => {
2366
+ const checklistData = {
2367
+ schedule: value.schedule,
2368
+ name: area.name,
2369
+ type: "common",
2370
+ checklist: area.units && area.units.length > 0 ? [
2371
+ {
2372
+ set: area.set || 0,
2373
+ units: area.units.map((unit) => ({
2374
+ name: unit.name
2375
+ }))
2376
+ }
2377
+ ] : []
2378
+ };
2379
+ const insertedId = await _createAreaChecklist(
2380
+ checklistData,
2381
+ session
2382
+ );
2383
+ totalChecklistsCreated++;
2384
+ return insertedId;
2385
+ });
2386
+ const batchResults = await Promise.all(batchPromises);
2387
+ results.push(...batchResults);
3736
2388
  }
3737
- import_node_server_utils22.logger.info(
3738
- `Created ${results.length} cleaner area checklists for site: ${value.site}`
2389
+ import_node_server_utils14.logger.info(
2390
+ `Created ${commonAreas.length} common area checklists for site: ${value.site}`
3739
2391
  );
2392
+ } else {
2393
+ import_node_server_utils14.logger.warn(`No common areas found for site: ${value.site}`);
3740
2394
  }
3741
- if (value.type === "toilet") {
3742
- const toiletAreasResult = await getToiletLocations({
3743
- site: value.site
3744
- });
3745
- const toiletAreas = toiletAreasResult.items || [];
3746
- if (toiletAreas.length === 0) {
3747
- import_node_server_utils22.logger.warn(`No toilet locations found for site: ${value.site}`);
3748
- return results;
3749
- }
3750
- for (const toiletLocation of toiletAreas) {
3751
- const checklistData = {
3752
- type: "toilet",
3753
- site: value.site,
3754
- parentChecklist: value.parentChecklist,
3755
- area: toiletLocation._id,
3756
- name: toiletLocation.name,
3757
- createdBy: value.createdBy
3758
- };
3759
- const insertedId = await _createAreaChecklist(checklistData);
3760
- results.push(insertedId);
2395
+ const toiletAreasResult = await getAreasForChecklist({
2396
+ site: value.site,
2397
+ type: "toilet"
2398
+ });
2399
+ const toiletAreas = toiletAreasResult || [];
2400
+ if (toiletAreas.length > 0) {
2401
+ for (let i = 0; i < toiletAreas.length; i += BATCH_SIZE) {
2402
+ const batch = toiletAreas.slice(i, i + BATCH_SIZE);
2403
+ const batchPromises = batch.map(async (toiletLocation) => {
2404
+ const checklistData = {
2405
+ schedule: value.schedule,
2406
+ name: toiletLocation.name,
2407
+ type: "toilet",
2408
+ checklist: toiletLocation.units && toiletLocation.units.length > 0 ? [
2409
+ {
2410
+ set: toiletLocation.set || 0,
2411
+ units: toiletLocation.units.map((unit) => ({
2412
+ name: unit.name
2413
+ }))
2414
+ }
2415
+ ] : []
2416
+ };
2417
+ const insertedId = await _createAreaChecklist(
2418
+ checklistData,
2419
+ session
2420
+ );
2421
+ totalChecklistsCreated++;
2422
+ return insertedId;
2423
+ });
2424
+ const batchResults = await Promise.all(batchPromises);
2425
+ results.push(...batchResults);
3761
2426
  }
3762
- import_node_server_utils22.logger.info(
3763
- `Created ${results.length} toilet area checklists for site: ${value.site}`
2427
+ import_node_server_utils14.logger.info(
2428
+ `Created ${toiletAreas.length} toilet area checklists for site: ${value.site}`
3764
2429
  );
2430
+ } else {
2431
+ import_node_server_utils14.logger.warn(`No toilet locations found for site: ${value.site}`);
3765
2432
  }
2433
+ await session?.commitTransaction();
2434
+ import_node_server_utils14.logger.info(
2435
+ `Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
2436
+ );
3766
2437
  return results;
3767
2438
  } catch (error) {
3768
- import_node_server_utils22.logger.error(`Error generating area checklists:`, error);
2439
+ import_node_server_utils14.logger.error(`Error generating area checklists:`, error);
2440
+ if (session?.inTransaction()) {
2441
+ await session?.abortTransaction();
2442
+ }
3769
2443
  throw error;
2444
+ } finally {
2445
+ session?.endSession();
3770
2446
  }
3771
2447
  }
3772
2448
  return { createAreaChecklist };
@@ -3785,69 +2461,62 @@ function useAreaChecklistController() {
3785
2461
  } = useAreaChecklistRepo();
3786
2462
  const { createAreaChecklist: _createAreaChecklist } = useAreaChecklistService();
3787
2463
  async function createAreaChecklist(req, res, next) {
3788
- const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
3789
- (acc, [key, value]) => ({ ...acc, [key]: value }),
3790
- {}
3791
- ) : {};
3792
- const createdBy = cookies["user"] || "";
3793
- const payload = { ...req.body, ...req.params, createdBy };
3794
- const validation = import_joi12.default.object({
3795
- type: import_joi12.default.string().required().valid(...allowedTypes),
3796
- site: import_joi12.default.string().hex().required(),
3797
- parentChecklist: import_joi12.default.string().hex().required(),
3798
- createdBy: import_joi12.default.string().hex().optional().allow("", null)
2464
+ const payload = {
2465
+ site: req.params.site,
2466
+ schedule: req.params.schedule
2467
+ };
2468
+ const validation = import_joi8.default.object({
2469
+ site: import_joi8.default.string().hex().required(),
2470
+ schedule: import_joi8.default.string().hex().required()
3799
2471
  });
3800
2472
  const { error } = validation.validate(payload);
3801
2473
  if (error) {
3802
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3803
- next(new import_node_server_utils23.BadRequestError(error.message));
2474
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2475
+ next(new import_node_server_utils15.BadRequestError(error.message));
3804
2476
  return;
3805
2477
  }
3806
2478
  try {
3807
2479
  await _createAreaChecklist(payload);
3808
- res.status(201).json({ message: "Area checklists generated successfully." });
2480
+ res.status(201).json({ message: "Area checklist generated successfully." });
3809
2481
  return;
3810
2482
  } catch (error2) {
3811
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2483
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3812
2484
  next(error2);
3813
2485
  return;
3814
2486
  }
3815
2487
  }
3816
2488
  async function getAllAreaChecklist(req, res, next) {
3817
2489
  const query = { ...req.query, ...req.params };
3818
- const validation = import_joi12.default.object({
3819
- page: import_joi12.default.number().min(1).optional().allow("", null),
3820
- limit: import_joi12.default.number().min(1).optional().allow("", null),
3821
- search: import_joi12.default.string().optional().allow("", null),
3822
- site: import_joi12.default.string().hex().required(),
3823
- type: import_joi12.default.string().valid(...allowedTypes).required(),
3824
- parentChecklist: import_joi12.default.string().hex().required()
2490
+ const validation = import_joi8.default.object({
2491
+ page: import_joi8.default.number().min(1).optional().allow("", null),
2492
+ limit: import_joi8.default.number().min(1).optional().allow("", null),
2493
+ search: import_joi8.default.string().optional().allow("", null),
2494
+ type: import_joi8.default.string().optional().allow("", ...allowedTypes),
2495
+ schedule: import_joi8.default.string().hex().required()
3825
2496
  });
3826
2497
  const { error } = validation.validate(query);
3827
2498
  if (error) {
3828
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3829
- next(new import_node_server_utils23.BadRequestError(error.message));
2499
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2500
+ next(new import_node_server_utils15.BadRequestError(error.message));
3830
2501
  return;
3831
2502
  }
3832
2503
  const page = parseInt(req.query.page) ?? 1;
3833
2504
  const limit = parseInt(req.query.limit) ?? 20;
3834
2505
  const search = req.query.search ?? "";
3835
- const site = req.params.site ?? "";
3836
- const type = req.params.type ?? "";
3837
- const parentChecklist = req.params.parentChecklist ?? "";
2506
+ const type = req.query.type ?? "";
2507
+ const schedule = req.params.schedule ?? "";
3838
2508
  try {
3839
2509
  const data = await _getAllAreaChecklist({
3840
2510
  page,
3841
2511
  limit,
3842
2512
  search,
3843
- site,
3844
2513
  type,
3845
- parentChecklist
2514
+ schedule
3846
2515
  });
3847
2516
  res.json(data);
3848
2517
  return;
3849
2518
  } catch (error2) {
3850
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2519
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3851
2520
  next(error2);
3852
2521
  return;
3853
2522
  }
@@ -3859,29 +2528,29 @@ function useAreaChecklistController() {
3859
2528
  ) : {};
3860
2529
  const user = cookies["user"] || "";
3861
2530
  const query = { ...req.query, ...req.params, user };
3862
- const validation = import_joi12.default.object({
3863
- page: import_joi12.default.number().min(1).optional().allow("", null),
3864
- limit: import_joi12.default.number().min(1).optional().allow("", null),
3865
- search: import_joi12.default.string().optional().allow("", null),
3866
- site: import_joi12.default.string().hex().required(),
3867
- type: import_joi12.default.string().valid(...allowedTypes).required(),
3868
- parentChecklist: import_joi12.default.string().hex().required(),
3869
- status: import_joi12.default.string().allow("", null, ...allowedStatus),
3870
- createdAt: import_joi12.default.alternatives().try(import_joi12.default.date(), import_joi12.default.string()).optional().allow("", null),
3871
- user: import_joi12.default.string().hex().optional().allow("", null)
2531
+ const validation = import_joi8.default.object({
2532
+ page: import_joi8.default.number().min(1).optional().allow("", null),
2533
+ limit: import_joi8.default.number().min(1).optional().allow("", null),
2534
+ search: import_joi8.default.string().optional().allow("", null),
2535
+ site: import_joi8.default.string().hex().required(),
2536
+ type: import_joi8.default.string().valid(...allowedTypes).required(),
2537
+ schedule: import_joi8.default.string().hex().required(),
2538
+ status: import_joi8.default.string().allow("", null, ...allowedStatus),
2539
+ createdAt: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
2540
+ user: import_joi8.default.string().hex().optional().allow("", null)
3872
2541
  });
3873
2542
  const { error } = validation.validate(query);
3874
2543
  if (error) {
3875
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3876
- next(new import_node_server_utils23.BadRequestError(error.message));
2544
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2545
+ next(new import_node_server_utils15.BadRequestError(error.message));
3877
2546
  return;
3878
2547
  }
3879
2548
  const page = parseInt(req.query.page) ?? 1;
3880
2549
  const limit = parseInt(req.query.limit) ?? 20;
3881
2550
  const search = req.query.search ?? "";
3882
2551
  const site = req.params.site ?? "";
3883
- const type = req.params.type ?? "";
3884
- const parentChecklist = req.params.parentChecklist ?? "";
2552
+ const type = req.query.type ?? "";
2553
+ const schedule = req.params.schedule ?? "";
3885
2554
  const status = req.query.status ?? "";
3886
2555
  const createdAt = req.query.createdAt ?? "";
3887
2556
  try {
@@ -3891,7 +2560,7 @@ function useAreaChecklistController() {
3891
2560
  search,
3892
2561
  site,
3893
2562
  type,
3894
- parentChecklist,
2563
+ schedule,
3895
2564
  status,
3896
2565
  createdAt,
3897
2566
  user
@@ -3899,18 +2568,18 @@ function useAreaChecklistController() {
3899
2568
  res.json(data);
3900
2569
  return;
3901
2570
  } catch (error2) {
3902
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2571
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3903
2572
  next(error2);
3904
2573
  return;
3905
2574
  }
3906
2575
  }
3907
2576
  async function getAreaChecklistHistoryDetails(req, res, next) {
3908
- const validation = import_joi12.default.string().hex().required();
2577
+ const validation = import_joi8.default.string().hex().required();
3909
2578
  const _id = req.params.id;
3910
2579
  const { error } = validation.validate(_id);
3911
2580
  if (error) {
3912
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3913
- next(new import_node_server_utils23.BadRequestError(error.message));
2581
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2582
+ next(new import_node_server_utils15.BadRequestError(error.message));
3914
2583
  return;
3915
2584
  }
3916
2585
  try {
@@ -3918,7 +2587,7 @@ function useAreaChecklistController() {
3918
2587
  res.json(data);
3919
2588
  return;
3920
2589
  } catch (error2) {
3921
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2590
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3922
2591
  next(error2);
3923
2592
  return;
3924
2593
  }
@@ -3930,14 +2599,14 @@ function useAreaChecklistController() {
3930
2599
  ) : {};
3931
2600
  const acceptedBy = cookies["user"] || "";
3932
2601
  const payload = { id: req.params.id, acceptedBy };
3933
- const validation = import_joi12.default.object({
3934
- id: import_joi12.default.string().hex().required(),
3935
- acceptedBy: import_joi12.default.string().hex().required()
2602
+ const validation = import_joi8.default.object({
2603
+ id: import_joi8.default.string().hex().required(),
2604
+ acceptedBy: import_joi8.default.string().hex().required()
3936
2605
  });
3937
2606
  const { error } = validation.validate(payload);
3938
2607
  if (error) {
3939
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3940
- next(new import_node_server_utils23.BadRequestError(error.message));
2608
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2609
+ next(new import_node_server_utils15.BadRequestError(error.message));
3941
2610
  return;
3942
2611
  }
3943
2612
  try {
@@ -3945,21 +2614,21 @@ function useAreaChecklistController() {
3945
2614
  res.json({ message: "Area checklist updated successfully." });
3946
2615
  return;
3947
2616
  } catch (error2) {
3948
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2617
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3949
2618
  next(error2);
3950
2619
  return;
3951
2620
  }
3952
2621
  }
3953
2622
  async function attachImageAreaChecklist(req, res, next) {
3954
2623
  const payload = { id: req.params.id, attachments: req.body.attachments };
3955
- const validation = import_joi12.default.object({
3956
- id: import_joi12.default.string().hex().required(),
3957
- attachments: import_joi12.default.array().items(import_joi12.default.string()).optional()
2624
+ const validation = import_joi8.default.object({
2625
+ id: import_joi8.default.string().hex().required(),
2626
+ attachments: import_joi8.default.array().items(import_joi8.default.string()).optional()
3958
2627
  });
3959
2628
  const { error } = validation.validate(payload);
3960
2629
  if (error) {
3961
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3962
- next(new import_node_server_utils23.BadRequestError(error.message));
2630
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2631
+ next(new import_node_server_utils15.BadRequestError(error.message));
3963
2632
  return;
3964
2633
  }
3965
2634
  try {
@@ -3967,21 +2636,21 @@ function useAreaChecklistController() {
3967
2636
  res.json({ message: "Area checklist attachments updated successfully." });
3968
2637
  return;
3969
2638
  } catch (error2) {
3970
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2639
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3971
2640
  next(error2);
3972
2641
  return;
3973
2642
  }
3974
2643
  }
3975
2644
  async function submitAreaChecklist(req, res, next) {
3976
2645
  const payload = { id: req.params.id, signature: req.body.signature };
3977
- const validation = import_joi12.default.object({
3978
- id: import_joi12.default.string().hex().required(),
3979
- signature: import_joi12.default.string().required()
2646
+ const validation = import_joi8.default.object({
2647
+ id: import_joi8.default.string().hex().required(),
2648
+ signature: import_joi8.default.string().required()
3980
2649
  });
3981
2650
  const { error } = validation.validate(payload);
3982
2651
  if (error) {
3983
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
3984
- next(new import_node_server_utils23.BadRequestError(error.message));
2652
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2653
+ next(new import_node_server_utils15.BadRequestError(error.message));
3985
2654
  return;
3986
2655
  }
3987
2656
  try {
@@ -3989,21 +2658,21 @@ function useAreaChecklistController() {
3989
2658
  res.json({ message: "Area checklist submitted successfully." });
3990
2659
  return;
3991
2660
  } catch (error2) {
3992
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2661
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
3993
2662
  next(error2);
3994
2663
  return;
3995
2664
  }
3996
2665
  }
3997
2666
  async function completeAreaChecklist(req, res, next) {
3998
2667
  const payload = { id: req.params.id, signature: req.body.signature };
3999
- const validation = import_joi12.default.object({
4000
- id: import_joi12.default.string().hex().required(),
4001
- signature: import_joi12.default.string().required()
2668
+ const validation = import_joi8.default.object({
2669
+ id: import_joi8.default.string().hex().required(),
2670
+ signature: import_joi8.default.string().required()
4002
2671
  });
4003
2672
  const { error } = validation.validate(payload);
4004
2673
  if (error) {
4005
- import_node_server_utils23.logger.log({ level: "error", message: error.message });
4006
- next(new import_node_server_utils23.BadRequestError(error.message));
2674
+ import_node_server_utils15.logger.log({ level: "error", message: error.message });
2675
+ next(new import_node_server_utils15.BadRequestError(error.message));
4007
2676
  return;
4008
2677
  }
4009
2678
  try {
@@ -4011,7 +2680,7 @@ function useAreaChecklistController() {
4011
2680
  res.json({ message: "Area checklist completed successfully." });
4012
2681
  return;
4013
2682
  } catch (error2) {
4014
- import_node_server_utils23.logger.log({ level: "error", message: error2.message });
2683
+ import_node_server_utils15.logger.log({ level: "error", message: error2.message });
4015
2684
  next(error2);
4016
2685
  return;
4017
2686
  }
@@ -4029,57 +2698,57 @@ function useAreaChecklistController() {
4029
2698
  }
4030
2699
 
4031
2700
  // src/models/hygiene-unit-checklist.model.ts
4032
- var import_node_server_utils24 = require("@iservice365/node-server-utils");
4033
- var import_joi13 = __toESM(require("joi"));
4034
- var import_mongodb13 = require("mongodb");
4035
- var unitChecklistSchema = import_joi13.default.object({
4036
- site: import_joi13.default.string().hex().required(),
4037
- type: import_joi13.default.string().valid(...allowedTypes).required(),
4038
- parentChecklist: import_joi13.default.string().hex().required(),
4039
- areaChecklist: import_joi13.default.string().hex().required(),
4040
- unit: import_joi13.default.string().hex().required(),
4041
- name: import_joi13.default.string().optional().allow("", null),
4042
- createdBy: import_joi13.default.string().hex().optional().allow("", null)
2701
+ var import_node_server_utils16 = require("@iservice365/node-server-utils");
2702
+ var import_joi9 = __toESM(require("joi"));
2703
+ var import_mongodb9 = require("mongodb");
2704
+ var unitChecklistSchema = import_joi9.default.object({
2705
+ site: import_joi9.default.string().hex().required(),
2706
+ type: import_joi9.default.string().valid(...allowedTypes).required(),
2707
+ parentChecklist: import_joi9.default.string().hex().required(),
2708
+ areaChecklist: import_joi9.default.string().hex().required(),
2709
+ unit: import_joi9.default.string().hex().required(),
2710
+ name: import_joi9.default.string().optional().allow("", null),
2711
+ createdBy: import_joi9.default.string().hex().optional().allow("", null)
4043
2712
  });
4044
2713
  function MUnitChecklist(value) {
4045
2714
  const { error } = unitChecklistSchema.validate(value);
4046
2715
  if (error) {
4047
- import_node_server_utils24.logger.info(`Hygiene Checklist Unit Model: ${error.message}`);
4048
- throw new import_node_server_utils24.BadRequestError(error.message);
2716
+ import_node_server_utils16.logger.info(`Hygiene Checklist Unit Model: ${error.message}`);
2717
+ throw new import_node_server_utils16.BadRequestError(error.message);
4049
2718
  }
4050
2719
  if (value.site) {
4051
2720
  try {
4052
- value.site = new import_mongodb13.ObjectId(value.site);
2721
+ value.site = new import_mongodb9.ObjectId(value.site);
4053
2722
  } catch (error2) {
4054
- throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
2723
+ throw new import_node_server_utils16.BadRequestError("Invalid site ID format.");
4055
2724
  }
4056
2725
  }
4057
2726
  if (value.parentChecklist) {
4058
2727
  try {
4059
- value.parentChecklist = new import_mongodb13.ObjectId(value.parentChecklist);
2728
+ value.parentChecklist = new import_mongodb9.ObjectId(value.parentChecklist);
4060
2729
  } catch (error2) {
4061
- throw new import_node_server_utils24.BadRequestError("Invalid parent checklist ID format.");
2730
+ throw new import_node_server_utils16.BadRequestError("Invalid parent checklist ID format.");
4062
2731
  }
4063
2732
  }
4064
2733
  if (value.areaChecklist) {
4065
2734
  try {
4066
- value.areaChecklist = new import_mongodb13.ObjectId(value.areaChecklist);
2735
+ value.areaChecklist = new import_mongodb9.ObjectId(value.areaChecklist);
4067
2736
  } catch (error2) {
4068
- throw new import_node_server_utils24.BadRequestError("Invalid area checklist ID format.");
2737
+ throw new import_node_server_utils16.BadRequestError("Invalid area checklist ID format.");
4069
2738
  }
4070
2739
  }
4071
2740
  if (value.unit) {
4072
2741
  try {
4073
- value.unit = new import_mongodb13.ObjectId(value.unit);
2742
+ value.unit = new import_mongodb9.ObjectId(value.unit);
4074
2743
  } catch (error2) {
4075
- throw new import_node_server_utils24.BadRequestError("Invalid unit ID format.");
2744
+ throw new import_node_server_utils16.BadRequestError("Invalid unit ID format.");
4076
2745
  }
4077
2746
  }
4078
2747
  if (value.createdBy) {
4079
2748
  try {
4080
- value.createdBy = new import_mongodb13.ObjectId(value.createdBy);
2749
+ value.createdBy = new import_mongodb9.ObjectId(value.createdBy);
4081
2750
  } catch (error2) {
4082
- throw new import_node_server_utils24.BadRequestError("Invalid createdBy ID format.");
2751
+ throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
4083
2752
  }
4084
2753
  }
4085
2754
  return {
@@ -4098,16 +2767,16 @@ function MUnitChecklist(value) {
4098
2767
  }
4099
2768
 
4100
2769
  // src/repositories/hygiene-unit-checklist.repository.ts
4101
- var import_node_server_utils25 = require("@iservice365/node-server-utils");
4102
- var import_mongodb14 = require("mongodb");
2770
+ var import_node_server_utils17 = require("@iservice365/node-server-utils");
2771
+ var import_mongodb10 = require("mongodb");
4103
2772
  function useUnitChecklistRepo() {
4104
- const db = import_node_server_utils25.useAtlas.getDb();
2773
+ const db = import_node_server_utils17.useAtlas.getDb();
4105
2774
  if (!db) {
4106
- throw new import_node_server_utils25.InternalServerError("Unable to connect to server.");
2775
+ throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
4107
2776
  }
4108
2777
  const namespace_collection = "hygiene-checklist.units";
4109
2778
  const collection = db.collection(namespace_collection);
4110
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils25.useCache)(namespace_collection);
2779
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
4111
2780
  async function createIndex() {
4112
2781
  try {
4113
2782
  await collection.createIndexes([
@@ -4122,7 +2791,7 @@ function useUnitChecklistRepo() {
4122
2791
  { key: { "metadata.workOrder.site": 1 } }
4123
2792
  ]);
4124
2793
  } catch (error) {
4125
- throw new import_node_server_utils25.InternalServerError(
2794
+ throw new import_node_server_utils17.InternalServerError(
4126
2795
  "Failed to create index on hygiene unit checklist."
4127
2796
  );
4128
2797
  }
@@ -4131,7 +2800,7 @@ function useUnitChecklistRepo() {
4131
2800
  try {
4132
2801
  await collection.createIndex({ name: "text" });
4133
2802
  } catch (error) {
4134
- throw new import_node_server_utils25.InternalServerError(
2803
+ throw new import_node_server_utils17.InternalServerError(
4135
2804
  "Failed to create text index on hygiene unit checklist."
4136
2805
  );
4137
2806
  }
@@ -4141,9 +2810,9 @@ function useUnitChecklistRepo() {
4141
2810
  value = MUnitChecklist(value);
4142
2811
  const res = await collection.insertOne(value, { session });
4143
2812
  delNamespace().then(() => {
4144
- import_node_server_utils25.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
2813
+ import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4145
2814
  }).catch((err) => {
4146
- import_node_server_utils25.logger.error(
2815
+ import_node_server_utils17.logger.error(
4147
2816
  `Failed to clear cache for namespace: ${namespace_collection}`,
4148
2817
  err
4149
2818
  );
@@ -4169,31 +2838,31 @@ function useUnitChecklistRepo() {
4169
2838
  limit
4170
2839
  };
4171
2840
  try {
4172
- query.site = new import_mongodb14.ObjectId(site);
2841
+ query.site = new import_mongodb10.ObjectId(site);
4173
2842
  cacheOptions.site = site.toString();
4174
2843
  } catch (error) {
4175
- throw new import_node_server_utils25.BadRequestError("Invalid site ID format.");
2844
+ throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
4176
2845
  }
4177
2846
  try {
4178
- query.parentChecklist = new import_mongodb14.ObjectId(parentChecklist);
2847
+ query.parentChecklist = new import_mongodb10.ObjectId(parentChecklist);
4179
2848
  cacheOptions.parentChecklist = parentChecklist.toString();
4180
2849
  } catch (error) {
4181
- throw new import_node_server_utils25.BadRequestError("Invalid parent checklist ID format.");
2850
+ throw new import_node_server_utils17.BadRequestError("Invalid parent checklist ID format.");
4182
2851
  }
4183
2852
  try {
4184
- query.areaChecklist = new import_mongodb14.ObjectId(areaChecklist);
2853
+ query.areaChecklist = new import_mongodb10.ObjectId(areaChecklist);
4185
2854
  cacheOptions.areaChecklist = areaChecklist.toString();
4186
2855
  } catch (error) {
4187
- throw new import_node_server_utils25.BadRequestError("Invalid area checklist ID format.");
2856
+ throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
4188
2857
  }
4189
2858
  if (search) {
4190
2859
  query.$text = { $search: search };
4191
2860
  cacheOptions.search = search;
4192
2861
  }
4193
- const cacheKey = (0, import_node_server_utils25.makeCacheKey)(namespace_collection, cacheOptions);
2862
+ const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
4194
2863
  const cachedData = await getCache(cacheKey);
4195
2864
  if (cachedData) {
4196
- import_node_server_utils25.logger.info(`Cache hit for key: ${cacheKey}`);
2865
+ import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
4197
2866
  return cachedData;
4198
2867
  }
4199
2868
  try {
@@ -4306,15 +2975,15 @@ function useUnitChecklistRepo() {
4306
2975
  ];
4307
2976
  const items = await collection.aggregate(pipeline).toArray();
4308
2977
  const length = await collection.countDocuments(query);
4309
- const paginatedData = (0, import_node_server_utils25.paginate)(items, page, limit, length);
2978
+ const paginatedData = (0, import_node_server_utils17.paginate)(items, page, limit, length);
4310
2979
  const data = {
4311
2980
  attachments: areaAttachments,
4312
2981
  ...paginatedData
4313
2982
  };
4314
2983
  setCache(cacheKey, data, 15 * 60).then(() => {
4315
- import_node_server_utils25.logger.info(`Cache set for key: ${cacheKey}`);
2984
+ import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
4316
2985
  }).catch((err) => {
4317
- import_node_server_utils25.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2986
+ import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4318
2987
  });
4319
2988
  return data;
4320
2989
  } catch (error) {
@@ -4323,9 +2992,9 @@ function useUnitChecklistRepo() {
4323
2992
  }
4324
2993
  async function getUnitChecklistById(_id) {
4325
2994
  try {
4326
- _id = new import_mongodb14.ObjectId(_id);
2995
+ _id = new import_mongodb10.ObjectId(_id);
4327
2996
  } catch (error) {
4328
- throw new import_node_server_utils25.BadRequestError("Invalid unit checklist ID format.");
2997
+ throw new import_node_server_utils17.BadRequestError("Invalid unit checklist ID format.");
4329
2998
  }
4330
2999
  try {
4331
3000
  return await collection.findOne({ _id });
@@ -4335,52 +3004,52 @@ function useUnitChecklistRepo() {
4335
3004
  }
4336
3005
  async function updateUnitChecklist(_id, value, session) {
4337
3006
  try {
4338
- _id = new import_mongodb14.ObjectId(_id);
3007
+ _id = new import_mongodb10.ObjectId(_id);
4339
3008
  } catch (error) {
4340
- throw new import_node_server_utils25.BadRequestError("Invalid unit checklist ID format.");
3009
+ throw new import_node_server_utils17.BadRequestError("Invalid unit checklist ID format.");
4341
3010
  }
4342
3011
  if (value.checkedBy && typeof value.checkedBy === "string") {
4343
3012
  try {
4344
- value.checkedBy = new import_mongodb14.ObjectId(value.checkedBy);
3013
+ value.checkedBy = new import_mongodb10.ObjectId(value.checkedBy);
4345
3014
  } catch (error) {
4346
- throw new import_node_server_utils25.BadRequestError("Invalid checkedBy ID format.");
3015
+ throw new import_node_server_utils17.BadRequestError("Invalid checkedBy ID format.");
4347
3016
  }
4348
3017
  }
4349
3018
  if ("metadata" in value && value.metadata?.workOrder) {
4350
3019
  const workOrder = value.metadata.workOrder;
4351
3020
  if (workOrder.category && typeof workOrder.category === "string") {
4352
3021
  try {
4353
- workOrder.category = new import_mongodb14.ObjectId(workOrder.category);
3022
+ workOrder.category = new import_mongodb10.ObjectId(workOrder.category);
4354
3023
  } catch (error) {
4355
- throw new import_node_server_utils25.BadRequestError("Invalid category ID format.");
3024
+ throw new import_node_server_utils17.BadRequestError("Invalid category ID format.");
4356
3025
  }
4357
3026
  }
4358
3027
  if (workOrder.createdBy && typeof workOrder.createdBy === "string") {
4359
3028
  try {
4360
- workOrder.createdBy = new import_mongodb14.ObjectId(workOrder.createdBy);
3029
+ workOrder.createdBy = new import_mongodb10.ObjectId(workOrder.createdBy);
4361
3030
  } catch (error) {
4362
- throw new import_node_server_utils25.BadRequestError("Invalid createdBy ID format.");
3031
+ throw new import_node_server_utils17.BadRequestError("Invalid createdBy ID format.");
4363
3032
  }
4364
3033
  }
4365
3034
  if (workOrder.serviceProvider && typeof workOrder.serviceProvider === "string") {
4366
3035
  try {
4367
- workOrder.serviceProvider = new import_mongodb14.ObjectId(workOrder.serviceProvider);
3036
+ workOrder.serviceProvider = new import_mongodb10.ObjectId(workOrder.serviceProvider);
4368
3037
  } catch (error) {
4369
- throw new import_node_server_utils25.BadRequestError("Invalid serviceProvider ID format.");
3038
+ throw new import_node_server_utils17.BadRequestError("Invalid serviceProvider ID format.");
4370
3039
  }
4371
3040
  }
4372
3041
  if (workOrder.organization && typeof workOrder.organization === "string") {
4373
3042
  try {
4374
- workOrder.organization = new import_mongodb14.ObjectId(workOrder.organization);
3043
+ workOrder.organization = new import_mongodb10.ObjectId(workOrder.organization);
4375
3044
  } catch (error) {
4376
- throw new import_node_server_utils25.BadRequestError("Invalid organization ID format.");
3045
+ throw new import_node_server_utils17.BadRequestError("Invalid organization ID format.");
4377
3046
  }
4378
3047
  }
4379
3048
  if (workOrder.site && typeof workOrder.site === "string") {
4380
3049
  try {
4381
- workOrder.site = new import_mongodb14.ObjectId(workOrder.site);
3050
+ workOrder.site = new import_mongodb10.ObjectId(workOrder.site);
4382
3051
  } catch (error) {
4383
- throw new import_node_server_utils25.BadRequestError("Invalid site ID format.");
3052
+ throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
4384
3053
  }
4385
3054
  }
4386
3055
  }
@@ -4392,12 +3061,12 @@ function useUnitChecklistRepo() {
4392
3061
  { session }
4393
3062
  );
4394
3063
  if (res.modifiedCount === 0) {
4395
- throw new import_node_server_utils25.InternalServerError("Unable to update unit checklist.");
3064
+ throw new import_node_server_utils17.InternalServerError("Unable to update unit checklist.");
4396
3065
  }
4397
3066
  delNamespace().then(() => {
4398
- import_node_server_utils25.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3067
+ import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4399
3068
  }).catch((err) => {
4400
- import_node_server_utils25.logger.error(
3069
+ import_node_server_utils17.logger.error(
4401
3070
  `Failed to clear cache for namespace: ${namespace_collection}`,
4402
3071
  err
4403
3072
  );
@@ -4418,11 +3087,11 @@ function useUnitChecklistRepo() {
4418
3087
  }
4419
3088
 
4420
3089
  // src/controllers/hygiene-unit-checklist.controller.ts
4421
- var import_node_server_utils27 = require("@iservice365/node-server-utils");
4422
- var import_joi14 = __toESM(require("joi"));
3090
+ var import_node_server_utils19 = require("@iservice365/node-server-utils");
3091
+ var import_joi10 = __toESM(require("joi"));
4423
3092
 
4424
3093
  // src/services/hygiene-unit-checklist.service.ts
4425
- var import_node_server_utils26 = require("@iservice365/node-server-utils");
3094
+ var import_node_server_utils18 = require("@iservice365/node-server-utils");
4426
3095
  var import_core = require("@iservice365/core");
4427
3096
  function useUnitChecklistService() {
4428
3097
  const {
@@ -4438,7 +3107,7 @@ function useUnitChecklistService() {
4438
3107
  const result = await _updateUnitChecklist(id, value);
4439
3108
  return result;
4440
3109
  } catch (error) {
4441
- import_node_server_utils26.logger.error(`Error updating unit checklist with id ${id}:`, error);
3110
+ import_node_server_utils18.logger.error(`Error updating unit checklist with id ${id}:`, error);
4442
3111
  throw error;
4443
3112
  }
4444
3113
  }
@@ -4449,12 +3118,12 @@ function useUnitChecklistService() {
4449
3118
  if (value.metadata?.workOrder) {
4450
3119
  const existingChecklist = await _getUnitChecklistById(id);
4451
3120
  if (!existingChecklist)
4452
- throw new import_node_server_utils26.NotFoundError("Unit checklist not found.");
3121
+ throw new import_node_server_utils18.NotFoundError("Unit checklist not found.");
4453
3122
  const site = await getSiteById(
4454
3123
  existingChecklist.site
4455
3124
  );
4456
3125
  if (!site)
4457
- throw new import_node_server_utils26.NotFoundError("Site not found.");
3126
+ throw new import_node_server_utils18.NotFoundError("Site not found.");
4458
3127
  const workOrderData = {
4459
3128
  ...value.metadata.workOrder,
4460
3129
  attachments: value.metadata.attachments,
@@ -4467,12 +3136,12 @@ function useUnitChecklistService() {
4467
3136
  fullHost
4468
3137
  );
4469
3138
  if (!workOrder)
4470
- throw new import_node_server_utils26.NotFoundError("Failed to create work order.");
3139
+ throw new import_node_server_utils18.NotFoundError("Failed to create work order.");
4471
3140
  }
4472
3141
  const result = await _updateUnitChecklist(id, value);
4473
3142
  return result;
4474
3143
  } catch (error) {
4475
- import_node_server_utils26.logger.error(`Error updating unit checklist with id ${id}:`, error);
3144
+ import_node_server_utils18.logger.error(`Error updating unit checklist with id ${id}:`, error);
4476
3145
  throw error;
4477
3146
  }
4478
3147
  }
@@ -4502,8 +3171,8 @@ function useUnitChecklistController() {
4502
3171
  const payload = { ...req.body, ...req.params, createdBy };
4503
3172
  const { error } = unitChecklistSchema.validate(payload);
4504
3173
  if (error) {
4505
- import_node_server_utils27.logger.log({ level: "error", message: error.message });
4506
- next(new import_node_server_utils27.BadRequestError(error.message));
3174
+ import_node_server_utils19.logger.log({ level: "error", message: error.message });
3175
+ next(new import_node_server_utils19.BadRequestError(error.message));
4507
3176
  return;
4508
3177
  }
4509
3178
  try {
@@ -4511,26 +3180,26 @@ function useUnitChecklistController() {
4511
3180
  res.status(201).json({ message: "Unit checklist created successfully.", id });
4512
3181
  return;
4513
3182
  } catch (error2) {
4514
- import_node_server_utils27.logger.log({ level: "error", message: error2.message });
3183
+ import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4515
3184
  next(error2);
4516
3185
  return;
4517
3186
  }
4518
3187
  }
4519
3188
  async function getAllUnitChecklist(req, res, next) {
4520
3189
  const query = { ...req.query, ...req.params };
4521
- const validation = import_joi14.default.object({
4522
- page: import_joi14.default.number().min(1).optional().allow("", null),
4523
- limit: import_joi14.default.number().min(1).optional().allow("", null),
4524
- search: import_joi14.default.string().optional().allow("", null),
4525
- site: import_joi14.default.string().hex().required(),
4526
- type: import_joi14.default.string().valid(...allowedTypes).required(),
4527
- parentChecklist: import_joi14.default.string().hex().required(),
4528
- areaChecklist: import_joi14.default.string().hex().required()
3190
+ const validation = import_joi10.default.object({
3191
+ page: import_joi10.default.number().min(1).optional().allow("", null),
3192
+ limit: import_joi10.default.number().min(1).optional().allow("", null),
3193
+ search: import_joi10.default.string().optional().allow("", null),
3194
+ site: import_joi10.default.string().hex().required(),
3195
+ type: import_joi10.default.string().valid(...allowedTypes).required(),
3196
+ parentChecklist: import_joi10.default.string().hex().required(),
3197
+ areaChecklist: import_joi10.default.string().hex().required()
4529
3198
  });
4530
3199
  const { error } = validation.validate(query);
4531
3200
  if (error) {
4532
- import_node_server_utils27.logger.log({ level: "error", message: error.message });
4533
- next(new import_node_server_utils27.BadRequestError(error.message));
3201
+ import_node_server_utils19.logger.log({ level: "error", message: error.message });
3202
+ next(new import_node_server_utils19.BadRequestError(error.message));
4534
3203
  return;
4535
3204
  }
4536
3205
  const page = parseInt(req.query.page) ?? 1;
@@ -4553,7 +3222,7 @@ function useUnitChecklistController() {
4553
3222
  res.json(data);
4554
3223
  return;
4555
3224
  } catch (error2) {
4556
- import_node_server_utils27.logger.log({ level: "error", message: error2.message });
3225
+ import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4557
3226
  next(error2);
4558
3227
  return;
4559
3228
  }
@@ -4565,14 +3234,14 @@ function useUnitChecklistController() {
4565
3234
  ) : {};
4566
3235
  const checkedBy = cookies["user"] || "";
4567
3236
  const payload = { id: req.params.id, checkedBy };
4568
- const validation = import_joi14.default.object({
4569
- id: import_joi14.default.string().hex().required(),
4570
- checkedBy: import_joi14.default.string().hex().required()
3237
+ const validation = import_joi10.default.object({
3238
+ id: import_joi10.default.string().hex().required(),
3239
+ checkedBy: import_joi10.default.string().hex().required()
4571
3240
  });
4572
3241
  const { error } = validation.validate(payload);
4573
3242
  if (error) {
4574
- import_node_server_utils27.logger.log({ level: "error", message: error.message });
4575
- next(new import_node_server_utils27.BadRequestError(error.message));
3243
+ import_node_server_utils19.logger.log({ level: "error", message: error.message });
3244
+ next(new import_node_server_utils19.BadRequestError(error.message));
4576
3245
  return;
4577
3246
  }
4578
3247
  try {
@@ -4581,7 +3250,7 @@ function useUnitChecklistController() {
4581
3250
  res.json({ message: "Unit checklist approved successfully." });
4582
3251
  return;
4583
3252
  } catch (error2) {
4584
- import_node_server_utils27.logger.log({ level: "error", message: error2.message });
3253
+ import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4585
3254
  next(error2);
4586
3255
  return;
4587
3256
  }
@@ -4596,17 +3265,17 @@ function useUnitChecklistController() {
4596
3265
  req.body.workOrder.createdBy = checkedBy;
4597
3266
  }
4598
3267
  const payload = { id: req.params.id, checkedBy, ...req.body };
4599
- const validation = import_joi14.default.object({
4600
- id: import_joi14.default.string().hex().required(),
4601
- attachments: import_joi14.default.array().items(import_joi14.default.string()).optional(),
4602
- remarks: import_joi14.default.string().required(),
3268
+ const validation = import_joi10.default.object({
3269
+ id: import_joi10.default.string().hex().required(),
3270
+ attachments: import_joi10.default.array().items(import_joi10.default.string()).optional(),
3271
+ remarks: import_joi10.default.string().required(),
4603
3272
  workOrder: import_core2.workOrderSchema.optional(),
4604
- checkedBy: import_joi14.default.string().hex().required()
3273
+ checkedBy: import_joi10.default.string().hex().required()
4605
3274
  });
4606
3275
  const { error } = validation.validate(payload);
4607
3276
  if (error) {
4608
- import_node_server_utils27.logger.log({ level: "error", message: error.message });
4609
- next(new import_node_server_utils27.BadRequestError(error.message));
3277
+ import_node_server_utils19.logger.log({ level: "error", message: error.message });
3278
+ next(new import_node_server_utils19.BadRequestError(error.message));
4610
3279
  return;
4611
3280
  }
4612
3281
  try {
@@ -4630,7 +3299,7 @@ function useUnitChecklistController() {
4630
3299
  res.json({ message: "Unit checklist rejected successfully." });
4631
3300
  return;
4632
3301
  } catch (error2) {
4633
- import_node_server_utils27.logger.log({ level: "error", message: error2.message });
3302
+ import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4634
3303
  next(error2);
4635
3304
  return;
4636
3305
  }
@@ -4647,32 +3316,21 @@ function useUnitChecklistController() {
4647
3316
  MArea,
4648
3317
  MAreaChecklist,
4649
3318
  MParentChecklist,
4650
- MScheduleTaskArea,
4651
- MToiletLocation,
4652
3319
  MUnit,
4653
3320
  MUnitChecklist,
4654
- allowedStatus,
4655
- allowedTypes,
3321
+ allowedChecklistStatus,
4656
3322
  areaChecklistSchema,
4657
3323
  areaSchema,
4658
3324
  parentChecklistSchema,
4659
- scheduleTaskAreaSchema,
4660
- toiletLocationSchema,
4661
3325
  unitChecklistSchema,
4662
3326
  unitSchema,
4663
3327
  useAreaChecklistController,
4664
3328
  useAreaChecklistRepo,
4665
3329
  useAreaController,
4666
- useAreaRepository,
3330
+ useAreaRepo,
4667
3331
  useAreaService,
4668
3332
  useParentChecklistController,
4669
3333
  useParentChecklistRepo,
4670
- useScheduleTaskAreaController,
4671
- useScheduleTaskAreaRepository,
4672
- useScheduleTaskAreaService,
4673
- useToiletLocationController,
4674
- useToiletLocationRepository,
4675
- useToiletLocationService,
4676
3334
  useUnitChecklistController,
4677
3335
  useUnitChecklistRepo,
4678
3336
  useUnitController,