@7365admin1/module-hygiene 4.7.0 → 4.9.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
@@ -84,7 +84,12 @@ module.exports = __toCommonJS(src_exports);
84
84
 
85
85
  // src/models/hygiene-base.model.ts
86
86
  var allowedTypes = ["common", "toilet"];
87
- var allowedStatus = ["ready", "ongoing", "completed"];
87
+ var allowedStatus = [
88
+ "open",
89
+ "ongoing",
90
+ "completed",
91
+ "closed"
92
+ ];
88
93
  var allowedPeriods = ["today", "thisWeek", "thisMonth"];
89
94
 
90
95
  // src/repositories/hygiene-dashboard.repository.ts
@@ -1366,10 +1371,14 @@ function useAreaService() {
1366
1371
  try {
1367
1372
  dataArray = JSON.parse(dataJson);
1368
1373
  } catch (error) {
1369
- throw new import_node_server_utils8.BadRequestError("Invalid JSON format for data in excel");
1374
+ throw new import_node_server_utils8.BadRequestError(
1375
+ "We couldn't read the uploaded file. Please make sure you're uploading the correct file and try again."
1376
+ );
1370
1377
  }
1371
1378
  if (!dataArray || dataArray.length === 0) {
1372
- throw new import_node_server_utils8.NotFoundError("No data found in the uploaded file");
1379
+ throw new import_node_server_utils8.NotFoundError(
1380
+ "The uploaded file is empty. Please make sure your file contains data and try again."
1381
+ );
1373
1382
  }
1374
1383
  let availableUnits = [];
1375
1384
  try {
@@ -1470,33 +1479,35 @@ function useAreaService() {
1470
1479
  }
1471
1480
  }
1472
1481
  }
1473
- let message = `Upload completed: ${insertedAreaIds.length} areas successfully created`;
1482
+ let message = `Upload complete! ${insertedAreaIds.length} ${insertedAreaIds.length === 1 ? "area was" : "areas were"} successfully added`;
1474
1483
  if (duplicateAreas.length > 0) {
1475
- message += `, ${duplicateAreas.length} areas skipped (already exist)`;
1484
+ message += `, ${duplicateAreas.length} ${duplicateAreas.length === 1 ? "area was" : "areas were"} skipped because they already exist`;
1476
1485
  }
1477
1486
  if (failedAreas.length > 0) {
1478
- message += `, ${failedAreas.length} areas failed`;
1487
+ message += `, ${failedAreas.length} ${failedAreas.length === 1 ? "area" : "areas"} could not be saved`;
1479
1488
  }
1480
1489
  if (skippedRows.length > 0) {
1481
- message += `, ${skippedRows.length} rows skipped (invalid data)`;
1490
+ message += `, ${skippedRows.length} ${skippedRows.length === 1 ? "row was" : "rows were"} skipped due to missing information`;
1482
1491
  }
1483
1492
  import_node_server_utils8.logger.info(message);
1484
1493
  if (insertedAreaIds.length === 0) {
1485
1494
  if (duplicateAreas.length > 0 && failedAreas.length === 0 && skippedRows.length === 0) {
1486
1495
  return {
1487
- message: `No new areas were created. All ${duplicateAreas.length} areas already exist in the system: ${duplicateAreas.join(", ")}`
1496
+ message: `No new areas were added. All ${duplicateAreas.length} ${duplicateAreas.length === 1 ? "area" : "areas"} in your file already exist in the system: ${duplicateAreas.join(
1497
+ ", "
1498
+ )}.`
1488
1499
  };
1489
1500
  } else if (failedAreas.length > 0) {
1490
1501
  throw new import_node_server_utils8.BadRequestError(
1491
- `No areas were created. ${failedAreas.length} areas failed due to errors. Please check your data format and ensure area names are valid.`
1502
+ `No areas were added. ${failedAreas.length} ${failedAreas.length === 1 ? "area" : "areas"} could not be saved. Please review the area names and information in your file, then try again.`
1492
1503
  );
1493
1504
  } else if (skippedRows.length > 0 && duplicateAreas.length === 0) {
1494
1505
  throw new import_node_server_utils8.BadRequestError(
1495
- `No areas were created. All ${skippedRows.length} rows contained invalid or missing data.`
1506
+ `No areas were added. ${skippedRows.length} ${skippedRows.length === 1 ? "row" : "rows"} in your file had missing or incomplete information. Please fill in all required fields and try again.`
1496
1507
  );
1497
1508
  } else {
1498
1509
  return {
1499
- message: `No new areas were created. ${duplicateAreas.length} areas already exist, ${skippedRows.length} rows had invalid data.`
1510
+ message: `No new areas were added. ${duplicateAreas.length} ${duplicateAreas.length === 1 ? "area" : "areas"} already exist${skippedRows.length > 0 ? `, and ${skippedRows.length} ${skippedRows.length === 1 ? "row" : "rows"} had missing or incomplete information` : ""}.`
1500
1511
  };
1501
1512
  }
1502
1513
  }
@@ -1507,11 +1518,11 @@ function useAreaService() {
1507
1518
  throw error;
1508
1519
  } else if (error.message.includes("validation")) {
1509
1520
  throw new import_node_server_utils8.BadRequestError(
1510
- "Upload failed due to invalid data format. Please check that all required fields are properly filled."
1521
+ "Upload failed because some required information is missing or incorrect. Please review your file and make sure all fields are filled in properly."
1511
1522
  );
1512
1523
  } else {
1513
1524
  throw new import_node_server_utils8.BadRequestError(
1514
- `Upload failed: ${error.message || "Please check your data format and try again."}`
1525
+ "Something went wrong while uploading. Please check your file and try again."
1515
1526
  );
1516
1527
  }
1517
1528
  }
@@ -1520,11 +1531,15 @@ function useAreaService() {
1520
1531
  try {
1521
1532
  const areas = await getAreasForChecklist(site);
1522
1533
  if (!areas || !Array.isArray(areas) || areas.length === 0) {
1523
- throw new import_node_server_utils8.BadRequestError("No data found to export");
1534
+ throw new import_node_server_utils8.BadRequestError(
1535
+ "There are no areas to export yet. Please add some areas first, then try again."
1536
+ );
1524
1537
  }
1525
1538
  const excelBuffer = await generateAreaExcel(areas);
1526
1539
  if (!excelBuffer || excelBuffer.length === 0) {
1527
- throw new Error("Generated Excel file is empty or invalid.");
1540
+ throw new Error(
1541
+ "Something went wrong while preparing your export file. Please try again."
1542
+ );
1528
1543
  }
1529
1544
  return excelBuffer;
1530
1545
  } catch (error) {
@@ -1824,10 +1839,14 @@ function useUnitService() {
1824
1839
  try {
1825
1840
  dataArray = JSON.parse(dataJson);
1826
1841
  } catch (error) {
1827
- throw new import_node_server_utils11.BadRequestError("Invalid JSON format for data in excel");
1842
+ throw new import_node_server_utils11.BadRequestError(
1843
+ "We couldn't read the uploaded file. Please make sure you're uploading the correct file and try again."
1844
+ );
1828
1845
  }
1829
1846
  if (!dataArray || dataArray.length === 0) {
1830
- throw new import_node_server_utils11.NotFoundError("No data found in the uploaded file");
1847
+ throw new import_node_server_utils11.NotFoundError(
1848
+ "The uploaded file is empty. Please make sure your file contains data and try again."
1849
+ );
1831
1850
  }
1832
1851
  const insertedUnitIds = [];
1833
1852
  const duplicateUnits = [];
@@ -1868,29 +1887,31 @@ function useUnitService() {
1868
1887
  }
1869
1888
  }
1870
1889
  }
1871
- let message = `Upload completed: ${insertedUnitIds.length} units successfully created`;
1890
+ let message = `Upload complete! ${insertedUnitIds.length} ${insertedUnitIds.length === 1 ? "unit was" : "units were"} successfully added`;
1872
1891
  if (duplicateUnits.length > 0) {
1873
- message += `, ${duplicateUnits.length} units skipped (already exist)`;
1892
+ message += `, ${duplicateUnits.length} ${duplicateUnits.length === 1 ? "unit was" : "units were"} skipped because they already exist`;
1874
1893
  }
1875
1894
  if (failedUnits.length > 0) {
1876
- message += `, ${failedUnits.length} units failed`;
1895
+ message += `, ${failedUnits.length} ${failedUnits.length === 1 ? "unit" : "units"} could not be saved`;
1877
1896
  }
1878
1897
  if (skippedRows.length > 0) {
1879
- message += `, ${skippedRows.length} rows skipped (invalid data)`;
1898
+ message += `, ${skippedRows.length} ${skippedRows.length === 1 ? "row was" : "rows were"} skipped due to missing information`;
1880
1899
  }
1881
1900
  import_node_server_utils11.logger.info(message);
1882
1901
  if (insertedUnitIds.length === 0) {
1883
1902
  if (duplicateUnits.length > 0 && failedUnits.length === 0) {
1884
1903
  throw new import_node_server_utils11.BadRequestError(
1885
- `No new units were created. All ${duplicateUnits.length} units already exist in the system: ${duplicateUnits.join(", ")}`
1904
+ `No new units were added. All ${duplicateUnits.length} ${duplicateUnits.length === 1 ? "unit" : "units"} in your file already exist in the system: ${duplicateUnits.join(
1905
+ ", "
1906
+ )}.`
1886
1907
  );
1887
1908
  } else if (failedUnits.length > 0) {
1888
1909
  throw new import_node_server_utils11.BadRequestError(
1889
- `No units were created. Please check your data format and ensure unit names are valid.`
1910
+ `No units were added. ${failedUnits.length} ${failedUnits.length === 1 ? "unit" : "units"} could not be saved. Please review the unit names in your file and try again.`
1890
1911
  );
1891
1912
  } else if (skippedRows.length > 0) {
1892
1913
  throw new import_node_server_utils11.BadRequestError(
1893
- `No units were created. All rows contained invalid or missing unit names.`
1914
+ `No units were added. ${skippedRows.length} ${skippedRows.length === 1 ? "row" : "rows"} in your file had missing or incomplete information. Please fill in all required fields and try again.`
1894
1915
  );
1895
1916
  }
1896
1917
  }
@@ -1901,15 +1922,15 @@ function useUnitService() {
1901
1922
  throw error;
1902
1923
  } else if (error.message.includes("duplicate")) {
1903
1924
  throw new import_node_server_utils11.BadRequestError(
1904
- "Upload failed due to duplicate unit names. Please ensure all unit names are unique."
1925
+ "Upload failed because some unit names are already taken. Please make sure each unit has a unique name and try again."
1905
1926
  );
1906
1927
  } else if (error.message.includes("validation")) {
1907
1928
  throw new import_node_server_utils11.BadRequestError(
1908
- "Upload failed due to invalid data format. Please check that all required fields are properly filled."
1929
+ "Upload failed because some required information is missing or incorrect. Please review your file and make sure all fields are filled in properly."
1909
1930
  );
1910
1931
  } else {
1911
1932
  throw new import_node_server_utils11.BadRequestError(
1912
- `Upload failed: ${error.message || "Please check your data format and try again."}`
1933
+ "Something went wrong while uploading. Please check your file and try again."
1913
1934
  );
1914
1935
  }
1915
1936
  }
@@ -1941,7 +1962,9 @@ function useUnitService() {
1941
1962
  session?.startTransaction();
1942
1963
  const isExistingArea = await verifyAreaByUnitId(_id);
1943
1964
  if (isExistingArea) {
1944
- throw new import_node_server_utils11.BadRequestError("Failed to delete unit, unit is in use.");
1965
+ throw new import_node_server_utils11.BadRequestError(
1966
+ "This unit can't be deleted because it's currently being used in one or more areas. Please remove it from those areas first, then try again."
1967
+ );
1945
1968
  }
1946
1969
  const result = await _deleteUnit(_id, session);
1947
1970
  await session?.commitTransaction();
@@ -1967,11 +1990,15 @@ function useUnitService() {
1967
1990
  site
1968
1991
  });
1969
1992
  if (!data || !data.items || data.items.length === 0) {
1970
- throw new import_node_server_utils11.BadRequestError("No data found to export");
1993
+ throw new import_node_server_utils11.BadRequestError(
1994
+ "There are no units to export yet. Please add some units first, then try again."
1995
+ );
1971
1996
  }
1972
1997
  const excelBuffer = await _generateUnitExcel(data.items);
1973
1998
  if (!excelBuffer || excelBuffer.length === 0) {
1974
- throw new Error("Generated Excel file is empty or invalid.");
1999
+ throw new Error(
2000
+ "Something went wrong while preparing your export file. Please try again."
2001
+ );
1975
2002
  }
1976
2003
  return excelBuffer;
1977
2004
  } catch (error) {
@@ -2178,7 +2205,7 @@ function MParentChecklist(value) {
2178
2205
  }
2179
2206
  return {
2180
2207
  site: value.site,
2181
- status: "ready",
2208
+ status: "open",
2182
2209
  createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
2183
2210
  updatedAt: value.updatedAt ?? ""
2184
2211
  };
@@ -2368,18 +2395,23 @@ function useParentChecklistRepo() {
2368
2395
  status: {
2369
2396
  $switch: {
2370
2397
  branches: [
2371
- { case: { $eq: ["$status", "ready"] }, then: "Ready" },
2398
+ { case: { $eq: ["$status", "open"] }, then: "Open" },
2372
2399
  {
2373
2400
  case: { $eq: ["$status", "ongoing"] },
2374
2401
  then: "Ongoing"
2375
2402
  },
2376
- { case: { $eq: ["$status", "completed"] }, then: "Completed" }
2403
+ { case: { $eq: ["$status", "completed"] }, then: "Completed" },
2404
+ {
2405
+ case: { $eq: ["$status", "closed"] },
2406
+ then: "Closed"
2407
+ }
2377
2408
  ],
2378
2409
  default: "$status"
2379
2410
  }
2380
2411
  },
2381
2412
  completedAt: 1,
2382
- createdAt: 1
2413
+ createdAt: 1,
2414
+ closeIn: { $add: ["$createdAt", 24 * 60 * 60 * 1e3] }
2383
2415
  }
2384
2416
  });
2385
2417
  pipeline.push(
@@ -2467,11 +2499,42 @@ function useParentChecklistRepo() {
2467
2499
  throw error;
2468
2500
  }
2469
2501
  }
2502
+ async function closeExpiredParentChecklists() {
2503
+ try {
2504
+ const expiryDate = new Date(Date.now() - 24 * 60 * 60 * 1e3);
2505
+ const result = await collection.updateMany(
2506
+ {
2507
+ status: { $in: ["open", "ongoing", "completed"] },
2508
+ createdAt: { $lte: expiryDate }
2509
+ },
2510
+ {
2511
+ $set: {
2512
+ status: "closed",
2513
+ updatedAt: /* @__PURE__ */ new Date()
2514
+ }
2515
+ }
2516
+ );
2517
+ if (result.modifiedCount > 0) {
2518
+ delNamespace().catch((err) => {
2519
+ import_node_server_utils14.logger.error(
2520
+ "Failed to invalidate cache after closing expired parent checklists",
2521
+ err
2522
+ );
2523
+ });
2524
+ import_node_server_utils14.logger.info(`Closed ${result.modifiedCount} expired parent checklists`);
2525
+ }
2526
+ return result.modifiedCount;
2527
+ } catch (error) {
2528
+ import_node_server_utils14.logger.error("Failed to close expired parent checklists", error);
2529
+ throw error;
2530
+ }
2531
+ }
2470
2532
  return {
2471
2533
  createIndex,
2472
2534
  createParentChecklist,
2473
2535
  getAllParentChecklist,
2474
- updateParentChecklistStatuses
2536
+ updateParentChecklistStatuses,
2537
+ closeExpiredParentChecklists
2475
2538
  };
2476
2539
  }
2477
2540
 
@@ -2553,7 +2616,7 @@ function useParentChecklistController() {
2553
2616
  var import_joi8 = __toESM(require("joi"));
2554
2617
  var import_mongodb8 = require("mongodb");
2555
2618
  var import_node_server_utils16 = require("@7365admin1/node-server-utils");
2556
- var allowedChecklistStatus = ["ready", "completed"];
2619
+ var allowedChecklistStatus = ["open", "completed", "closed"];
2557
2620
  var areaChecklistSchema = import_joi8.default.object({
2558
2621
  schedule: import_joi8.default.string().hex().required(),
2559
2622
  area: import_joi8.default.string().hex().required(),
@@ -2601,7 +2664,7 @@ function MAreaChecklist(value) {
2601
2664
  name: unit.name,
2602
2665
  approve: false,
2603
2666
  reject: false,
2604
- status: "ready",
2667
+ status: "open",
2605
2668
  remarks: "",
2606
2669
  completedBy: "",
2607
2670
  timestamp: ""
@@ -2622,7 +2685,7 @@ function MAreaChecklist(value) {
2622
2685
  name: value.name,
2623
2686
  type: value.type,
2624
2687
  checklist: value.checklist || [],
2625
- status: "ready",
2688
+ status: "open",
2626
2689
  createdBy: value.createdBy,
2627
2690
  createdAt: /* @__PURE__ */ new Date(),
2628
2691
  completedAt: "",
@@ -2786,11 +2849,15 @@ function useAreaChecklistRepo() {
2786
2849
  status: {
2787
2850
  $switch: {
2788
2851
  branches: [
2789
- { case: { $eq: ["$status", "ready"] }, then: "Ready" },
2852
+ { case: { $eq: ["$status", "open"] }, then: "Open" },
2790
2853
  { case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
2791
2854
  {
2792
2855
  case: { $eq: ["$status", "completed"] },
2793
2856
  then: "Completed"
2857
+ },
2858
+ {
2859
+ case: { $eq: ["$status", "closed"] },
2860
+ then: "Closed"
2794
2861
  }
2795
2862
  ],
2796
2863
  default: "$status"
@@ -2892,11 +2959,15 @@ function useAreaChecklistRepo() {
2892
2959
  status: {
2893
2960
  $switch: {
2894
2961
  branches: [
2895
- { case: { $eq: ["$status", "ready"] }, then: "Ready" },
2962
+ { case: { $eq: ["$status", "open"] }, then: "Open" },
2896
2963
  { case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
2897
2964
  {
2898
2965
  case: { $eq: ["$status", "completed"] },
2899
2966
  then: "Completed"
2967
+ },
2968
+ {
2969
+ case: { $eq: ["$status", "closed"] },
2970
+ then: "Closed"
2900
2971
  }
2901
2972
  ],
2902
2973
  default: "$status"
@@ -2961,11 +3032,15 @@ function useAreaChecklistRepo() {
2961
3032
  status: {
2962
3033
  $switch: {
2963
3034
  branches: [
2964
- { case: { $eq: ["$status", "ready"] }, then: "Ready" },
3035
+ { case: { $eq: ["$status", "open"] }, then: "Open" },
2965
3036
  { case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
2966
3037
  {
2967
3038
  case: { $eq: ["$status", "completed"] },
2968
3039
  then: "Completed"
3040
+ },
3041
+ {
3042
+ case: { $eq: ["$status", "closed"] },
3043
+ then: "Closed"
2969
3044
  }
2970
3045
  ],
2971
3046
  default: "$status"
@@ -3025,12 +3100,16 @@ function useAreaChecklistRepo() {
3025
3100
  $switch: {
3026
3101
  branches: [
3027
3102
  {
3028
- case: { $eq: ["$checklist.units.status", "ready"] },
3029
- then: "Ready"
3103
+ case: { $eq: ["$checklist.units.status", "open"] },
3104
+ then: "Open"
3030
3105
  },
3031
3106
  {
3032
3107
  case: { $eq: ["$checklist.units.status", "completed"] },
3033
3108
  then: "Completed"
3109
+ },
3110
+ {
3111
+ case: { $eq: ["$checklist.units.status", "closed"] },
3112
+ then: "Closed"
3034
3113
  }
3035
3114
  ],
3036
3115
  default: "$checklist.units.status"
@@ -3131,6 +3210,38 @@ function useAreaChecklistRepo() {
3131
3210
  preserveNullAndEmptyArrays: false
3132
3211
  }
3133
3212
  },
3213
+ {
3214
+ $addFields: {
3215
+ isCompleted: { $ne: ["$checklist.units.completedBy", ""] }
3216
+ }
3217
+ },
3218
+ {
3219
+ $lookup: {
3220
+ from: "users",
3221
+ let: { completedById: "$checklist.units.completedBy" },
3222
+ pipeline: [
3223
+ {
3224
+ $match: {
3225
+ $expr: {
3226
+ $and: [
3227
+ { $ne: ["$$completedById", ""] },
3228
+ { $eq: ["$_id", "$$completedById"] }
3229
+ ]
3230
+ }
3231
+ }
3232
+ },
3233
+ { $project: { name: 1 } }
3234
+ ],
3235
+ as: "completedBy"
3236
+ }
3237
+ },
3238
+ {
3239
+ $unwind: {
3240
+ path: "$completedBy",
3241
+ preserveNullAndEmptyArrays: true
3242
+ }
3243
+ },
3244
+ { $sort: { set: 1, isCompleted: -1, "checklist.units.timestamp": 1 } },
3134
3245
  {
3135
3246
  $project: {
3136
3247
  _id: 0,
@@ -3145,25 +3256,30 @@ function useAreaChecklistRepo() {
3145
3256
  $switch: {
3146
3257
  branches: [
3147
3258
  {
3148
- case: { $eq: ["$checklist.units.status", "ready"] },
3149
- then: "Ready"
3259
+ case: { $eq: ["$checklist.units.status", "open"] },
3260
+ then: "Open"
3150
3261
  },
3151
3262
  {
3152
3263
  case: { $eq: ["$checklist.units.status", "completed"] },
3153
3264
  then: "Completed"
3265
+ },
3266
+ {
3267
+ case: { $eq: ["$checklist.units.status", "closed"] },
3268
+ then: "Closed"
3154
3269
  }
3155
3270
  ],
3156
3271
  default: "$checklist.units.status"
3157
3272
  }
3158
- }
3273
+ },
3274
+ completedByName: "$completedBy.name"
3159
3275
  }
3160
3276
  },
3161
- { $sort: { set: 1, name: 1 } },
3162
3277
  {
3163
3278
  $group: {
3164
3279
  _id: "$set",
3165
3280
  remarks: { $first: "$remarks" },
3166
3281
  attachment: { $first: "$attachment" },
3282
+ completedByName: { $first: "$completedByName" },
3167
3283
  units: {
3168
3284
  $push: {
3169
3285
  unit: "$unit",
@@ -3171,7 +3287,8 @@ function useAreaChecklistRepo() {
3171
3287
  approve: "$approve",
3172
3288
  reject: "$reject",
3173
3289
  status: "$status",
3174
- remarks: "$remarks"
3290
+ remarks: "$remarks",
3291
+ completedByName: "$completedByName"
3175
3292
  }
3176
3293
  }
3177
3294
  }
@@ -3182,6 +3299,7 @@ function useAreaChecklistRepo() {
3182
3299
  set: "$_id",
3183
3300
  remarks: "$remarks",
3184
3301
  attachment: "$attachment",
3302
+ completedByName: 1,
3185
3303
  units: 1
3186
3304
  }
3187
3305
  },
@@ -3280,7 +3398,7 @@ function useAreaChecklistRepo() {
3280
3398
  } else if (value.reject === true) {
3281
3399
  updateValue["checklist.$[checklist].units.$[unit].approve"] = false;
3282
3400
  updateValue["checklist.$[checklist].units.$[unit].reject"] = true;
3283
- updateValue["checklist.$[checklist].units.$[unit].status"] = "ready";
3401
+ updateValue["checklist.$[checklist].units.$[unit].status"] = "open";
3284
3402
  }
3285
3403
  if (value.remarks) {
3286
3404
  updateValue["checklist.$[checklist].units.$[unit].remarks"] = value.remarks;
@@ -3406,6 +3524,42 @@ function useAreaChecklistRepo() {
3406
3524
  return 0;
3407
3525
  }
3408
3526
  }
3527
+ async function closeExpiredAreaChecklists() {
3528
+ try {
3529
+ const expiryDate = new Date(Date.now() - 24 * 60 * 60 * 1e3);
3530
+ const result = await collection.updateMany(
3531
+ {
3532
+ status: { $in: ["open", "ongoing", "completed"] },
3533
+ createdAt: { $lte: expiryDate }
3534
+ },
3535
+ {
3536
+ $set: {
3537
+ status: "closed",
3538
+ updatedAt: /* @__PURE__ */ new Date(),
3539
+ "checklist.$[].units.$[unit].status": "closed"
3540
+ }
3541
+ },
3542
+ {
3543
+ arrayFilters: [{ "unit.status": { $in: ["open", "completed"] } }]
3544
+ }
3545
+ );
3546
+ if (result.modifiedCount > 0) {
3547
+ delNamespace().catch((err) => {
3548
+ import_node_server_utils17.logger.error(
3549
+ "Failed to invalidate cache after closing expired area checklists",
3550
+ err
3551
+ );
3552
+ });
3553
+ import_node_server_utils17.logger.info(
3554
+ `Closed ${result.modifiedCount} expired area checklists and their units`
3555
+ );
3556
+ }
3557
+ return result.modifiedCount;
3558
+ } catch (error) {
3559
+ import_node_server_utils17.logger.error("Failed to close expired area checklists", error);
3560
+ throw error;
3561
+ }
3562
+ }
3409
3563
  return {
3410
3564
  createIndex,
3411
3565
  createTextIndex,
@@ -3419,7 +3573,8 @@ function useAreaChecklistRepo() {
3419
3573
  updateAreaChecklist,
3420
3574
  updateAreaChecklistStatus,
3421
3575
  updateAreaChecklistUnits,
3422
- getMaxSetNumberForArea
3576
+ getMaxSetNumberForArea,
3577
+ closeExpiredAreaChecklists
3423
3578
  };
3424
3579
  }
3425
3580
 
@@ -3515,12 +3670,12 @@ function useAreaChecklistService() {
3515
3670
  },
3516
3671
  session
3517
3672
  );
3518
- let areaStatus = "ready";
3673
+ let areaStatus = "open";
3519
3674
  if (allUnitsResult && allUnitsResult.items && allUnitsResult.items.length > 0) {
3520
3675
  const sets = allUnitsResult.items;
3521
3676
  const allUnits = sets.flatMap((set2) => set2.units || []);
3522
- const readyCount = allUnits.filter(
3523
- (unit) => unit.status === "Ready"
3677
+ const openCount = allUnits.filter(
3678
+ (unit) => unit.status === "Open"
3524
3679
  ).length;
3525
3680
  const completedCount = allUnits.filter(
3526
3681
  (unit) => unit.status === "Completed"
@@ -3528,8 +3683,8 @@ function useAreaChecklistService() {
3528
3683
  const totalCount = allUnits.length;
3529
3684
  if (completedCount === totalCount) {
3530
3685
  areaStatus = "completed";
3531
- } else if (readyCount === totalCount) {
3532
- areaStatus = "ready";
3686
+ } else if (openCount === totalCount) {
3687
+ areaStatus = "open";
3533
3688
  } else {
3534
3689
  areaStatus = "ongoing";
3535
3690
  }
@@ -3548,18 +3703,18 @@ function useAreaChecklistService() {
3548
3703
  );
3549
3704
  if (allAreasResult && allAreasResult.items && allAreasResult.items.length > 0) {
3550
3705
  const areas = allAreasResult.items;
3551
- const readyAreasCount = areas.filter(
3552
- (area) => area.status === "Ready"
3706
+ const openAreasCount = areas.filter(
3707
+ (area) => area.status === "Open"
3553
3708
  ).length;
3554
3709
  const completedAreasCount = areas.filter(
3555
3710
  (area) => area.status === "Completed"
3556
3711
  ).length;
3557
3712
  const totalAreasCount = areas.length;
3558
- let parentStatus = "ready";
3713
+ let parentStatus = "open";
3559
3714
  if (completedAreasCount === totalAreasCount) {
3560
3715
  parentStatus = "completed";
3561
- } else if (readyAreasCount === totalAreasCount) {
3562
- parentStatus = "ready";
3716
+ } else if (openAreasCount === totalAreasCount) {
3717
+ parentStatus = "open";
3563
3718
  } else {
3564
3719
  parentStatus = "ongoing";
3565
3720
  }
@@ -3570,7 +3725,7 @@ function useAreaChecklistService() {
3570
3725
  );
3571
3726
  } else {
3572
3727
  import_node_server_utils18.logger.info(
3573
- "No area checklists found, keeping parent status as ready"
3728
+ "No area checklists found, keeping parent status as open"
3574
3729
  );
3575
3730
  }
3576
3731
  }
@@ -3591,7 +3746,223 @@ function useAreaChecklistService() {
3591
3746
 
3592
3747
  // src/controllers/hygiene-area-checklist.controller.ts
3593
3748
  var import_joi9 = __toESM(require("joi"));
3749
+ var import_node_server_utils20 = require("@7365admin1/node-server-utils");
3750
+
3751
+ // src/services/hygiene-checklist-pdf.service.ts
3752
+ var import_puppeteer = require("puppeteer");
3594
3753
  var import_node_server_utils19 = require("@7365admin1/node-server-utils");
3754
+ var import_mongodb10 = require("mongodb");
3755
+ function escapeHtml(text) {
3756
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
3757
+ }
3758
+ function buildChecklistHtml(areaChecklists) {
3759
+ const areaSections = areaChecklists.map((area) => {
3760
+ const sortedChecklist = [...area.checklist || []].sort(
3761
+ (a, b) => a.set - b.set
3762
+ );
3763
+ const setRows = sortedChecklist.map((setItem) => {
3764
+ const unitRows = (setItem.units || []).map(
3765
+ (unit) => `
3766
+ <tr>
3767
+ <td class="unit-name">${escapeHtml(unit.name || "")}</td>
3768
+ <td class="icon-cell">${unit.reject ? '<span class="reject-icon">&#10007;</span>' : ""}</td>
3769
+ <td class="icon-cell">${unit.approve ? '<span class="approve-icon">&#10003;</span>' : ""}</td>
3770
+ </tr>`
3771
+ ).join("");
3772
+ return `
3773
+ <tr class="set-header-row">
3774
+ <td colspan="3">Set ${setItem.set}</td>
3775
+ </tr>
3776
+ ${unitRows}`;
3777
+ }).join("");
3778
+ return `
3779
+ <div class="area-section">
3780
+ <div class="area-header">
3781
+ <span class="area-name">${escapeHtml(area.name || "")}</span>
3782
+ <span class="area-type">${escapeHtml(area.type || "")}</span>
3783
+ </div>
3784
+ <table class="checklist-table">
3785
+ <thead>
3786
+ <tr>
3787
+ <th class="col-unit">Unit</th>
3788
+ <th class="col-icon">&#10007;</th>
3789
+ <th class="col-icon">&#10003;</th>
3790
+ </tr>
3791
+ </thead>
3792
+ <tbody>
3793
+ ${setRows}
3794
+ </tbody>
3795
+ </table>
3796
+ </div>`;
3797
+ }).join("");
3798
+ return `<!DOCTYPE html>
3799
+ <html lang="en">
3800
+ <head>
3801
+ <meta charset="UTF-8">
3802
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3803
+ <title>Checklist</title>
3804
+ <style>
3805
+ * {
3806
+ margin: 0;
3807
+ padding: 0;
3808
+ box-sizing: border-box;
3809
+ }
3810
+ body {
3811
+ font-family: Arial, Helvetica, sans-serif;
3812
+ background: #ffffff;
3813
+ padding: 30px 35px;
3814
+ color: #1a1a1a;
3815
+ font-size: 13px;
3816
+ }
3817
+ .page-header {
3818
+ display: flex;
3819
+ align-items: center;
3820
+ justify-content: flex-start;
3821
+ background: #1a3a6b;
3822
+ margin-bottom: 24px;
3823
+ padding: 12px 16px;
3824
+ border-radius: 4px;
3825
+ }
3826
+ .page-logo {
3827
+ height: 40px;
3828
+ width: auto;
3829
+ object-fit: contain;
3830
+ }
3831
+ .area-section {
3832
+ margin-bottom: 22px;
3833
+ border: 1px solid #dce1e7;
3834
+ border-radius: 4px;
3835
+ overflow: hidden;
3836
+ page-break-inside: avoid;
3837
+ }
3838
+ .area-header {
3839
+ display: flex;
3840
+ align-items: center;
3841
+ justify-content: space-between;
3842
+ background: #2c3e50;
3843
+ color: #ffffff;
3844
+ padding: 9px 12px;
3845
+ }
3846
+ .area-name {
3847
+ font-size: 14px;
3848
+ font-weight: 600;
3849
+ }
3850
+ .area-type {
3851
+ font-size: 11px;
3852
+ text-transform: capitalize;
3853
+ background: rgba(255,255,255,0.2);
3854
+ padding: 2px 8px;
3855
+ border-radius: 10px;
3856
+ }
3857
+ .checklist-table {
3858
+ width: 100%;
3859
+ border-collapse: collapse;
3860
+ }
3861
+ .checklist-table thead tr th {
3862
+ background: #34495e;
3863
+ color: #ffffff;
3864
+ padding: 7px 10px;
3865
+ text-align: left;
3866
+ font-size: 12px;
3867
+ font-weight: 600;
3868
+ letter-spacing: 0.3px;
3869
+ }
3870
+ .checklist-table thead tr th.col-icon {
3871
+ text-align: center;
3872
+ width: 52px;
3873
+ }
3874
+ .checklist-table thead tr th.col-unit {
3875
+ width: auto;
3876
+ }
3877
+ .set-header-row td {
3878
+ background: #ecf0f1;
3879
+ color: #555;
3880
+ font-weight: 700;
3881
+ font-size: 12px;
3882
+ padding: 5px 10px;
3883
+ border-bottom: 1px solid #dce1e7;
3884
+ text-transform: uppercase;
3885
+ letter-spacing: 0.4px;
3886
+ }
3887
+ .checklist-table tbody tr td {
3888
+ padding: 7px 10px;
3889
+ border-bottom: 1px solid #f0f2f4;
3890
+ font-size: 13px;
3891
+ }
3892
+ .checklist-table tbody tr:last-child td {
3893
+ border-bottom: none;
3894
+ }
3895
+ .icon-cell {
3896
+ text-align: center;
3897
+ width: 52px;
3898
+ }
3899
+ .approve-icon {
3900
+ color: #27ae60;
3901
+ font-size: 16px;
3902
+ font-weight: bold;
3903
+ }
3904
+ .reject-icon {
3905
+ color: #e74c3c;
3906
+ font-size: 16px;
3907
+ font-weight: bold;
3908
+ }
3909
+ </style>
3910
+ </head>
3911
+ <body>
3912
+ <div class="page-header">
3913
+ <img class="page-logo" src="https://seven365-storage.sgp1.cdn.digitaloceanspaces.com/seven365-public/images/seven365-logo.png" alt="Seven365 Logo" />
3914
+ </div>
3915
+ ${areaSections}
3916
+ </body>
3917
+ </html>`;
3918
+ }
3919
+ function useChecklistPdfService() {
3920
+ async function generateChecklistPdf(scheduleId) {
3921
+ const db = import_node_server_utils19.useAtlas.getDb();
3922
+ if (!db) {
3923
+ throw new import_node_server_utils19.InternalServerError("Unable to connect to server.");
3924
+ }
3925
+ const collection = db.collection("site.cleaning.schedule.areas");
3926
+ let scheduleObjectId;
3927
+ try {
3928
+ scheduleObjectId = new import_mongodb10.ObjectId(scheduleId);
3929
+ } catch {
3930
+ throw new import_node_server_utils19.InternalServerError("Invalid schedule ID format.");
3931
+ }
3932
+ const areaChecklists = await collection.find({ schedule: scheduleObjectId }).sort({ createdAt: 1, name: 1 }).toArray();
3933
+ const html = buildChecklistHtml(areaChecklists);
3934
+ const browser = await (0, import_puppeteer.launch)({
3935
+ headless: true,
3936
+ executablePath: process.env.CHROME_BINARY,
3937
+ args: ["--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage"]
3938
+ });
3939
+ try {
3940
+ const page = await browser.newPage();
3941
+ await page.setViewport({ width: 794, height: 1123 });
3942
+ await page.setContent(html, {
3943
+ waitUntil: ["load", "networkidle0"]
3944
+ });
3945
+ const pdfBuffer = await page.pdf({
3946
+ format: "A4",
3947
+ printBackground: true,
3948
+ margin: {
3949
+ top: "15mm",
3950
+ right: "15mm",
3951
+ bottom: "15mm",
3952
+ left: "15mm"
3953
+ }
3954
+ });
3955
+ return pdfBuffer;
3956
+ } finally {
3957
+ await browser.close();
3958
+ }
3959
+ }
3960
+ return {
3961
+ generateChecklistPdf
3962
+ };
3963
+ }
3964
+
3965
+ // src/controllers/hygiene-area-checklist.controller.ts
3595
3966
  function useAreaChecklistController() {
3596
3967
  const {
3597
3968
  getAllAreaChecklist: _getAllAreaChecklist,
@@ -3603,6 +3974,7 @@ function useAreaChecklistController() {
3603
3974
  createAreaChecklist: _createAreaChecklist,
3604
3975
  updateAreaChecklistUnits: _updateAreaChecklistUnits
3605
3976
  } = useAreaChecklistService();
3977
+ const { generateChecklistPdf: _generateChecklistPdf } = useChecklistPdfService();
3606
3978
  async function createAreaChecklist(req, res, next) {
3607
3979
  const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
3608
3980
  (acc, [key, value2]) => ({ ...acc, [key]: value2 }),
@@ -3621,8 +3993,8 @@ function useAreaChecklistController() {
3621
3993
  });
3622
3994
  const { error, value } = validation.validate(payload);
3623
3995
  if (error) {
3624
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3625
- next(new import_node_server_utils19.BadRequestError(error.message));
3996
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
3997
+ next(new import_node_server_utils20.BadRequestError(error.message));
3626
3998
  return;
3627
3999
  }
3628
4000
  try {
@@ -3630,7 +4002,7 @@ function useAreaChecklistController() {
3630
4002
  res.status(201).json({ message: "Area checklist generated successfully." });
3631
4003
  return;
3632
4004
  } catch (error2) {
3633
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4005
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
3634
4006
  next(error2);
3635
4007
  return;
3636
4008
  }
@@ -3647,8 +4019,8 @@ function useAreaChecklistController() {
3647
4019
  });
3648
4020
  const { error } = validation.validate(query);
3649
4021
  if (error) {
3650
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3651
- next(new import_node_server_utils19.BadRequestError(error.message));
4022
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
4023
+ next(new import_node_server_utils20.BadRequestError(error.message));
3652
4024
  return;
3653
4025
  }
3654
4026
  const page = parseInt(req.query.page) ?? 1;
@@ -3669,7 +4041,7 @@ function useAreaChecklistController() {
3669
4041
  res.json(data);
3670
4042
  return;
3671
4043
  } catch (error2) {
3672
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4044
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
3673
4045
  next(error2);
3674
4046
  return;
3675
4047
  }
@@ -3687,8 +4059,8 @@ function useAreaChecklistController() {
3687
4059
  });
3688
4060
  const { error } = validation.validate(query);
3689
4061
  if (error) {
3690
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3691
- next(new import_node_server_utils19.BadRequestError(error.message));
4062
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
4063
+ next(new import_node_server_utils20.BadRequestError(error.message));
3692
4064
  return;
3693
4065
  }
3694
4066
  const page = parseInt(req.query.page) ?? 1;
@@ -3711,7 +4083,7 @@ function useAreaChecklistController() {
3711
4083
  res.json(data);
3712
4084
  return;
3713
4085
  } catch (error2) {
3714
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4086
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
3715
4087
  next(error2);
3716
4088
  return;
3717
4089
  }
@@ -3721,8 +4093,8 @@ function useAreaChecklistController() {
3721
4093
  const _id = req.params.id;
3722
4094
  const { error, value } = validation.validate(_id);
3723
4095
  if (error) {
3724
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3725
- next(new import_node_server_utils19.BadRequestError(error.message));
4096
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
4097
+ next(new import_node_server_utils20.BadRequestError(error.message));
3726
4098
  return;
3727
4099
  }
3728
4100
  try {
@@ -3730,7 +4102,7 @@ function useAreaChecklistController() {
3730
4102
  res.json(data);
3731
4103
  return;
3732
4104
  } catch (error2) {
3733
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4105
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
3734
4106
  next(error2);
3735
4107
  return;
3736
4108
  }
@@ -3745,8 +4117,8 @@ function useAreaChecklistController() {
3745
4117
  });
3746
4118
  const { error } = validation.validate(query);
3747
4119
  if (error) {
3748
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3749
- next(new import_node_server_utils19.BadRequestError(error.message));
4120
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
4121
+ next(new import_node_server_utils20.BadRequestError(error.message));
3750
4122
  return;
3751
4123
  }
3752
4124
  const page = parseInt(req.query.page) ?? 1;
@@ -3763,7 +4135,7 @@ function useAreaChecklistController() {
3763
4135
  res.json(data);
3764
4136
  return;
3765
4137
  } catch (error2) {
3766
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4138
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
3767
4139
  next(error2);
3768
4140
  return;
3769
4141
  }
@@ -3802,8 +4174,8 @@ function useAreaChecklistController() {
3802
4174
  });
3803
4175
  const { error } = validation.validate(payload);
3804
4176
  if (error) {
3805
- import_node_server_utils19.logger.log({ level: "error", message: error.message });
3806
- next(new import_node_server_utils19.BadRequestError(error.message));
4177
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
4178
+ next(new import_node_server_utils20.BadRequestError(error.message));
3807
4179
  return;
3808
4180
  }
3809
4181
  try {
@@ -3812,7 +4184,39 @@ function useAreaChecklistController() {
3812
4184
  res.json({ message: "Area checklist updated successfully." });
3813
4185
  return;
3814
4186
  } catch (error2) {
3815
- import_node_server_utils19.logger.log({ level: "error", message: error2.message });
4187
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
4188
+ next(error2);
4189
+ return;
4190
+ }
4191
+ }
4192
+ async function downloadChecklistPdf(req, res, next) {
4193
+ const validation = import_joi9.default.string().hex().required();
4194
+ const schedule = req.params.schedule;
4195
+ const { error, value } = validation.validate(schedule);
4196
+ if (error) {
4197
+ import_node_server_utils20.logger.log({ level: "error", message: error.message });
4198
+ next(new import_node_server_utils20.BadRequestError(error.message));
4199
+ return;
4200
+ }
4201
+ try {
4202
+ const pdfBuffer = await _generateChecklistPdf(value);
4203
+ if (!pdfBuffer || pdfBuffer.length === 0) {
4204
+ throw new import_node_server_utils20.InternalServerError("Generated checklist PDF is empty or invalid.");
4205
+ }
4206
+ const date = /* @__PURE__ */ new Date();
4207
+ const formattedDate = `${String(date.getDate()).padStart(2, "0")}_${String(
4208
+ date.getMonth() + 1
4209
+ ).padStart(2, "0")}_${date.getFullYear()}`;
4210
+ res.setHeader("Content-Type", "application/pdf");
4211
+ res.setHeader(
4212
+ "Content-Disposition",
4213
+ `attachment; filename="CHECKLIST_${formattedDate}.pdf"`
4214
+ );
4215
+ res.setHeader("Content-Length", pdfBuffer.length);
4216
+ res.end(pdfBuffer);
4217
+ return;
4218
+ } catch (error2) {
4219
+ import_node_server_utils20.logger.log({ level: "error", message: error2.message });
3816
4220
  next(error2);
3817
4221
  return;
3818
4222
  }
@@ -3823,14 +4227,15 @@ function useAreaChecklistController() {
3823
4227
  getAreaChecklistHistory,
3824
4228
  getAreaChecklistHistoryDetails,
3825
4229
  getAreaChecklistUnits,
3826
- updateAreaChecklistUnits
4230
+ updateAreaChecklistUnits,
4231
+ downloadChecklistPdf
3827
4232
  };
3828
4233
  }
3829
4234
 
3830
4235
  // src/models/hygiene-supply.model.ts
3831
4236
  var import_joi10 = __toESM(require("joi"));
3832
- var import_mongodb10 = require("mongodb");
3833
- var import_node_server_utils20 = require("@7365admin1/node-server-utils");
4237
+ var import_mongodb11 = require("mongodb");
4238
+ var import_node_server_utils21 = require("@7365admin1/node-server-utils");
3834
4239
  var supplySchema = import_joi10.default.object({
3835
4240
  site: import_joi10.default.string().hex().required(),
3836
4241
  name: import_joi10.default.string().required(),
@@ -3839,14 +4244,14 @@ var supplySchema = import_joi10.default.object({
3839
4244
  function MSupply(value) {
3840
4245
  const { error } = supplySchema.validate(value);
3841
4246
  if (error) {
3842
- import_node_server_utils20.logger.info(`Hygiene Supply Model: ${error.message}`);
3843
- throw new import_node_server_utils20.BadRequestError(error.message);
4247
+ import_node_server_utils21.logger.info(`Hygiene Supply Model: ${error.message}`);
4248
+ throw new import_node_server_utils21.BadRequestError(error.message);
3844
4249
  }
3845
4250
  if (value.site) {
3846
4251
  try {
3847
- value.site = new import_mongodb10.ObjectId(value.site);
4252
+ value.site = new import_mongodb11.ObjectId(value.site);
3848
4253
  } catch (error2) {
3849
- throw new import_node_server_utils20.BadRequestError("Invalid site ID format.");
4254
+ throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
3850
4255
  }
3851
4256
  }
3852
4257
  return {
@@ -3862,21 +4267,21 @@ function MSupply(value) {
3862
4267
  }
3863
4268
 
3864
4269
  // src/repositories/hygiene-supply.repository.ts
3865
- var import_mongodb11 = require("mongodb");
3866
- var import_node_server_utils21 = require("@7365admin1/node-server-utils");
4270
+ var import_mongodb12 = require("mongodb");
4271
+ var import_node_server_utils22 = require("@7365admin1/node-server-utils");
3867
4272
  function useSupplyRepository() {
3868
- const db = import_node_server_utils21.useAtlas.getDb();
4273
+ const db = import_node_server_utils22.useAtlas.getDb();
3869
4274
  if (!db) {
3870
- throw new import_node_server_utils21.InternalServerError("Unable to connect to server.");
4275
+ throw new import_node_server_utils22.InternalServerError("Unable to connect to server.");
3871
4276
  }
3872
4277
  const namespace_collection = "site.supplies";
3873
4278
  const collection = db.collection(namespace_collection);
3874
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils21.useCache)(namespace_collection);
4279
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils22.useCache)(namespace_collection);
3875
4280
  async function createIndex() {
3876
4281
  try {
3877
4282
  await collection.createIndexes([{ key: { site: 1 } }]);
3878
4283
  } catch (error) {
3879
- throw new import_node_server_utils21.InternalServerError(
4284
+ throw new import_node_server_utils22.InternalServerError(
3880
4285
  "Failed to create index on hygiene supply."
3881
4286
  );
3882
4287
  }
@@ -3885,7 +4290,7 @@ function useSupplyRepository() {
3885
4290
  try {
3886
4291
  await collection.createIndex({ name: "text" });
3887
4292
  } catch (error) {
3888
- throw new import_node_server_utils21.InternalServerError(
4293
+ throw new import_node_server_utils22.InternalServerError(
3889
4294
  "Failed to create text index on hygiene supply."
3890
4295
  );
3891
4296
  }
@@ -3897,7 +4302,7 @@ function useSupplyRepository() {
3897
4302
  { unique: true }
3898
4303
  );
3899
4304
  } catch (error) {
3900
- throw new import_node_server_utils21.InternalServerError(
4305
+ throw new import_node_server_utils22.InternalServerError(
3901
4306
  "Failed to create unique index on hygiene supply."
3902
4307
  );
3903
4308
  }
@@ -3907,9 +4312,9 @@ function useSupplyRepository() {
3907
4312
  value = MSupply(value);
3908
4313
  const res = await collection.insertOne(value, { session });
3909
4314
  delNamespace().then(() => {
3910
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4315
+ import_node_server_utils22.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
3911
4316
  }).catch((err) => {
3912
- import_node_server_utils21.logger.error(
4317
+ import_node_server_utils22.logger.error(
3913
4318
  `Failed to clear cache for namespace: ${namespace_collection}`,
3914
4319
  err
3915
4320
  );
@@ -3918,7 +4323,7 @@ function useSupplyRepository() {
3918
4323
  } catch (error) {
3919
4324
  const isDuplicated = error.message.includes("duplicate");
3920
4325
  if (isDuplicated) {
3921
- throw new import_node_server_utils21.BadRequestError("Supply already exists.");
4326
+ throw new import_node_server_utils22.BadRequestError("Supply already exists.");
3922
4327
  }
3923
4328
  throw error;
3924
4329
  }
@@ -3938,20 +4343,20 @@ function useSupplyRepository() {
3938
4343
  limit
3939
4344
  };
3940
4345
  try {
3941
- site = new import_mongodb11.ObjectId(site);
4346
+ site = new import_mongodb12.ObjectId(site);
3942
4347
  query.site = site;
3943
4348
  cacheOptions.site = site.toString();
3944
4349
  } catch (error) {
3945
- throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
4350
+ throw new import_node_server_utils22.BadRequestError("Invalid site ID format.");
3946
4351
  }
3947
4352
  if (search) {
3948
4353
  query.$text = { $search: search };
3949
4354
  cacheOptions.search = search;
3950
4355
  }
3951
- const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, cacheOptions);
4356
+ const cacheKey = (0, import_node_server_utils22.makeCacheKey)(namespace_collection, cacheOptions);
3952
4357
  const cachedData = await getCache(cacheKey);
3953
4358
  if (cachedData) {
3954
- import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
4359
+ import_node_server_utils22.logger.info(`Cache hit for key: ${cacheKey}`);
3955
4360
  return cachedData;
3956
4361
  }
3957
4362
  try {
@@ -3969,11 +4374,11 @@ function useSupplyRepository() {
3969
4374
  { $limit: limit }
3970
4375
  ]).toArray();
3971
4376
  const length = await collection.countDocuments(query);
3972
- const data = (0, import_node_server_utils21.paginate)(items, page, limit, length);
4377
+ const data = (0, import_node_server_utils22.paginate)(items, page, limit, length);
3973
4378
  setCache(cacheKey, data, 15 * 60).then(() => {
3974
- import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
4379
+ import_node_server_utils22.logger.info(`Cache set for key: ${cacheKey}`);
3975
4380
  }).catch((err) => {
3976
- import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4381
+ import_node_server_utils22.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
3977
4382
  });
3978
4383
  return data;
3979
4384
  } catch (error) {
@@ -3982,25 +4387,25 @@ function useSupplyRepository() {
3982
4387
  }
3983
4388
  async function getSupplyById(_id, session) {
3984
4389
  try {
3985
- _id = new import_mongodb11.ObjectId(_id);
4390
+ _id = new import_mongodb12.ObjectId(_id);
3986
4391
  } catch (error) {
3987
- throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
4392
+ throw new import_node_server_utils22.BadRequestError("Invalid supply ID format.");
3988
4393
  }
3989
4394
  const query = {
3990
4395
  _id,
3991
4396
  status: { $ne: "deleted" }
3992
4397
  };
3993
- const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, {
4398
+ const cacheKey = (0, import_node_server_utils22.makeCacheKey)(namespace_collection, {
3994
4399
  _id: _id.toString()
3995
4400
  });
3996
4401
  if (!session) {
3997
4402
  const cachedData = await getCache(cacheKey);
3998
4403
  if (cachedData) {
3999
- import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
4404
+ import_node_server_utils22.logger.info(`Cache hit for key: ${cacheKey}`);
4000
4405
  return cachedData;
4001
4406
  }
4002
4407
  } else {
4003
- import_node_server_utils21.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
4408
+ import_node_server_utils22.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
4004
4409
  }
4005
4410
  try {
4006
4411
  const data = await collection.aggregate([
@@ -4014,12 +4419,12 @@ function useSupplyRepository() {
4014
4419
  }
4015
4420
  ]).toArray();
4016
4421
  if (!data || data.length === 0) {
4017
- throw new import_node_server_utils21.NotFoundError("Supply not found.");
4422
+ throw new import_node_server_utils22.NotFoundError("Supply not found.");
4018
4423
  }
4019
4424
  setCache(cacheKey, data[0], 15 * 60).then(() => {
4020
- import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
4425
+ import_node_server_utils22.logger.info(`Cache set for key: ${cacheKey}`);
4021
4426
  }).catch((err) => {
4022
- import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4427
+ import_node_server_utils22.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4023
4428
  });
4024
4429
  return data[0];
4025
4430
  } catch (error) {
@@ -4028,9 +4433,9 @@ function useSupplyRepository() {
4028
4433
  }
4029
4434
  async function updateSupply(_id, value, session) {
4030
4435
  try {
4031
- _id = new import_mongodb11.ObjectId(_id);
4436
+ _id = new import_mongodb12.ObjectId(_id);
4032
4437
  } catch (error) {
4033
- throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
4438
+ throw new import_node_server_utils22.BadRequestError("Invalid supply ID format.");
4034
4439
  }
4035
4440
  try {
4036
4441
  const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
@@ -4040,12 +4445,12 @@ function useSupplyRepository() {
4040
4445
  { session }
4041
4446
  );
4042
4447
  if (res.modifiedCount === 0) {
4043
- throw new import_node_server_utils21.InternalServerError("Unable to update cleaning supply.");
4448
+ throw new import_node_server_utils22.InternalServerError("Unable to update cleaning supply.");
4044
4449
  }
4045
4450
  delNamespace().then(() => {
4046
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4451
+ import_node_server_utils22.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4047
4452
  }).catch((err) => {
4048
- import_node_server_utils21.logger.error(
4453
+ import_node_server_utils22.logger.error(
4049
4454
  `Failed to clear cache for namespace: ${namespace_collection}`,
4050
4455
  err
4051
4456
  );
@@ -4054,16 +4459,16 @@ function useSupplyRepository() {
4054
4459
  } catch (error) {
4055
4460
  const isDuplicated = error.message.includes("duplicate");
4056
4461
  if (isDuplicated) {
4057
- throw new import_node_server_utils21.BadRequestError("Supply already exists.");
4462
+ throw new import_node_server_utils22.BadRequestError("Supply already exists.");
4058
4463
  }
4059
4464
  throw error;
4060
4465
  }
4061
4466
  }
4062
4467
  async function deleteSupply(_id, session) {
4063
4468
  try {
4064
- _id = new import_mongodb11.ObjectId(_id);
4469
+ _id = new import_mongodb12.ObjectId(_id);
4065
4470
  } catch (error) {
4066
- throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
4471
+ throw new import_node_server_utils22.BadRequestError("Invalid supply ID format.");
4067
4472
  }
4068
4473
  try {
4069
4474
  const updateValue = {
@@ -4077,12 +4482,12 @@ function useSupplyRepository() {
4077
4482
  { session }
4078
4483
  );
4079
4484
  if (res.modifiedCount === 0) {
4080
- throw new import_node_server_utils21.InternalServerError("Unable to delete supply.");
4485
+ throw new import_node_server_utils22.InternalServerError("Unable to delete supply.");
4081
4486
  }
4082
4487
  delNamespace().then(() => {
4083
- import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4488
+ import_node_server_utils22.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4084
4489
  }).catch((err) => {
4085
- import_node_server_utils21.logger.error(
4490
+ import_node_server_utils22.logger.error(
4086
4491
  `Failed to clear cache for namespace: ${namespace_collection}`,
4087
4492
  err
4088
4493
  );
@@ -4106,7 +4511,7 @@ function useSupplyRepository() {
4106
4511
 
4107
4512
  // src/controllers/hygiene-supply.controller.ts
4108
4513
  var import_joi11 = __toESM(require("joi"));
4109
- var import_node_server_utils22 = require("@7365admin1/node-server-utils");
4514
+ var import_node_server_utils23 = require("@7365admin1/node-server-utils");
4110
4515
  function useSupplyController() {
4111
4516
  const {
4112
4517
  createSupply: _createSupply,
@@ -4119,8 +4524,8 @@ function useSupplyController() {
4119
4524
  const payload = { ...req.body, ...req.params };
4120
4525
  const { error } = supplySchema.validate(payload);
4121
4526
  if (error) {
4122
- import_node_server_utils22.logger.log({ level: "error", message: error.message });
4123
- next(new import_node_server_utils22.BadRequestError(error.message));
4527
+ import_node_server_utils23.logger.log({ level: "error", message: error.message });
4528
+ next(new import_node_server_utils23.BadRequestError(error.message));
4124
4529
  return;
4125
4530
  }
4126
4531
  try {
@@ -4128,7 +4533,7 @@ function useSupplyController() {
4128
4533
  res.status(201).json({ message: "Supply created successfully.", id });
4129
4534
  return;
4130
4535
  } catch (error2) {
4131
- import_node_server_utils22.logger.log({ level: "error", message: error2.message });
4536
+ import_node_server_utils23.logger.log({ level: "error", message: error2.message });
4132
4537
  next(error2);
4133
4538
  return;
4134
4539
  }
@@ -4143,8 +4548,8 @@ function useSupplyController() {
4143
4548
  });
4144
4549
  const { error } = validation.validate(query);
4145
4550
  if (error) {
4146
- import_node_server_utils22.logger.log({ level: "error", message: error.message });
4147
- next(new import_node_server_utils22.BadRequestError(error.message));
4551
+ import_node_server_utils23.logger.log({ level: "error", message: error.message });
4552
+ next(new import_node_server_utils23.BadRequestError(error.message));
4148
4553
  return;
4149
4554
  }
4150
4555
  const page = parseInt(req.query.page) ?? 1;
@@ -4161,7 +4566,7 @@ function useSupplyController() {
4161
4566
  res.json(data);
4162
4567
  return;
4163
4568
  } catch (error2) {
4164
- import_node_server_utils22.logger.log({ level: "error", message: error2.message });
4569
+ import_node_server_utils23.logger.log({ level: "error", message: error2.message });
4165
4570
  next(error2);
4166
4571
  return;
4167
4572
  }
@@ -4171,8 +4576,8 @@ function useSupplyController() {
4171
4576
  const _id = req.params.id;
4172
4577
  const { error, value } = validation.validate(_id);
4173
4578
  if (error) {
4174
- import_node_server_utils22.logger.log({ level: "error", message: error.message });
4175
- next(new import_node_server_utils22.BadRequestError(error.message));
4579
+ import_node_server_utils23.logger.log({ level: "error", message: error.message });
4580
+ next(new import_node_server_utils23.BadRequestError(error.message));
4176
4581
  return;
4177
4582
  }
4178
4583
  try {
@@ -4180,7 +4585,7 @@ function useSupplyController() {
4180
4585
  res.json(data);
4181
4586
  return;
4182
4587
  } catch (error2) {
4183
- import_node_server_utils22.logger.log({ level: "error", message: error2.message });
4588
+ import_node_server_utils23.logger.log({ level: "error", message: error2.message });
4184
4589
  next(error2);
4185
4590
  return;
4186
4591
  }
@@ -4195,8 +4600,8 @@ function useSupplyController() {
4195
4600
  });
4196
4601
  const { error } = validation.validate(payload);
4197
4602
  if (error) {
4198
- import_node_server_utils22.logger.log({ level: "error", message: error.message });
4199
- next(new import_node_server_utils22.BadRequestError(error.message));
4603
+ import_node_server_utils23.logger.log({ level: "error", message: error.message });
4604
+ next(new import_node_server_utils23.BadRequestError(error.message));
4200
4605
  return;
4201
4606
  }
4202
4607
  try {
@@ -4205,7 +4610,7 @@ function useSupplyController() {
4205
4610
  res.json({ message: "Supply updated successfully." });
4206
4611
  return;
4207
4612
  } catch (error2) {
4208
- import_node_server_utils22.logger.log({ level: "error", message: error2.message });
4613
+ import_node_server_utils23.logger.log({ level: "error", message: error2.message });
4209
4614
  next(error2);
4210
4615
  return;
4211
4616
  }
@@ -4217,8 +4622,8 @@ function useSupplyController() {
4217
4622
  });
4218
4623
  const { error, value } = validation.validate({ id });
4219
4624
  if (error) {
4220
- import_node_server_utils22.logger.log({ level: "error", message: error.message });
4221
- next(new import_node_server_utils22.BadRequestError(error.message));
4625
+ import_node_server_utils23.logger.log({ level: "error", message: error.message });
4626
+ next(new import_node_server_utils23.BadRequestError(error.message));
4222
4627
  return;
4223
4628
  }
4224
4629
  try {
@@ -4226,7 +4631,7 @@ function useSupplyController() {
4226
4631
  res.json({ message: "Supply deleted successfully." });
4227
4632
  return;
4228
4633
  } catch (error2) {
4229
- import_node_server_utils22.logger.log({ level: "error", message: error2.message });
4634
+ import_node_server_utils23.logger.log({ level: "error", message: error2.message });
4230
4635
  next(error2);
4231
4636
  return;
4232
4637
  }
@@ -4242,8 +4647,8 @@ function useSupplyController() {
4242
4647
 
4243
4648
  // src/models/hygiene-stock.model.ts
4244
4649
  var import_joi12 = __toESM(require("joi"));
4245
- var import_mongodb12 = require("mongodb");
4246
- var import_node_server_utils23 = require("@7365admin1/node-server-utils");
4650
+ var import_mongodb13 = require("mongodb");
4651
+ var import_node_server_utils24 = require("@7365admin1/node-server-utils");
4247
4652
  var stockSchema = import_joi12.default.object({
4248
4653
  site: import_joi12.default.string().hex().required(),
4249
4654
  supply: import_joi12.default.string().hex().required(),
@@ -4255,21 +4660,21 @@ var stockSchema = import_joi12.default.object({
4255
4660
  function MStock(value) {
4256
4661
  const { error } = stockSchema.validate(value);
4257
4662
  if (error) {
4258
- import_node_server_utils23.logger.info(`Hygiene Stock Model: ${error.message}`);
4259
- throw new import_node_server_utils23.BadRequestError(error.message);
4663
+ import_node_server_utils24.logger.info(`Hygiene Stock Model: ${error.message}`);
4664
+ throw new import_node_server_utils24.BadRequestError(error.message);
4260
4665
  }
4261
4666
  if (value.site) {
4262
4667
  try {
4263
- value.site = new import_mongodb12.ObjectId(value.site);
4668
+ value.site = new import_mongodb13.ObjectId(value.site);
4264
4669
  } catch (error2) {
4265
- throw new import_node_server_utils23.BadRequestError("Invalid site ID format.");
4670
+ throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
4266
4671
  }
4267
4672
  }
4268
4673
  if (value.supply) {
4269
4674
  try {
4270
- value.supply = new import_mongodb12.ObjectId(value.supply);
4675
+ value.supply = new import_mongodb13.ObjectId(value.supply);
4271
4676
  } catch (error2) {
4272
- throw new import_node_server_utils23.BadRequestError("Invalid supply ID format.");
4677
+ throw new import_node_server_utils24.BadRequestError("Invalid supply ID format.");
4273
4678
  }
4274
4679
  }
4275
4680
  return {
@@ -4287,18 +4692,18 @@ function MStock(value) {
4287
4692
  }
4288
4693
 
4289
4694
  // src/repositories/hygiene-stock.repository.ts
4290
- var import_mongodb13 = require("mongodb");
4291
- var import_node_server_utils24 = require("@7365admin1/node-server-utils");
4695
+ var import_mongodb14 = require("mongodb");
4696
+ var import_node_server_utils25 = require("@7365admin1/node-server-utils");
4292
4697
  function useStockRepository() {
4293
- const db = import_node_server_utils24.useAtlas.getDb();
4698
+ const db = import_node_server_utils25.useAtlas.getDb();
4294
4699
  if (!db) {
4295
- throw new import_node_server_utils24.InternalServerError("Unable to connect to server.");
4700
+ throw new import_node_server_utils25.InternalServerError("Unable to connect to server.");
4296
4701
  }
4297
4702
  const namespace_collection = "site.supply.stocks";
4298
4703
  const supply_collection = "site.supplies";
4299
4704
  const collection = db.collection(namespace_collection);
4300
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils24.useCache)(namespace_collection);
4301
- const { delNamespace: delSupplyNamespace } = (0, import_node_server_utils24.useCache)(supply_collection);
4705
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils25.useCache)(namespace_collection);
4706
+ const { delNamespace: delSupplyNamespace } = (0, import_node_server_utils25.useCache)(supply_collection);
4302
4707
  async function createIndex() {
4303
4708
  try {
4304
4709
  await collection.createIndexes([
@@ -4308,7 +4713,7 @@ function useStockRepository() {
4308
4713
  { key: { status: 1 } }
4309
4714
  ]);
4310
4715
  } catch (error) {
4311
- throw new import_node_server_utils24.InternalServerError("Failed to create index on hygiene stock.");
4716
+ throw new import_node_server_utils25.InternalServerError("Failed to create index on hygiene stock.");
4312
4717
  }
4313
4718
  }
4314
4719
  async function createStock(value, session) {
@@ -4316,17 +4721,17 @@ function useStockRepository() {
4316
4721
  value = MStock(value);
4317
4722
  const res = await collection.insertOne(value, { session });
4318
4723
  delNamespace().then(() => {
4319
- import_node_server_utils24.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4724
+ import_node_server_utils25.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4320
4725
  }).catch((err) => {
4321
- import_node_server_utils24.logger.error(
4726
+ import_node_server_utils25.logger.error(
4322
4727
  `Failed to clear cache for namespace: ${namespace_collection}`,
4323
4728
  err
4324
4729
  );
4325
4730
  });
4326
4731
  delSupplyNamespace().then(() => {
4327
- import_node_server_utils24.logger.info(`Cache cleared for namespace: ${supply_collection}`);
4732
+ import_node_server_utils25.logger.info(`Cache cleared for namespace: ${supply_collection}`);
4328
4733
  }).catch((err) => {
4329
- import_node_server_utils24.logger.error(
4734
+ import_node_server_utils25.logger.error(
4330
4735
  `Failed to clear cache for namespace: ${supply_collection}`,
4331
4736
  err
4332
4737
  );
@@ -4352,27 +4757,27 @@ function useStockRepository() {
4352
4757
  limit
4353
4758
  };
4354
4759
  try {
4355
- site = new import_mongodb13.ObjectId(site);
4760
+ site = new import_mongodb14.ObjectId(site);
4356
4761
  query.site = site;
4357
4762
  cacheOptions.site = site.toString();
4358
4763
  } catch (error) {
4359
- throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
4764
+ throw new import_node_server_utils25.BadRequestError("Invalid site ID format.");
4360
4765
  }
4361
4766
  try {
4362
- supply = new import_mongodb13.ObjectId(supply);
4767
+ supply = new import_mongodb14.ObjectId(supply);
4363
4768
  query.supply = supply;
4364
4769
  cacheOptions.supply = supply.toString();
4365
4770
  } catch (error) {
4366
- throw new import_node_server_utils24.BadRequestError("Invalid supply ID format.");
4771
+ throw new import_node_server_utils25.BadRequestError("Invalid supply ID format.");
4367
4772
  }
4368
4773
  if (search) {
4369
4774
  query.$text = { $search: search };
4370
4775
  cacheOptions.search = search;
4371
4776
  }
4372
- const cacheKey = (0, import_node_server_utils24.makeCacheKey)(namespace_collection, cacheOptions);
4777
+ const cacheKey = (0, import_node_server_utils25.makeCacheKey)(namespace_collection, cacheOptions);
4373
4778
  const cachedData = await getCache(cacheKey);
4374
4779
  if (cachedData) {
4375
- import_node_server_utils24.logger.info(`Cache hit for key: ${cacheKey}`);
4780
+ import_node_server_utils25.logger.info(`Cache hit for key: ${cacheKey}`);
4376
4781
  return cachedData;
4377
4782
  }
4378
4783
  try {
@@ -4391,11 +4796,11 @@ function useStockRepository() {
4391
4796
  { $limit: limit }
4392
4797
  ]).toArray();
4393
4798
  const length = await collection.countDocuments(query);
4394
- const data = (0, import_node_server_utils24.paginate)(items, page, limit, length);
4799
+ const data = (0, import_node_server_utils25.paginate)(items, page, limit, length);
4395
4800
  setCache(cacheKey, data, 15 * 60).then(() => {
4396
- import_node_server_utils24.logger.info(`Cache set for key: ${cacheKey}`);
4801
+ import_node_server_utils25.logger.info(`Cache set for key: ${cacheKey}`);
4397
4802
  }).catch((err) => {
4398
- import_node_server_utils24.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4803
+ import_node_server_utils25.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4399
4804
  });
4400
4805
  return data;
4401
4806
  } catch (error) {
@@ -4410,14 +4815,14 @@ function useStockRepository() {
4410
4815
  }
4411
4816
 
4412
4817
  // src/services/hygiene-stock.service.ts
4413
- var import_node_server_utils25 = require("@7365admin1/node-server-utils");
4818
+ var import_node_server_utils26 = require("@7365admin1/node-server-utils");
4414
4819
  function useStockService() {
4415
4820
  const { createStock: _createStock } = useStockRepository();
4416
4821
  const { getSupplyById, updateSupply } = useSupplyRepository();
4417
4822
  async function createStock(value, out = false, session) {
4418
4823
  let ownSession = false;
4419
4824
  if (!session) {
4420
- session = import_node_server_utils25.useAtlas.getClient()?.startSession();
4825
+ session = import_node_server_utils26.useAtlas.getClient()?.startSession();
4421
4826
  ownSession = true;
4422
4827
  }
4423
4828
  try {
@@ -4426,11 +4831,11 @@ function useStockService() {
4426
4831
  const { qty, ...stockData } = value;
4427
4832
  const supply = await getSupplyById(value.supply, session);
4428
4833
  if (!supply || supply.qty === void 0) {
4429
- throw new import_node_server_utils25.NotFoundError("Supply not found.");
4834
+ throw new import_node_server_utils26.NotFoundError("Supply not found.");
4430
4835
  }
4431
4836
  const newSupplyQty = out ? supply.qty - qty : supply.qty + qty;
4432
4837
  if (out && newSupplyQty < 0) {
4433
- throw new import_node_server_utils25.BadRequestError(
4838
+ throw new import_node_server_utils26.BadRequestError(
4434
4839
  `Insufficient stock. Available: ${supply.qty}, Requested: ${qty}`
4435
4840
  );
4436
4841
  }
@@ -4461,7 +4866,7 @@ function useStockService() {
4461
4866
 
4462
4867
  // src/controllers/hygiene-stock.controller.ts
4463
4868
  var import_joi13 = __toESM(require("joi"));
4464
- var import_node_server_utils26 = require("@7365admin1/node-server-utils");
4869
+ var import_node_server_utils27 = require("@7365admin1/node-server-utils");
4465
4870
  function useStockController() {
4466
4871
  const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
4467
4872
  const { createStock: _createStock } = useStockService();
@@ -4475,8 +4880,8 @@ function useStockController() {
4475
4880
  });
4476
4881
  const { error } = validation.validate(payload);
4477
4882
  if (error) {
4478
- import_node_server_utils26.logger.log({ level: "error", message: error.message });
4479
- next(new import_node_server_utils26.BadRequestError(error.message));
4883
+ import_node_server_utils27.logger.log({ level: "error", message: error.message });
4884
+ next(new import_node_server_utils27.BadRequestError(error.message));
4480
4885
  return;
4481
4886
  }
4482
4887
  try {
@@ -4484,7 +4889,7 @@ function useStockController() {
4484
4889
  res.status(201).json({ message: "Stock created successfully.", id });
4485
4890
  return;
4486
4891
  } catch (error2) {
4487
- import_node_server_utils26.logger.log({ level: "error", message: error2.message });
4892
+ import_node_server_utils27.logger.log({ level: "error", message: error2.message });
4488
4893
  next(error2);
4489
4894
  return;
4490
4895
  }
@@ -4500,8 +4905,8 @@ function useStockController() {
4500
4905
  });
4501
4906
  const { error } = validation.validate(query);
4502
4907
  if (error) {
4503
- import_node_server_utils26.logger.log({ level: "error", message: error.message });
4504
- next(new import_node_server_utils26.BadRequestError(error.message));
4908
+ import_node_server_utils27.logger.log({ level: "error", message: error.message });
4909
+ next(new import_node_server_utils27.BadRequestError(error.message));
4505
4910
  return;
4506
4911
  }
4507
4912
  const page = parseInt(req.query.page) ?? 1;
@@ -4520,7 +4925,7 @@ function useStockController() {
4520
4925
  res.json(data);
4521
4926
  return;
4522
4927
  } catch (error2) {
4523
- import_node_server_utils26.logger.log({ level: "error", message: error2.message });
4928
+ import_node_server_utils27.logger.log({ level: "error", message: error2.message });
4524
4929
  next(error2);
4525
4930
  return;
4526
4931
  }
@@ -4533,8 +4938,8 @@ function useStockController() {
4533
4938
 
4534
4939
  // src/models/hygiene-checkout-item.model.ts
4535
4940
  var import_joi14 = __toESM(require("joi"));
4536
- var import_mongodb14 = require("mongodb");
4537
- var import_node_server_utils27 = require("@7365admin1/node-server-utils");
4941
+ var import_mongodb15 = require("mongodb");
4942
+ var import_node_server_utils28 = require("@7365admin1/node-server-utils");
4538
4943
  var allowedCheckOutItemStatus = ["pending", "completed"];
4539
4944
  var checkOutItemSchema = import_joi14.default.object({
4540
4945
  site: import_joi14.default.string().hex().required(),
@@ -4548,21 +4953,21 @@ var checkOutItemSchema = import_joi14.default.object({
4548
4953
  function MCheckOutItem(value) {
4549
4954
  const { error } = checkOutItemSchema.validate(value);
4550
4955
  if (error) {
4551
- import_node_server_utils27.logger.info(`Hygiene Check Out Item Model: ${error.message}`);
4552
- throw new import_node_server_utils27.BadRequestError(error.message);
4956
+ import_node_server_utils28.logger.info(`Hygiene Check Out Item Model: ${error.message}`);
4957
+ throw new import_node_server_utils28.BadRequestError(error.message);
4553
4958
  }
4554
4959
  if (value.site) {
4555
4960
  try {
4556
- value.site = new import_mongodb14.ObjectId(value.site);
4961
+ value.site = new import_mongodb15.ObjectId(value.site);
4557
4962
  } catch (error2) {
4558
- throw new import_node_server_utils27.BadRequestError("Invalid site ID format.");
4963
+ throw new import_node_server_utils28.BadRequestError("Invalid site ID format.");
4559
4964
  }
4560
4965
  }
4561
4966
  if (value.supply) {
4562
4967
  try {
4563
- value.supply = new import_mongodb14.ObjectId(value.supply);
4968
+ value.supply = new import_mongodb15.ObjectId(value.supply);
4564
4969
  } catch (error2) {
4565
- throw new import_node_server_utils27.BadRequestError("Invalid supply ID format.");
4970
+ throw new import_node_server_utils28.BadRequestError("Invalid supply ID format.");
4566
4971
  }
4567
4972
  }
4568
4973
  return {
@@ -4581,16 +4986,16 @@ function MCheckOutItem(value) {
4581
4986
  }
4582
4987
 
4583
4988
  // src/repositories/hygiene-checkout-item.repository.ts
4584
- var import_mongodb15 = require("mongodb");
4585
- var import_node_server_utils28 = require("@7365admin1/node-server-utils");
4989
+ var import_mongodb16 = require("mongodb");
4990
+ var import_node_server_utils29 = require("@7365admin1/node-server-utils");
4586
4991
  function useCheckOutItemRepository() {
4587
- const db = import_node_server_utils28.useAtlas.getDb();
4992
+ const db = import_node_server_utils29.useAtlas.getDb();
4588
4993
  if (!db) {
4589
- throw new import_node_server_utils28.InternalServerError("Unable to connect to server.");
4994
+ throw new import_node_server_utils29.InternalServerError("Unable to connect to server.");
4590
4995
  }
4591
4996
  const namespace_collection = "site.supply.checkouts";
4592
4997
  const collection = db.collection(namespace_collection);
4593
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils28.useCache)(namespace_collection);
4998
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils29.useCache)(namespace_collection);
4594
4999
  async function createIndex() {
4595
5000
  try {
4596
5001
  await collection.createIndexes([
@@ -4599,7 +5004,7 @@ function useCheckOutItemRepository() {
4599
5004
  { key: { status: 1 } }
4600
5005
  ]);
4601
5006
  } catch (error) {
4602
- throw new import_node_server_utils28.InternalServerError(
5007
+ throw new import_node_server_utils29.InternalServerError(
4603
5008
  "Failed to create index on hygiene check out item."
4604
5009
  );
4605
5010
  }
@@ -4608,7 +5013,7 @@ function useCheckOutItemRepository() {
4608
5013
  try {
4609
5014
  await collection.createIndex({ supplyName: "text" });
4610
5015
  } catch (error) {
4611
- throw new import_node_server_utils28.InternalServerError(
5016
+ throw new import_node_server_utils29.InternalServerError(
4612
5017
  "Failed to create text index on hygiene supply."
4613
5018
  );
4614
5019
  }
@@ -4618,9 +5023,9 @@ function useCheckOutItemRepository() {
4618
5023
  value = MCheckOutItem(value);
4619
5024
  const res = await collection.insertOne(value, { session });
4620
5025
  delNamespace().then(() => {
4621
- import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
5026
+ import_node_server_utils29.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4622
5027
  }).catch((err) => {
4623
- import_node_server_utils28.logger.error(
5028
+ import_node_server_utils29.logger.error(
4624
5029
  `Failed to clear cache for namespace: ${namespace_collection}`,
4625
5030
  err
4626
5031
  );
@@ -4645,20 +5050,20 @@ function useCheckOutItemRepository() {
4645
5050
  limit
4646
5051
  };
4647
5052
  try {
4648
- site = new import_mongodb15.ObjectId(site);
5053
+ site = new import_mongodb16.ObjectId(site);
4649
5054
  query.site = site;
4650
5055
  cacheOptions.site = site.toString();
4651
5056
  } catch (error) {
4652
- throw new import_node_server_utils28.BadRequestError("Invalid site ID format.");
5057
+ throw new import_node_server_utils29.BadRequestError("Invalid site ID format.");
4653
5058
  }
4654
5059
  if (search) {
4655
5060
  query.$text = { $search: search };
4656
5061
  cacheOptions.search = search;
4657
5062
  }
4658
- const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, cacheOptions);
5063
+ const cacheKey = (0, import_node_server_utils29.makeCacheKey)(namespace_collection, cacheOptions);
4659
5064
  const cachedData = await getCache(cacheKey);
4660
5065
  if (cachedData) {
4661
- import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
5066
+ import_node_server_utils29.logger.info(`Cache hit for key: ${cacheKey}`);
4662
5067
  return cachedData;
4663
5068
  }
4664
5069
  try {
@@ -4705,11 +5110,11 @@ function useCheckOutItemRepository() {
4705
5110
  { $limit: limit }
4706
5111
  ]).toArray();
4707
5112
  const length = await collection.countDocuments(query);
4708
- const data = (0, import_node_server_utils28.paginate)(items, page, limit, length);
5113
+ const data = (0, import_node_server_utils29.paginate)(items, page, limit, length);
4709
5114
  setCache(cacheKey, data, 15 * 60).then(() => {
4710
- import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
5115
+ import_node_server_utils29.logger.info(`Cache set for key: ${cacheKey}`);
4711
5116
  }).catch((err) => {
4712
- import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5117
+ import_node_server_utils29.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4713
5118
  });
4714
5119
  return data;
4715
5120
  } catch (error) {
@@ -4718,22 +5123,22 @@ function useCheckOutItemRepository() {
4718
5123
  }
4719
5124
  async function getCheckOutItemById(_id, session) {
4720
5125
  try {
4721
- _id = new import_mongodb15.ObjectId(_id);
5126
+ _id = new import_mongodb16.ObjectId(_id);
4722
5127
  } catch (error) {
4723
- throw new import_node_server_utils28.BadRequestError("Invalid check out item ID format.");
5128
+ throw new import_node_server_utils29.BadRequestError("Invalid check out item ID format.");
4724
5129
  }
4725
5130
  const query = { _id };
4726
- const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, {
5131
+ const cacheKey = (0, import_node_server_utils29.makeCacheKey)(namespace_collection, {
4727
5132
  _id: _id.toString()
4728
5133
  });
4729
5134
  if (!session) {
4730
5135
  const cachedData = await getCache(cacheKey);
4731
5136
  if (cachedData) {
4732
- import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
5137
+ import_node_server_utils29.logger.info(`Cache hit for key: ${cacheKey}`);
4733
5138
  return cachedData;
4734
5139
  }
4735
5140
  } else {
4736
- import_node_server_utils28.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
5141
+ import_node_server_utils29.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
4737
5142
  }
4738
5143
  try {
4739
5144
  const data = await collection.aggregate(
@@ -4768,12 +5173,12 @@ function useCheckOutItemRepository() {
4768
5173
  session ? { session } : void 0
4769
5174
  ).toArray();
4770
5175
  if (!data || data.length === 0) {
4771
- throw new import_node_server_utils28.NotFoundError("Check out item not found.");
5176
+ throw new import_node_server_utils29.NotFoundError("Check out item not found.");
4772
5177
  }
4773
5178
  setCache(cacheKey, data[0], 15 * 60).then(() => {
4774
- import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
5179
+ import_node_server_utils29.logger.info(`Cache set for key: ${cacheKey}`);
4775
5180
  }).catch((err) => {
4776
- import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5181
+ import_node_server_utils29.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4777
5182
  });
4778
5183
  return data[0];
4779
5184
  } catch (error) {
@@ -4782,9 +5187,9 @@ function useCheckOutItemRepository() {
4782
5187
  }
4783
5188
  async function completeCheckOutItem(_id, session) {
4784
5189
  try {
4785
- _id = new import_mongodb15.ObjectId(_id);
5190
+ _id = new import_mongodb16.ObjectId(_id);
4786
5191
  } catch (error) {
4787
- throw new import_node_server_utils28.BadRequestError("Invalid check out item ID format.");
5192
+ throw new import_node_server_utils29.BadRequestError("Invalid check out item ID format.");
4788
5193
  }
4789
5194
  try {
4790
5195
  const updateValue = {
@@ -4797,12 +5202,12 @@ function useCheckOutItemRepository() {
4797
5202
  { session }
4798
5203
  );
4799
5204
  if (res.modifiedCount === 0) {
4800
- throw new import_node_server_utils28.InternalServerError("Unable to complete check out item.");
5205
+ throw new import_node_server_utils29.InternalServerError("Unable to complete check out item.");
4801
5206
  }
4802
5207
  delNamespace().then(() => {
4803
- import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
5208
+ import_node_server_utils29.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
4804
5209
  }).catch((err) => {
4805
- import_node_server_utils28.logger.error(
5210
+ import_node_server_utils29.logger.error(
4806
5211
  `Failed to clear cache for namespace: ${namespace_collection}`,
4807
5212
  err
4808
5213
  );
@@ -4824,7 +5229,7 @@ function useCheckOutItemRepository() {
4824
5229
 
4825
5230
  // src/services/hygiene-checkout-item.service.ts
4826
5231
  var import_core = require("@7365admin1/core");
4827
- var import_node_server_utils29 = require("@7365admin1/node-server-utils");
5232
+ var import_node_server_utils30 = require("@7365admin1/node-server-utils");
4828
5233
  function useCheckOutItemService() {
4829
5234
  const {
4830
5235
  createCheckOutItem: _createCheckOutItem,
@@ -4835,7 +5240,7 @@ function useCheckOutItemService() {
4835
5240
  const { getUserById } = (0, import_core.useUserRepo)();
4836
5241
  const { createStock } = useStockService();
4837
5242
  async function createCheckOutItem(value) {
4838
- const session = import_node_server_utils29.useAtlas.getClient()?.startSession();
5243
+ const session = import_node_server_utils30.useAtlas.getClient()?.startSession();
4839
5244
  try {
4840
5245
  session?.startTransaction();
4841
5246
  const supplyData = await getSupplyById(value.supply);
@@ -4853,7 +5258,7 @@ function useCheckOutItemService() {
4853
5258
  session
4854
5259
  );
4855
5260
  if (!checkOutItem) {
4856
- throw new import_node_server_utils29.BadRequestError("Failed to create check out item.");
5261
+ throw new import_node_server_utils30.BadRequestError("Failed to create check out item.");
4857
5262
  }
4858
5263
  const createdStocks = await createStock(
4859
5264
  {
@@ -4875,10 +5280,10 @@ function useCheckOutItemService() {
4875
5280
  }
4876
5281
  }
4877
5282
  async function createCheckOutItemByBatch(value) {
4878
- const session = import_node_server_utils29.useAtlas.getClient()?.startSession();
5283
+ const session = import_node_server_utils30.useAtlas.getClient()?.startSession();
4879
5284
  try {
4880
5285
  session?.startTransaction();
4881
- const { site, attachment, createdBy, items } = value;
5286
+ const { site, createdBy, items } = value;
4882
5287
  const createdByData = await getUserById(createdBy);
4883
5288
  const createdCheckOutItemIds = [];
4884
5289
  for (const item of items) {
@@ -4889,7 +5294,7 @@ function useCheckOutItemService() {
4889
5294
  supply: item.supply,
4890
5295
  supplyName: supplyData?.name || "",
4891
5296
  qty: item.qty,
4892
- attachment,
5297
+ attachment: item.attachment,
4893
5298
  createdBy,
4894
5299
  createdByName: createdByData?.name || ""
4895
5300
  },
@@ -4923,7 +5328,7 @@ function useCheckOutItemService() {
4923
5328
 
4924
5329
  // src/controllers/hygiene-checkout-item.controller.ts
4925
5330
  var import_joi15 = __toESM(require("joi"));
4926
- var import_node_server_utils30 = require("@7365admin1/node-server-utils");
5331
+ var import_node_server_utils31 = require("@7365admin1/node-server-utils");
4927
5332
  function useCheckOutItemController() {
4928
5333
  const {
4929
5334
  getCheckOutItems: _getCheckOutItems,
@@ -4953,8 +5358,8 @@ function useCheckOutItemController() {
4953
5358
  });
4954
5359
  const { error } = validation.validate(payload);
4955
5360
  if (error) {
4956
- import_node_server_utils30.logger.log({ level: "error", message: error.message });
4957
- next(new import_node_server_utils30.BadRequestError(error.message));
5361
+ import_node_server_utils31.logger.log({ level: "error", message: error.message });
5362
+ next(new import_node_server_utils31.BadRequestError(error.message));
4958
5363
  return;
4959
5364
  }
4960
5365
  try {
@@ -4962,7 +5367,7 @@ function useCheckOutItemController() {
4962
5367
  res.status(201).json({ message: "Check out item created successfully.", id });
4963
5368
  return;
4964
5369
  } catch (error2) {
4965
- import_node_server_utils30.logger.log({ level: "error", message: error2.message });
5370
+ import_node_server_utils31.logger.log({ level: "error", message: error2.message });
4966
5371
  next(error2);
4967
5372
  return;
4968
5373
  }
@@ -4980,19 +5385,19 @@ function useCheckOutItemController() {
4980
5385
  };
4981
5386
  const validation = import_joi15.default.object({
4982
5387
  site: import_joi15.default.string().hex().required(),
4983
- attachment: import_joi15.default.array().items(import_joi15.default.string()).optional().allow(null),
4984
5388
  createdBy: import_joi15.default.string().hex().required(),
4985
5389
  items: import_joi15.default.array().items(
4986
5390
  import_joi15.default.object({
4987
5391
  supply: import_joi15.default.string().hex().required(),
4988
- qty: import_joi15.default.number().min(0).required()
5392
+ qty: import_joi15.default.number().min(0).required(),
5393
+ attachment: import_joi15.default.array().items(import_joi15.default.string()).optional().allow(null)
4989
5394
  })
4990
5395
  ).min(1).required()
4991
5396
  });
4992
5397
  const { error } = validation.validate(payload);
4993
5398
  if (error) {
4994
- import_node_server_utils30.logger.log({ level: "error", message: error.message });
4995
- next(new import_node_server_utils30.BadRequestError(error.message));
5399
+ import_node_server_utils31.logger.log({ level: "error", message: error.message });
5400
+ next(new import_node_server_utils31.BadRequestError(error.message));
4996
5401
  return;
4997
5402
  }
4998
5403
  try {
@@ -5000,7 +5405,7 @@ function useCheckOutItemController() {
5000
5405
  res.status(201).json({ message: "Check out items created successfully." });
5001
5406
  return;
5002
5407
  } catch (error2) {
5003
- import_node_server_utils30.logger.log({ level: "error", message: error2.message });
5408
+ import_node_server_utils31.logger.log({ level: "error", message: error2.message });
5004
5409
  next(error2);
5005
5410
  return;
5006
5411
  }
@@ -5015,8 +5420,8 @@ function useCheckOutItemController() {
5015
5420
  });
5016
5421
  const { error } = validation.validate(query);
5017
5422
  if (error) {
5018
- import_node_server_utils30.logger.log({ level: "error", message: error.message });
5019
- next(new import_node_server_utils30.BadRequestError(error.message));
5423
+ import_node_server_utils31.logger.log({ level: "error", message: error.message });
5424
+ next(new import_node_server_utils31.BadRequestError(error.message));
5020
5425
  return;
5021
5426
  }
5022
5427
  const page = parseInt(req.query.page) ?? 1;
@@ -5033,7 +5438,7 @@ function useCheckOutItemController() {
5033
5438
  res.json(data);
5034
5439
  return;
5035
5440
  } catch (error2) {
5036
- import_node_server_utils30.logger.log({ level: "error", message: error2.message });
5441
+ import_node_server_utils31.logger.log({ level: "error", message: error2.message });
5037
5442
  next(error2);
5038
5443
  return;
5039
5444
  }
@@ -5043,8 +5448,8 @@ function useCheckOutItemController() {
5043
5448
  const _id = req.params.id;
5044
5449
  const { error, value } = validation.validate(_id);
5045
5450
  if (error) {
5046
- import_node_server_utils30.logger.log({ level: "error", message: error.message });
5047
- next(new import_node_server_utils30.BadRequestError(error.message));
5451
+ import_node_server_utils31.logger.log({ level: "error", message: error.message });
5452
+ next(new import_node_server_utils31.BadRequestError(error.message));
5048
5453
  return;
5049
5454
  }
5050
5455
  try {
@@ -5052,7 +5457,7 @@ function useCheckOutItemController() {
5052
5457
  res.json(data);
5053
5458
  return;
5054
5459
  } catch (error2) {
5055
- import_node_server_utils30.logger.log({ level: "error", message: error2.message });
5460
+ import_node_server_utils31.logger.log({ level: "error", message: error2.message });
5056
5461
  next(error2);
5057
5462
  return;
5058
5463
  }
@@ -5066,15 +5471,16 @@ function useCheckOutItemController() {
5066
5471
  }
5067
5472
 
5068
5473
  // src/models/hygiene-schedule-task.model.ts
5069
- var import_node_server_utils31 = require("@7365admin1/node-server-utils");
5474
+ var import_node_server_utils32 = require("@7365admin1/node-server-utils");
5070
5475
  var import_joi16 = __toESM(require("joi"));
5071
- var import_mongodb16 = require("mongodb");
5476
+ var import_mongodb17 = require("mongodb");
5072
5477
  var scheduleTaskSchema = import_joi16.default.object({
5073
5478
  site: import_joi16.default.string().hex().required(),
5074
5479
  title: import_joi16.default.string().required(),
5075
5480
  time: import_joi16.default.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).required(),
5076
- startDate: import_joi16.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).required(),
5077
- endDate: import_joi16.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow("", null),
5481
+ dates: import_joi16.default.array().min(1).items(
5482
+ import_joi16.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).required()
5483
+ ).required(),
5078
5484
  description: import_joi16.default.string().optional().allow("", null),
5079
5485
  areas: import_joi16.default.array().min(1).items(
5080
5486
  import_joi16.default.object({
@@ -5087,14 +5493,14 @@ var scheduleTaskSchema = import_joi16.default.object({
5087
5493
  function MScheduleTask(value) {
5088
5494
  const { error } = scheduleTaskSchema.validate(value);
5089
5495
  if (error) {
5090
- import_node_server_utils31.logger.info(`Hygiene Schedule Task Model: ${error.message}`);
5091
- throw new import_node_server_utils31.BadRequestError(error.message);
5496
+ import_node_server_utils32.logger.info(`Hygiene Schedule Task Model: ${error.message}`);
5497
+ throw new import_node_server_utils32.BadRequestError(error.message);
5092
5498
  }
5093
5499
  if (value.site) {
5094
5500
  try {
5095
- value.site = new import_mongodb16.ObjectId(value.site);
5501
+ value.site = new import_mongodb17.ObjectId(value.site);
5096
5502
  } catch (error2) {
5097
- throw new import_node_server_utils31.BadRequestError("Invalid site ID format.");
5503
+ throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
5098
5504
  }
5099
5505
  }
5100
5506
  if (value.areas && Array.isArray(value.areas)) {
@@ -5102,26 +5508,25 @@ function MScheduleTask(value) {
5102
5508
  try {
5103
5509
  return {
5104
5510
  name: area.name,
5105
- value: new import_mongodb16.ObjectId(area.value.toString())
5511
+ value: new import_mongodb17.ObjectId(area.value.toString())
5106
5512
  };
5107
5513
  } catch (error2) {
5108
- throw new import_node_server_utils31.BadRequestError(`Invalid area value format: ${area.name}`);
5514
+ throw new import_node_server_utils32.BadRequestError(`Invalid area value format: ${area.name}`);
5109
5515
  }
5110
5516
  });
5111
5517
  }
5112
5518
  if (value.createdBy) {
5113
5519
  try {
5114
- value.createdBy = new import_mongodb16.ObjectId(value.createdBy);
5520
+ value.createdBy = new import_mongodb17.ObjectId(value.createdBy);
5115
5521
  } catch (error2) {
5116
- throw new import_node_server_utils31.BadRequestError("Invalid createdBy ID format.");
5522
+ throw new import_node_server_utils32.BadRequestError("Invalid createdBy ID format.");
5117
5523
  }
5118
5524
  }
5119
5525
  return {
5120
5526
  site: value.site,
5121
5527
  title: value.title,
5122
5528
  time: value.time,
5123
- startDate: value.startDate,
5124
- endDate: value.endDate,
5529
+ dates: value.dates,
5125
5530
  description: value.description,
5126
5531
  areas: value.areas,
5127
5532
  status: "active",
@@ -5133,16 +5538,16 @@ function MScheduleTask(value) {
5133
5538
  }
5134
5539
 
5135
5540
  // src/repositories/hygiene-schedule-task.repository.ts
5136
- var import_mongodb17 = require("mongodb");
5137
- var import_node_server_utils32 = require("@7365admin1/node-server-utils");
5541
+ var import_mongodb18 = require("mongodb");
5542
+ var import_node_server_utils33 = require("@7365admin1/node-server-utils");
5138
5543
  function useScheduleTaskRepository() {
5139
- const db = import_node_server_utils32.useAtlas.getDb();
5544
+ const db = import_node_server_utils33.useAtlas.getDb();
5140
5545
  if (!db) {
5141
- throw new import_node_server_utils32.InternalServerError("Unable to connect to server.");
5546
+ throw new import_node_server_utils33.InternalServerError("Unable to connect to server.");
5142
5547
  }
5143
5548
  const namespace_collection = "site.schedule-tasks";
5144
5549
  const collection = db.collection(namespace_collection);
5145
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils32.useCache)(namespace_collection);
5550
+ const { delNamespace, setCache, getCache } = (0, import_node_server_utils33.useCache)(namespace_collection);
5146
5551
  async function createIndex() {
5147
5552
  try {
5148
5553
  await collection.createIndexes([
@@ -5150,7 +5555,7 @@ function useScheduleTaskRepository() {
5150
5555
  { key: { status: 1 } }
5151
5556
  ]);
5152
5557
  } catch (error) {
5153
- throw new import_node_server_utils32.InternalServerError(
5558
+ throw new import_node_server_utils33.InternalServerError(
5154
5559
  "Failed to create index on hygiene schedule task."
5155
5560
  );
5156
5561
  }
@@ -5159,7 +5564,7 @@ function useScheduleTaskRepository() {
5159
5564
  try {
5160
5565
  await collection.createIndex({ title: "text", description: "text" });
5161
5566
  } catch (error) {
5162
- throw new import_node_server_utils32.InternalServerError(
5567
+ throw new import_node_server_utils33.InternalServerError(
5163
5568
  "Failed to create text index on hygiene schedule task."
5164
5569
  );
5165
5570
  }
@@ -5169,9 +5574,9 @@ function useScheduleTaskRepository() {
5169
5574
  value = MScheduleTask(value);
5170
5575
  const res = await collection.insertOne(value, { session });
5171
5576
  delNamespace().then(() => {
5172
- import_node_server_utils32.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
5577
+ import_node_server_utils33.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
5173
5578
  }).catch((err) => {
5174
- import_node_server_utils32.logger.error(
5579
+ import_node_server_utils33.logger.error(
5175
5580
  `Failed to clear cache for namespace: ${namespace_collection}`,
5176
5581
  err
5177
5582
  );
@@ -5196,20 +5601,20 @@ function useScheduleTaskRepository() {
5196
5601
  limit
5197
5602
  };
5198
5603
  try {
5199
- site = new import_mongodb17.ObjectId(site);
5604
+ site = new import_mongodb18.ObjectId(site);
5200
5605
  query.site = site;
5201
5606
  cacheOptions.site = site.toString();
5202
5607
  } catch (error) {
5203
- throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
5608
+ throw new import_node_server_utils33.BadRequestError("Invalid site ID format.");
5204
5609
  }
5205
5610
  if (search) {
5206
5611
  query.$or = [{ name: { $regex: search, $options: "i" } }];
5207
5612
  cacheOptions.search = search;
5208
5613
  }
5209
- const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, cacheOptions);
5614
+ const cacheKey = (0, import_node_server_utils33.makeCacheKey)(namespace_collection, cacheOptions);
5210
5615
  const cachedData = await getCache(cacheKey);
5211
5616
  if (cachedData) {
5212
- import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
5617
+ import_node_server_utils33.logger.info(`Cache hit for key: ${cacheKey}`);
5213
5618
  return cachedData;
5214
5619
  }
5215
5620
  try {
@@ -5227,11 +5632,11 @@ function useScheduleTaskRepository() {
5227
5632
  { $limit: limit }
5228
5633
  ]).toArray();
5229
5634
  const length = await collection.countDocuments(query);
5230
- const data = (0, import_node_server_utils32.paginate)(items, page, limit, length);
5635
+ const data = (0, import_node_server_utils33.paginate)(items, page, limit, length);
5231
5636
  setCache(cacheKey, data, 15 * 60).then(() => {
5232
- import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
5637
+ import_node_server_utils33.logger.info(`Cache set for key: ${cacheKey}`);
5233
5638
  }).catch((err) => {
5234
- import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5639
+ import_node_server_utils33.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5235
5640
  });
5236
5641
  return data;
5237
5642
  } catch (error) {
@@ -5264,20 +5669,20 @@ function useScheduleTaskRepository() {
5264
5669
  limit
5265
5670
  };
5266
5671
  try {
5267
- site = new import_mongodb17.ObjectId(site);
5672
+ site = new import_mongodb18.ObjectId(site);
5268
5673
  query.site = site;
5269
5674
  cacheOptions.site = site.toString();
5270
5675
  } catch (error) {
5271
- throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
5676
+ throw new import_node_server_utils33.BadRequestError("Invalid site ID format.");
5272
5677
  }
5273
5678
  if (search) {
5274
5679
  query.$or = [{ name: { $regex: search, $options: "i" } }];
5275
5680
  cacheOptions.search = search;
5276
5681
  }
5277
- const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, cacheOptions);
5682
+ const cacheKey = (0, import_node_server_utils33.makeCacheKey)(namespace_collection, cacheOptions);
5278
5683
  const cachedData = await getCache(cacheKey);
5279
5684
  if (cachedData) {
5280
- import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
5685
+ import_node_server_utils33.logger.info(`Cache hit for key: ${cacheKey}`);
5281
5686
  return cachedData;
5282
5687
  }
5283
5688
  try {
@@ -5294,11 +5699,11 @@ function useScheduleTaskRepository() {
5294
5699
  { $limit: limit }
5295
5700
  ]).toArray();
5296
5701
  const length = await collection.countDocuments(query);
5297
- const data = (0, import_node_server_utils32.paginate)(items, page, limit, length);
5702
+ const data = (0, import_node_server_utils33.paginate)(items, page, limit, length);
5298
5703
  setCache(cacheKey, data, 15 * 60).then(() => {
5299
- import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
5704
+ import_node_server_utils33.logger.info(`Cache set for key: ${cacheKey}`);
5300
5705
  }).catch((err) => {
5301
- import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5706
+ import_node_server_utils33.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5302
5707
  });
5303
5708
  return data;
5304
5709
  } catch (error) {
@@ -5307,25 +5712,25 @@ function useScheduleTaskRepository() {
5307
5712
  }
5308
5713
  async function getScheduleTaskById(_id, session) {
5309
5714
  try {
5310
- _id = new import_mongodb17.ObjectId(_id);
5715
+ _id = new import_mongodb18.ObjectId(_id);
5311
5716
  } catch (error) {
5312
- throw new import_node_server_utils32.BadRequestError("Invalid schedule task ID format.");
5717
+ throw new import_node_server_utils33.BadRequestError("Invalid schedule task ID format.");
5313
5718
  }
5314
5719
  const query = {
5315
5720
  _id,
5316
5721
  status: { $ne: "deleted" }
5317
5722
  };
5318
- const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, {
5723
+ const cacheKey = (0, import_node_server_utils33.makeCacheKey)(namespace_collection, {
5319
5724
  _id: _id.toString()
5320
5725
  });
5321
5726
  if (!session) {
5322
5727
  const cachedData = await getCache(cacheKey);
5323
5728
  if (cachedData) {
5324
- import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
5729
+ import_node_server_utils33.logger.info(`Cache hit for key: ${cacheKey}`);
5325
5730
  return cachedData;
5326
5731
  }
5327
5732
  } else {
5328
- import_node_server_utils32.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
5733
+ import_node_server_utils33.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
5329
5734
  }
5330
5735
  try {
5331
5736
  const data = await collection.aggregate([
@@ -5334,8 +5739,7 @@ function useScheduleTaskRepository() {
5334
5739
  $project: {
5335
5740
  title: 1,
5336
5741
  time: 1,
5337
- startDate: 1,
5338
- endDate: 1,
5742
+ dates: 1,
5339
5743
  description: 1,
5340
5744
  areas: 1,
5341
5745
  status: 1,
@@ -5344,12 +5748,12 @@ function useScheduleTaskRepository() {
5344
5748
  }
5345
5749
  ]).toArray();
5346
5750
  if (!data || data.length === 0) {
5347
- throw new import_node_server_utils32.NotFoundError("Schedule task not found.");
5751
+ throw new import_node_server_utils33.NotFoundError("Schedule task not found.");
5348
5752
  }
5349
5753
  setCache(cacheKey, data[0], 15 * 60).then(() => {
5350
- import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
5754
+ import_node_server_utils33.logger.info(`Cache set for key: ${cacheKey}`);
5351
5755
  }).catch((err) => {
5352
- import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5756
+ import_node_server_utils33.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
5353
5757
  });
5354
5758
  return data[0];
5355
5759
  } catch (error) {
@@ -5358,19 +5762,19 @@ function useScheduleTaskRepository() {
5358
5762
  }
5359
5763
  async function updateScheduleTask(_id, value, session) {
5360
5764
  try {
5361
- _id = new import_mongodb17.ObjectId(_id);
5765
+ _id = new import_mongodb18.ObjectId(_id);
5362
5766
  } catch (error) {
5363
- throw new import_node_server_utils32.BadRequestError("Invalid schedule task ID format.");
5767
+ throw new import_node_server_utils33.BadRequestError("Invalid schedule task ID format.");
5364
5768
  }
5365
5769
  if (value.areas && Array.isArray(value.areas)) {
5366
5770
  value.areas = value.areas.map((area) => {
5367
5771
  try {
5368
5772
  return {
5369
5773
  name: area.name,
5370
- value: new import_mongodb17.ObjectId(area.value.toString())
5774
+ value: new import_mongodb18.ObjectId(area.value.toString())
5371
5775
  };
5372
5776
  } catch (error) {
5373
- throw new import_node_server_utils32.BadRequestError(`Invalid area value format: ${area.name}`);
5777
+ throw new import_node_server_utils33.BadRequestError(`Invalid area value format: ${area.name}`);
5374
5778
  }
5375
5779
  });
5376
5780
  }
@@ -5382,14 +5786,14 @@ function useScheduleTaskRepository() {
5382
5786
  { session }
5383
5787
  );
5384
5788
  if (res.modifiedCount === 0) {
5385
- throw new import_node_server_utils32.InternalServerError(
5789
+ throw new import_node_server_utils33.InternalServerError(
5386
5790
  "Unable to update hygiene schedule task."
5387
5791
  );
5388
5792
  }
5389
5793
  delNamespace().then(() => {
5390
- import_node_server_utils32.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
5794
+ import_node_server_utils33.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
5391
5795
  }).catch((err) => {
5392
- import_node_server_utils32.logger.error(
5796
+ import_node_server_utils33.logger.error(
5393
5797
  `Failed to clear cache for namespace: ${namespace_collection}`,
5394
5798
  err
5395
5799
  );
@@ -5412,7 +5816,7 @@ function useScheduleTaskRepository() {
5412
5816
  }
5413
5817
 
5414
5818
  // src/services/hygiene-schedule-task.service.ts
5415
- var import_node_server_utils33 = require("@7365admin1/node-server-utils");
5819
+ var import_node_server_utils34 = require("@7365admin1/node-server-utils");
5416
5820
  function useScheduleTaskService() {
5417
5821
  const { createParentChecklist } = useParentChecklistRepo();
5418
5822
  const { getAllScheduleTask } = useScheduleTaskRepository();
@@ -5432,43 +5836,38 @@ function useScheduleTaskService() {
5432
5836
  timeZone: "Asia/Singapore"
5433
5837
  });
5434
5838
  const [currentHour, currentMinute] = timeString.split(":").map(Number);
5435
- const currentDateString = now.toLocaleDateString("en-US", {
5839
+ import_node_server_utils34.logger.info(
5840
+ `Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Schedule time ${schedule.time}, Dates ${JSON.stringify(schedule.dates)}`
5841
+ );
5842
+ const currentDateFormatted = now.toLocaleDateString("en-CA", {
5436
5843
  timeZone: "Asia/Singapore"
5437
5844
  });
5438
- import_node_server_utils33.logger.info(
5439
- `Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Current date ${currentDateString}, Schedule time ${schedule.time}, Start date ${schedule.startDate}, End date ${schedule.endDate}`
5440
- );
5441
- const startDate = /* @__PURE__ */ new Date(schedule.startDate + "T00:00:00");
5442
- const currentDateOnly = /* @__PURE__ */ new Date(currentDateString + "T00:00:00");
5443
- if (currentDateOnly < startDate) {
5444
- import_node_server_utils33.logger.info(
5445
- `Schedule ${schedule._id}: Current date ${currentDateString} is before start date ${schedule.startDate}`
5446
- );
5845
+ if (!schedule.dates || !Array.isArray(schedule.dates) || schedule.dates.length === 0) {
5846
+ import_node_server_utils34.logger.info(`Schedule ${schedule._id}: No dates configured, skipping`);
5447
5847
  return false;
5448
5848
  }
5449
- if (schedule.endDate) {
5450
- const endDate = /* @__PURE__ */ new Date(schedule.endDate + "T00:00:00");
5451
- if (currentDateOnly > endDate) {
5452
- import_node_server_utils33.logger.info(
5453
- `Schedule ${schedule._id}: Current date ${currentDateString} is after end date ${schedule.endDate}`
5454
- );
5455
- return false;
5456
- }
5849
+ if (!schedule.dates.includes(currentDateFormatted)) {
5850
+ import_node_server_utils34.logger.info(
5851
+ `Schedule ${schedule._id}: Current date ${currentDateFormatted} is not in scheduled dates [${schedule.dates.join(
5852
+ ", "
5853
+ )}]`
5854
+ );
5855
+ return false;
5457
5856
  }
5458
5857
  const [scheduleHour, scheduleMinute] = schedule.time.split(":").map(Number);
5459
5858
  const timeMatches = currentHour === scheduleHour && currentMinute === scheduleMinute;
5460
5859
  if (!timeMatches) {
5461
- import_node_server_utils33.logger.info(
5860
+ import_node_server_utils34.logger.info(
5462
5861
  `Schedule ${schedule._id}: Time does not match. Current: ${currentHour}:${currentMinute}, Expected: ${scheduleHour}:${scheduleMinute}`
5463
5862
  );
5464
5863
  return false;
5465
5864
  }
5466
- import_node_server_utils33.logger.info(
5865
+ import_node_server_utils34.logger.info(
5467
5866
  `Schedule ${schedule._id}: All conditions matched - Date is within range and time matches`
5468
5867
  );
5469
5868
  return true;
5470
5869
  } catch (error) {
5471
- import_node_server_utils33.logger.error(
5870
+ import_node_server_utils34.logger.error(
5472
5871
  `Error checking schedule conditions for ${schedule._id}:`,
5473
5872
  error
5474
5873
  );
@@ -5477,40 +5876,42 @@ function useScheduleTaskService() {
5477
5876
  }
5478
5877
  async function processScheduledTasks(currentDate) {
5479
5878
  try {
5480
- import_node_server_utils33.logger.info("Starting scheduled task processing...");
5879
+ import_node_server_utils34.logger.info("Starting scheduled task processing...");
5481
5880
  const scheduleTasks = await getAllScheduleTask();
5482
5881
  if (!scheduleTasks || scheduleTasks.length === 0) {
5483
- import_node_server_utils33.logger.info("No schedule tasks found to process");
5882
+ import_node_server_utils34.logger.info("No schedule tasks found to process");
5484
5883
  return { processed: 0, validated: 0 };
5485
5884
  }
5486
- import_node_server_utils33.logger.info(`Found ${scheduleTasks.length} schedule tasks to check`);
5885
+ import_node_server_utils34.logger.info(`Found ${scheduleTasks.length} schedule tasks to check`);
5487
5886
  let processedCount = 0;
5488
5887
  let validatedCount = 0;
5489
5888
  const validatedTasks = [];
5490
5889
  for (const scheduleTask of scheduleTasks) {
5491
5890
  try {
5492
- import_node_server_utils33.logger.info(
5493
- `Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, startDate=${scheduleTask.startDate}, endDate=${scheduleTask.endDate}`
5891
+ import_node_server_utils34.logger.info(
5892
+ `Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, dates=${JSON.stringify(
5893
+ scheduleTask.dates
5894
+ )}`
5494
5895
  );
5495
5896
  const shouldRun = checkScheduleConditions(scheduleTask, currentDate);
5496
5897
  if (!shouldRun) {
5497
- import_node_server_utils33.logger.info(
5898
+ import_node_server_utils34.logger.info(
5498
5899
  `Schedule ${scheduleTask._id} conditions not met, skipping`
5499
5900
  );
5500
5901
  continue;
5501
5902
  }
5502
- import_node_server_utils33.logger.info(
5903
+ import_node_server_utils34.logger.info(
5503
5904
  `Schedule ${scheduleTask._id} conditions validated, creating area checklists`
5504
5905
  );
5505
5906
  if (!scheduleTask._id) {
5506
- import_node_server_utils33.logger.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
5907
+ import_node_server_utils34.logger.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
5507
5908
  continue;
5508
5909
  }
5509
5910
  if (!scheduleTask.site) {
5510
- import_node_server_utils33.logger.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
5911
+ import_node_server_utils34.logger.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
5511
5912
  continue;
5512
5913
  }
5513
- import_node_server_utils33.logger.info(
5914
+ import_node_server_utils34.logger.info(
5514
5915
  `Getting or creating parent checklist for schedule ${scheduleTask._id} in site ${scheduleTask.site}`
5515
5916
  );
5516
5917
  const parentChecklistIds = await createParentChecklist({
@@ -5518,7 +5919,7 @@ function useScheduleTaskService() {
5518
5919
  createdAt: /* @__PURE__ */ new Date()
5519
5920
  });
5520
5921
  const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
5521
- import_node_server_utils33.logger.info(
5922
+ import_node_server_utils34.logger.info(
5522
5923
  `Using parent checklist ${parentChecklistId}, now creating/updating area checklists`
5523
5924
  );
5524
5925
  for (const area of scheduleTask.areas) {
@@ -5531,14 +5932,14 @@ function useScheduleTaskService() {
5531
5932
  unit: unit.unit.toString(),
5532
5933
  name: unit.name
5533
5934
  }));
5534
- import_node_server_utils33.logger.info(
5935
+ import_node_server_utils34.logger.info(
5535
5936
  `Area ${area.name} (${areaId}): Using units from area details: ${JSON.stringify(
5536
5937
  units
5537
5938
  )}`
5538
5939
  );
5539
5940
  }
5540
5941
  if (units.length === 0) {
5541
- import_node_server_utils33.logger.warn(
5942
+ import_node_server_utils34.logger.warn(
5542
5943
  `Area ${area.name} (${areaId}): No units found, skipping area.`
5543
5944
  );
5544
5945
  continue;
@@ -5549,11 +5950,11 @@ function useScheduleTaskService() {
5549
5950
  parentChecklistId.toString(),
5550
5951
  areaId
5551
5952
  );
5552
- import_node_server_utils33.logger.info(
5953
+ import_node_server_utils34.logger.info(
5553
5954
  `Area ${area.name} (${areaId}): Existing area checklist found: ${existingAreaChecklist ? "Yes" : "No"}`
5554
5955
  );
5555
5956
  if (existingAreaChecklist) {
5556
- import_node_server_utils33.logger.info(
5957
+ import_node_server_utils34.logger.info(
5557
5958
  `Area ${area.name} (${areaId}): Existing checklist content: ${JSON.stringify(
5558
5959
  existingAreaChecklist.checklist
5559
5960
  )}`
@@ -5561,7 +5962,7 @@ function useScheduleTaskService() {
5561
5962
  }
5562
5963
  } catch (error) {
5563
5964
  existingAreaChecklist = null;
5564
- import_node_server_utils33.logger.info(
5965
+ import_node_server_utils34.logger.info(
5565
5966
  `Area ${area.name} (${areaId}): No existing area checklist found (exception).`
5566
5967
  );
5567
5968
  }
@@ -5575,7 +5976,7 @@ function useScheduleTaskService() {
5575
5976
  ...existingAreaChecklist.checklist || [],
5576
5977
  newSet
5577
5978
  ];
5578
- import_node_server_utils33.logger.info(
5979
+ import_node_server_utils34.logger.info(
5579
5980
  `Area ${area.name} (${areaId}): Appending new set ${newSet.set} to checklist. Updated checklist: ${JSON.stringify(
5580
5981
  updatedChecklist
5581
5982
  )}`
@@ -5583,7 +5984,7 @@ function useScheduleTaskService() {
5583
5984
  await updateAreaChecklist(existingAreaChecklist._id, {
5584
5985
  checklist: updatedChecklist
5585
5986
  });
5586
- import_node_server_utils33.logger.info(
5987
+ import_node_server_utils34.logger.info(
5587
5988
  `Appended set ${newSet.set} to area checklist for area ${area.name}`
5588
5989
  );
5589
5990
  try {
@@ -5591,13 +5992,13 @@ function useScheduleTaskService() {
5591
5992
  parentChecklistId.toString(),
5592
5993
  areaId
5593
5994
  );
5594
- import_node_server_utils33.logger.info(
5995
+ import_node_server_utils34.logger.info(
5595
5996
  `Area ${area.name} (${areaId}): Checklist after update: ${JSON.stringify(
5596
5997
  verifyChecklist.checklist
5597
5998
  )}`
5598
5999
  );
5599
6000
  } catch (verifyError) {
5600
- import_node_server_utils33.logger.warn(
6001
+ import_node_server_utils34.logger.warn(
5601
6002
  `Area ${area.name} (${areaId}): Error verifying checklist after update:`,
5602
6003
  verifyError
5603
6004
  );
@@ -5616,50 +6017,50 @@ function useScheduleTaskService() {
5616
6017
  ],
5617
6018
  createdBy: scheduleTask.createdBy
5618
6019
  };
5619
- import_node_server_utils33.logger.info(
6020
+ import_node_server_utils34.logger.info(
5620
6021
  `Area ${area.name} (${areaId}): Creating new area checklist with data: ${JSON.stringify(
5621
6022
  checklistData
5622
6023
  )}`
5623
6024
  );
5624
6025
  await createAreaChecklist(checklistData);
5625
- import_node_server_utils33.logger.info(`Created new area checklist for area ${area.name}`);
6026
+ import_node_server_utils34.logger.info(`Created new area checklist for area ${area.name}`);
5626
6027
  try {
5627
6028
  const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
5628
6029
  parentChecklistId.toString(),
5629
6030
  areaId
5630
6031
  );
5631
- import_node_server_utils33.logger.info(
6032
+ import_node_server_utils34.logger.info(
5632
6033
  `Area ${area.name} (${areaId}): Checklist after creation: ${JSON.stringify(
5633
6034
  verifyChecklist.checklist
5634
6035
  )}`
5635
6036
  );
5636
6037
  } catch (verifyError) {
5637
- import_node_server_utils33.logger.warn(
6038
+ import_node_server_utils34.logger.warn(
5638
6039
  `Area ${area.name} (${areaId}): Error verifying checklist after creation:`,
5639
6040
  verifyError
5640
6041
  );
5641
6042
  }
5642
6043
  }
5643
6044
  } catch (error) {
5644
- import_node_server_utils33.logger.error(`Error processing area ${area.name}:`, error);
6045
+ import_node_server_utils34.logger.error(`Error processing area ${area.name}:`, error);
5645
6046
  continue;
5646
6047
  }
5647
6048
  }
5648
6049
  processedCount++;
5649
6050
  validatedCount++;
5650
6051
  validatedTasks.push(scheduleTask);
5651
- import_node_server_utils33.logger.info(
6052
+ import_node_server_utils34.logger.info(
5652
6053
  `Successfully processed schedule ${scheduleTask._id}, created/updated area checklists for all areas.`
5653
6054
  );
5654
6055
  } catch (error) {
5655
- import_node_server_utils33.logger.error(
6056
+ import_node_server_utils34.logger.error(
5656
6057
  `Error processing schedule task ${scheduleTask._id}:`,
5657
6058
  error
5658
6059
  );
5659
6060
  continue;
5660
6061
  }
5661
6062
  }
5662
- import_node_server_utils33.logger.info(
6063
+ import_node_server_utils34.logger.info(
5663
6064
  `Scheduled task processing completed. Processed: ${processedCount}, Validated: ${validatedCount} tasks`
5664
6065
  );
5665
6066
  return {
@@ -5668,7 +6069,7 @@ function useScheduleTaskService() {
5668
6069
  tasks: validatedTasks
5669
6070
  };
5670
6071
  } catch (error) {
5671
- import_node_server_utils33.logger.error("Error processing scheduled tasks:", error);
6072
+ import_node_server_utils34.logger.error("Error processing scheduled tasks:", error);
5672
6073
  throw error;
5673
6074
  }
5674
6075
  }
@@ -5677,7 +6078,7 @@ function useScheduleTaskService() {
5677
6078
 
5678
6079
  // src/controllers/hygiene-schedule-task.controller.ts
5679
6080
  var import_joi17 = __toESM(require("joi"));
5680
- var import_node_server_utils34 = require("@7365admin1/node-server-utils");
6081
+ var import_node_server_utils35 = require("@7365admin1/node-server-utils");
5681
6082
  function useScheduleTaskController() {
5682
6083
  const {
5683
6084
  createScheduleTask: _createScheduleTask,
@@ -5695,8 +6096,8 @@ function useScheduleTaskController() {
5695
6096
  const payload = { ...req.body, ...req.params, createdBy };
5696
6097
  const { error } = scheduleTaskSchema.validate(payload);
5697
6098
  if (error) {
5698
- import_node_server_utils34.logger.log({ level: "error", message: error.message });
5699
- next(new import_node_server_utils34.BadRequestError(error.message));
6099
+ import_node_server_utils35.logger.log({ level: "error", message: error.message });
6100
+ next(new import_node_server_utils35.BadRequestError(error.message));
5700
6101
  return;
5701
6102
  }
5702
6103
  try {
@@ -5704,7 +6105,7 @@ function useScheduleTaskController() {
5704
6105
  res.status(201).json({ message: "Schedule task created successfully.", id });
5705
6106
  return;
5706
6107
  } catch (error2) {
5707
- import_node_server_utils34.logger.log({ level: "error", message: error2.message });
6108
+ import_node_server_utils35.logger.log({ level: "error", message: error2.message });
5708
6109
  next(error2);
5709
6110
  return;
5710
6111
  }
@@ -5719,8 +6120,8 @@ function useScheduleTaskController() {
5719
6120
  });
5720
6121
  const { error } = validation.validate(query);
5721
6122
  if (error) {
5722
- import_node_server_utils34.logger.log({ level: "error", message: error.message });
5723
- next(new import_node_server_utils34.BadRequestError(error.message));
6123
+ import_node_server_utils35.logger.log({ level: "error", message: error.message });
6124
+ next(new import_node_server_utils35.BadRequestError(error.message));
5724
6125
  return;
5725
6126
  }
5726
6127
  const page = parseInt(req.query.page) ?? 1;
@@ -5737,7 +6138,7 @@ function useScheduleTaskController() {
5737
6138
  res.json(data);
5738
6139
  return;
5739
6140
  } catch (error2) {
5740
- import_node_server_utils34.logger.log({ level: "error", message: error2.message });
6141
+ import_node_server_utils35.logger.log({ level: "error", message: error2.message });
5741
6142
  next(error2);
5742
6143
  return;
5743
6144
  }
@@ -5752,8 +6153,8 @@ function useScheduleTaskController() {
5752
6153
  });
5753
6154
  const { error } = validation.validate(query);
5754
6155
  if (error) {
5755
- import_node_server_utils34.logger.log({ level: "error", message: error.message });
5756
- next(new import_node_server_utils34.BadRequestError(error.message));
6156
+ import_node_server_utils35.logger.log({ level: "error", message: error.message });
6157
+ next(new import_node_server_utils35.BadRequestError(error.message));
5757
6158
  return;
5758
6159
  }
5759
6160
  const page = parseInt(req.query.page) ?? 1;
@@ -5770,7 +6171,7 @@ function useScheduleTaskController() {
5770
6171
  res.json(data);
5771
6172
  return;
5772
6173
  } catch (error2) {
5773
- import_node_server_utils34.logger.log({ level: "error", message: error2.message });
6174
+ import_node_server_utils35.logger.log({ level: "error", message: error2.message });
5774
6175
  next(error2);
5775
6176
  return;
5776
6177
  }
@@ -5780,8 +6181,8 @@ function useScheduleTaskController() {
5780
6181
  const _id = req.params.id;
5781
6182
  const { error, value } = validation.validate(_id);
5782
6183
  if (error) {
5783
- import_node_server_utils34.logger.log({ level: "error", message: error.message });
5784
- next(new import_node_server_utils34.BadRequestError(error.message));
6184
+ import_node_server_utils35.logger.log({ level: "error", message: error.message });
6185
+ next(new import_node_server_utils35.BadRequestError(error.message));
5785
6186
  return;
5786
6187
  }
5787
6188
  try {
@@ -5789,7 +6190,7 @@ function useScheduleTaskController() {
5789
6190
  res.json(data);
5790
6191
  return;
5791
6192
  } catch (error2) {
5792
- import_node_server_utils34.logger.log({ level: "error", message: error2.message });
6193
+ import_node_server_utils35.logger.log({ level: "error", message: error2.message });
5793
6194
  next(error2);
5794
6195
  return;
5795
6196
  }
@@ -5800,8 +6201,9 @@ function useScheduleTaskController() {
5800
6201
  id: import_joi17.default.string().hex().required(),
5801
6202
  title: import_joi17.default.string().optional().allow("", null),
5802
6203
  time: import_joi17.default.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).optional().allow("", null),
5803
- startDate: import_joi17.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow("", null),
5804
- endDate: import_joi17.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow("", null),
6204
+ dates: import_joi17.default.array().min(1).items(
6205
+ import_joi17.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).required()
6206
+ ).optional(),
5805
6207
  description: import_joi17.default.string().optional().allow("", null),
5806
6208
  areas: import_joi17.default.array().min(1).items(
5807
6209
  import_joi17.default.object({
@@ -5812,8 +6214,8 @@ function useScheduleTaskController() {
5812
6214
  });
5813
6215
  const { error } = validation.validate(payload);
5814
6216
  if (error) {
5815
- import_node_server_utils34.logger.log({ level: "error", message: error.message });
5816
- next(new import_node_server_utils34.BadRequestError(error.message));
6217
+ import_node_server_utils35.logger.log({ level: "error", message: error.message });
6218
+ next(new import_node_server_utils35.BadRequestError(error.message));
5817
6219
  return;
5818
6220
  }
5819
6221
  try {
@@ -5822,7 +6224,7 @@ function useScheduleTaskController() {
5822
6224
  res.json({ message: "Schedule task updated successfully." });
5823
6225
  return;
5824
6226
  } catch (error2) {
5825
- import_node_server_utils34.logger.log({ level: "error", message: error2.message });
6227
+ import_node_server_utils35.logger.log({ level: "error", message: error2.message });
5826
6228
  next(error2);
5827
6229
  return;
5828
6230
  }
@@ -5837,8 +6239,8 @@ function useScheduleTaskController() {
5837
6239
  }
5838
6240
 
5839
6241
  // src/services/hygiene-qr.service.ts
5840
- var import_node_server_utils35 = require("@7365admin1/node-server-utils");
5841
- var import_puppeteer = require("puppeteer");
6242
+ var import_node_server_utils36 = require("@7365admin1/node-server-utils");
6243
+ var import_puppeteer2 = require("puppeteer");
5842
6244
  var import_qrcode = __toESM(require("qrcode"));
5843
6245
  function useQRService() {
5844
6246
  async function generateQRDataUrl(qrUrl) {
@@ -5855,7 +6257,7 @@ function useQRService() {
5855
6257
  async function generateQRImage(qrUrl) {
5856
6258
  try {
5857
6259
  const qrDataUrl = await generateQRDataUrl(qrUrl);
5858
- const browser = await (0, import_puppeteer.launch)({
6260
+ const browser = await (0, import_puppeteer2.launch)({
5859
6261
  headless: true,
5860
6262
  executablePath: process.env.CHROME_BINARY,
5861
6263
  args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
@@ -5908,17 +6310,17 @@ function useQRService() {
5908
6310
  await browser.close();
5909
6311
  return imageBuffer;
5910
6312
  } catch (error) {
5911
- import_node_server_utils35.logger.log({
6313
+ import_node_server_utils36.logger.log({
5912
6314
  level: "error",
5913
6315
  message: `Failed to generate QR image: ${error.message}`
5914
6316
  });
5915
6317
  throw error;
5916
6318
  }
5917
6319
  }
5918
- async function generateQRPDF(qrUrl, title) {
6320
+ async function generateQRPDF(qrUrl, title, subtitle) {
5919
6321
  try {
5920
6322
  const qrDataUrl = await generateQRDataUrl(qrUrl);
5921
- const browser = await (0, import_puppeteer.launch)({
6323
+ const browser = await (0, import_puppeteer2.launch)({
5922
6324
  headless: true,
5923
6325
  executablePath: process.env.CHROME_BINARY,
5924
6326
  args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
@@ -5929,6 +6331,7 @@ function useQRService() {
5929
6331
  height: 1100
5930
6332
  });
5931
6333
  const escapedTitle = (title || "Cleaning Schedule QR Code").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
6334
+ const escapedSubtitle = subtitle ? subtitle.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;") : "";
5932
6335
  const html = `
5933
6336
  <!DOCTYPE html>
5934
6337
  <html>
@@ -5956,10 +6359,16 @@ function useQRService() {
5956
6359
  padding: 0;
5957
6360
  }
5958
6361
  h1 {
5959
- font-size: 28px;
6362
+ font-size: 38px;
5960
6363
  color: #333;
5961
- margin-bottom: 20px;
5962
- font-weight: 600;
6364
+ margin-bottom: 8px;
6365
+ font-weight: 700;
6366
+ }
6367
+ .subtitle {
6368
+ font-size: 26px;
6369
+ color: #555;
6370
+ margin-bottom: 12px;
6371
+ font-weight: 500;
5963
6372
  }
5964
6373
  .qr-wrapper {
5965
6374
  display: inline-block;
@@ -5994,6 +6403,7 @@ function useQRService() {
5994
6403
  <body>
5995
6404
  <div class="qr-container">
5996
6405
  <h1>${escapedTitle}</h1>
6406
+ ${escapedSubtitle ? `<p class="subtitle">${escapedSubtitle}</p>` : ""}
5997
6407
  <div class="qr-wrapper">
5998
6408
  <img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
5999
6409
  </div>
@@ -6031,7 +6441,7 @@ function useQRService() {
6031
6441
  await browser.close();
6032
6442
  return pdfBuffer;
6033
6443
  } catch (error) {
6034
- import_node_server_utils35.logger.log({
6444
+ import_node_server_utils36.logger.log({
6035
6445
  level: "error",
6036
6446
  message: `Failed to generate QR PDF: ${error.message}`
6037
6447
  });
@@ -6046,7 +6456,7 @@ function useQRService() {
6046
6456
 
6047
6457
  // src/controllers/hygiene-qr.controller.ts
6048
6458
  var import_joi18 = __toESM(require("joi"));
6049
- var import_node_server_utils36 = require("@7365admin1/node-server-utils");
6459
+ var import_node_server_utils37 = require("@7365admin1/node-server-utils");
6050
6460
  function useQRController() {
6051
6461
  const { generateQRImage: _generateQRImage, generateQRPDF: _generateQRPDF } = useQRService();
6052
6462
  async function generateQR(req, res, next) {
@@ -6054,19 +6464,20 @@ function useQRController() {
6054
6464
  url: import_joi18.default.string().uri().required(),
6055
6465
  filename: import_joi18.default.string().optional().allow("", null),
6056
6466
  title: import_joi18.default.string().optional().allow("", null),
6467
+ subtitle: import_joi18.default.string().optional().allow("", null),
6057
6468
  download: import_joi18.default.boolean().optional().default(false)
6058
6469
  });
6059
6470
  const query = { ...req.query };
6060
6471
  const { error, value } = validation.validate(query);
6061
6472
  if (error) {
6062
- import_node_server_utils36.logger.log({ level: "error", message: error.message });
6063
- next(new import_node_server_utils36.BadRequestError(error.message));
6473
+ import_node_server_utils37.logger.log({ level: "error", message: error.message });
6474
+ next(new import_node_server_utils37.BadRequestError(error.message));
6064
6475
  return;
6065
6476
  }
6066
6477
  try {
6067
- const { url, filename, title, download } = value;
6478
+ const { url, filename, title, subtitle, download } = value;
6068
6479
  if (download) {
6069
- const pdfBuffer = await _generateQRPDF(url, title);
6480
+ const pdfBuffer = await _generateQRPDF(url, title, subtitle);
6070
6481
  if (!pdfBuffer || pdfBuffer.length === 0) {
6071
6482
  throw new Error("Generated QR PDF is empty or invalid.");
6072
6483
  }
@@ -6095,7 +6506,7 @@ function useQRController() {
6095
6506
  }
6096
6507
  return;
6097
6508
  } catch (error2) {
6098
- import_node_server_utils36.logger.log({ level: "error", message: error2.message });
6509
+ import_node_server_utils37.logger.log({ level: "error", message: error2.message });
6099
6510
  next(error2);
6100
6511
  return;
6101
6512
  }