@7365admin1/module-hygiene 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1014,12 +1014,294 @@ function useAreaRepo() {
1014
1014
 
1015
1015
  // src/services/hygiene-area.service.ts
1016
1016
  import {
1017
- BadRequestError as BadRequestError5,
1018
- logger as logger5,
1017
+ BadRequestError as BadRequestError7,
1018
+ logger as logger8,
1019
1019
  NotFoundError as NotFoundError2
1020
1020
  } from "@7365admin1/node-server-utils";
1021
+
1022
+ // src/services/hygiene-area-export.service.ts
1023
+ import { logger as logger5 } from "@7365admin1/node-server-utils";
1024
+ import * as xlsx from "xlsx";
1025
+ function useAreaExportService() {
1026
+ async function generateAreaExcel(areas) {
1027
+ try {
1028
+ const rows = [];
1029
+ rows.push(["AREA", "TYPE", "SET", "UNITS"]);
1030
+ for (const area of areas) {
1031
+ const areaName = area.name || "";
1032
+ const areaType = area.type || "";
1033
+ const areaSet = String(area.set || 0);
1034
+ const unitsString = area.units && area.units.length > 0 ? area.units.map((u) => u.name || "").join(", ") : "";
1035
+ rows.push([areaName, areaType, areaSet, unitsString]);
1036
+ }
1037
+ const workbook = xlsx.utils.book_new();
1038
+ const worksheet = xlsx.utils.aoa_to_sheet(rows);
1039
+ worksheet["!cols"] = [
1040
+ { width: 30 },
1041
+ // AREA
1042
+ { width: 20 },
1043
+ // TYPE
1044
+ { width: 10 },
1045
+ // SET
1046
+ { width: 40 }
1047
+ // UNITS
1048
+ ];
1049
+ xlsx.utils.book_append_sheet(workbook, worksheet, "Areas");
1050
+ const excelBuffer = xlsx.write(workbook, {
1051
+ type: "buffer",
1052
+ bookType: "xlsx"
1053
+ });
1054
+ return excelBuffer;
1055
+ } catch (error) {
1056
+ logger5.log({
1057
+ level: "error",
1058
+ message: `Failed to generate area Excel: ${error.message}`
1059
+ });
1060
+ throw error;
1061
+ }
1062
+ }
1063
+ return {
1064
+ generateAreaExcel
1065
+ };
1066
+ }
1067
+
1068
+ // src/repositories/hygiene-unit.repository.ts
1069
+ import { ObjectId as ObjectId5 } from "mongodb";
1070
+ import {
1071
+ useAtlas as useAtlas3,
1072
+ InternalServerError as InternalServerError3,
1073
+ paginate as paginate2,
1074
+ BadRequestError as BadRequestError6,
1075
+ useCache as useCache3,
1076
+ logger as logger7,
1077
+ makeCacheKey as makeCacheKey3
1078
+ } from "@7365admin1/node-server-utils";
1079
+
1080
+ // src/models/hygiene-unit.model.ts
1081
+ import Joi3 from "joi";
1082
+ import { ObjectId as ObjectId4 } from "mongodb";
1083
+ import { BadRequestError as BadRequestError5, logger as logger6 } from "@7365admin1/node-server-utils";
1084
+ var unitSchema = Joi3.object({
1085
+ site: Joi3.string().hex().required(),
1086
+ name: Joi3.string().required()
1087
+ });
1088
+ function MUnit(value) {
1089
+ const { error } = unitSchema.validate(value);
1090
+ if (error) {
1091
+ logger6.info(`Hygiene Unit Model: ${error.message}`);
1092
+ throw new BadRequestError5(error.message);
1093
+ }
1094
+ if (value.site) {
1095
+ try {
1096
+ value.site = new ObjectId4(value.site);
1097
+ } catch (error2) {
1098
+ throw new BadRequestError5("Invalid site ID format.");
1099
+ }
1100
+ }
1101
+ return {
1102
+ site: value.site,
1103
+ name: value.name,
1104
+ status: "active",
1105
+ createdAt: /* @__PURE__ */ new Date(),
1106
+ updatedAt: "",
1107
+ deletedAt: ""
1108
+ };
1109
+ }
1110
+
1111
+ // src/repositories/hygiene-unit.repository.ts
1112
+ function useUnitRepository() {
1113
+ const db = useAtlas3.getDb();
1114
+ if (!db) {
1115
+ throw new InternalServerError3("Unable to connect to server.");
1116
+ }
1117
+ const namespace_collection = "site.cleaning.area.unit";
1118
+ const collection = db.collection(namespace_collection);
1119
+ const { delNamespace, setCache, getCache } = useCache3(namespace_collection);
1120
+ async function createIndex() {
1121
+ try {
1122
+ await collection.createIndexes([
1123
+ { key: { site: 1 } },
1124
+ { key: { status: 1 } }
1125
+ ]);
1126
+ } catch (error) {
1127
+ throw new InternalServerError3("Failed to create index on hygiene unit.");
1128
+ }
1129
+ }
1130
+ async function createTextIndex() {
1131
+ try {
1132
+ await collection.createIndex({ name: "text" });
1133
+ } catch (error) {
1134
+ throw new InternalServerError3(
1135
+ "Failed to create text index on hygiene unit."
1136
+ );
1137
+ }
1138
+ }
1139
+ async function createUniqueIndex() {
1140
+ try {
1141
+ await collection.createIndex(
1142
+ { site: 1, name: 1, deletedAt: 1 },
1143
+ { unique: true }
1144
+ );
1145
+ } catch (error) {
1146
+ throw new InternalServerError3(
1147
+ "Failed to create unique index on hygiene unit."
1148
+ );
1149
+ }
1150
+ }
1151
+ async function createUnit(value, session) {
1152
+ try {
1153
+ value = MUnit(value);
1154
+ const res = await collection.insertOne(value, { session });
1155
+ delNamespace().then(() => {
1156
+ logger7.info(`Cache cleared for namespace: ${namespace_collection}`);
1157
+ }).catch((err) => {
1158
+ logger7.error(
1159
+ `Failed to clear cache for namespace: ${namespace_collection}`,
1160
+ err
1161
+ );
1162
+ });
1163
+ return res.insertedId;
1164
+ } catch (error) {
1165
+ const isDuplicated = error.message.includes("duplicate");
1166
+ if (isDuplicated) {
1167
+ throw new BadRequestError6("Unit already exists.");
1168
+ }
1169
+ throw error;
1170
+ }
1171
+ }
1172
+ async function getUnits({
1173
+ page = 1,
1174
+ limit = 10,
1175
+ search = "",
1176
+ site
1177
+ }) {
1178
+ page = page > 0 ? page - 1 : 0;
1179
+ const query = {
1180
+ status: { $ne: "deleted" }
1181
+ };
1182
+ const cacheOptions = {
1183
+ page,
1184
+ limit
1185
+ };
1186
+ try {
1187
+ site = new ObjectId5(site);
1188
+ query.site = site;
1189
+ cacheOptions.site = site.toString();
1190
+ } catch (error) {
1191
+ throw new BadRequestError6("Invalid site ID format.");
1192
+ }
1193
+ if (search) {
1194
+ query.$or = [{ name: { $regex: search, $options: "i" } }];
1195
+ cacheOptions.search = search;
1196
+ }
1197
+ const cacheKey = makeCacheKey3(namespace_collection, cacheOptions);
1198
+ const cachedData = await getCache(cacheKey);
1199
+ if (cachedData) {
1200
+ logger7.info(`Cache hit for key: ${cacheKey}`);
1201
+ return cachedData;
1202
+ }
1203
+ try {
1204
+ const items = await collection.aggregate([
1205
+ { $match: query },
1206
+ { $project: { name: 1 } },
1207
+ { $sort: { _id: -1 } },
1208
+ { $skip: page * limit },
1209
+ { $limit: limit }
1210
+ ]).toArray();
1211
+ const length = await collection.countDocuments(query);
1212
+ const data = paginate2(items, page, limit, length);
1213
+ setCache(cacheKey, data, 15 * 60).then(() => {
1214
+ logger7.info(`Cache set for key: ${cacheKey}`);
1215
+ }).catch((err) => {
1216
+ logger7.error(`Failed to set cache for key: ${cacheKey}`, err);
1217
+ });
1218
+ return data;
1219
+ } catch (error) {
1220
+ throw error;
1221
+ }
1222
+ }
1223
+ async function updateUnit(_id, value, session) {
1224
+ try {
1225
+ _id = new ObjectId5(_id);
1226
+ } catch (error) {
1227
+ throw new BadRequestError6("Invalid unit ID format.");
1228
+ }
1229
+ try {
1230
+ const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
1231
+ const res = await collection.updateOne(
1232
+ { _id },
1233
+ { $set: updateValue },
1234
+ { session }
1235
+ );
1236
+ if (res.modifiedCount === 0) {
1237
+ throw new InternalServerError3("Unable to update cleaning unit.");
1238
+ }
1239
+ delNamespace().then(() => {
1240
+ logger7.info(`Cache cleared for namespace: ${namespace_collection}`);
1241
+ }).catch((err) => {
1242
+ logger7.error(
1243
+ `Failed to clear cache for namespace: ${namespace_collection}`,
1244
+ err
1245
+ );
1246
+ });
1247
+ return res.modifiedCount;
1248
+ } catch (error) {
1249
+ const isDuplicated = error.message.includes("duplicate");
1250
+ if (isDuplicated) {
1251
+ throw new BadRequestError6("Area already exists.");
1252
+ }
1253
+ throw error;
1254
+ }
1255
+ }
1256
+ async function deleteUnit(_id, session) {
1257
+ try {
1258
+ _id = new ObjectId5(_id);
1259
+ } catch (error) {
1260
+ throw new BadRequestError6("Invalid unit ID format.");
1261
+ }
1262
+ try {
1263
+ const updateValue = {
1264
+ status: "deleted",
1265
+ updatedAt: /* @__PURE__ */ new Date(),
1266
+ deletedAt: /* @__PURE__ */ new Date()
1267
+ };
1268
+ const res = await collection.updateOne(
1269
+ { _id },
1270
+ { $set: updateValue },
1271
+ { session }
1272
+ );
1273
+ if (res.modifiedCount === 0) {
1274
+ throw new InternalServerError3("Unable to delete unit.");
1275
+ }
1276
+ delNamespace().then(() => {
1277
+ logger7.info(`Cache cleared for namespace: ${namespace_collection}`);
1278
+ }).catch((err) => {
1279
+ logger7.error(
1280
+ `Failed to clear cache for namespace: ${namespace_collection}`,
1281
+ err
1282
+ );
1283
+ });
1284
+ return res.modifiedCount;
1285
+ } catch (error) {
1286
+ throw error;
1287
+ }
1288
+ }
1289
+ return {
1290
+ createIndex,
1291
+ createTextIndex,
1292
+ createUniqueIndex,
1293
+ createUnit,
1294
+ getUnits,
1295
+ updateUnit,
1296
+ deleteUnit
1297
+ };
1298
+ }
1299
+
1300
+ // src/services/hygiene-area.service.ts
1021
1301
  function useAreaService() {
1022
- const { createArea: _createArea } = useAreaRepo();
1302
+ const { createArea: _createArea, getAreasForChecklist } = useAreaRepo();
1303
+ const { generateAreaExcel } = useAreaExportService();
1304
+ const { getUnits: _getUnits } = useUnitRepository();
1023
1305
  async function importArea({
1024
1306
  dataJson,
1025
1307
  site
@@ -1028,11 +1310,25 @@ function useAreaService() {
1028
1310
  try {
1029
1311
  dataArray = JSON.parse(dataJson);
1030
1312
  } catch (error) {
1031
- throw new BadRequestError5("Invalid JSON format for data in excel");
1313
+ throw new BadRequestError7("Invalid JSON format for data in excel");
1032
1314
  }
1033
1315
  if (!dataArray || dataArray.length === 0) {
1034
1316
  throw new NotFoundError2("No data found in the uploaded file");
1035
1317
  }
1318
+ let availableUnits = [];
1319
+ try {
1320
+ const unitsData = await _getUnits({
1321
+ page: 1,
1322
+ limit: 999999,
1323
+ search: "",
1324
+ site
1325
+ });
1326
+ if (unitsData && unitsData.items) {
1327
+ availableUnits = unitsData.items;
1328
+ }
1329
+ } catch (error) {
1330
+ logger8.warn(`Failed to fetch units for site: ${error}`);
1331
+ }
1036
1332
  const insertedAreaIds = [];
1037
1333
  const duplicateAreas = [];
1038
1334
  const failedAreas = [];
@@ -1041,42 +1337,74 @@ function useAreaService() {
1041
1337
  for (let i = 0; i < dataArray.length; i++) {
1042
1338
  const row = dataArray[i];
1043
1339
  if (!row?.TYPE) {
1044
- logger5.warn(`Skipping row ${i + 1} with missing TYPE:`, row);
1340
+ logger8.warn(`Skipping row ${i + 1} with missing TYPE:`, row);
1045
1341
  skippedRows.push(i + 1);
1046
1342
  continue;
1047
1343
  }
1048
1344
  const areaType = String(row.TYPE).trim().toLowerCase();
1049
1345
  if (!areaType) {
1050
- logger5.warn(`Skipping row ${i + 1} with empty area type`);
1346
+ logger8.warn(`Skipping row ${i + 1} with empty area type`);
1051
1347
  skippedRows.push(i + 1);
1052
1348
  continue;
1053
1349
  }
1054
- if (!row?.AREA) {
1055
- logger5.warn(`Skipping row ${i + 1} with missing AREA:`, row);
1350
+ const areaNameValue = row?.NAME || row?.AREA;
1351
+ if (!areaNameValue) {
1352
+ logger8.warn(`Skipping row ${i + 1} with missing NAME/AREA:`, row);
1056
1353
  skippedRows.push(i + 1);
1057
1354
  continue;
1058
1355
  }
1059
- const areaName = String(row.AREA).trim();
1356
+ const areaName = String(areaNameValue).trim();
1060
1357
  if (!areaName) {
1061
- logger5.warn(`Skipping row ${i + 1} with empty ${areaType} area name`);
1358
+ logger8.warn(`Skipping row ${i + 1} with empty ${areaType} area name`);
1062
1359
  skippedRows.push(i + 1);
1063
1360
  continue;
1064
1361
  }
1065
1362
  if (areaName.startsWith("Sample:")) {
1066
- logger5.warn(`Skipping row ${i + 1} with sample area: ${areaName}`);
1363
+ logger8.warn(`Skipping row ${i + 1} with sample area: ${areaName}`);
1067
1364
  skippedRows.push(i + 1);
1068
1365
  continue;
1069
1366
  }
1070
1367
  try {
1071
- const insertedId = await _createArea({
1368
+ const areaData = {
1072
1369
  type: areaType,
1073
1370
  name: areaName,
1074
1371
  site
1075
- });
1372
+ };
1373
+ if (row.SET !== void 0 && row.SET !== null && row.SET !== "") {
1374
+ const setNumber = parseInt(String(row.SET).trim());
1375
+ if (!isNaN(setNumber) && setNumber >= 0) {
1376
+ areaData.set = setNumber;
1377
+ }
1378
+ }
1379
+ if (row.UNITS && availableUnits.length > 0) {
1380
+ const unitNames = String(row.UNITS).split(",").map((u) => u.trim()).filter((u) => u);
1381
+ if (unitNames.length > 0) {
1382
+ const areaUnits = [];
1383
+ for (const unitName of unitNames) {
1384
+ const foundUnit = availableUnits.find(
1385
+ (u) => u.name.toLowerCase() === unitName.toLowerCase()
1386
+ );
1387
+ if (foundUnit) {
1388
+ areaUnits.push({
1389
+ unit: foundUnit._id,
1390
+ name: foundUnit.name
1391
+ });
1392
+ } else {
1393
+ logger8.warn(
1394
+ `Unit "${unitName}" not found in site for area "${areaName}"`
1395
+ );
1396
+ }
1397
+ }
1398
+ if (areaUnits.length > 0) {
1399
+ areaData.units = areaUnits;
1400
+ }
1401
+ }
1402
+ }
1403
+ const insertedId = await _createArea(areaData);
1076
1404
  insertedAreaIds.push(insertedId);
1077
- logger5.info(`Successfully created ${areaType} area: ${areaName}`);
1405
+ logger8.info(`Successfully created ${areaType} area: ${areaName}`);
1078
1406
  } catch (error) {
1079
- logger5.error(
1407
+ logger8.error(
1080
1408
  `Error creating ${areaType} area "${areaName}": ${error.message}`
1081
1409
  );
1082
1410
  if (error.message.includes("duplicate")) {
@@ -1096,18 +1424,18 @@ function useAreaService() {
1096
1424
  if (skippedRows.length > 0) {
1097
1425
  message += `, ${skippedRows.length} rows skipped (invalid data)`;
1098
1426
  }
1099
- logger5.info(message);
1427
+ logger8.info(message);
1100
1428
  if (insertedAreaIds.length === 0) {
1101
1429
  if (duplicateAreas.length > 0 && failedAreas.length === 0 && skippedRows.length === 0) {
1102
1430
  return {
1103
1431
  message: `No new areas were created. All ${duplicateAreas.length} areas already exist in the system: ${duplicateAreas.join(", ")}`
1104
1432
  };
1105
1433
  } else if (failedAreas.length > 0) {
1106
- throw new BadRequestError5(
1434
+ throw new BadRequestError7(
1107
1435
  `No areas were created. ${failedAreas.length} areas failed due to errors. Please check your data format and ensure area names are valid.`
1108
1436
  );
1109
1437
  } else if (skippedRows.length > 0 && duplicateAreas.length === 0) {
1110
- throw new BadRequestError5(
1438
+ throw new BadRequestError7(
1111
1439
  `No areas were created. All ${skippedRows.length} rows contained invalid or missing data.`
1112
1440
  );
1113
1441
  } else {
@@ -1118,30 +1446,46 @@ function useAreaService() {
1118
1446
  }
1119
1447
  return { message };
1120
1448
  } catch (error) {
1121
- logger5.error("Error while uploading area information", error);
1122
- if (error instanceof BadRequestError5) {
1449
+ logger8.error("Error while uploading area information", error);
1450
+ if (error instanceof BadRequestError7) {
1123
1451
  throw error;
1124
1452
  } else if (error.message.includes("validation")) {
1125
- throw new BadRequestError5(
1453
+ throw new BadRequestError7(
1126
1454
  "Upload failed due to invalid data format. Please check that all required fields are properly filled."
1127
1455
  );
1128
1456
  } else {
1129
- throw new BadRequestError5(
1457
+ throw new BadRequestError7(
1130
1458
  `Upload failed: ${error.message || "Please check your data format and try again."}`
1131
1459
  );
1132
1460
  }
1133
1461
  }
1134
1462
  }
1135
- return { importArea };
1463
+ async function exportAreas(site) {
1464
+ try {
1465
+ const areas = await getAreasForChecklist(site);
1466
+ if (!areas || !Array.isArray(areas) || areas.length === 0) {
1467
+ throw new BadRequestError7("No data found to export");
1468
+ }
1469
+ const excelBuffer = await generateAreaExcel(areas);
1470
+ if (!excelBuffer || excelBuffer.length === 0) {
1471
+ throw new Error("Generated Excel file is empty or invalid.");
1472
+ }
1473
+ return excelBuffer;
1474
+ } catch (error) {
1475
+ logger8.error(`Error downloading areas: ${error.message}`);
1476
+ throw error;
1477
+ }
1478
+ }
1479
+ return { importArea, exportAreas };
1136
1480
  }
1137
1481
 
1138
1482
  // src/controllers/hygiene-area.controller.ts
1139
- import Joi3 from "joi";
1140
- import { BadRequestError as BadRequestError6, logger as logger6 } from "@7365admin1/node-server-utils";
1483
+ import Joi4 from "joi";
1484
+ import { BadRequestError as BadRequestError8, logger as logger9 } from "@7365admin1/node-server-utils";
1141
1485
 
1142
1486
  // src/utils/convert-excel.util.ts
1143
1487
  import { Readable } from "stream";
1144
- import * as xlsx from "xlsx";
1488
+ import * as xlsx2 from "xlsx";
1145
1489
  function convertBufferFile(bufferFile) {
1146
1490
  return new Promise((resolve, reject) => {
1147
1491
  const fileStream = Readable.from(bufferFile);
@@ -1151,10 +1495,10 @@ function convertBufferFile(bufferFile) {
1151
1495
  });
1152
1496
  fileStream.on("end", () => {
1153
1497
  try {
1154
- const workbook = xlsx.read(fileBuffer, { type: "buffer" });
1498
+ const workbook = xlsx2.read(fileBuffer, { type: "buffer" });
1155
1499
  const sheetName = workbook.SheetNames[0];
1156
1500
  const sheet = workbook.Sheets[sheetName];
1157
- const jsonData = xlsx.utils.sheet_to_json(sheet);
1501
+ const jsonData = xlsx2.utils.sheet_to_json(sheet);
1158
1502
  resolve(jsonData);
1159
1503
  } catch (error) {
1160
1504
  reject("Error parsing file");
@@ -1175,13 +1519,13 @@ function useAreaController() {
1175
1519
  updateArea: _updateArea,
1176
1520
  deleteArea: _deleteById
1177
1521
  } = useAreaRepo();
1178
- const { importArea: _importArea } = useAreaService();
1522
+ const { importArea: _importArea, exportAreas: _exportAreas } = useAreaService();
1179
1523
  async function createArea(req, res, next) {
1180
1524
  const payload = { ...req.body, ...req.params };
1181
1525
  const { error } = areaSchema.validate(payload);
1182
1526
  if (error) {
1183
- logger6.log({ level: "error", message: error.message });
1184
- next(new BadRequestError6(error.message));
1527
+ logger9.log({ level: "error", message: error.message });
1528
+ next(new BadRequestError8(error.message));
1185
1529
  return;
1186
1530
  }
1187
1531
  try {
@@ -1189,24 +1533,24 @@ function useAreaController() {
1189
1533
  res.status(201).json({ message: "Area created successfully.", id });
1190
1534
  return;
1191
1535
  } catch (error2) {
1192
- logger6.log({ level: "error", message: error2.message });
1536
+ logger9.log({ level: "error", message: error2.message });
1193
1537
  next(error2);
1194
1538
  return;
1195
1539
  }
1196
1540
  }
1197
1541
  async function getAreas(req, res, next) {
1198
1542
  const query = { ...req.query, ...req.params };
1199
- const validation = Joi3.object({
1200
- page: Joi3.number().min(1).optional().allow("", null),
1201
- limit: Joi3.number().min(1).optional().allow("", null),
1202
- search: Joi3.string().optional().allow("", null),
1203
- type: Joi3.string().valid("all", ...allowedTypes).optional().allow("", null),
1204
- site: Joi3.string().hex().required()
1543
+ const validation = Joi4.object({
1544
+ page: Joi4.number().min(1).optional().allow("", null),
1545
+ limit: Joi4.number().min(1).optional().allow("", null),
1546
+ search: Joi4.string().optional().allow("", null),
1547
+ type: Joi4.string().valid("all", ...allowedTypes).optional().allow("", null),
1548
+ site: Joi4.string().hex().required()
1205
1549
  });
1206
1550
  const { error } = validation.validate(query);
1207
1551
  if (error) {
1208
- logger6.log({ level: "error", message: error.message });
1209
- next(new BadRequestError6(error.message));
1552
+ logger9.log({ level: "error", message: error.message });
1553
+ next(new BadRequestError8(error.message));
1210
1554
  return;
1211
1555
  }
1212
1556
  const page = parseInt(req.query.page) ?? 1;
@@ -1230,12 +1574,12 @@ function useAreaController() {
1230
1574
  }
1231
1575
  }
1232
1576
  async function getAreaById(req, res, next) {
1233
- const validation = Joi3.string().hex().required();
1577
+ const validation = Joi4.string().hex().required();
1234
1578
  const _id = req.params.id;
1235
1579
  const { error, value } = validation.validate(_id);
1236
1580
  if (error) {
1237
- logger6.log({ level: "error", message: error.message });
1238
- next(new BadRequestError6(error.message));
1581
+ logger9.log({ level: "error", message: error.message });
1582
+ next(new BadRequestError8(error.message));
1239
1583
  return;
1240
1584
  }
1241
1585
  try {
@@ -1243,332 +1587,173 @@ function useAreaController() {
1243
1587
  res.json(data);
1244
1588
  return;
1245
1589
  } catch (error2) {
1246
- logger6.log({ level: "error", message: error2.message });
1247
- next(error2);
1248
- return;
1249
- }
1250
- }
1251
- async function updateArea(req, res, next) {
1252
- const payload = { id: req.params.id, ...req.body };
1253
- const schema = Joi3.object({
1254
- id: Joi3.string().hex().required(),
1255
- name: Joi3.string().optional().allow("", null),
1256
- type: Joi3.string().optional().allow("", null, ...allowedTypes),
1257
- set: Joi3.number().min(0).optional(),
1258
- units: Joi3.array().items(
1259
- Joi3.object({
1260
- unit: Joi3.string().hex().required(),
1261
- name: Joi3.string().required()
1262
- }).required()
1263
- ).min(1).unique("unit", { ignoreUndefined: true }).optional().messages({
1264
- "array.unique": "Duplicate area units are not allowed"
1265
- })
1266
- });
1267
- const { error } = schema.validate(payload);
1268
- if (error) {
1269
- logger6.log({ level: "error", message: error.message });
1270
- next(new BadRequestError6(error.message));
1271
- return;
1272
- }
1273
- try {
1274
- const { id, ...value } = payload;
1275
- await _updateArea(id, value);
1276
- res.json({ message: "Area updated successfully." });
1277
- return;
1278
- } catch (error2) {
1279
- logger6.log({ level: "error", message: error2.message });
1280
- next(error2);
1281
- return;
1282
- }
1283
- }
1284
- async function deleteArea(req, res, next) {
1285
- const id = req.params.id;
1286
- const validation = Joi3.string().hex().required();
1287
- const { error, value } = validation.validate(id);
1288
- if (error) {
1289
- logger6.log({ level: "error", message: error.message });
1290
- next(new BadRequestError6(error.message));
1291
- return;
1292
- }
1293
- try {
1294
- await _deleteById(value);
1295
- res.json({ message: "Area deleted successfully." });
1296
- return;
1297
- } catch (error2) {
1298
- logger6.log({ level: "error", message: error2.message });
1299
- next(error2);
1300
- return;
1301
- }
1302
- }
1303
- async function importArea(req, res, next) {
1304
- if (!req.file) {
1305
- next(new BadRequestError6("File is required!"));
1306
- return;
1307
- }
1308
- const { site } = req.params;
1309
- const schema = Joi3.string().hex().required();
1310
- const { error, value } = schema.validate(site);
1311
- if (error) {
1312
- logger6.log({ level: "error", message: error.message });
1313
- next(new BadRequestError6(error.message));
1314
- return;
1315
- }
1316
- try {
1317
- const xlsData = await convertBufferFile(req.file.buffer);
1318
- const dataJson = JSON.stringify(xlsData);
1319
- const result = await _importArea({ dataJson, site: value });
1320
- return res.status(201).json(result);
1321
- } catch (error2) {
1322
- logger6.log({ level: "error", message: error2.message });
1590
+ logger9.log({ level: "error", message: error2.message });
1323
1591
  next(error2);
1324
- return;
1325
- }
1326
- }
1327
- return {
1328
- createArea,
1329
- getAreas,
1330
- getAreaById,
1331
- updateArea,
1332
- deleteArea,
1333
- importArea
1334
- };
1335
- }
1336
-
1337
- // src/models/hygiene-unit.model.ts
1338
- import Joi4 from "joi";
1339
- import { ObjectId as ObjectId4 } from "mongodb";
1340
- import { BadRequestError as BadRequestError7, logger as logger7 } from "@7365admin1/node-server-utils";
1341
- var unitSchema = Joi4.object({
1342
- site: Joi4.string().hex().required(),
1343
- name: Joi4.string().required()
1344
- });
1345
- function MUnit(value) {
1346
- const { error } = unitSchema.validate(value);
1347
- if (error) {
1348
- logger7.info(`Hygiene Unit Model: ${error.message}`);
1349
- throw new BadRequestError7(error.message);
1350
- }
1351
- if (value.site) {
1352
- try {
1353
- value.site = new ObjectId4(value.site);
1354
- } catch (error2) {
1355
- throw new BadRequestError7("Invalid site ID format.");
1356
- }
1357
- }
1358
- return {
1359
- site: value.site,
1360
- name: value.name,
1361
- status: "active",
1362
- createdAt: /* @__PURE__ */ new Date(),
1363
- updatedAt: "",
1364
- deletedAt: ""
1365
- };
1366
- }
1367
-
1368
- // src/services/hygiene-unit.service.ts
1369
- import {
1370
- BadRequestError as BadRequestError9,
1371
- logger as logger9,
1372
- NotFoundError as NotFoundError3,
1373
- useAtlas as useAtlas4
1374
- } from "@7365admin1/node-server-utils";
1375
-
1376
- // src/repositories/hygiene-unit.repository.ts
1377
- import { ObjectId as ObjectId5 } from "mongodb";
1378
- import {
1379
- useAtlas as useAtlas3,
1380
- InternalServerError as InternalServerError3,
1381
- paginate as paginate2,
1382
- BadRequestError as BadRequestError8,
1383
- useCache as useCache3,
1384
- logger as logger8,
1385
- makeCacheKey as makeCacheKey3
1386
- } from "@7365admin1/node-server-utils";
1387
- function useUnitRepository() {
1388
- const db = useAtlas3.getDb();
1389
- if (!db) {
1390
- throw new InternalServerError3("Unable to connect to server.");
1391
- }
1392
- const namespace_collection = "site.cleaning.area.unit";
1393
- const collection = db.collection(namespace_collection);
1394
- const { delNamespace, setCache, getCache } = useCache3(namespace_collection);
1395
- async function createIndex() {
1396
- try {
1397
- await collection.createIndexes([
1398
- { key: { site: 1 } },
1399
- { key: { status: 1 } }
1400
- ]);
1401
- } catch (error) {
1402
- throw new InternalServerError3("Failed to create index on hygiene unit.");
1403
- }
1404
- }
1405
- async function createTextIndex() {
1406
- try {
1407
- await collection.createIndex({ name: "text" });
1408
- } catch (error) {
1409
- throw new InternalServerError3(
1410
- "Failed to create text index on hygiene unit."
1411
- );
1412
- }
1413
- }
1414
- async function createUniqueIndex() {
1415
- try {
1416
- await collection.createIndex(
1417
- { site: 1, name: 1, deletedAt: 1 },
1418
- { unique: true }
1419
- );
1420
- } catch (error) {
1421
- throw new InternalServerError3(
1422
- "Failed to create unique index on hygiene unit."
1423
- );
1424
- }
1425
- }
1426
- async function createUnit(value, session) {
1427
- try {
1428
- value = MUnit(value);
1429
- const res = await collection.insertOne(value, { session });
1430
- delNamespace().then(() => {
1431
- logger8.info(`Cache cleared for namespace: ${namespace_collection}`);
1432
- }).catch((err) => {
1433
- logger8.error(
1434
- `Failed to clear cache for namespace: ${namespace_collection}`,
1435
- err
1436
- );
1437
- });
1438
- return res.insertedId;
1439
- } catch (error) {
1440
- const isDuplicated = error.message.includes("duplicate");
1441
- if (isDuplicated) {
1442
- throw new BadRequestError8("Unit already exists.");
1443
- }
1444
- throw error;
1592
+ return;
1445
1593
  }
1446
1594
  }
1447
- async function getUnits({
1448
- page = 1,
1449
- limit = 10,
1450
- search = "",
1451
- site
1452
- }) {
1453
- page = page > 0 ? page - 1 : 0;
1454
- const query = {
1455
- status: { $ne: "deleted" }
1456
- };
1457
- const cacheOptions = {
1458
- page,
1459
- limit
1460
- };
1461
- try {
1462
- site = new ObjectId5(site);
1463
- query.site = site;
1464
- cacheOptions.site = site.toString();
1465
- } catch (error) {
1466
- throw new BadRequestError8("Invalid site ID format.");
1595
+ async function updateArea(req, res, next) {
1596
+ const payload = { id: req.params.id, ...req.body };
1597
+ const schema = Joi4.object({
1598
+ id: Joi4.string().hex().required(),
1599
+ name: Joi4.string().optional().allow("", null),
1600
+ type: Joi4.string().optional().allow("", null, ...allowedTypes),
1601
+ set: Joi4.number().min(0).optional(),
1602
+ units: Joi4.array().items(
1603
+ Joi4.object({
1604
+ unit: Joi4.string().hex().required(),
1605
+ name: Joi4.string().required()
1606
+ }).required()
1607
+ ).min(1).unique("unit", { ignoreUndefined: true }).optional().messages({
1608
+ "array.unique": "Duplicate area units are not allowed"
1609
+ })
1610
+ });
1611
+ const { error } = schema.validate(payload);
1612
+ if (error) {
1613
+ logger9.log({ level: "error", message: error.message });
1614
+ next(new BadRequestError8(error.message));
1615
+ return;
1467
1616
  }
1468
- if (search) {
1469
- query.$or = [{ name: { $regex: search, $options: "i" } }];
1470
- cacheOptions.search = search;
1617
+ try {
1618
+ const { id, ...value } = payload;
1619
+ await _updateArea(id, value);
1620
+ res.json({ message: "Area updated successfully." });
1621
+ return;
1622
+ } catch (error2) {
1623
+ logger9.log({ level: "error", message: error2.message });
1624
+ next(error2);
1625
+ return;
1471
1626
  }
1472
- const cacheKey = makeCacheKey3(namespace_collection, cacheOptions);
1473
- const cachedData = await getCache(cacheKey);
1474
- if (cachedData) {
1475
- logger8.info(`Cache hit for key: ${cacheKey}`);
1476
- return cachedData;
1627
+ }
1628
+ async function deleteArea(req, res, next) {
1629
+ const id = req.params.id;
1630
+ const validation = Joi4.string().hex().required();
1631
+ const { error, value } = validation.validate(id);
1632
+ if (error) {
1633
+ logger9.log({ level: "error", message: error.message });
1634
+ next(new BadRequestError8(error.message));
1635
+ return;
1477
1636
  }
1478
1637
  try {
1479
- const items = await collection.aggregate([
1480
- { $match: query },
1481
- { $project: { name: 1 } },
1482
- { $sort: { _id: -1 } },
1483
- { $skip: page * limit },
1484
- { $limit: limit }
1485
- ]).toArray();
1486
- const length = await collection.countDocuments(query);
1487
- const data = paginate2(items, page, limit, length);
1488
- setCache(cacheKey, data, 15 * 60).then(() => {
1489
- logger8.info(`Cache set for key: ${cacheKey}`);
1490
- }).catch((err) => {
1491
- logger8.error(`Failed to set cache for key: ${cacheKey}`, err);
1492
- });
1493
- return data;
1494
- } catch (error) {
1495
- throw error;
1638
+ await _deleteById(value);
1639
+ res.json({ message: "Area deleted successfully." });
1640
+ return;
1641
+ } catch (error2) {
1642
+ logger9.log({ level: "error", message: error2.message });
1643
+ next(error2);
1644
+ return;
1496
1645
  }
1497
1646
  }
1498
- async function updateUnit(_id, value, session) {
1499
- try {
1500
- _id = new ObjectId5(_id);
1501
- } catch (error) {
1502
- throw new BadRequestError8("Invalid unit ID format.");
1647
+ async function importArea(req, res, next) {
1648
+ if (!req.file) {
1649
+ next(new BadRequestError8("File is required!"));
1650
+ return;
1651
+ }
1652
+ const { site } = req.params;
1653
+ const schema = Joi4.string().hex().required();
1654
+ const { error, value } = schema.validate(site);
1655
+ if (error) {
1656
+ logger9.log({ level: "error", message: error.message });
1657
+ next(new BadRequestError8(error.message));
1658
+ return;
1503
1659
  }
1504
1660
  try {
1505
- const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
1506
- const res = await collection.updateOne(
1507
- { _id },
1508
- { $set: updateValue },
1509
- { session }
1510
- );
1511
- if (res.modifiedCount === 0) {
1512
- throw new InternalServerError3("Unable to update cleaning unit.");
1513
- }
1514
- delNamespace().then(() => {
1515
- logger8.info(`Cache cleared for namespace: ${namespace_collection}`);
1516
- }).catch((err) => {
1517
- logger8.error(
1518
- `Failed to clear cache for namespace: ${namespace_collection}`,
1519
- err
1520
- );
1521
- });
1522
- return res.modifiedCount;
1523
- } catch (error) {
1524
- const isDuplicated = error.message.includes("duplicate");
1525
- if (isDuplicated) {
1526
- throw new BadRequestError8("Area already exists.");
1527
- }
1528
- throw error;
1661
+ const xlsData = await convertBufferFile(req.file.buffer);
1662
+ const dataJson = JSON.stringify(xlsData);
1663
+ const result = await _importArea({ dataJson, site: value });
1664
+ return res.status(201).json(result);
1665
+ } catch (error2) {
1666
+ logger9.log({ level: "error", message: error2.message });
1667
+ next(error2);
1668
+ return;
1529
1669
  }
1530
1670
  }
1531
- async function deleteUnit(_id, session) {
1532
- try {
1533
- _id = new ObjectId5(_id);
1534
- } catch (error) {
1535
- throw new BadRequestError8("Invalid unit ID format.");
1671
+ async function exportAreas(req, res, next) {
1672
+ const { site } = req.params;
1673
+ const validation = Joi4.string().hex().required();
1674
+ const { error, value } = validation.validate(site);
1675
+ if (error) {
1676
+ logger9.log({ level: "error", message: error.message });
1677
+ next(new BadRequestError8(error.message));
1678
+ return;
1536
1679
  }
1537
1680
  try {
1538
- const updateValue = {
1539
- status: "deleted",
1540
- updatedAt: /* @__PURE__ */ new Date(),
1541
- deletedAt: /* @__PURE__ */ new Date()
1542
- };
1543
- const res = await collection.updateOne(
1544
- { _id },
1545
- { $set: updateValue },
1546
- { session }
1681
+ const excelBuffer = await _exportAreas(value);
1682
+ const date = /* @__PURE__ */ new Date();
1683
+ const formattedDate = `${String(date.getMonth() + 1).padStart(
1684
+ 2,
1685
+ "0"
1686
+ )}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
1687
+ res.setHeader(
1688
+ "Content-Type",
1689
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1547
1690
  );
1548
- if (res.modifiedCount === 0) {
1549
- throw new InternalServerError3("Unable to delete unit.");
1691
+ res.setHeader(
1692
+ "Content-Disposition",
1693
+ `attachment; filename="areas-${formattedDate}.xlsx"`
1694
+ );
1695
+ res.setHeader("Content-Length", excelBuffer.length);
1696
+ res.end(excelBuffer);
1697
+ return;
1698
+ } catch (error2) {
1699
+ logger9.log({ level: "error", message: error2.message });
1700
+ next(error2);
1701
+ return;
1702
+ }
1703
+ }
1704
+ return {
1705
+ createArea,
1706
+ getAreas,
1707
+ getAreaById,
1708
+ updateArea,
1709
+ deleteArea,
1710
+ importArea,
1711
+ exportAreas
1712
+ };
1713
+ }
1714
+
1715
+ // src/services/hygiene-unit.service.ts
1716
+ import {
1717
+ BadRequestError as BadRequestError9,
1718
+ logger as logger11,
1719
+ NotFoundError as NotFoundError3,
1720
+ useAtlas as useAtlas4
1721
+ } from "@7365admin1/node-server-utils";
1722
+
1723
+ // src/services/hygiene-unit-export.service.ts
1724
+ import { logger as logger10 } from "@7365admin1/node-server-utils";
1725
+ import * as xlsx3 from "xlsx";
1726
+ function useUnitExportService() {
1727
+ async function generateUnitExcel(units) {
1728
+ try {
1729
+ const rows = [];
1730
+ rows.push(["UNIT"]);
1731
+ for (const unit of units) {
1732
+ const unitName = unit.name || "";
1733
+ rows.push([unitName]);
1550
1734
  }
1551
- delNamespace().then(() => {
1552
- logger8.info(`Cache cleared for namespace: ${namespace_collection}`);
1553
- }).catch((err) => {
1554
- logger8.error(
1555
- `Failed to clear cache for namespace: ${namespace_collection}`,
1556
- err
1557
- );
1735
+ const workbook = xlsx3.utils.book_new();
1736
+ const worksheet = xlsx3.utils.aoa_to_sheet(rows);
1737
+ worksheet["!cols"] = [
1738
+ { width: 25 }
1739
+ // UNIT
1740
+ ];
1741
+ xlsx3.utils.book_append_sheet(workbook, worksheet, "Units");
1742
+ const excelBuffer = xlsx3.write(workbook, {
1743
+ type: "buffer",
1744
+ bookType: "xlsx"
1558
1745
  });
1559
- return res.modifiedCount;
1746
+ return excelBuffer;
1560
1747
  } catch (error) {
1748
+ logger10.log({
1749
+ level: "error",
1750
+ message: `Failed to generate unit Excel: ${error.message}`
1751
+ });
1561
1752
  throw error;
1562
1753
  }
1563
1754
  }
1564
1755
  return {
1565
- createIndex,
1566
- createTextIndex,
1567
- createUniqueIndex,
1568
- createUnit,
1569
- getUnits,
1570
- updateUnit,
1571
- deleteUnit
1756
+ generateUnitExcel
1572
1757
  };
1573
1758
  }
1574
1759
 
@@ -1601,18 +1786,18 @@ function useUnitService() {
1601
1786
  for (let i = 0; i < dataArray.length; i++) {
1602
1787
  const row = dataArray[i];
1603
1788
  if (!row?.UNIT) {
1604
- logger9.warn(`Skipping row ${i + 1} with missing UNIT:`, row);
1789
+ logger11.warn(`Skipping row ${i + 1} with missing UNIT:`, row);
1605
1790
  skippedRows.push(i + 1);
1606
1791
  continue;
1607
1792
  }
1608
1793
  const unitName = String(row.UNIT).trim();
1609
1794
  if (!unitName) {
1610
- logger9.warn(`Skipping row ${i + 1} with empty unit name`);
1795
+ logger11.warn(`Skipping row ${i + 1} with empty unit name`);
1611
1796
  skippedRows.push(i + 1);
1612
1797
  continue;
1613
1798
  }
1614
1799
  if (unitName.startsWith("Sample:")) {
1615
- logger9.warn(`Skipping row ${i + 1} with sample unit: ${unitName}`);
1800
+ logger11.warn(`Skipping row ${i + 1} with sample unit: ${unitName}`);
1616
1801
  skippedRows.push(i + 1);
1617
1802
  continue;
1618
1803
  }
@@ -1622,9 +1807,9 @@ function useUnitService() {
1622
1807
  site
1623
1808
  });
1624
1809
  insertedUnitIds.push(insertedId);
1625
- logger9.info(`Successfully created unit: ${unitName}`);
1810
+ logger11.info(`Successfully created unit: ${unitName}`);
1626
1811
  } catch (error) {
1627
- logger9.error(`Error creating unit "${unitName}": ${error.message}`);
1812
+ logger11.error(`Error creating unit "${unitName}": ${error.message}`);
1628
1813
  if (error.message.includes("Unit already exists")) {
1629
1814
  duplicateUnits.push(unitName);
1630
1815
  } else {
@@ -1642,7 +1827,7 @@ function useUnitService() {
1642
1827
  if (skippedRows.length > 0) {
1643
1828
  message += `, ${skippedRows.length} rows skipped (invalid data)`;
1644
1829
  }
1645
- logger9.info(message);
1830
+ logger11.info(message);
1646
1831
  if (insertedUnitIds.length === 0) {
1647
1832
  if (duplicateUnits.length > 0 && failedUnits.length === 0) {
1648
1833
  throw new BadRequestError9(
@@ -1660,7 +1845,7 @@ function useUnitService() {
1660
1845
  }
1661
1846
  return { message };
1662
1847
  } catch (error) {
1663
- logger9.error("Error while uploading unit information", error);
1848
+ logger11.error("Error while uploading unit information", error);
1664
1849
  if (error instanceof BadRequestError9) {
1665
1850
  throw error;
1666
1851
  } else if (error.message.includes("duplicate")) {
@@ -1690,7 +1875,7 @@ function useUnitService() {
1690
1875
  await session?.commitTransaction();
1691
1876
  return result;
1692
1877
  } catch (error) {
1693
- logger9.error(`Error updating unit and associated areas:`, error);
1878
+ logger11.error(`Error updating unit and associated areas:`, error);
1694
1879
  if (session?.inTransaction()) {
1695
1880
  await session?.abortTransaction();
1696
1881
  }
@@ -1711,7 +1896,7 @@ function useUnitService() {
1711
1896
  await session?.commitTransaction();
1712
1897
  return result;
1713
1898
  } catch (error) {
1714
- logger9.error(`Error deleting unit:`, error);
1899
+ logger11.error(`Error deleting unit:`, error);
1715
1900
  if (session?.inTransaction()) {
1716
1901
  await session?.abortTransaction();
1717
1902
  }
@@ -1720,24 +1905,48 @@ function useUnitService() {
1720
1905
  session?.endSession();
1721
1906
  }
1722
1907
  }
1723
- return { importUnit, updateUnit, deleteUnit };
1908
+ async function exportUnits(site) {
1909
+ const { generateUnitExcel: _generateUnitExcel } = useUnitExportService();
1910
+ const { getUnits: _getUnits } = useUnitRepository();
1911
+ try {
1912
+ const data = await _getUnits({
1913
+ page: 1,
1914
+ limit: 999999,
1915
+ search: "",
1916
+ site
1917
+ });
1918
+ if (!data || !data.items || data.items.length === 0) {
1919
+ throw new BadRequestError9("No data found to export");
1920
+ }
1921
+ const excelBuffer = await _generateUnitExcel(data.items);
1922
+ if (!excelBuffer || excelBuffer.length === 0) {
1923
+ throw new Error("Generated Excel file is empty or invalid.");
1924
+ }
1925
+ return excelBuffer;
1926
+ } catch (error) {
1927
+ logger11.error(`Error downloading units: ${error.message}`);
1928
+ throw error;
1929
+ }
1930
+ }
1931
+ return { importUnit, updateUnit, deleteUnit, exportUnits };
1724
1932
  }
1725
1933
 
1726
1934
  // src/controllers/hygiene-unit.controller.ts
1727
1935
  import Joi5 from "joi";
1728
- import { BadRequestError as BadRequestError10, logger as logger10 } from "@7365admin1/node-server-utils";
1936
+ import { BadRequestError as BadRequestError10, logger as logger12 } from "@7365admin1/node-server-utils";
1729
1937
  function useUnitController() {
1730
1938
  const { createUnit: _createUnit, getUnits: _getUnits } = useUnitRepository();
1731
1939
  const {
1732
1940
  updateUnit: _updateUnit,
1733
1941
  deleteUnit: _deleteUnit,
1734
- importUnit: _importUnit
1942
+ importUnit: _importUnit,
1943
+ exportUnits: _exportUnits
1735
1944
  } = useUnitService();
1736
1945
  async function createUnit(req, res, next) {
1737
1946
  const payload = { ...req.body, ...req.params };
1738
1947
  const { error } = unitSchema.validate(payload);
1739
1948
  if (error) {
1740
- logger10.log({ level: "error", message: error.message });
1949
+ logger12.log({ level: "error", message: error.message });
1741
1950
  next(new BadRequestError10(error.message));
1742
1951
  return;
1743
1952
  }
@@ -1746,7 +1955,7 @@ function useUnitController() {
1746
1955
  res.status(201).json({ message: "Unit created successfully.", id });
1747
1956
  return;
1748
1957
  } catch (error2) {
1749
- logger10.log({ level: "error", message: error2.message });
1958
+ logger12.log({ level: "error", message: error2.message });
1750
1959
  next(error2);
1751
1960
  return;
1752
1961
  }
@@ -1761,7 +1970,7 @@ function useUnitController() {
1761
1970
  });
1762
1971
  const { error } = validation.validate(query);
1763
1972
  if (error) {
1764
- logger10.log({ level: "error", message: error.message });
1973
+ logger12.log({ level: "error", message: error.message });
1765
1974
  next(new BadRequestError10(error.message));
1766
1975
  return;
1767
1976
  }
@@ -1779,7 +1988,7 @@ function useUnitController() {
1779
1988
  res.json(data);
1780
1989
  return;
1781
1990
  } catch (error2) {
1782
- logger10.log({ level: "error", message: error2.message });
1991
+ logger12.log({ level: "error", message: error2.message });
1783
1992
  next(error2);
1784
1993
  return;
1785
1994
  }
@@ -1792,7 +2001,7 @@ function useUnitController() {
1792
2001
  });
1793
2002
  const { error } = validation.validate(payload);
1794
2003
  if (error) {
1795
- logger10.log({ level: "error", message: error.message });
2004
+ logger12.log({ level: "error", message: error.message });
1796
2005
  next(new BadRequestError10(error.message));
1797
2006
  return;
1798
2007
  }
@@ -1802,7 +2011,7 @@ function useUnitController() {
1802
2011
  res.json({ message: "Unit updated successfully." });
1803
2012
  return;
1804
2013
  } catch (error2) {
1805
- logger10.log({ level: "error", message: error2.message });
2014
+ logger12.log({ level: "error", message: error2.message });
1806
2015
  next(error2);
1807
2016
  return;
1808
2017
  }
@@ -1814,7 +2023,7 @@ function useUnitController() {
1814
2023
  });
1815
2024
  const { error, value } = validation.validate({ id });
1816
2025
  if (error) {
1817
- logger10.log({ level: "error", message: error.message });
2026
+ logger12.log({ level: "error", message: error.message });
1818
2027
  next(new BadRequestError10(error.message));
1819
2028
  return;
1820
2029
  }
@@ -1823,7 +2032,7 @@ function useUnitController() {
1823
2032
  res.json({ message: "Unit deleted successfully." });
1824
2033
  return;
1825
2034
  } catch (error2) {
1826
- logger10.log({ level: "error", message: error2.message });
2035
+ logger12.log({ level: "error", message: error2.message });
1827
2036
  next(error2);
1828
2037
  return;
1829
2038
  }
@@ -1837,7 +2046,7 @@ function useUnitController() {
1837
2046
  const validation = Joi5.string().hex().required();
1838
2047
  const { error, value } = validation.validate(site);
1839
2048
  if (error) {
1840
- logger10.log({ level: "error", message: error.message });
2049
+ logger12.log({ level: "error", message: error.message });
1841
2050
  next(new BadRequestError10(error.message));
1842
2051
  return;
1843
2052
  }
@@ -1847,7 +2056,40 @@ function useUnitController() {
1847
2056
  const result = await _importUnit({ dataJson, site: value });
1848
2057
  return res.status(201).json(result);
1849
2058
  } catch (error2) {
1850
- logger10.log({ level: "error", message: error2.message });
2059
+ logger12.log({ level: "error", message: error2.message });
2060
+ next(error2);
2061
+ return;
2062
+ }
2063
+ }
2064
+ async function exportUnits(req, res, next) {
2065
+ const { site } = req.params;
2066
+ const validation = Joi5.string().hex().required();
2067
+ const { error, value } = validation.validate(site);
2068
+ if (error) {
2069
+ logger12.log({ level: "error", message: error.message });
2070
+ next(new BadRequestError10(error.message));
2071
+ return;
2072
+ }
2073
+ try {
2074
+ const excelBuffer = await _exportUnits(value);
2075
+ const date = /* @__PURE__ */ new Date();
2076
+ const formattedDate = `${String(date.getMonth() + 1).padStart(
2077
+ 2,
2078
+ "0"
2079
+ )}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
2080
+ res.setHeader(
2081
+ "Content-Type",
2082
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
2083
+ );
2084
+ res.setHeader(
2085
+ "Content-Disposition",
2086
+ `attachment; filename="units-${formattedDate}.xlsx"`
2087
+ );
2088
+ res.setHeader("Content-Length", excelBuffer.length);
2089
+ res.end(excelBuffer);
2090
+ return;
2091
+ } catch (error2) {
2092
+ logger12.log({ level: "error", message: error2.message });
1851
2093
  next(error2);
1852
2094
  return;
1853
2095
  }
@@ -1857,14 +2099,15 @@ function useUnitController() {
1857
2099
  getUnits,
1858
2100
  updateUnit,
1859
2101
  deleteUnit,
1860
- importUnit
2102
+ importUnit,
2103
+ exportUnits
1861
2104
  };
1862
2105
  }
1863
2106
 
1864
2107
  // src/models/hygiene-parent-checklist.model.ts
1865
2108
  import Joi6 from "joi";
1866
2109
  import { ObjectId as ObjectId6 } from "mongodb";
1867
- import { BadRequestError as BadRequestError11, logger as logger11 } from "@7365admin1/node-server-utils";
2110
+ import { BadRequestError as BadRequestError11, logger as logger13 } from "@7365admin1/node-server-utils";
1868
2111
  var parentChecklistSchema = Joi6.object({
1869
2112
  createdAt: Joi6.alternatives().try(Joi6.date(), Joi6.string()).optional().allow("", null),
1870
2113
  site: Joi6.string().hex().required()
@@ -1872,7 +2115,7 @@ var parentChecklistSchema = Joi6.object({
1872
2115
  function MParentChecklist(value) {
1873
2116
  const { error } = parentChecklistSchema.validate(value);
1874
2117
  if (error) {
1875
- logger11.info(`Hygiene Parent Checklist Model: ${error.message}`);
2118
+ logger13.info(`Hygiene Parent Checklist Model: ${error.message}`);
1876
2119
  throw new BadRequestError11(error.message);
1877
2120
  }
1878
2121
  if (value.site) {
@@ -1897,7 +2140,7 @@ import {
1897
2140
  InternalServerError as InternalServerError4,
1898
2141
  paginate as paginate3,
1899
2142
  useCache as useCache4,
1900
- logger as logger12,
2143
+ logger as logger14,
1901
2144
  makeCacheKey as makeCacheKey4,
1902
2145
  BadRequestError as BadRequestError12
1903
2146
  } from "@7365admin1/node-server-utils";
@@ -1940,7 +2183,7 @@ function useParentChecklistRepo() {
1940
2183
  if (value.site) {
1941
2184
  try {
1942
2185
  existingQuery.site = new ObjectId7(value.site);
1943
- logger12.info(
2186
+ logger14.info(
1944
2187
  `createParentChecklist: Looking for existing checklist with query: ${JSON.stringify(
1945
2188
  { ...existingQuery, site: value.site }
1946
2189
  )}`
@@ -1949,7 +2192,7 @@ function useParentChecklistRepo() {
1949
2192
  throw new BadRequestError12("Invalid site ID format.");
1950
2193
  }
1951
2194
  } else {
1952
- logger12.info(
2195
+ logger14.info(
1953
2196
  `createParentChecklist: Looking for existing checklist with query (no site filter): ${JSON.stringify(
1954
2197
  existingQuery
1955
2198
  )}`
@@ -1958,7 +2201,7 @@ function useParentChecklistRepo() {
1958
2201
  const existingChecklist = await collection.findOne(existingQuery);
1959
2202
  if (existingChecklist) {
1960
2203
  const dateStr2 = currentDate.toISOString().split("T")[0];
1961
- logger12.info(
2204
+ logger14.info(
1962
2205
  `Parent checklist already exists for ${value.site ? `site ${value.site} on` : ""} today: ${dateStr2}. Found checklist: ${JSON.stringify({
1963
2206
  _id: existingChecklist._id,
1964
2207
  site: existingChecklist.site
@@ -1973,26 +2216,26 @@ function useParentChecklistRepo() {
1973
2216
  });
1974
2217
  const result2 = await collection.insertOne(checklistDoc, { session });
1975
2218
  delNamespace().then(() => {
1976
- logger12.info(`Cache cleared for namespace: ${namespace_collection}`);
2219
+ logger14.info(`Cache cleared for namespace: ${namespace_collection}`);
1977
2220
  }).catch((err) => {
1978
- logger12.error(
2221
+ logger14.error(
1979
2222
  `Failed to clear cache for namespace: ${namespace_collection}`,
1980
2223
  err
1981
2224
  );
1982
2225
  });
1983
2226
  const dateStr2 = currentDate.toISOString().split("T")[0];
1984
- logger12.info(
2227
+ logger14.info(
1985
2228
  `Created parent checklist for site ${value.site} for today: ${dateStr2}`
1986
2229
  );
1987
2230
  return result2.insertedId;
1988
2231
  }
1989
2232
  const siteIds = await getHygieneSiteIds();
1990
2233
  if (!Array.isArray(siteIds)) {
1991
- logger12.error("getHygieneSiteIds returned non-array value:", siteIds);
2234
+ logger14.error("getHygieneSiteIds returned non-array value:", siteIds);
1992
2235
  throw new InternalServerError4("Failed to retrieve site IDs");
1993
2236
  }
1994
2237
  if (siteIds.length === 0) {
1995
- logger12.warn("No sites found for creating parent checklist");
2238
+ logger14.warn("No sites found for creating parent checklist");
1996
2239
  throw new BadRequestError12("No sites available for checklist creation");
1997
2240
  }
1998
2241
  const checklistDocs = [];
@@ -2006,20 +2249,20 @@ function useParentChecklistRepo() {
2006
2249
  }
2007
2250
  const result = await collection.insertMany(checklistDocs, { session });
2008
2251
  delNamespace().then(() => {
2009
- logger12.info(`Cache cleared for namespace: ${namespace_collection}`);
2252
+ logger14.info(`Cache cleared for namespace: ${namespace_collection}`);
2010
2253
  }).catch((err) => {
2011
- logger12.error(
2254
+ logger14.error(
2012
2255
  `Failed to clear cache for namespace: ${namespace_collection}`,
2013
2256
  err
2014
2257
  );
2015
2258
  });
2016
2259
  const dateStr = currentDate.toISOString().split("T")[0];
2017
- logger12.info(
2260
+ logger14.info(
2018
2261
  `Created ${Object.keys(result.insertedIds).length} parent checklists for today: ${dateStr}`
2019
2262
  );
2020
2263
  return Object.values(result.insertedIds);
2021
2264
  } catch (error) {
2022
- logger12.error("Failed to create daily parent checklist", error);
2265
+ logger14.error("Failed to create daily parent checklist", error);
2023
2266
  throw error;
2024
2267
  }
2025
2268
  }
@@ -2070,7 +2313,7 @@ function useParentChecklistRepo() {
2070
2313
  const cacheKey = makeCacheKey4(namespace_collection, cacheOptions);
2071
2314
  const cachedData = await getCache(cacheKey);
2072
2315
  if (cachedData) {
2073
- logger12.info(`Cache hit for key: ${cacheKey}`);
2316
+ logger14.info(`Cache hit for key: ${cacheKey}`);
2074
2317
  return cachedData;
2075
2318
  }
2076
2319
  try {
@@ -2105,9 +2348,9 @@ function useParentChecklistRepo() {
2105
2348
  const length = await collection.countDocuments(query);
2106
2349
  const data = paginate3(items, page, limit, length);
2107
2350
  setCache(cacheKey, data, 15 * 60).then(() => {
2108
- logger12.info(`Cache set for key: ${cacheKey}`);
2351
+ logger14.info(`Cache set for key: ${cacheKey}`);
2109
2352
  }).catch((err) => {
2110
- logger12.error(`Failed to set cache for key: ${cacheKey}`, err);
2353
+ logger14.error(`Failed to set cache for key: ${cacheKey}`, err);
2111
2354
  });
2112
2355
  return data;
2113
2356
  } catch (error) {
@@ -2139,9 +2382,9 @@ function useParentChecklistRepo() {
2139
2382
  );
2140
2383
  }
2141
2384
  delNamespace().then(() => {
2142
- logger12.info(`Cache cleared for namespace: ${namespace_collection}`);
2385
+ logger14.info(`Cache cleared for namespace: ${namespace_collection}`);
2143
2386
  }).catch((err) => {
2144
- logger12.error(
2387
+ logger14.error(
2145
2388
  `Failed to clear cache for namespace: ${namespace_collection}`,
2146
2389
  err
2147
2390
  );
@@ -2158,7 +2401,7 @@ function useParentChecklistRepo() {
2158
2401
  const cacheKey = makeCacheKey4(site_collection, { tag: "site-ids" });
2159
2402
  const cachedData = await getCache(cacheKey);
2160
2403
  if (cachedData && Array.isArray(cachedData)) {
2161
- logger12.info(`Cache hit for key: ${cacheKey}`);
2404
+ logger14.info(`Cache hit for key: ${cacheKey}`);
2162
2405
  return cachedData;
2163
2406
  }
2164
2407
  try {
@@ -2170,14 +2413,14 @@ function useParentChecklistRepo() {
2170
2413
  const siteIds = items.map((item) => item._id.toString());
2171
2414
  if (siteIds.length > 0) {
2172
2415
  setCache(cacheKey, siteIds, 15 * 60).then(() => {
2173
- logger12.info(`Cache set for key: ${cacheKey}`);
2416
+ logger14.info(`Cache set for key: ${cacheKey}`);
2174
2417
  }).catch((err) => {
2175
- logger12.error(`Failed to set cache for key: ${cacheKey}`, err);
2418
+ logger14.error(`Failed to set cache for key: ${cacheKey}`, err);
2176
2419
  });
2177
2420
  }
2178
2421
  return siteIds;
2179
2422
  } catch (error) {
2180
- logger12.error("Failed to get hygiene site IDs", error);
2423
+ logger14.error("Failed to get hygiene site IDs", error);
2181
2424
  throw error;
2182
2425
  }
2183
2426
  }
@@ -2191,7 +2434,7 @@ function useParentChecklistRepo() {
2191
2434
 
2192
2435
  // src/controllers/hygiene-parent-checklist.controller.ts
2193
2436
  import Joi7 from "joi";
2194
- import { BadRequestError as BadRequestError13, logger as logger13 } from "@7365admin1/node-server-utils";
2437
+ import { BadRequestError as BadRequestError13, logger as logger15 } from "@7365admin1/node-server-utils";
2195
2438
  function useParentChecklistController() {
2196
2439
  const {
2197
2440
  createParentChecklist: _createParentChecklist,
@@ -2201,7 +2444,7 @@ function useParentChecklistController() {
2201
2444
  const payload = req.body;
2202
2445
  const { error } = parentChecklistSchema.validate(payload);
2203
2446
  if (error) {
2204
- logger13.log({ level: "error", message: error.message });
2447
+ logger15.log({ level: "error", message: error.message });
2205
2448
  next(new BadRequestError13(error.message));
2206
2449
  return;
2207
2450
  }
@@ -2210,7 +2453,7 @@ function useParentChecklistController() {
2210
2453
  res.status(201).json({ message: "Parent checklist created successfully.", id });
2211
2454
  return;
2212
2455
  } catch (error2) {
2213
- logger13.log({ level: "error", message: error2.message });
2456
+ logger15.log({ level: "error", message: error2.message });
2214
2457
  next(error2);
2215
2458
  return;
2216
2459
  }
@@ -2228,7 +2471,7 @@ function useParentChecklistController() {
2228
2471
  });
2229
2472
  const { error } = validation.validate(query);
2230
2473
  if (error) {
2231
- logger13.log({ level: "error", message: error.message });
2474
+ logger15.log({ level: "error", message: error.message });
2232
2475
  next(new BadRequestError13(error.message));
2233
2476
  return;
2234
2477
  }
@@ -2252,7 +2495,7 @@ function useParentChecklistController() {
2252
2495
  res.json(data);
2253
2496
  return;
2254
2497
  } catch (error2) {
2255
- logger13.log({ level: "error", message: error2.message });
2498
+ logger15.log({ level: "error", message: error2.message });
2256
2499
  next(error2);
2257
2500
  return;
2258
2501
  }
@@ -2266,7 +2509,7 @@ function useParentChecklistController() {
2266
2509
  // src/models/hygiene-area-checklist.model.ts
2267
2510
  import Joi8 from "joi";
2268
2511
  import { ObjectId as ObjectId8 } from "mongodb";
2269
- import { BadRequestError as BadRequestError14, logger as logger14 } from "@7365admin1/node-server-utils";
2512
+ import { BadRequestError as BadRequestError14, logger as logger16 } from "@7365admin1/node-server-utils";
2270
2513
  var allowedChecklistStatus = ["ready", "completed"];
2271
2514
  var areaChecklistSchema = Joi8.object({
2272
2515
  schedule: Joi8.string().hex().required(),
@@ -2289,7 +2532,7 @@ var areaChecklistSchema = Joi8.object({
2289
2532
  function MAreaChecklist(value) {
2290
2533
  const { error } = areaChecklistSchema.validate(value);
2291
2534
  if (error) {
2292
- logger14.info(`Hygiene Checklist Area Model: ${error.message}`);
2535
+ logger16.info(`Hygiene Checklist Area Model: ${error.message}`);
2293
2536
  throw new BadRequestError14(error.message);
2294
2537
  }
2295
2538
  if (value.schedule) {
@@ -2343,14 +2586,14 @@ function MAreaChecklist(value) {
2343
2586
  }
2344
2587
 
2345
2588
  // src/services/hygiene-area-checklist.service.ts
2346
- import { logger as logger16, useAtlas as useAtlas7 } from "@7365admin1/node-server-utils";
2589
+ import { logger as logger18, useAtlas as useAtlas7 } from "@7365admin1/node-server-utils";
2347
2590
 
2348
2591
  // src/repositories/hygiene-area-checklist.repository.ts
2349
2592
  import { ObjectId as ObjectId9 } from "mongodb";
2350
2593
  import {
2351
2594
  BadRequestError as BadRequestError15,
2352
2595
  InternalServerError as InternalServerError5,
2353
- logger as logger15,
2596
+ logger as logger17,
2354
2597
  makeCacheKey as makeCacheKey5,
2355
2598
  paginate as paginate4,
2356
2599
  useAtlas as useAtlas6,
@@ -2411,7 +2654,7 @@ function useAreaChecklistRepo() {
2411
2654
  }
2412
2655
  });
2413
2656
  if (existingChecklist) {
2414
- logger15.info(
2657
+ logger17.info(
2415
2658
  `Area checklist already exists for area ${value.name} on ${currentDate.toISOString().split("T")[0]}`
2416
2659
  );
2417
2660
  return existingChecklist._id;
@@ -2419,9 +2662,9 @@ function useAreaChecklistRepo() {
2419
2662
  const processedValue = MAreaChecklist(value);
2420
2663
  const result = await collection.insertOne(processedValue, { session });
2421
2664
  delNamespace().then(() => {
2422
- logger15.info(`Cache cleared for namespace: ${namespace_collection}`);
2665
+ logger17.info(`Cache cleared for namespace: ${namespace_collection}`);
2423
2666
  }).catch((err) => {
2424
- logger15.error(
2667
+ logger17.error(
2425
2668
  `Failed to clear cache for namespace: ${namespace_collection}`,
2426
2669
  err
2427
2670
  );
@@ -2467,7 +2710,7 @@ function useAreaChecklistRepo() {
2467
2710
  if (!session) {
2468
2711
  const cachedData = await getCache(cacheKey);
2469
2712
  if (cachedData) {
2470
- logger15.info(`Cache hit for key: ${cacheKey}`);
2713
+ logger17.info(`Cache hit for key: ${cacheKey}`);
2471
2714
  return cachedData;
2472
2715
  }
2473
2716
  }
@@ -2543,9 +2786,9 @@ function useAreaChecklistRepo() {
2543
2786
  const length = await collection.countDocuments(query, { session });
2544
2787
  const data = paginate4(items, page, limit, length);
2545
2788
  setCache(cacheKey, data, 15 * 60).then(() => {
2546
- logger15.info(`Cache set for key: ${cacheKey}`);
2789
+ logger17.info(`Cache set for key: ${cacheKey}`);
2547
2790
  }).catch((err) => {
2548
- logger15.error(`Failed to set cache for key: ${cacheKey}`, err);
2791
+ logger17.error(`Failed to set cache for key: ${cacheKey}`, err);
2549
2792
  });
2550
2793
  return data;
2551
2794
  } catch (error) {
@@ -2597,7 +2840,7 @@ function useAreaChecklistRepo() {
2597
2840
  const cacheKey = makeCacheKey5(namespace_collection, cacheOptions);
2598
2841
  const cachedData = await getCache(cacheKey);
2599
2842
  if (cachedData) {
2600
- logger15.info(`Cache hit for key: ${cacheKey}`);
2843
+ logger17.info(`Cache hit for key: ${cacheKey}`);
2601
2844
  return cachedData;
2602
2845
  }
2603
2846
  try {
@@ -2647,9 +2890,9 @@ function useAreaChecklistRepo() {
2647
2890
  const length = await collection.countDocuments(query);
2648
2891
  const data = paginate4(items, page, limit, length);
2649
2892
  setCache(cacheKey, data, 15 * 60).then(() => {
2650
- logger15.info(`Cache set for key: ${cacheKey}`);
2893
+ logger17.info(`Cache set for key: ${cacheKey}`);
2651
2894
  }).catch((err) => {
2652
- logger15.error(`Failed to set cache for key: ${cacheKey}`, err);
2895
+ logger17.error(`Failed to set cache for key: ${cacheKey}`, err);
2653
2896
  });
2654
2897
  return data;
2655
2898
  } catch (error) {
@@ -2667,7 +2910,7 @@ function useAreaChecklistRepo() {
2667
2910
  });
2668
2911
  const cachedData = await getCache(cacheKey);
2669
2912
  if (cachedData) {
2670
- logger15.info(`Cache hit for key: ${cacheKey}`);
2913
+ logger17.info(`Cache hit for key: ${cacheKey}`);
2671
2914
  return cachedData;
2672
2915
  }
2673
2916
  try {
@@ -2797,9 +3040,9 @@ function useAreaChecklistRepo() {
2797
3040
  units
2798
3041
  };
2799
3042
  setCache(cacheKey, items, 15 * 60).then(() => {
2800
- logger15.info(`Cache set for key: ${cacheKey}`);
3043
+ logger17.info(`Cache set for key: ${cacheKey}`);
2801
3044
  }).catch((err) => {
2802
- logger15.error(`Failed to set cache for key: ${cacheKey}`, err);
3045
+ logger17.error(`Failed to set cache for key: ${cacheKey}`, err);
2803
3046
  });
2804
3047
  return items;
2805
3048
  } catch (error) {
@@ -2832,7 +3075,7 @@ function useAreaChecklistRepo() {
2832
3075
  if (!session) {
2833
3076
  const cachedData = await getCache(cacheKey);
2834
3077
  if (cachedData) {
2835
- logger15.info(`Cache hit for key: ${cacheKey}`);
3078
+ logger17.info(`Cache hit for key: ${cacheKey}`);
2836
3079
  return cachedData;
2837
3080
  }
2838
3081
  }
@@ -2922,9 +3165,9 @@ function useAreaChecklistRepo() {
2922
3165
  const length = countResult.length > 0 ? countResult[0].total : 0;
2923
3166
  const data = paginate4(items, page, limit, length);
2924
3167
  setCache(cacheKey, data, 15 * 60).then(() => {
2925
- logger15.info(`Cache set for key: ${cacheKey}`);
3168
+ logger17.info(`Cache set for key: ${cacheKey}`);
2926
3169
  }).catch((err) => {
2927
- logger15.error(`Failed to set cache for key: ${cacheKey}`, err);
3170
+ logger17.error(`Failed to set cache for key: ${cacheKey}`, err);
2928
3171
  });
2929
3172
  return data;
2930
3173
  } catch (error) {
@@ -3004,16 +3247,16 @@ function useAreaChecklistRepo() {
3004
3247
  throw new InternalServerError5("Unable to update area checklist unit.");
3005
3248
  }
3006
3249
  delNamespace().then(() => {
3007
- logger15.info(`Cache cleared for namespace: ${namespace_collection}`);
3250
+ logger17.info(`Cache cleared for namespace: ${namespace_collection}`);
3008
3251
  }).catch((err) => {
3009
- logger15.error(
3252
+ logger17.error(
3010
3253
  `Failed to clear cache for namespace: ${namespace_collection}`,
3011
3254
  err
3012
3255
  );
3013
3256
  });
3014
3257
  return res.modifiedCount;
3015
3258
  } catch (error) {
3016
- logger15.error("Error updating area checklist unit:", error.message);
3259
+ logger17.error("Error updating area checklist unit:", error.message);
3017
3260
  throw error;
3018
3261
  }
3019
3262
  }
@@ -3037,9 +3280,9 @@ function useAreaChecklistRepo() {
3037
3280
  throw new InternalServerError5("Unable to update area checklist.");
3038
3281
  }
3039
3282
  delNamespace().then(() => {
3040
- logger15.info(`Cache cleared for namespace: ${namespace_collection}`);
3283
+ logger17.info(`Cache cleared for namespace: ${namespace_collection}`);
3041
3284
  }).catch((err) => {
3042
- logger15.error(
3285
+ logger17.error(
3043
3286
  `Failed to clear cache for namespace: ${namespace_collection}`,
3044
3287
  err
3045
3288
  );
@@ -3074,9 +3317,9 @@ function useAreaChecklistRepo() {
3074
3317
  );
3075
3318
  }
3076
3319
  delNamespace().then(() => {
3077
- logger15.info(`Cache cleared for namespace: ${namespace_collection}`);
3320
+ logger17.info(`Cache cleared for namespace: ${namespace_collection}`);
3078
3321
  }).catch((err) => {
3079
- logger15.error(
3322
+ logger17.error(
3080
3323
  `Failed to clear cache for namespace: ${namespace_collection}`,
3081
3324
  err
3082
3325
  );
@@ -3099,7 +3342,7 @@ function useAreaChecklistRepo() {
3099
3342
  ).toArray();
3100
3343
  return result.length > 0 && result[0].maxSet ? result[0].maxSet : 0;
3101
3344
  } catch (error) {
3102
- logger15.error(`Error getting max set number for area ${areaId}:`, error);
3345
+ logger17.error(`Error getting max set number for area ${areaId}:`, error);
3103
3346
  return 0;
3104
3347
  }
3105
3348
  }
@@ -3147,7 +3390,7 @@ function useAreaChecklistService() {
3147
3390
  const batch = areas.slice(i, i + BATCH_SIZE);
3148
3391
  const batchPromises = batch.map(async (area) => {
3149
3392
  if (!area.units || area.units.length === 0) {
3150
- logger16.warn(
3393
+ logger18.warn(
3151
3394
  `Skipping area ${area.name} (${area._id}): No units defined`
3152
3395
  );
3153
3396
  return null;
@@ -3178,19 +3421,19 @@ function useAreaChecklistService() {
3178
3421
  const batchResults = await Promise.all(batchPromises);
3179
3422
  results.push(...batchResults.filter((id) => id !== null));
3180
3423
  }
3181
- logger16.info(
3424
+ logger18.info(
3182
3425
  `Created ${totalChecklistsCreated} area checklists out of ${areas.length} areas for site: ${value.site}`
3183
3426
  );
3184
3427
  } else {
3185
- logger16.warn(`No common areas found for site: ${value.site}`);
3428
+ logger18.warn(`No common areas found for site: ${value.site}`);
3186
3429
  }
3187
3430
  await session?.commitTransaction();
3188
- logger16.info(
3431
+ logger18.info(
3189
3432
  `Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
3190
3433
  );
3191
3434
  return results;
3192
3435
  } catch (error) {
3193
- logger16.error(`Error generating area checklists:`, error);
3436
+ logger18.error(`Error generating area checklists:`, error);
3194
3437
  if (session?.inTransaction()) {
3195
3438
  await session?.abortTransaction();
3196
3439
  }
@@ -3266,7 +3509,7 @@ function useAreaChecklistService() {
3266
3509
  session
3267
3510
  );
3268
3511
  } else {
3269
- logger16.info(
3512
+ logger18.info(
3270
3513
  "No area checklists found, keeping parent status as ready"
3271
3514
  );
3272
3515
  }
@@ -3274,7 +3517,7 @@ function useAreaChecklistService() {
3274
3517
  await session?.commitTransaction();
3275
3518
  return;
3276
3519
  } catch (error) {
3277
- logger16.error(`Error updating area checklist unit and statuses:`, error);
3520
+ logger18.error(`Error updating area checklist unit and statuses:`, error);
3278
3521
  if (session?.inTransaction()) {
3279
3522
  await session?.abortTransaction();
3280
3523
  }
@@ -3288,7 +3531,7 @@ function useAreaChecklistService() {
3288
3531
 
3289
3532
  // src/controllers/hygiene-area-checklist.controller.ts
3290
3533
  import Joi9 from "joi";
3291
- import { BadRequestError as BadRequestError16, logger as logger17 } from "@7365admin1/node-server-utils";
3534
+ import { BadRequestError as BadRequestError16, logger as logger19 } from "@7365admin1/node-server-utils";
3292
3535
  function useAreaChecklistController() {
3293
3536
  const {
3294
3537
  getAllAreaChecklist: _getAllAreaChecklist,
@@ -3318,7 +3561,7 @@ function useAreaChecklistController() {
3318
3561
  });
3319
3562
  const { error, value } = validation.validate(payload);
3320
3563
  if (error) {
3321
- logger17.log({ level: "error", message: error.message });
3564
+ logger19.log({ level: "error", message: error.message });
3322
3565
  next(new BadRequestError16(error.message));
3323
3566
  return;
3324
3567
  }
@@ -3327,7 +3570,7 @@ function useAreaChecklistController() {
3327
3570
  res.status(201).json({ message: "Area checklist generated successfully." });
3328
3571
  return;
3329
3572
  } catch (error2) {
3330
- logger17.log({ level: "error", message: error2.message });
3573
+ logger19.log({ level: "error", message: error2.message });
3331
3574
  next(error2);
3332
3575
  return;
3333
3576
  }
@@ -3344,7 +3587,7 @@ function useAreaChecklistController() {
3344
3587
  });
3345
3588
  const { error } = validation.validate(query);
3346
3589
  if (error) {
3347
- logger17.log({ level: "error", message: error.message });
3590
+ logger19.log({ level: "error", message: error.message });
3348
3591
  next(new BadRequestError16(error.message));
3349
3592
  return;
3350
3593
  }
@@ -3366,7 +3609,7 @@ function useAreaChecklistController() {
3366
3609
  res.json(data);
3367
3610
  return;
3368
3611
  } catch (error2) {
3369
- logger17.log({ level: "error", message: error2.message });
3612
+ logger19.log({ level: "error", message: error2.message });
3370
3613
  next(error2);
3371
3614
  return;
3372
3615
  }
@@ -3384,7 +3627,7 @@ function useAreaChecklistController() {
3384
3627
  });
3385
3628
  const { error } = validation.validate(query);
3386
3629
  if (error) {
3387
- logger17.log({ level: "error", message: error.message });
3630
+ logger19.log({ level: "error", message: error.message });
3388
3631
  next(new BadRequestError16(error.message));
3389
3632
  return;
3390
3633
  }
@@ -3408,7 +3651,7 @@ function useAreaChecklistController() {
3408
3651
  res.json(data);
3409
3652
  return;
3410
3653
  } catch (error2) {
3411
- logger17.log({ level: "error", message: error2.message });
3654
+ logger19.log({ level: "error", message: error2.message });
3412
3655
  next(error2);
3413
3656
  return;
3414
3657
  }
@@ -3418,7 +3661,7 @@ function useAreaChecklistController() {
3418
3661
  const _id = req.params.id;
3419
3662
  const { error, value } = validation.validate(_id);
3420
3663
  if (error) {
3421
- logger17.log({ level: "error", message: error.message });
3664
+ logger19.log({ level: "error", message: error.message });
3422
3665
  next(new BadRequestError16(error.message));
3423
3666
  return;
3424
3667
  }
@@ -3427,7 +3670,7 @@ function useAreaChecklistController() {
3427
3670
  res.json(data);
3428
3671
  return;
3429
3672
  } catch (error2) {
3430
- logger17.log({ level: "error", message: error2.message });
3673
+ logger19.log({ level: "error", message: error2.message });
3431
3674
  next(error2);
3432
3675
  return;
3433
3676
  }
@@ -3442,7 +3685,7 @@ function useAreaChecklistController() {
3442
3685
  });
3443
3686
  const { error } = validation.validate(query);
3444
3687
  if (error) {
3445
- logger17.log({ level: "error", message: error.message });
3688
+ logger19.log({ level: "error", message: error.message });
3446
3689
  next(new BadRequestError16(error.message));
3447
3690
  return;
3448
3691
  }
@@ -3460,7 +3703,7 @@ function useAreaChecklistController() {
3460
3703
  res.json(data);
3461
3704
  return;
3462
3705
  } catch (error2) {
3463
- logger17.log({ level: "error", message: error2.message });
3706
+ logger19.log({ level: "error", message: error2.message });
3464
3707
  next(error2);
3465
3708
  return;
3466
3709
  }
@@ -3485,7 +3728,7 @@ function useAreaChecklistController() {
3485
3728
  });
3486
3729
  const { error } = validation.validate(payload);
3487
3730
  if (error) {
3488
- logger17.log({ level: "error", message: error.message });
3731
+ logger19.log({ level: "error", message: error.message });
3489
3732
  next(new BadRequestError16(error.message));
3490
3733
  return;
3491
3734
  }
@@ -3500,7 +3743,7 @@ function useAreaChecklistController() {
3500
3743
  res.json({ message: "Area checklist updated successfully." });
3501
3744
  return;
3502
3745
  } catch (error2) {
3503
- logger17.log({ level: "error", message: error2.message });
3746
+ logger19.log({ level: "error", message: error2.message });
3504
3747
  next(error2);
3505
3748
  return;
3506
3749
  }
@@ -3518,7 +3761,7 @@ function useAreaChecklistController() {
3518
3761
  // src/models/hygiene-supply.model.ts
3519
3762
  import Joi10 from "joi";
3520
3763
  import { ObjectId as ObjectId10 } from "mongodb";
3521
- import { BadRequestError as BadRequestError17, logger as logger18 } from "@7365admin1/node-server-utils";
3764
+ import { BadRequestError as BadRequestError17, logger as logger20 } from "@7365admin1/node-server-utils";
3522
3765
  var supplySchema = Joi10.object({
3523
3766
  site: Joi10.string().hex().required(),
3524
3767
  name: Joi10.string().required(),
@@ -3527,7 +3770,7 @@ var supplySchema = Joi10.object({
3527
3770
  function MSupply(value) {
3528
3771
  const { error } = supplySchema.validate(value);
3529
3772
  if (error) {
3530
- logger18.info(`Hygiene Supply Model: ${error.message}`);
3773
+ logger20.info(`Hygiene Supply Model: ${error.message}`);
3531
3774
  throw new BadRequestError17(error.message);
3532
3775
  }
3533
3776
  if (value.site) {
@@ -3557,7 +3800,7 @@ import {
3557
3800
  paginate as paginate5,
3558
3801
  BadRequestError as BadRequestError18,
3559
3802
  useCache as useCache6,
3560
- logger as logger19,
3803
+ logger as logger21,
3561
3804
  makeCacheKey as makeCacheKey6,
3562
3805
  NotFoundError as NotFoundError4
3563
3806
  } from "@7365admin1/node-server-utils";
@@ -3604,9 +3847,9 @@ function useSupplyRepository() {
3604
3847
  value = MSupply(value);
3605
3848
  const res = await collection.insertOne(value, { session });
3606
3849
  delNamespace().then(() => {
3607
- logger19.info(`Cache cleared for namespace: ${namespace_collection}`);
3850
+ logger21.info(`Cache cleared for namespace: ${namespace_collection}`);
3608
3851
  }).catch((err) => {
3609
- logger19.error(
3852
+ logger21.error(
3610
3853
  `Failed to clear cache for namespace: ${namespace_collection}`,
3611
3854
  err
3612
3855
  );
@@ -3648,7 +3891,7 @@ function useSupplyRepository() {
3648
3891
  const cacheKey = makeCacheKey6(namespace_collection, cacheOptions);
3649
3892
  const cachedData = await getCache(cacheKey);
3650
3893
  if (cachedData) {
3651
- logger19.info(`Cache hit for key: ${cacheKey}`);
3894
+ logger21.info(`Cache hit for key: ${cacheKey}`);
3652
3895
  return cachedData;
3653
3896
  }
3654
3897
  try {
@@ -3668,9 +3911,9 @@ function useSupplyRepository() {
3668
3911
  const length = await collection.countDocuments(query);
3669
3912
  const data = paginate5(items, page, limit, length);
3670
3913
  setCache(cacheKey, data, 15 * 60).then(() => {
3671
- logger19.info(`Cache set for key: ${cacheKey}`);
3914
+ logger21.info(`Cache set for key: ${cacheKey}`);
3672
3915
  }).catch((err) => {
3673
- logger19.error(`Failed to set cache for key: ${cacheKey}`, err);
3916
+ logger21.error(`Failed to set cache for key: ${cacheKey}`, err);
3674
3917
  });
3675
3918
  return data;
3676
3919
  } catch (error) {
@@ -3693,11 +3936,11 @@ function useSupplyRepository() {
3693
3936
  if (!session) {
3694
3937
  const cachedData = await getCache(cacheKey);
3695
3938
  if (cachedData) {
3696
- logger19.info(`Cache hit for key: ${cacheKey}`);
3939
+ logger21.info(`Cache hit for key: ${cacheKey}`);
3697
3940
  return cachedData;
3698
3941
  }
3699
3942
  } else {
3700
- logger19.info(`Skipping cache during transaction for key: ${cacheKey}`);
3943
+ logger21.info(`Skipping cache during transaction for key: ${cacheKey}`);
3701
3944
  }
3702
3945
  try {
3703
3946
  const data = await collection.aggregate([
@@ -3714,9 +3957,9 @@ function useSupplyRepository() {
3714
3957
  throw new NotFoundError4("Supply not found.");
3715
3958
  }
3716
3959
  setCache(cacheKey, data[0], 15 * 60).then(() => {
3717
- logger19.info(`Cache set for key: ${cacheKey}`);
3960
+ logger21.info(`Cache set for key: ${cacheKey}`);
3718
3961
  }).catch((err) => {
3719
- logger19.error(`Failed to set cache for key: ${cacheKey}`, err);
3962
+ logger21.error(`Failed to set cache for key: ${cacheKey}`, err);
3720
3963
  });
3721
3964
  return data[0];
3722
3965
  } catch (error) {
@@ -3740,9 +3983,9 @@ function useSupplyRepository() {
3740
3983
  throw new InternalServerError6("Unable to update cleaning supply.");
3741
3984
  }
3742
3985
  delNamespace().then(() => {
3743
- logger19.info(`Cache cleared for namespace: ${namespace_collection}`);
3986
+ logger21.info(`Cache cleared for namespace: ${namespace_collection}`);
3744
3987
  }).catch((err) => {
3745
- logger19.error(
3988
+ logger21.error(
3746
3989
  `Failed to clear cache for namespace: ${namespace_collection}`,
3747
3990
  err
3748
3991
  );
@@ -3777,9 +4020,9 @@ function useSupplyRepository() {
3777
4020
  throw new InternalServerError6("Unable to delete supply.");
3778
4021
  }
3779
4022
  delNamespace().then(() => {
3780
- logger19.info(`Cache cleared for namespace: ${namespace_collection}`);
4023
+ logger21.info(`Cache cleared for namespace: ${namespace_collection}`);
3781
4024
  }).catch((err) => {
3782
- logger19.error(
4025
+ logger21.error(
3783
4026
  `Failed to clear cache for namespace: ${namespace_collection}`,
3784
4027
  err
3785
4028
  );
@@ -3803,7 +4046,7 @@ function useSupplyRepository() {
3803
4046
 
3804
4047
  // src/controllers/hygiene-supply.controller.ts
3805
4048
  import Joi11 from "joi";
3806
- import { BadRequestError as BadRequestError19, logger as logger20 } from "@7365admin1/node-server-utils";
4049
+ import { BadRequestError as BadRequestError19, logger as logger22 } from "@7365admin1/node-server-utils";
3807
4050
  function useSupplyController() {
3808
4051
  const {
3809
4052
  createSupply: _createSupply,
@@ -3816,7 +4059,7 @@ function useSupplyController() {
3816
4059
  const payload = { ...req.body, ...req.params };
3817
4060
  const { error } = supplySchema.validate(payload);
3818
4061
  if (error) {
3819
- logger20.log({ level: "error", message: error.message });
4062
+ logger22.log({ level: "error", message: error.message });
3820
4063
  next(new BadRequestError19(error.message));
3821
4064
  return;
3822
4065
  }
@@ -3825,7 +4068,7 @@ function useSupplyController() {
3825
4068
  res.status(201).json({ message: "Supply created successfully.", id });
3826
4069
  return;
3827
4070
  } catch (error2) {
3828
- logger20.log({ level: "error", message: error2.message });
4071
+ logger22.log({ level: "error", message: error2.message });
3829
4072
  next(error2);
3830
4073
  return;
3831
4074
  }
@@ -3840,7 +4083,7 @@ function useSupplyController() {
3840
4083
  });
3841
4084
  const { error } = validation.validate(query);
3842
4085
  if (error) {
3843
- logger20.log({ level: "error", message: error.message });
4086
+ logger22.log({ level: "error", message: error.message });
3844
4087
  next(new BadRequestError19(error.message));
3845
4088
  return;
3846
4089
  }
@@ -3858,7 +4101,7 @@ function useSupplyController() {
3858
4101
  res.json(data);
3859
4102
  return;
3860
4103
  } catch (error2) {
3861
- logger20.log({ level: "error", message: error2.message });
4104
+ logger22.log({ level: "error", message: error2.message });
3862
4105
  next(error2);
3863
4106
  return;
3864
4107
  }
@@ -3868,7 +4111,7 @@ function useSupplyController() {
3868
4111
  const _id = req.params.id;
3869
4112
  const { error, value } = validation.validate(_id);
3870
4113
  if (error) {
3871
- logger20.log({ level: "error", message: error.message });
4114
+ logger22.log({ level: "error", message: error.message });
3872
4115
  next(new BadRequestError19(error.message));
3873
4116
  return;
3874
4117
  }
@@ -3877,7 +4120,7 @@ function useSupplyController() {
3877
4120
  res.json(data);
3878
4121
  return;
3879
4122
  } catch (error2) {
3880
- logger20.log({ level: "error", message: error2.message });
4123
+ logger22.log({ level: "error", message: error2.message });
3881
4124
  next(error2);
3882
4125
  return;
3883
4126
  }
@@ -3892,7 +4135,7 @@ function useSupplyController() {
3892
4135
  });
3893
4136
  const { error } = validation.validate(payload);
3894
4137
  if (error) {
3895
- logger20.log({ level: "error", message: error.message });
4138
+ logger22.log({ level: "error", message: error.message });
3896
4139
  next(new BadRequestError19(error.message));
3897
4140
  return;
3898
4141
  }
@@ -3902,7 +4145,7 @@ function useSupplyController() {
3902
4145
  res.json({ message: "Supply updated successfully." });
3903
4146
  return;
3904
4147
  } catch (error2) {
3905
- logger20.log({ level: "error", message: error2.message });
4148
+ logger22.log({ level: "error", message: error2.message });
3906
4149
  next(error2);
3907
4150
  return;
3908
4151
  }
@@ -3914,7 +4157,7 @@ function useSupplyController() {
3914
4157
  });
3915
4158
  const { error, value } = validation.validate({ id });
3916
4159
  if (error) {
3917
- logger20.log({ level: "error", message: error.message });
4160
+ logger22.log({ level: "error", message: error.message });
3918
4161
  next(new BadRequestError19(error.message));
3919
4162
  return;
3920
4163
  }
@@ -3923,7 +4166,7 @@ function useSupplyController() {
3923
4166
  res.json({ message: "Supply deleted successfully." });
3924
4167
  return;
3925
4168
  } catch (error2) {
3926
- logger20.log({ level: "error", message: error2.message });
4169
+ logger22.log({ level: "error", message: error2.message });
3927
4170
  next(error2);
3928
4171
  return;
3929
4172
  }
@@ -3940,7 +4183,7 @@ function useSupplyController() {
3940
4183
  // src/models/hygiene-stock.model.ts
3941
4184
  import Joi12 from "joi";
3942
4185
  import { ObjectId as ObjectId12 } from "mongodb";
3943
- import { BadRequestError as BadRequestError20, logger as logger21 } from "@7365admin1/node-server-utils";
4186
+ import { BadRequestError as BadRequestError20, logger as logger23 } from "@7365admin1/node-server-utils";
3944
4187
  var stockSchema = Joi12.object({
3945
4188
  site: Joi12.string().hex().required(),
3946
4189
  supply: Joi12.string().hex().required(),
@@ -3952,7 +4195,7 @@ var stockSchema = Joi12.object({
3952
4195
  function MStock(value) {
3953
4196
  const { error } = stockSchema.validate(value);
3954
4197
  if (error) {
3955
- logger21.info(`Hygiene Stock Model: ${error.message}`);
4198
+ logger23.info(`Hygiene Stock Model: ${error.message}`);
3956
4199
  throw new BadRequestError20(error.message);
3957
4200
  }
3958
4201
  if (value.site) {
@@ -3990,7 +4233,7 @@ import {
3990
4233
  InternalServerError as InternalServerError7,
3991
4234
  BadRequestError as BadRequestError21,
3992
4235
  useCache as useCache7,
3993
- logger as logger22,
4236
+ logger as logger24,
3994
4237
  makeCacheKey as makeCacheKey7,
3995
4238
  paginate as paginate6
3996
4239
  } from "@7365admin1/node-server-utils";
@@ -4021,17 +4264,17 @@ function useStockRepository() {
4021
4264
  value = MStock(value);
4022
4265
  const res = await collection.insertOne(value, { session });
4023
4266
  delNamespace().then(() => {
4024
- logger22.info(`Cache cleared for namespace: ${namespace_collection}`);
4267
+ logger24.info(`Cache cleared for namespace: ${namespace_collection}`);
4025
4268
  }).catch((err) => {
4026
- logger22.error(
4269
+ logger24.error(
4027
4270
  `Failed to clear cache for namespace: ${namespace_collection}`,
4028
4271
  err
4029
4272
  );
4030
4273
  });
4031
4274
  delSupplyNamespace().then(() => {
4032
- logger22.info(`Cache cleared for namespace: ${supply_collection}`);
4275
+ logger24.info(`Cache cleared for namespace: ${supply_collection}`);
4033
4276
  }).catch((err) => {
4034
- logger22.error(
4277
+ logger24.error(
4035
4278
  `Failed to clear cache for namespace: ${supply_collection}`,
4036
4279
  err
4037
4280
  );
@@ -4077,7 +4320,7 @@ function useStockRepository() {
4077
4320
  const cacheKey = makeCacheKey7(namespace_collection, cacheOptions);
4078
4321
  const cachedData = await getCache(cacheKey);
4079
4322
  if (cachedData) {
4080
- logger22.info(`Cache hit for key: ${cacheKey}`);
4323
+ logger24.info(`Cache hit for key: ${cacheKey}`);
4081
4324
  return cachedData;
4082
4325
  }
4083
4326
  try {
@@ -4098,9 +4341,9 @@ function useStockRepository() {
4098
4341
  const length = await collection.countDocuments(query);
4099
4342
  const data = paginate6(items, page, limit, length);
4100
4343
  setCache(cacheKey, data, 15 * 60).then(() => {
4101
- logger22.info(`Cache set for key: ${cacheKey}`);
4344
+ logger24.info(`Cache set for key: ${cacheKey}`);
4102
4345
  }).catch((err) => {
4103
- logger22.error(`Failed to set cache for key: ${cacheKey}`, err);
4346
+ logger24.error(`Failed to set cache for key: ${cacheKey}`, err);
4104
4347
  });
4105
4348
  return data;
4106
4349
  } catch (error) {
@@ -4170,7 +4413,7 @@ function useStockService() {
4170
4413
 
4171
4414
  // src/controllers/hygiene-stock.controller.ts
4172
4415
  import Joi13 from "joi";
4173
- import { BadRequestError as BadRequestError23, logger as logger23 } from "@7365admin1/node-server-utils";
4416
+ import { BadRequestError as BadRequestError23, logger as logger25 } from "@7365admin1/node-server-utils";
4174
4417
  function useStockController() {
4175
4418
  const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
4176
4419
  const { createStock: _createStock } = useStockService();
@@ -4184,7 +4427,7 @@ function useStockController() {
4184
4427
  });
4185
4428
  const { error } = validation.validate(payload);
4186
4429
  if (error) {
4187
- logger23.log({ level: "error", message: error.message });
4430
+ logger25.log({ level: "error", message: error.message });
4188
4431
  next(new BadRequestError23(error.message));
4189
4432
  return;
4190
4433
  }
@@ -4193,7 +4436,7 @@ function useStockController() {
4193
4436
  res.status(201).json({ message: "Stock created successfully.", id });
4194
4437
  return;
4195
4438
  } catch (error2) {
4196
- logger23.log({ level: "error", message: error2.message });
4439
+ logger25.log({ level: "error", message: error2.message });
4197
4440
  next(error2);
4198
4441
  return;
4199
4442
  }
@@ -4209,7 +4452,7 @@ function useStockController() {
4209
4452
  });
4210
4453
  const { error } = validation.validate(query);
4211
4454
  if (error) {
4212
- logger23.log({ level: "error", message: error.message });
4455
+ logger25.log({ level: "error", message: error.message });
4213
4456
  next(new BadRequestError23(error.message));
4214
4457
  return;
4215
4458
  }
@@ -4229,7 +4472,7 @@ function useStockController() {
4229
4472
  res.json(data);
4230
4473
  return;
4231
4474
  } catch (error2) {
4232
- logger23.log({ level: "error", message: error2.message });
4475
+ logger25.log({ level: "error", message: error2.message });
4233
4476
  next(error2);
4234
4477
  return;
4235
4478
  }
@@ -4243,7 +4486,7 @@ function useStockController() {
4243
4486
  // src/models/hygiene-checkout-item.model.ts
4244
4487
  import Joi14 from "joi";
4245
4488
  import { ObjectId as ObjectId14 } from "mongodb";
4246
- import { BadRequestError as BadRequestError24, logger as logger24 } from "@7365admin1/node-server-utils";
4489
+ import { BadRequestError as BadRequestError24, logger as logger26 } from "@7365admin1/node-server-utils";
4247
4490
  var allowedCheckOutItemStatus = ["pending", "completed"];
4248
4491
  var checkOutItemSchema = Joi14.object({
4249
4492
  site: Joi14.string().hex().required(),
@@ -4257,7 +4500,7 @@ var checkOutItemSchema = Joi14.object({
4257
4500
  function MCheckOutItem(value) {
4258
4501
  const { error } = checkOutItemSchema.validate(value);
4259
4502
  if (error) {
4260
- logger24.info(`Hygiene Check Out Item Model: ${error.message}`);
4503
+ logger26.info(`Hygiene Check Out Item Model: ${error.message}`);
4261
4504
  throw new BadRequestError24(error.message);
4262
4505
  }
4263
4506
  if (value.site) {
@@ -4295,7 +4538,7 @@ import {
4295
4538
  useAtlas as useAtlas11,
4296
4539
  InternalServerError as InternalServerError8,
4297
4540
  useCache as useCache8,
4298
- logger as logger25,
4541
+ logger as logger27,
4299
4542
  makeCacheKey as makeCacheKey8,
4300
4543
  paginate as paginate7,
4301
4544
  BadRequestError as BadRequestError25,
@@ -4336,9 +4579,9 @@ function useCheckOutItemRepository() {
4336
4579
  value = MCheckOutItem(value);
4337
4580
  const res = await collection.insertOne(value, { session });
4338
4581
  delNamespace().then(() => {
4339
- logger25.info(`Cache cleared for namespace: ${namespace_collection}`);
4582
+ logger27.info(`Cache cleared for namespace: ${namespace_collection}`);
4340
4583
  }).catch((err) => {
4341
- logger25.error(
4584
+ logger27.error(
4342
4585
  `Failed to clear cache for namespace: ${namespace_collection}`,
4343
4586
  err
4344
4587
  );
@@ -4376,7 +4619,7 @@ function useCheckOutItemRepository() {
4376
4619
  const cacheKey = makeCacheKey8(namespace_collection, cacheOptions);
4377
4620
  const cachedData = await getCache(cacheKey);
4378
4621
  if (cachedData) {
4379
- logger25.info(`Cache hit for key: ${cacheKey}`);
4622
+ logger27.info(`Cache hit for key: ${cacheKey}`);
4380
4623
  return cachedData;
4381
4624
  }
4382
4625
  try {
@@ -4425,9 +4668,9 @@ function useCheckOutItemRepository() {
4425
4668
  const length = await collection.countDocuments(query);
4426
4669
  const data = paginate7(items, page, limit, length);
4427
4670
  setCache(cacheKey, data, 15 * 60).then(() => {
4428
- logger25.info(`Cache set for key: ${cacheKey}`);
4671
+ logger27.info(`Cache set for key: ${cacheKey}`);
4429
4672
  }).catch((err) => {
4430
- logger25.error(`Failed to set cache for key: ${cacheKey}`, err);
4673
+ logger27.error(`Failed to set cache for key: ${cacheKey}`, err);
4431
4674
  });
4432
4675
  return data;
4433
4676
  } catch (error) {
@@ -4447,11 +4690,11 @@ function useCheckOutItemRepository() {
4447
4690
  if (!session) {
4448
4691
  const cachedData = await getCache(cacheKey);
4449
4692
  if (cachedData) {
4450
- logger25.info(`Cache hit for key: ${cacheKey}`);
4693
+ logger27.info(`Cache hit for key: ${cacheKey}`);
4451
4694
  return cachedData;
4452
4695
  }
4453
4696
  } else {
4454
- logger25.info(`Skipping cache during transaction for key: ${cacheKey}`);
4697
+ logger27.info(`Skipping cache during transaction for key: ${cacheKey}`);
4455
4698
  }
4456
4699
  try {
4457
4700
  const data = await collection.aggregate(
@@ -4489,9 +4732,9 @@ function useCheckOutItemRepository() {
4489
4732
  throw new NotFoundError6("Check out item not found.");
4490
4733
  }
4491
4734
  setCache(cacheKey, data[0], 15 * 60).then(() => {
4492
- logger25.info(`Cache set for key: ${cacheKey}`);
4735
+ logger27.info(`Cache set for key: ${cacheKey}`);
4493
4736
  }).catch((err) => {
4494
- logger25.error(`Failed to set cache for key: ${cacheKey}`, err);
4737
+ logger27.error(`Failed to set cache for key: ${cacheKey}`, err);
4495
4738
  });
4496
4739
  return data[0];
4497
4740
  } catch (error) {
@@ -4518,9 +4761,9 @@ function useCheckOutItemRepository() {
4518
4761
  throw new InternalServerError8("Unable to complete check out item.");
4519
4762
  }
4520
4763
  delNamespace().then(() => {
4521
- logger25.info(`Cache cleared for namespace: ${namespace_collection}`);
4764
+ logger27.info(`Cache cleared for namespace: ${namespace_collection}`);
4522
4765
  }).catch((err) => {
4523
- logger25.error(
4766
+ logger27.error(
4524
4767
  `Failed to clear cache for namespace: ${namespace_collection}`,
4525
4768
  err
4526
4769
  );
@@ -4641,7 +4884,7 @@ function useCheckOutItemService() {
4641
4884
 
4642
4885
  // src/controllers/hygiene-checkout-item.controller.ts
4643
4886
  import Joi15 from "joi";
4644
- import { BadRequestError as BadRequestError27, logger as logger26 } from "@7365admin1/node-server-utils";
4887
+ import { BadRequestError as BadRequestError27, logger as logger28 } from "@7365admin1/node-server-utils";
4645
4888
  function useCheckOutItemController() {
4646
4889
  const {
4647
4890
  getCheckOutItems: _getCheckOutItems,
@@ -4671,7 +4914,7 @@ function useCheckOutItemController() {
4671
4914
  });
4672
4915
  const { error } = validation.validate(payload);
4673
4916
  if (error) {
4674
- logger26.log({ level: "error", message: error.message });
4917
+ logger28.log({ level: "error", message: error.message });
4675
4918
  next(new BadRequestError27(error.message));
4676
4919
  return;
4677
4920
  }
@@ -4680,7 +4923,7 @@ function useCheckOutItemController() {
4680
4923
  res.status(201).json({ message: "Check out item created successfully.", id });
4681
4924
  return;
4682
4925
  } catch (error2) {
4683
- logger26.log({ level: "error", message: error2.message });
4926
+ logger28.log({ level: "error", message: error2.message });
4684
4927
  next(error2);
4685
4928
  return;
4686
4929
  }
@@ -4709,7 +4952,7 @@ function useCheckOutItemController() {
4709
4952
  });
4710
4953
  const { error } = validation.validate(payload);
4711
4954
  if (error) {
4712
- logger26.log({ level: "error", message: error.message });
4955
+ logger28.log({ level: "error", message: error.message });
4713
4956
  next(new BadRequestError27(error.message));
4714
4957
  return;
4715
4958
  }
@@ -4718,7 +4961,7 @@ function useCheckOutItemController() {
4718
4961
  res.status(201).json({ message: "Check out items created successfully." });
4719
4962
  return;
4720
4963
  } catch (error2) {
4721
- logger26.log({ level: "error", message: error2.message });
4964
+ logger28.log({ level: "error", message: error2.message });
4722
4965
  next(error2);
4723
4966
  return;
4724
4967
  }
@@ -4733,7 +4976,7 @@ function useCheckOutItemController() {
4733
4976
  });
4734
4977
  const { error } = validation.validate(query);
4735
4978
  if (error) {
4736
- logger26.log({ level: "error", message: error.message });
4979
+ logger28.log({ level: "error", message: error.message });
4737
4980
  next(new BadRequestError27(error.message));
4738
4981
  return;
4739
4982
  }
@@ -4751,7 +4994,7 @@ function useCheckOutItemController() {
4751
4994
  res.json(data);
4752
4995
  return;
4753
4996
  } catch (error2) {
4754
- logger26.log({ level: "error", message: error2.message });
4997
+ logger28.log({ level: "error", message: error2.message });
4755
4998
  next(error2);
4756
4999
  return;
4757
5000
  }
@@ -4761,7 +5004,7 @@ function useCheckOutItemController() {
4761
5004
  const _id = req.params.id;
4762
5005
  const { error, value } = validation.validate(_id);
4763
5006
  if (error) {
4764
- logger26.log({ level: "error", message: error.message });
5007
+ logger28.log({ level: "error", message: error.message });
4765
5008
  next(new BadRequestError27(error.message));
4766
5009
  return;
4767
5010
  }
@@ -4770,7 +5013,7 @@ function useCheckOutItemController() {
4770
5013
  res.json(data);
4771
5014
  return;
4772
5015
  } catch (error2) {
4773
- logger26.log({ level: "error", message: error2.message });
5016
+ logger28.log({ level: "error", message: error2.message });
4774
5017
  next(error2);
4775
5018
  return;
4776
5019
  }
@@ -4784,7 +5027,7 @@ function useCheckOutItemController() {
4784
5027
  }
4785
5028
 
4786
5029
  // src/models/hygiene-schedule-task.model.ts
4787
- import { BadRequestError as BadRequestError28, logger as logger27 } from "@7365admin1/node-server-utils";
5030
+ import { BadRequestError as BadRequestError28, logger as logger29 } from "@7365admin1/node-server-utils";
4788
5031
  import Joi16 from "joi";
4789
5032
  import { ObjectId as ObjectId16 } from "mongodb";
4790
5033
  var scheduleTaskSchema = Joi16.object({
@@ -4805,7 +5048,7 @@ var scheduleTaskSchema = Joi16.object({
4805
5048
  function MScheduleTask(value) {
4806
5049
  const { error } = scheduleTaskSchema.validate(value);
4807
5050
  if (error) {
4808
- logger27.info(`Hygiene Schedule Task Model: ${error.message}`);
5051
+ logger29.info(`Hygiene Schedule Task Model: ${error.message}`);
4809
5052
  throw new BadRequestError28(error.message);
4810
5053
  }
4811
5054
  if (value.site) {
@@ -4858,7 +5101,7 @@ import {
4858
5101
  paginate as paginate8,
4859
5102
  BadRequestError as BadRequestError29,
4860
5103
  useCache as useCache9,
4861
- logger as logger28,
5104
+ logger as logger30,
4862
5105
  makeCacheKey as makeCacheKey9,
4863
5106
  NotFoundError as NotFoundError7
4864
5107
  } from "@7365admin1/node-server-utils";
@@ -4896,9 +5139,9 @@ function useScheduleTaskRepository() {
4896
5139
  value = MScheduleTask(value);
4897
5140
  const res = await collection.insertOne(value, { session });
4898
5141
  delNamespace().then(() => {
4899
- logger28.info(`Cache cleared for namespace: ${namespace_collection}`);
5142
+ logger30.info(`Cache cleared for namespace: ${namespace_collection}`);
4900
5143
  }).catch((err) => {
4901
- logger28.error(
5144
+ logger30.error(
4902
5145
  `Failed to clear cache for namespace: ${namespace_collection}`,
4903
5146
  err
4904
5147
  );
@@ -4936,7 +5179,7 @@ function useScheduleTaskRepository() {
4936
5179
  const cacheKey = makeCacheKey9(namespace_collection, cacheOptions);
4937
5180
  const cachedData = await getCache(cacheKey);
4938
5181
  if (cachedData) {
4939
- logger28.info(`Cache hit for key: ${cacheKey}`);
5182
+ logger30.info(`Cache hit for key: ${cacheKey}`);
4940
5183
  return cachedData;
4941
5184
  }
4942
5185
  try {
@@ -4956,9 +5199,9 @@ function useScheduleTaskRepository() {
4956
5199
  const length = await collection.countDocuments(query);
4957
5200
  const data = paginate8(items, page, limit, length);
4958
5201
  setCache(cacheKey, data, 15 * 60).then(() => {
4959
- logger28.info(`Cache set for key: ${cacheKey}`);
5202
+ logger30.info(`Cache set for key: ${cacheKey}`);
4960
5203
  }).catch((err) => {
4961
- logger28.error(`Failed to set cache for key: ${cacheKey}`, err);
5204
+ logger30.error(`Failed to set cache for key: ${cacheKey}`, err);
4962
5205
  });
4963
5206
  return data;
4964
5207
  } catch (error) {
@@ -5004,7 +5247,7 @@ function useScheduleTaskRepository() {
5004
5247
  const cacheKey = makeCacheKey9(namespace_collection, cacheOptions);
5005
5248
  const cachedData = await getCache(cacheKey);
5006
5249
  if (cachedData) {
5007
- logger28.info(`Cache hit for key: ${cacheKey}`);
5250
+ logger30.info(`Cache hit for key: ${cacheKey}`);
5008
5251
  return cachedData;
5009
5252
  }
5010
5253
  try {
@@ -5023,9 +5266,9 @@ function useScheduleTaskRepository() {
5023
5266
  const length = await collection.countDocuments(query);
5024
5267
  const data = paginate8(items, page, limit, length);
5025
5268
  setCache(cacheKey, data, 15 * 60).then(() => {
5026
- logger28.info(`Cache set for key: ${cacheKey}`);
5269
+ logger30.info(`Cache set for key: ${cacheKey}`);
5027
5270
  }).catch((err) => {
5028
- logger28.error(`Failed to set cache for key: ${cacheKey}`, err);
5271
+ logger30.error(`Failed to set cache for key: ${cacheKey}`, err);
5029
5272
  });
5030
5273
  return data;
5031
5274
  } catch (error) {
@@ -5048,11 +5291,11 @@ function useScheduleTaskRepository() {
5048
5291
  if (!session) {
5049
5292
  const cachedData = await getCache(cacheKey);
5050
5293
  if (cachedData) {
5051
- logger28.info(`Cache hit for key: ${cacheKey}`);
5294
+ logger30.info(`Cache hit for key: ${cacheKey}`);
5052
5295
  return cachedData;
5053
5296
  }
5054
5297
  } else {
5055
- logger28.info(`Skipping cache during transaction for key: ${cacheKey}`);
5298
+ logger30.info(`Skipping cache during transaction for key: ${cacheKey}`);
5056
5299
  }
5057
5300
  try {
5058
5301
  const data = await collection.aggregate([
@@ -5074,9 +5317,9 @@ function useScheduleTaskRepository() {
5074
5317
  throw new NotFoundError7("Schedule task not found.");
5075
5318
  }
5076
5319
  setCache(cacheKey, data[0], 15 * 60).then(() => {
5077
- logger28.info(`Cache set for key: ${cacheKey}`);
5320
+ logger30.info(`Cache set for key: ${cacheKey}`);
5078
5321
  }).catch((err) => {
5079
- logger28.error(`Failed to set cache for key: ${cacheKey}`, err);
5322
+ logger30.error(`Failed to set cache for key: ${cacheKey}`, err);
5080
5323
  });
5081
5324
  return data[0];
5082
5325
  } catch (error) {
@@ -5114,9 +5357,9 @@ function useScheduleTaskRepository() {
5114
5357
  );
5115
5358
  }
5116
5359
  delNamespace().then(() => {
5117
- logger28.info(`Cache cleared for namespace: ${namespace_collection}`);
5360
+ logger30.info(`Cache cleared for namespace: ${namespace_collection}`);
5118
5361
  }).catch((err) => {
5119
- logger28.error(
5362
+ logger30.error(
5120
5363
  `Failed to clear cache for namespace: ${namespace_collection}`,
5121
5364
  err
5122
5365
  );
@@ -5139,7 +5382,7 @@ function useScheduleTaskRepository() {
5139
5382
  }
5140
5383
 
5141
5384
  // src/services/hygiene-schedule-task.service.ts
5142
- import { logger as logger29 } from "@7365admin1/node-server-utils";
5385
+ import { logger as logger31 } from "@7365admin1/node-server-utils";
5143
5386
  function useScheduleTaskService() {
5144
5387
  const { createParentChecklist } = useParentChecklistRepo();
5145
5388
  const { getAllScheduleTask } = useScheduleTaskRepository();
@@ -5162,13 +5405,13 @@ function useScheduleTaskService() {
5162
5405
  const currentDateString = now.toLocaleDateString("en-US", {
5163
5406
  timeZone: "Asia/Singapore"
5164
5407
  });
5165
- logger29.info(
5408
+ logger31.info(
5166
5409
  `Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Current date ${currentDateString}, Schedule time ${schedule.time}, Start date ${schedule.startDate}, End date ${schedule.endDate}`
5167
5410
  );
5168
5411
  const startDate = /* @__PURE__ */ new Date(schedule.startDate + "T00:00:00");
5169
5412
  const currentDateOnly = /* @__PURE__ */ new Date(currentDateString + "T00:00:00");
5170
5413
  if (currentDateOnly < startDate) {
5171
- logger29.info(
5414
+ logger31.info(
5172
5415
  `Schedule ${schedule._id}: Current date ${currentDateString} is before start date ${schedule.startDate}`
5173
5416
  );
5174
5417
  return false;
@@ -5176,7 +5419,7 @@ function useScheduleTaskService() {
5176
5419
  if (schedule.endDate) {
5177
5420
  const endDate = /* @__PURE__ */ new Date(schedule.endDate + "T00:00:00");
5178
5421
  if (currentDateOnly > endDate) {
5179
- logger29.info(
5422
+ logger31.info(
5180
5423
  `Schedule ${schedule._id}: Current date ${currentDateString} is after end date ${schedule.endDate}`
5181
5424
  );
5182
5425
  return false;
@@ -5185,17 +5428,17 @@ function useScheduleTaskService() {
5185
5428
  const [scheduleHour, scheduleMinute] = schedule.time.split(":").map(Number);
5186
5429
  const timeMatches = currentHour === scheduleHour && currentMinute === scheduleMinute;
5187
5430
  if (!timeMatches) {
5188
- logger29.info(
5431
+ logger31.info(
5189
5432
  `Schedule ${schedule._id}: Time does not match. Current: ${currentHour}:${currentMinute}, Expected: ${scheduleHour}:${scheduleMinute}`
5190
5433
  );
5191
5434
  return false;
5192
5435
  }
5193
- logger29.info(
5436
+ logger31.info(
5194
5437
  `Schedule ${schedule._id}: All conditions matched - Date is within range and time matches`
5195
5438
  );
5196
5439
  return true;
5197
5440
  } catch (error) {
5198
- logger29.error(
5441
+ logger31.error(
5199
5442
  `Error checking schedule conditions for ${schedule._id}:`,
5200
5443
  error
5201
5444
  );
@@ -5204,40 +5447,40 @@ function useScheduleTaskService() {
5204
5447
  }
5205
5448
  async function processScheduledTasks(currentDate) {
5206
5449
  try {
5207
- logger29.info("Starting scheduled task processing...");
5450
+ logger31.info("Starting scheduled task processing...");
5208
5451
  const scheduleTasks = await getAllScheduleTask();
5209
5452
  if (!scheduleTasks || scheduleTasks.length === 0) {
5210
- logger29.info("No schedule tasks found to process");
5453
+ logger31.info("No schedule tasks found to process");
5211
5454
  return { processed: 0, validated: 0 };
5212
5455
  }
5213
- logger29.info(`Found ${scheduleTasks.length} schedule tasks to check`);
5456
+ logger31.info(`Found ${scheduleTasks.length} schedule tasks to check`);
5214
5457
  let processedCount = 0;
5215
5458
  let validatedCount = 0;
5216
5459
  const validatedTasks = [];
5217
5460
  for (const scheduleTask of scheduleTasks) {
5218
5461
  try {
5219
- logger29.info(
5462
+ logger31.info(
5220
5463
  `Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, startDate=${scheduleTask.startDate}, endDate=${scheduleTask.endDate}`
5221
5464
  );
5222
5465
  const shouldRun = checkScheduleConditions(scheduleTask, currentDate);
5223
5466
  if (!shouldRun) {
5224
- logger29.info(
5467
+ logger31.info(
5225
5468
  `Schedule ${scheduleTask._id} conditions not met, skipping`
5226
5469
  );
5227
5470
  continue;
5228
5471
  }
5229
- logger29.info(
5472
+ logger31.info(
5230
5473
  `Schedule ${scheduleTask._id} conditions validated, creating area checklists`
5231
5474
  );
5232
5475
  if (!scheduleTask._id) {
5233
- logger29.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
5476
+ logger31.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
5234
5477
  continue;
5235
5478
  }
5236
5479
  if (!scheduleTask.site) {
5237
- logger29.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
5480
+ logger31.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
5238
5481
  continue;
5239
5482
  }
5240
- logger29.info(
5483
+ logger31.info(
5241
5484
  `Getting or creating parent checklist for schedule ${scheduleTask._id} in site ${scheduleTask.site}`
5242
5485
  );
5243
5486
  const parentChecklistIds = await createParentChecklist({
@@ -5245,7 +5488,7 @@ function useScheduleTaskService() {
5245
5488
  createdAt: /* @__PURE__ */ new Date()
5246
5489
  });
5247
5490
  const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
5248
- logger29.info(
5491
+ logger31.info(
5249
5492
  `Using parent checklist ${parentChecklistId}, now creating/updating area checklists`
5250
5493
  );
5251
5494
  for (const area of scheduleTask.areas) {
@@ -5258,14 +5501,14 @@ function useScheduleTaskService() {
5258
5501
  unit: unit.unit.toString(),
5259
5502
  name: unit.name
5260
5503
  }));
5261
- logger29.info(
5504
+ logger31.info(
5262
5505
  `Area ${area.name} (${areaId}): Using units from area details: ${JSON.stringify(
5263
5506
  units
5264
5507
  )}`
5265
5508
  );
5266
5509
  }
5267
5510
  if (units.length === 0) {
5268
- logger29.warn(
5511
+ logger31.warn(
5269
5512
  `Area ${area.name} (${areaId}): No units found, skipping area.`
5270
5513
  );
5271
5514
  continue;
@@ -5276,11 +5519,11 @@ function useScheduleTaskService() {
5276
5519
  parentChecklistId.toString(),
5277
5520
  areaId
5278
5521
  );
5279
- logger29.info(
5522
+ logger31.info(
5280
5523
  `Area ${area.name} (${areaId}): Existing area checklist found: ${existingAreaChecklist ? "Yes" : "No"}`
5281
5524
  );
5282
5525
  if (existingAreaChecklist) {
5283
- logger29.info(
5526
+ logger31.info(
5284
5527
  `Area ${area.name} (${areaId}): Existing checklist content: ${JSON.stringify(
5285
5528
  existingAreaChecklist.checklist
5286
5529
  )}`
@@ -5288,7 +5531,7 @@ function useScheduleTaskService() {
5288
5531
  }
5289
5532
  } catch (error) {
5290
5533
  existingAreaChecklist = null;
5291
- logger29.info(
5534
+ logger31.info(
5292
5535
  `Area ${area.name} (${areaId}): No existing area checklist found (exception).`
5293
5536
  );
5294
5537
  }
@@ -5302,7 +5545,7 @@ function useScheduleTaskService() {
5302
5545
  ...existingAreaChecklist.checklist || [],
5303
5546
  newSet
5304
5547
  ];
5305
- logger29.info(
5548
+ logger31.info(
5306
5549
  `Area ${area.name} (${areaId}): Appending new set ${newSet.set} to checklist. Updated checklist: ${JSON.stringify(
5307
5550
  updatedChecklist
5308
5551
  )}`
@@ -5310,7 +5553,7 @@ function useScheduleTaskService() {
5310
5553
  await updateAreaChecklist(existingAreaChecklist._id, {
5311
5554
  checklist: updatedChecklist
5312
5555
  });
5313
- logger29.info(
5556
+ logger31.info(
5314
5557
  `Appended set ${newSet.set} to area checklist for area ${area.name}`
5315
5558
  );
5316
5559
  try {
@@ -5318,13 +5561,13 @@ function useScheduleTaskService() {
5318
5561
  parentChecklistId.toString(),
5319
5562
  areaId
5320
5563
  );
5321
- logger29.info(
5564
+ logger31.info(
5322
5565
  `Area ${area.name} (${areaId}): Checklist after update: ${JSON.stringify(
5323
5566
  verifyChecklist.checklist
5324
5567
  )}`
5325
5568
  );
5326
5569
  } catch (verifyError) {
5327
- logger29.warn(
5570
+ logger31.warn(
5328
5571
  `Area ${area.name} (${areaId}): Error verifying checklist after update:`,
5329
5572
  verifyError
5330
5573
  );
@@ -5343,50 +5586,50 @@ function useScheduleTaskService() {
5343
5586
  ],
5344
5587
  createdBy: scheduleTask.createdBy
5345
5588
  };
5346
- logger29.info(
5589
+ logger31.info(
5347
5590
  `Area ${area.name} (${areaId}): Creating new area checklist with data: ${JSON.stringify(
5348
5591
  checklistData
5349
5592
  )}`
5350
5593
  );
5351
5594
  await createAreaChecklist(checklistData);
5352
- logger29.info(`Created new area checklist for area ${area.name}`);
5595
+ logger31.info(`Created new area checklist for area ${area.name}`);
5353
5596
  try {
5354
5597
  const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
5355
5598
  parentChecklistId.toString(),
5356
5599
  areaId
5357
5600
  );
5358
- logger29.info(
5601
+ logger31.info(
5359
5602
  `Area ${area.name} (${areaId}): Checklist after creation: ${JSON.stringify(
5360
5603
  verifyChecklist.checklist
5361
5604
  )}`
5362
5605
  );
5363
5606
  } catch (verifyError) {
5364
- logger29.warn(
5607
+ logger31.warn(
5365
5608
  `Area ${area.name} (${areaId}): Error verifying checklist after creation:`,
5366
5609
  verifyError
5367
5610
  );
5368
5611
  }
5369
5612
  }
5370
5613
  } catch (error) {
5371
- logger29.error(`Error processing area ${area.name}:`, error);
5614
+ logger31.error(`Error processing area ${area.name}:`, error);
5372
5615
  continue;
5373
5616
  }
5374
5617
  }
5375
5618
  processedCount++;
5376
5619
  validatedCount++;
5377
5620
  validatedTasks.push(scheduleTask);
5378
- logger29.info(
5621
+ logger31.info(
5379
5622
  `Successfully processed schedule ${scheduleTask._id}, created/updated area checklists for all areas.`
5380
5623
  );
5381
5624
  } catch (error) {
5382
- logger29.error(
5625
+ logger31.error(
5383
5626
  `Error processing schedule task ${scheduleTask._id}:`,
5384
5627
  error
5385
5628
  );
5386
5629
  continue;
5387
5630
  }
5388
5631
  }
5389
- logger29.info(
5632
+ logger31.info(
5390
5633
  `Scheduled task processing completed. Processed: ${processedCount}, Validated: ${validatedCount} tasks`
5391
5634
  );
5392
5635
  return {
@@ -5395,7 +5638,7 @@ function useScheduleTaskService() {
5395
5638
  tasks: validatedTasks
5396
5639
  };
5397
5640
  } catch (error) {
5398
- logger29.error("Error processing scheduled tasks:", error);
5641
+ logger31.error("Error processing scheduled tasks:", error);
5399
5642
  throw error;
5400
5643
  }
5401
5644
  }
@@ -5404,7 +5647,7 @@ function useScheduleTaskService() {
5404
5647
 
5405
5648
  // src/controllers/hygiene-schedule-task.controller.ts
5406
5649
  import Joi17 from "joi";
5407
- import { BadRequestError as BadRequestError30, logger as logger30 } from "@7365admin1/node-server-utils";
5650
+ import { BadRequestError as BadRequestError30, logger as logger32 } from "@7365admin1/node-server-utils";
5408
5651
  function useScheduleTaskController() {
5409
5652
  const {
5410
5653
  createScheduleTask: _createScheduleTask,
@@ -5422,7 +5665,7 @@ function useScheduleTaskController() {
5422
5665
  const payload = { ...req.body, ...req.params, createdBy };
5423
5666
  const { error } = scheduleTaskSchema.validate(payload);
5424
5667
  if (error) {
5425
- logger30.log({ level: "error", message: error.message });
5668
+ logger32.log({ level: "error", message: error.message });
5426
5669
  next(new BadRequestError30(error.message));
5427
5670
  return;
5428
5671
  }
@@ -5431,7 +5674,7 @@ function useScheduleTaskController() {
5431
5674
  res.status(201).json({ message: "Schedule task created successfully.", id });
5432
5675
  return;
5433
5676
  } catch (error2) {
5434
- logger30.log({ level: "error", message: error2.message });
5677
+ logger32.log({ level: "error", message: error2.message });
5435
5678
  next(error2);
5436
5679
  return;
5437
5680
  }
@@ -5446,7 +5689,7 @@ function useScheduleTaskController() {
5446
5689
  });
5447
5690
  const { error } = validation.validate(query);
5448
5691
  if (error) {
5449
- logger30.log({ level: "error", message: error.message });
5692
+ logger32.log({ level: "error", message: error.message });
5450
5693
  next(new BadRequestError30(error.message));
5451
5694
  return;
5452
5695
  }
@@ -5464,7 +5707,7 @@ function useScheduleTaskController() {
5464
5707
  res.json(data);
5465
5708
  return;
5466
5709
  } catch (error2) {
5467
- logger30.log({ level: "error", message: error2.message });
5710
+ logger32.log({ level: "error", message: error2.message });
5468
5711
  next(error2);
5469
5712
  return;
5470
5713
  }
@@ -5479,7 +5722,7 @@ function useScheduleTaskController() {
5479
5722
  });
5480
5723
  const { error } = validation.validate(query);
5481
5724
  if (error) {
5482
- logger30.log({ level: "error", message: error.message });
5725
+ logger32.log({ level: "error", message: error.message });
5483
5726
  next(new BadRequestError30(error.message));
5484
5727
  return;
5485
5728
  }
@@ -5497,7 +5740,7 @@ function useScheduleTaskController() {
5497
5740
  res.json(data);
5498
5741
  return;
5499
5742
  } catch (error2) {
5500
- logger30.log({ level: "error", message: error2.message });
5743
+ logger32.log({ level: "error", message: error2.message });
5501
5744
  next(error2);
5502
5745
  return;
5503
5746
  }
@@ -5507,7 +5750,7 @@ function useScheduleTaskController() {
5507
5750
  const _id = req.params.id;
5508
5751
  const { error, value } = validation.validate(_id);
5509
5752
  if (error) {
5510
- logger30.log({ level: "error", message: error.message });
5753
+ logger32.log({ level: "error", message: error.message });
5511
5754
  next(new BadRequestError30(error.message));
5512
5755
  return;
5513
5756
  }
@@ -5516,7 +5759,7 @@ function useScheduleTaskController() {
5516
5759
  res.json(data);
5517
5760
  return;
5518
5761
  } catch (error2) {
5519
- logger30.log({ level: "error", message: error2.message });
5762
+ logger32.log({ level: "error", message: error2.message });
5520
5763
  next(error2);
5521
5764
  return;
5522
5765
  }
@@ -5539,7 +5782,7 @@ function useScheduleTaskController() {
5539
5782
  });
5540
5783
  const { error } = validation.validate(payload);
5541
5784
  if (error) {
5542
- logger30.log({ level: "error", message: error.message });
5785
+ logger32.log({ level: "error", message: error.message });
5543
5786
  next(new BadRequestError30(error.message));
5544
5787
  return;
5545
5788
  }
@@ -5549,7 +5792,7 @@ function useScheduleTaskController() {
5549
5792
  res.json({ message: "Schedule task updated successfully." });
5550
5793
  return;
5551
5794
  } catch (error2) {
5552
- logger30.log({ level: "error", message: error2.message });
5795
+ logger32.log({ level: "error", message: error2.message });
5553
5796
  next(error2);
5554
5797
  return;
5555
5798
  }
@@ -5562,6 +5805,275 @@ function useScheduleTaskController() {
5562
5805
  updateScheduleTask
5563
5806
  };
5564
5807
  }
5808
+
5809
+ // src/services/hygiene-qr.service.ts
5810
+ import { logger as logger33 } from "@7365admin1/node-server-utils";
5811
+ import { launch } from "puppeteer";
5812
+ import QRCode from "qrcode";
5813
+ function useQRService() {
5814
+ async function generateQRDataUrl(qrUrl) {
5815
+ return QRCode.toDataURL(qrUrl, {
5816
+ width: 350,
5817
+ margin: 2,
5818
+ errorCorrectionLevel: "M",
5819
+ color: {
5820
+ dark: "#000000",
5821
+ light: "#FFFFFF"
5822
+ }
5823
+ });
5824
+ }
5825
+ async function generateQRImage(qrUrl) {
5826
+ try {
5827
+ const qrDataUrl = await generateQRDataUrl(qrUrl);
5828
+ const browser = await launch({
5829
+ headless: true,
5830
+ executablePath: process.env.CHROME_BINARY,
5831
+ args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
5832
+ });
5833
+ const page = await browser.newPage();
5834
+ await page.setViewport({
5835
+ width: 400,
5836
+ height: 400
5837
+ });
5838
+ const html = `
5839
+ <!DOCTYPE html>
5840
+ <html>
5841
+ <head>
5842
+ <meta charset="UTF-8">
5843
+ <style>
5844
+ body {
5845
+ margin: 0;
5846
+ padding: 20px;
5847
+ display: flex;
5848
+ justify-content: center;
5849
+ align-items: center;
5850
+ background: white;
5851
+ min-height: 100vh;
5852
+ }
5853
+ #qr-image {
5854
+ display: block;
5855
+ width: 350px;
5856
+ height: 350px;
5857
+ }
5858
+ </style>
5859
+ </head>
5860
+ <body>
5861
+ <img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
5862
+ </body>
5863
+ </html>
5864
+ `;
5865
+ await page.setContent(html, {
5866
+ waitUntil: ["load", "networkidle0"]
5867
+ });
5868
+ await page.waitForSelector("#qr-image", { timeout: 1e4 });
5869
+ const imageBuffer = await page.screenshot({
5870
+ type: "png",
5871
+ clip: {
5872
+ x: 0,
5873
+ y: 0,
5874
+ width: 400,
5875
+ height: 400
5876
+ }
5877
+ });
5878
+ await browser.close();
5879
+ return imageBuffer;
5880
+ } catch (error) {
5881
+ logger33.log({
5882
+ level: "error",
5883
+ message: `Failed to generate QR image: ${error.message}`
5884
+ });
5885
+ throw error;
5886
+ }
5887
+ }
5888
+ async function generateQRPDF(qrUrl, title) {
5889
+ try {
5890
+ const qrDataUrl = await generateQRDataUrl(qrUrl);
5891
+ const browser = await launch({
5892
+ headless: true,
5893
+ executablePath: process.env.CHROME_BINARY,
5894
+ args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
5895
+ });
5896
+ const page = await browser.newPage();
5897
+ await page.setViewport({
5898
+ width: 800,
5899
+ height: 1100
5900
+ });
5901
+ const escapedTitle = (title || "Cleaning Schedule QR Code").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5902
+ const html = `
5903
+ <!DOCTYPE html>
5904
+ <html>
5905
+ <head>
5906
+ <meta charset="UTF-8">
5907
+ <style>
5908
+ * {
5909
+ margin: 0;
5910
+ padding: 0;
5911
+ box-sizing: border-box;
5912
+ }
5913
+ body {
5914
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
5915
+ background: white;
5916
+ padding: 60px 40px;
5917
+ display: flex;
5918
+ flex-direction: column;
5919
+ align-items: center;
5920
+ justify-content: center;
5921
+ min-height: 100vh;
5922
+ }
5923
+ .qr-container {
5924
+ text-align: center;
5925
+ background: transparent;
5926
+ padding: 0;
5927
+ }
5928
+ h1 {
5929
+ font-size: 28px;
5930
+ color: #333;
5931
+ margin-bottom: 20px;
5932
+ font-weight: 600;
5933
+ }
5934
+ .qr-wrapper {
5935
+ display: inline-block;
5936
+ padding: 0;
5937
+ background: transparent;
5938
+ border: none;
5939
+ border-radius: 0;
5940
+ margin: 20px 0;
5941
+ }
5942
+ #qr-image {
5943
+ display: block;
5944
+ width: 350px;
5945
+ height: 350px;
5946
+ }
5947
+ .instructions {
5948
+ margin-top: 30px;
5949
+ font-size: 16px;
5950
+ color: #666;
5951
+ line-height: 1.6;
5952
+ }
5953
+ .url-info {
5954
+ margin-top: 20px;
5955
+ padding: 15px;
5956
+ background: #f5f5f5;
5957
+ border-radius: 6px;
5958
+ font-size: 12px;
5959
+ color: #888;
5960
+ word-break: break-all;
5961
+ }
5962
+ </style>
5963
+ </head>
5964
+ <body>
5965
+ <div class="qr-container">
5966
+ <h1>${escapedTitle}</h1>
5967
+ <div class="qr-wrapper">
5968
+ <img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
5969
+ </div>
5970
+ <div class="instructions">
5971
+ <p>Scan this QR code to access the cleaning schedule.</p>
5972
+ </div>
5973
+ <div class="url-info">
5974
+ ${qrUrl}
5975
+ </div>
5976
+ </div>
5977
+ </body>
5978
+ </html>
5979
+ `;
5980
+ await page.setContent(html, {
5981
+ waitUntil: ["load", "networkidle0"]
5982
+ });
5983
+ await page.waitForSelector("#qr-image", { timeout: 1e4 });
5984
+ await page.waitForFunction(
5985
+ () => {
5986
+ const img = document.getElementById("qr-image");
5987
+ return img && img.complete && img.naturalWidth > 0;
5988
+ },
5989
+ { timeout: 1e4 }
5990
+ );
5991
+ const pdfBuffer = await page.pdf({
5992
+ format: "A4",
5993
+ printBackground: true,
5994
+ margin: {
5995
+ top: "20mm",
5996
+ right: "20mm",
5997
+ bottom: "20mm",
5998
+ left: "20mm"
5999
+ }
6000
+ });
6001
+ await browser.close();
6002
+ return pdfBuffer;
6003
+ } catch (error) {
6004
+ logger33.log({
6005
+ level: "error",
6006
+ message: `Failed to generate QR PDF: ${error.message}`
6007
+ });
6008
+ throw error;
6009
+ }
6010
+ }
6011
+ return {
6012
+ generateQRImage,
6013
+ generateQRPDF
6014
+ };
6015
+ }
6016
+
6017
+ // src/controllers/hygiene-qr.controller.ts
6018
+ import Joi18 from "joi";
6019
+ import { BadRequestError as BadRequestError31, logger as logger34 } from "@7365admin1/node-server-utils";
6020
+ function useQRController() {
6021
+ const { generateQRImage: _generateQRImage, generateQRPDF: _generateQRPDF } = useQRService();
6022
+ async function generateQR(req, res, next) {
6023
+ const validation = Joi18.object({
6024
+ url: Joi18.string().uri().required(),
6025
+ filename: Joi18.string().optional().allow("", null),
6026
+ title: Joi18.string().optional().allow("", null),
6027
+ download: Joi18.boolean().optional().default(false)
6028
+ });
6029
+ const query = { ...req.query };
6030
+ const { error, value } = validation.validate(query);
6031
+ if (error) {
6032
+ logger34.log({ level: "error", message: error.message });
6033
+ next(new BadRequestError31(error.message));
6034
+ return;
6035
+ }
6036
+ try {
6037
+ const { url, filename, title, download } = value;
6038
+ if (download) {
6039
+ const pdfBuffer = await _generateQRPDF(url, title);
6040
+ if (!pdfBuffer || pdfBuffer.length === 0) {
6041
+ throw new Error("Generated QR PDF is empty or invalid.");
6042
+ }
6043
+ const sanitizedFilename = (filename || "qrcode").replace(/['"]/g, "").replace(/[^a-zA-Z0-9_-]/g, "_");
6044
+ const date = /* @__PURE__ */ new Date();
6045
+ const formattedDate = `${String(date.getMonth() + 1).padStart(
6046
+ 2,
6047
+ "0"
6048
+ )}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
6049
+ res.setHeader("Content-Type", "application/pdf");
6050
+ res.setHeader(
6051
+ "Content-Disposition",
6052
+ `attachment; filename="${sanitizedFilename}-${formattedDate}.pdf"`
6053
+ );
6054
+ res.setHeader("Content-Length", pdfBuffer.length);
6055
+ res.end(pdfBuffer);
6056
+ } else {
6057
+ const imageBuffer = await _generateQRImage(url);
6058
+ if (!imageBuffer || imageBuffer.length === 0) {
6059
+ throw new Error("Generated QR image is empty or invalid.");
6060
+ }
6061
+ res.setHeader("Content-Type", "image/png");
6062
+ res.setHeader("Cache-Control", "public, max-age=3600");
6063
+ res.setHeader("Content-Length", imageBuffer.length);
6064
+ res.end(imageBuffer);
6065
+ }
6066
+ return;
6067
+ } catch (error2) {
6068
+ logger34.log({ level: "error", message: error2.message });
6069
+ next(error2);
6070
+ return;
6071
+ }
6072
+ }
6073
+ return {
6074
+ generateQR
6075
+ };
6076
+ }
5565
6077
  export {
5566
6078
  MArea,
5567
6079
  MAreaChecklist,
@@ -5588,6 +6100,7 @@ export {
5588
6100
  useAreaChecklistRepo,
5589
6101
  useAreaChecklistService,
5590
6102
  useAreaController,
6103
+ useAreaExportService,
5591
6104
  useAreaRepo,
5592
6105
  useAreaService,
5593
6106
  useCheckOutItemController,
@@ -5597,6 +6110,8 @@ export {
5597
6110
  useHygieneDashboardRepository,
5598
6111
  useParentChecklistController,
5599
6112
  useParentChecklistRepo,
6113
+ useQRController,
6114
+ useQRService,
5600
6115
  useScheduleTaskController,
5601
6116
  useScheduleTaskRepository,
5602
6117
  useScheduleTaskService,
@@ -5606,6 +6121,7 @@ export {
5606
6121
  useSupplyController,
5607
6122
  useSupplyRepository,
5608
6123
  useUnitController,
6124
+ useUnitExportService,
5609
6125
  useUnitRepository,
5610
6126
  useUnitService
5611
6127
  };