@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/CHANGELOG.md +6 -0
- package/dist/index.d.ts +43 -1
- package/dist/index.js +1230 -710
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1089 -573
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -55,6 +55,7 @@ __export(src_exports, {
|
|
|
55
55
|
useAreaChecklistRepo: () => useAreaChecklistRepo,
|
|
56
56
|
useAreaChecklistService: () => useAreaChecklistService,
|
|
57
57
|
useAreaController: () => useAreaController,
|
|
58
|
+
useAreaExportService: () => useAreaExportService,
|
|
58
59
|
useAreaRepo: () => useAreaRepo,
|
|
59
60
|
useAreaService: () => useAreaService,
|
|
60
61
|
useCheckOutItemController: () => useCheckOutItemController,
|
|
@@ -64,6 +65,8 @@ __export(src_exports, {
|
|
|
64
65
|
useHygieneDashboardRepository: () => useHygieneDashboardRepository,
|
|
65
66
|
useParentChecklistController: () => useParentChecklistController,
|
|
66
67
|
useParentChecklistRepo: () => useParentChecklistRepo,
|
|
68
|
+
useQRController: () => useQRController,
|
|
69
|
+
useQRService: () => useQRService,
|
|
67
70
|
useScheduleTaskController: () => useScheduleTaskController,
|
|
68
71
|
useScheduleTaskRepository: () => useScheduleTaskRepository,
|
|
69
72
|
useScheduleTaskService: () => useScheduleTaskService,
|
|
@@ -73,6 +76,7 @@ __export(src_exports, {
|
|
|
73
76
|
useSupplyController: () => useSupplyController,
|
|
74
77
|
useSupplyRepository: () => useSupplyRepository,
|
|
75
78
|
useUnitController: () => useUnitController,
|
|
79
|
+
useUnitExportService: () => useUnitExportService,
|
|
76
80
|
useUnitRepository: () => useUnitRepository,
|
|
77
81
|
useUnitService: () => useUnitService
|
|
78
82
|
});
|
|
@@ -1077,9 +1081,283 @@ function useAreaRepo() {
|
|
|
1077
1081
|
}
|
|
1078
1082
|
|
|
1079
1083
|
// src/services/hygiene-area.service.ts
|
|
1084
|
+
var import_node_server_utils8 = require("@7365admin1/node-server-utils");
|
|
1085
|
+
|
|
1086
|
+
// src/services/hygiene-area-export.service.ts
|
|
1080
1087
|
var import_node_server_utils5 = require("@7365admin1/node-server-utils");
|
|
1088
|
+
var xlsx = __toESM(require("xlsx"));
|
|
1089
|
+
function useAreaExportService() {
|
|
1090
|
+
async function generateAreaExcel(areas) {
|
|
1091
|
+
try {
|
|
1092
|
+
const rows = [];
|
|
1093
|
+
rows.push(["AREA", "TYPE", "SET", "UNITS"]);
|
|
1094
|
+
for (const area of areas) {
|
|
1095
|
+
const areaName = area.name || "";
|
|
1096
|
+
const areaType = area.type || "";
|
|
1097
|
+
const areaSet = String(area.set || 0);
|
|
1098
|
+
const unitsString = area.units && area.units.length > 0 ? area.units.map((u) => u.name || "").join(", ") : "";
|
|
1099
|
+
rows.push([areaName, areaType, areaSet, unitsString]);
|
|
1100
|
+
}
|
|
1101
|
+
const workbook = xlsx.utils.book_new();
|
|
1102
|
+
const worksheet = xlsx.utils.aoa_to_sheet(rows);
|
|
1103
|
+
worksheet["!cols"] = [
|
|
1104
|
+
{ width: 30 },
|
|
1105
|
+
// AREA
|
|
1106
|
+
{ width: 20 },
|
|
1107
|
+
// TYPE
|
|
1108
|
+
{ width: 10 },
|
|
1109
|
+
// SET
|
|
1110
|
+
{ width: 40 }
|
|
1111
|
+
// UNITS
|
|
1112
|
+
];
|
|
1113
|
+
xlsx.utils.book_append_sheet(workbook, worksheet, "Areas");
|
|
1114
|
+
const excelBuffer = xlsx.write(workbook, {
|
|
1115
|
+
type: "buffer",
|
|
1116
|
+
bookType: "xlsx"
|
|
1117
|
+
});
|
|
1118
|
+
return excelBuffer;
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
import_node_server_utils5.logger.log({
|
|
1121
|
+
level: "error",
|
|
1122
|
+
message: `Failed to generate area Excel: ${error.message}`
|
|
1123
|
+
});
|
|
1124
|
+
throw error;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
return {
|
|
1128
|
+
generateAreaExcel
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
// src/repositories/hygiene-unit.repository.ts
|
|
1133
|
+
var import_mongodb5 = require("mongodb");
|
|
1134
|
+
var import_node_server_utils7 = require("@7365admin1/node-server-utils");
|
|
1135
|
+
|
|
1136
|
+
// src/models/hygiene-unit.model.ts
|
|
1137
|
+
var import_joi3 = __toESM(require("joi"));
|
|
1138
|
+
var import_mongodb4 = require("mongodb");
|
|
1139
|
+
var import_node_server_utils6 = require("@7365admin1/node-server-utils");
|
|
1140
|
+
var unitSchema = import_joi3.default.object({
|
|
1141
|
+
site: import_joi3.default.string().hex().required(),
|
|
1142
|
+
name: import_joi3.default.string().required()
|
|
1143
|
+
});
|
|
1144
|
+
function MUnit(value) {
|
|
1145
|
+
const { error } = unitSchema.validate(value);
|
|
1146
|
+
if (error) {
|
|
1147
|
+
import_node_server_utils6.logger.info(`Hygiene Unit Model: ${error.message}`);
|
|
1148
|
+
throw new import_node_server_utils6.BadRequestError(error.message);
|
|
1149
|
+
}
|
|
1150
|
+
if (value.site) {
|
|
1151
|
+
try {
|
|
1152
|
+
value.site = new import_mongodb4.ObjectId(value.site);
|
|
1153
|
+
} catch (error2) {
|
|
1154
|
+
throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return {
|
|
1158
|
+
site: value.site,
|
|
1159
|
+
name: value.name,
|
|
1160
|
+
status: "active",
|
|
1161
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1162
|
+
updatedAt: "",
|
|
1163
|
+
deletedAt: ""
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// src/repositories/hygiene-unit.repository.ts
|
|
1168
|
+
function useUnitRepository() {
|
|
1169
|
+
const db = import_node_server_utils7.useAtlas.getDb();
|
|
1170
|
+
if (!db) {
|
|
1171
|
+
throw new import_node_server_utils7.InternalServerError("Unable to connect to server.");
|
|
1172
|
+
}
|
|
1173
|
+
const namespace_collection = "site.cleaning.area.unit";
|
|
1174
|
+
const collection = db.collection(namespace_collection);
|
|
1175
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils7.useCache)(namespace_collection);
|
|
1176
|
+
async function createIndex() {
|
|
1177
|
+
try {
|
|
1178
|
+
await collection.createIndexes([
|
|
1179
|
+
{ key: { site: 1 } },
|
|
1180
|
+
{ key: { status: 1 } }
|
|
1181
|
+
]);
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
throw new import_node_server_utils7.InternalServerError("Failed to create index on hygiene unit.");
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
async function createTextIndex() {
|
|
1187
|
+
try {
|
|
1188
|
+
await collection.createIndex({ name: "text" });
|
|
1189
|
+
} catch (error) {
|
|
1190
|
+
throw new import_node_server_utils7.InternalServerError(
|
|
1191
|
+
"Failed to create text index on hygiene unit."
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
async function createUniqueIndex() {
|
|
1196
|
+
try {
|
|
1197
|
+
await collection.createIndex(
|
|
1198
|
+
{ site: 1, name: 1, deletedAt: 1 },
|
|
1199
|
+
{ unique: true }
|
|
1200
|
+
);
|
|
1201
|
+
} catch (error) {
|
|
1202
|
+
throw new import_node_server_utils7.InternalServerError(
|
|
1203
|
+
"Failed to create unique index on hygiene unit."
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
async function createUnit(value, session) {
|
|
1208
|
+
try {
|
|
1209
|
+
value = MUnit(value);
|
|
1210
|
+
const res = await collection.insertOne(value, { session });
|
|
1211
|
+
delNamespace().then(() => {
|
|
1212
|
+
import_node_server_utils7.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1213
|
+
}).catch((err) => {
|
|
1214
|
+
import_node_server_utils7.logger.error(
|
|
1215
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1216
|
+
err
|
|
1217
|
+
);
|
|
1218
|
+
});
|
|
1219
|
+
return res.insertedId;
|
|
1220
|
+
} catch (error) {
|
|
1221
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
1222
|
+
if (isDuplicated) {
|
|
1223
|
+
throw new import_node_server_utils7.BadRequestError("Unit already exists.");
|
|
1224
|
+
}
|
|
1225
|
+
throw error;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
async function getUnits({
|
|
1229
|
+
page = 1,
|
|
1230
|
+
limit = 10,
|
|
1231
|
+
search = "",
|
|
1232
|
+
site
|
|
1233
|
+
}) {
|
|
1234
|
+
page = page > 0 ? page - 1 : 0;
|
|
1235
|
+
const query = {
|
|
1236
|
+
status: { $ne: "deleted" }
|
|
1237
|
+
};
|
|
1238
|
+
const cacheOptions = {
|
|
1239
|
+
page,
|
|
1240
|
+
limit
|
|
1241
|
+
};
|
|
1242
|
+
try {
|
|
1243
|
+
site = new import_mongodb5.ObjectId(site);
|
|
1244
|
+
query.site = site;
|
|
1245
|
+
cacheOptions.site = site.toString();
|
|
1246
|
+
} catch (error) {
|
|
1247
|
+
throw new import_node_server_utils7.BadRequestError("Invalid site ID format.");
|
|
1248
|
+
}
|
|
1249
|
+
if (search) {
|
|
1250
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
1251
|
+
cacheOptions.search = search;
|
|
1252
|
+
}
|
|
1253
|
+
const cacheKey = (0, import_node_server_utils7.makeCacheKey)(namespace_collection, cacheOptions);
|
|
1254
|
+
const cachedData = await getCache(cacheKey);
|
|
1255
|
+
if (cachedData) {
|
|
1256
|
+
import_node_server_utils7.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1257
|
+
return cachedData;
|
|
1258
|
+
}
|
|
1259
|
+
try {
|
|
1260
|
+
const items = await collection.aggregate([
|
|
1261
|
+
{ $match: query },
|
|
1262
|
+
{ $project: { name: 1 } },
|
|
1263
|
+
{ $sort: { _id: -1 } },
|
|
1264
|
+
{ $skip: page * limit },
|
|
1265
|
+
{ $limit: limit }
|
|
1266
|
+
]).toArray();
|
|
1267
|
+
const length = await collection.countDocuments(query);
|
|
1268
|
+
const data = (0, import_node_server_utils7.paginate)(items, page, limit, length);
|
|
1269
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
1270
|
+
import_node_server_utils7.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1271
|
+
}).catch((err) => {
|
|
1272
|
+
import_node_server_utils7.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1273
|
+
});
|
|
1274
|
+
return data;
|
|
1275
|
+
} catch (error) {
|
|
1276
|
+
throw error;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
async function updateUnit(_id, value, session) {
|
|
1280
|
+
try {
|
|
1281
|
+
_id = new import_mongodb5.ObjectId(_id);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
throw new import_node_server_utils7.BadRequestError("Invalid unit ID format.");
|
|
1284
|
+
}
|
|
1285
|
+
try {
|
|
1286
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
1287
|
+
const res = await collection.updateOne(
|
|
1288
|
+
{ _id },
|
|
1289
|
+
{ $set: updateValue },
|
|
1290
|
+
{ session }
|
|
1291
|
+
);
|
|
1292
|
+
if (res.modifiedCount === 0) {
|
|
1293
|
+
throw new import_node_server_utils7.InternalServerError("Unable to update cleaning unit.");
|
|
1294
|
+
}
|
|
1295
|
+
delNamespace().then(() => {
|
|
1296
|
+
import_node_server_utils7.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1297
|
+
}).catch((err) => {
|
|
1298
|
+
import_node_server_utils7.logger.error(
|
|
1299
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1300
|
+
err
|
|
1301
|
+
);
|
|
1302
|
+
});
|
|
1303
|
+
return res.modifiedCount;
|
|
1304
|
+
} catch (error) {
|
|
1305
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
1306
|
+
if (isDuplicated) {
|
|
1307
|
+
throw new import_node_server_utils7.BadRequestError("Area already exists.");
|
|
1308
|
+
}
|
|
1309
|
+
throw error;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
async function deleteUnit(_id, session) {
|
|
1313
|
+
try {
|
|
1314
|
+
_id = new import_mongodb5.ObjectId(_id);
|
|
1315
|
+
} catch (error) {
|
|
1316
|
+
throw new import_node_server_utils7.BadRequestError("Invalid unit ID format.");
|
|
1317
|
+
}
|
|
1318
|
+
try {
|
|
1319
|
+
const updateValue = {
|
|
1320
|
+
status: "deleted",
|
|
1321
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
1322
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
1323
|
+
};
|
|
1324
|
+
const res = await collection.updateOne(
|
|
1325
|
+
{ _id },
|
|
1326
|
+
{ $set: updateValue },
|
|
1327
|
+
{ session }
|
|
1328
|
+
);
|
|
1329
|
+
if (res.modifiedCount === 0) {
|
|
1330
|
+
throw new import_node_server_utils7.InternalServerError("Unable to delete unit.");
|
|
1331
|
+
}
|
|
1332
|
+
delNamespace().then(() => {
|
|
1333
|
+
import_node_server_utils7.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1334
|
+
}).catch((err) => {
|
|
1335
|
+
import_node_server_utils7.logger.error(
|
|
1336
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1337
|
+
err
|
|
1338
|
+
);
|
|
1339
|
+
});
|
|
1340
|
+
return res.modifiedCount;
|
|
1341
|
+
} catch (error) {
|
|
1342
|
+
throw error;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return {
|
|
1346
|
+
createIndex,
|
|
1347
|
+
createTextIndex,
|
|
1348
|
+
createUniqueIndex,
|
|
1349
|
+
createUnit,
|
|
1350
|
+
getUnits,
|
|
1351
|
+
updateUnit,
|
|
1352
|
+
deleteUnit
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// src/services/hygiene-area.service.ts
|
|
1081
1357
|
function useAreaService() {
|
|
1082
|
-
const { createArea: _createArea } = useAreaRepo();
|
|
1358
|
+
const { createArea: _createArea, getAreasForChecklist } = useAreaRepo();
|
|
1359
|
+
const { generateAreaExcel } = useAreaExportService();
|
|
1360
|
+
const { getUnits: _getUnits } = useUnitRepository();
|
|
1083
1361
|
async function importArea({
|
|
1084
1362
|
dataJson,
|
|
1085
1363
|
site
|
|
@@ -1088,10 +1366,24 @@ function useAreaService() {
|
|
|
1088
1366
|
try {
|
|
1089
1367
|
dataArray = JSON.parse(dataJson);
|
|
1090
1368
|
} catch (error) {
|
|
1091
|
-
throw new
|
|
1369
|
+
throw new import_node_server_utils8.BadRequestError("Invalid JSON format for data in excel");
|
|
1092
1370
|
}
|
|
1093
1371
|
if (!dataArray || dataArray.length === 0) {
|
|
1094
|
-
throw new
|
|
1372
|
+
throw new import_node_server_utils8.NotFoundError("No data found in the uploaded file");
|
|
1373
|
+
}
|
|
1374
|
+
let availableUnits = [];
|
|
1375
|
+
try {
|
|
1376
|
+
const unitsData = await _getUnits({
|
|
1377
|
+
page: 1,
|
|
1378
|
+
limit: 999999,
|
|
1379
|
+
search: "",
|
|
1380
|
+
site
|
|
1381
|
+
});
|
|
1382
|
+
if (unitsData && unitsData.items) {
|
|
1383
|
+
availableUnits = unitsData.items;
|
|
1384
|
+
}
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
import_node_server_utils8.logger.warn(`Failed to fetch units for site: ${error}`);
|
|
1095
1387
|
}
|
|
1096
1388
|
const insertedAreaIds = [];
|
|
1097
1389
|
const duplicateAreas = [];
|
|
@@ -1101,42 +1393,74 @@ function useAreaService() {
|
|
|
1101
1393
|
for (let i = 0; i < dataArray.length; i++) {
|
|
1102
1394
|
const row = dataArray[i];
|
|
1103
1395
|
if (!row?.TYPE) {
|
|
1104
|
-
|
|
1396
|
+
import_node_server_utils8.logger.warn(`Skipping row ${i + 1} with missing TYPE:`, row);
|
|
1105
1397
|
skippedRows.push(i + 1);
|
|
1106
1398
|
continue;
|
|
1107
1399
|
}
|
|
1108
1400
|
const areaType = String(row.TYPE).trim().toLowerCase();
|
|
1109
1401
|
if (!areaType) {
|
|
1110
|
-
|
|
1402
|
+
import_node_server_utils8.logger.warn(`Skipping row ${i + 1} with empty area type`);
|
|
1111
1403
|
skippedRows.push(i + 1);
|
|
1112
1404
|
continue;
|
|
1113
1405
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1406
|
+
const areaNameValue = row?.NAME || row?.AREA;
|
|
1407
|
+
if (!areaNameValue) {
|
|
1408
|
+
import_node_server_utils8.logger.warn(`Skipping row ${i + 1} with missing NAME/AREA:`, row);
|
|
1116
1409
|
skippedRows.push(i + 1);
|
|
1117
1410
|
continue;
|
|
1118
1411
|
}
|
|
1119
|
-
const areaName = String(
|
|
1412
|
+
const areaName = String(areaNameValue).trim();
|
|
1120
1413
|
if (!areaName) {
|
|
1121
|
-
|
|
1414
|
+
import_node_server_utils8.logger.warn(`Skipping row ${i + 1} with empty ${areaType} area name`);
|
|
1122
1415
|
skippedRows.push(i + 1);
|
|
1123
1416
|
continue;
|
|
1124
1417
|
}
|
|
1125
1418
|
if (areaName.startsWith("Sample:")) {
|
|
1126
|
-
|
|
1419
|
+
import_node_server_utils8.logger.warn(`Skipping row ${i + 1} with sample area: ${areaName}`);
|
|
1127
1420
|
skippedRows.push(i + 1);
|
|
1128
1421
|
continue;
|
|
1129
1422
|
}
|
|
1130
1423
|
try {
|
|
1131
|
-
const
|
|
1424
|
+
const areaData = {
|
|
1132
1425
|
type: areaType,
|
|
1133
1426
|
name: areaName,
|
|
1134
1427
|
site
|
|
1135
|
-
}
|
|
1428
|
+
};
|
|
1429
|
+
if (row.SET !== void 0 && row.SET !== null && row.SET !== "") {
|
|
1430
|
+
const setNumber = parseInt(String(row.SET).trim());
|
|
1431
|
+
if (!isNaN(setNumber) && setNumber >= 0) {
|
|
1432
|
+
areaData.set = setNumber;
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
if (row.UNITS && availableUnits.length > 0) {
|
|
1436
|
+
const unitNames = String(row.UNITS).split(",").map((u) => u.trim()).filter((u) => u);
|
|
1437
|
+
if (unitNames.length > 0) {
|
|
1438
|
+
const areaUnits = [];
|
|
1439
|
+
for (const unitName of unitNames) {
|
|
1440
|
+
const foundUnit = availableUnits.find(
|
|
1441
|
+
(u) => u.name.toLowerCase() === unitName.toLowerCase()
|
|
1442
|
+
);
|
|
1443
|
+
if (foundUnit) {
|
|
1444
|
+
areaUnits.push({
|
|
1445
|
+
unit: foundUnit._id,
|
|
1446
|
+
name: foundUnit.name
|
|
1447
|
+
});
|
|
1448
|
+
} else {
|
|
1449
|
+
import_node_server_utils8.logger.warn(
|
|
1450
|
+
`Unit "${unitName}" not found in site for area "${areaName}"`
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
if (areaUnits.length > 0) {
|
|
1455
|
+
areaData.units = areaUnits;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
const insertedId = await _createArea(areaData);
|
|
1136
1460
|
insertedAreaIds.push(insertedId);
|
|
1137
|
-
|
|
1461
|
+
import_node_server_utils8.logger.info(`Successfully created ${areaType} area: ${areaName}`);
|
|
1138
1462
|
} catch (error) {
|
|
1139
|
-
|
|
1463
|
+
import_node_server_utils8.logger.error(
|
|
1140
1464
|
`Error creating ${areaType} area "${areaName}": ${error.message}`
|
|
1141
1465
|
);
|
|
1142
1466
|
if (error.message.includes("duplicate")) {
|
|
@@ -1156,18 +1480,18 @@ function useAreaService() {
|
|
|
1156
1480
|
if (skippedRows.length > 0) {
|
|
1157
1481
|
message += `, ${skippedRows.length} rows skipped (invalid data)`;
|
|
1158
1482
|
}
|
|
1159
|
-
|
|
1483
|
+
import_node_server_utils8.logger.info(message);
|
|
1160
1484
|
if (insertedAreaIds.length === 0) {
|
|
1161
1485
|
if (duplicateAreas.length > 0 && failedAreas.length === 0 && skippedRows.length === 0) {
|
|
1162
1486
|
return {
|
|
1163
1487
|
message: `No new areas were created. All ${duplicateAreas.length} areas already exist in the system: ${duplicateAreas.join(", ")}`
|
|
1164
1488
|
};
|
|
1165
1489
|
} else if (failedAreas.length > 0) {
|
|
1166
|
-
throw new
|
|
1490
|
+
throw new import_node_server_utils8.BadRequestError(
|
|
1167
1491
|
`No areas were created. ${failedAreas.length} areas failed due to errors. Please check your data format and ensure area names are valid.`
|
|
1168
1492
|
);
|
|
1169
1493
|
} else if (skippedRows.length > 0 && duplicateAreas.length === 0) {
|
|
1170
|
-
throw new
|
|
1494
|
+
throw new import_node_server_utils8.BadRequestError(
|
|
1171
1495
|
`No areas were created. All ${skippedRows.length} rows contained invalid or missing data.`
|
|
1172
1496
|
);
|
|
1173
1497
|
} else {
|
|
@@ -1178,30 +1502,46 @@ function useAreaService() {
|
|
|
1178
1502
|
}
|
|
1179
1503
|
return { message };
|
|
1180
1504
|
} catch (error) {
|
|
1181
|
-
|
|
1182
|
-
if (error instanceof
|
|
1505
|
+
import_node_server_utils8.logger.error("Error while uploading area information", error);
|
|
1506
|
+
if (error instanceof import_node_server_utils8.BadRequestError) {
|
|
1183
1507
|
throw error;
|
|
1184
1508
|
} else if (error.message.includes("validation")) {
|
|
1185
|
-
throw new
|
|
1509
|
+
throw new import_node_server_utils8.BadRequestError(
|
|
1186
1510
|
"Upload failed due to invalid data format. Please check that all required fields are properly filled."
|
|
1187
1511
|
);
|
|
1188
1512
|
} else {
|
|
1189
|
-
throw new
|
|
1513
|
+
throw new import_node_server_utils8.BadRequestError(
|
|
1190
1514
|
`Upload failed: ${error.message || "Please check your data format and try again."}`
|
|
1191
1515
|
);
|
|
1192
1516
|
}
|
|
1193
1517
|
}
|
|
1194
1518
|
}
|
|
1195
|
-
|
|
1519
|
+
async function exportAreas(site) {
|
|
1520
|
+
try {
|
|
1521
|
+
const areas = await getAreasForChecklist(site);
|
|
1522
|
+
if (!areas || !Array.isArray(areas) || areas.length === 0) {
|
|
1523
|
+
throw new import_node_server_utils8.BadRequestError("No data found to export");
|
|
1524
|
+
}
|
|
1525
|
+
const excelBuffer = await generateAreaExcel(areas);
|
|
1526
|
+
if (!excelBuffer || excelBuffer.length === 0) {
|
|
1527
|
+
throw new Error("Generated Excel file is empty or invalid.");
|
|
1528
|
+
}
|
|
1529
|
+
return excelBuffer;
|
|
1530
|
+
} catch (error) {
|
|
1531
|
+
import_node_server_utils8.logger.error(`Error downloading areas: ${error.message}`);
|
|
1532
|
+
throw error;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
return { importArea, exportAreas };
|
|
1196
1536
|
}
|
|
1197
1537
|
|
|
1198
1538
|
// src/controllers/hygiene-area.controller.ts
|
|
1199
|
-
var
|
|
1200
|
-
var
|
|
1539
|
+
var import_joi4 = __toESM(require("joi"));
|
|
1540
|
+
var import_node_server_utils9 = require("@7365admin1/node-server-utils");
|
|
1201
1541
|
|
|
1202
1542
|
// src/utils/convert-excel.util.ts
|
|
1203
1543
|
var import_stream = require("stream");
|
|
1204
|
-
var
|
|
1544
|
+
var xlsx2 = __toESM(require("xlsx"));
|
|
1205
1545
|
function convertBufferFile(bufferFile) {
|
|
1206
1546
|
return new Promise((resolve, reject) => {
|
|
1207
1547
|
const fileStream = import_stream.Readable.from(bufferFile);
|
|
@@ -1211,10 +1551,10 @@ function convertBufferFile(bufferFile) {
|
|
|
1211
1551
|
});
|
|
1212
1552
|
fileStream.on("end", () => {
|
|
1213
1553
|
try {
|
|
1214
|
-
const workbook =
|
|
1554
|
+
const workbook = xlsx2.read(fileBuffer, { type: "buffer" });
|
|
1215
1555
|
const sheetName = workbook.SheetNames[0];
|
|
1216
1556
|
const sheet = workbook.Sheets[sheetName];
|
|
1217
|
-
const jsonData =
|
|
1557
|
+
const jsonData = xlsx2.utils.sheet_to_json(sheet);
|
|
1218
1558
|
resolve(jsonData);
|
|
1219
1559
|
} catch (error) {
|
|
1220
1560
|
reject("Error parsing file");
|
|
@@ -1235,13 +1575,13 @@ function useAreaController() {
|
|
|
1235
1575
|
updateArea: _updateArea,
|
|
1236
1576
|
deleteArea: _deleteById
|
|
1237
1577
|
} = useAreaRepo();
|
|
1238
|
-
const { importArea: _importArea } = useAreaService();
|
|
1578
|
+
const { importArea: _importArea, exportAreas: _exportAreas } = useAreaService();
|
|
1239
1579
|
async function createArea(req, res, next) {
|
|
1240
1580
|
const payload = { ...req.body, ...req.params };
|
|
1241
1581
|
const { error } = areaSchema.validate(payload);
|
|
1242
1582
|
if (error) {
|
|
1243
|
-
|
|
1244
|
-
next(new
|
|
1583
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1584
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1245
1585
|
return;
|
|
1246
1586
|
}
|
|
1247
1587
|
try {
|
|
@@ -1249,24 +1589,24 @@ function useAreaController() {
|
|
|
1249
1589
|
res.status(201).json({ message: "Area created successfully.", id });
|
|
1250
1590
|
return;
|
|
1251
1591
|
} catch (error2) {
|
|
1252
|
-
|
|
1592
|
+
import_node_server_utils9.logger.log({ level: "error", message: error2.message });
|
|
1253
1593
|
next(error2);
|
|
1254
1594
|
return;
|
|
1255
1595
|
}
|
|
1256
1596
|
}
|
|
1257
1597
|
async function getAreas(req, res, next) {
|
|
1258
1598
|
const query = { ...req.query, ...req.params };
|
|
1259
|
-
const validation =
|
|
1260
|
-
page:
|
|
1261
|
-
limit:
|
|
1262
|
-
search:
|
|
1263
|
-
type:
|
|
1264
|
-
site:
|
|
1599
|
+
const validation = import_joi4.default.object({
|
|
1600
|
+
page: import_joi4.default.number().min(1).optional().allow("", null),
|
|
1601
|
+
limit: import_joi4.default.number().min(1).optional().allow("", null),
|
|
1602
|
+
search: import_joi4.default.string().optional().allow("", null),
|
|
1603
|
+
type: import_joi4.default.string().valid("all", ...allowedTypes).optional().allow("", null),
|
|
1604
|
+
site: import_joi4.default.string().hex().required()
|
|
1265
1605
|
});
|
|
1266
1606
|
const { error } = validation.validate(query);
|
|
1267
1607
|
if (error) {
|
|
1268
|
-
|
|
1269
|
-
next(new
|
|
1608
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1609
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1270
1610
|
return;
|
|
1271
1611
|
}
|
|
1272
1612
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -1290,12 +1630,12 @@ function useAreaController() {
|
|
|
1290
1630
|
}
|
|
1291
1631
|
}
|
|
1292
1632
|
async function getAreaById(req, res, next) {
|
|
1293
|
-
const validation =
|
|
1633
|
+
const validation = import_joi4.default.string().hex().required();
|
|
1294
1634
|
const _id = req.params.id;
|
|
1295
1635
|
const { error, value } = validation.validate(_id);
|
|
1296
1636
|
if (error) {
|
|
1297
|
-
|
|
1298
|
-
next(new
|
|
1637
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1638
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1299
1639
|
return;
|
|
1300
1640
|
}
|
|
1301
1641
|
try {
|
|
@@ -1303,22 +1643,22 @@ function useAreaController() {
|
|
|
1303
1643
|
res.json(data);
|
|
1304
1644
|
return;
|
|
1305
1645
|
} catch (error2) {
|
|
1306
|
-
|
|
1646
|
+
import_node_server_utils9.logger.log({ level: "error", message: error2.message });
|
|
1307
1647
|
next(error2);
|
|
1308
1648
|
return;
|
|
1309
1649
|
}
|
|
1310
1650
|
}
|
|
1311
1651
|
async function updateArea(req, res, next) {
|
|
1312
1652
|
const payload = { id: req.params.id, ...req.body };
|
|
1313
|
-
const schema =
|
|
1314
|
-
id:
|
|
1315
|
-
name:
|
|
1316
|
-
type:
|
|
1317
|
-
set:
|
|
1318
|
-
units:
|
|
1319
|
-
|
|
1320
|
-
unit:
|
|
1321
|
-
name:
|
|
1653
|
+
const schema = import_joi4.default.object({
|
|
1654
|
+
id: import_joi4.default.string().hex().required(),
|
|
1655
|
+
name: import_joi4.default.string().optional().allow("", null),
|
|
1656
|
+
type: import_joi4.default.string().optional().allow("", null, ...allowedTypes),
|
|
1657
|
+
set: import_joi4.default.number().min(0).optional(),
|
|
1658
|
+
units: import_joi4.default.array().items(
|
|
1659
|
+
import_joi4.default.object({
|
|
1660
|
+
unit: import_joi4.default.string().hex().required(),
|
|
1661
|
+
name: import_joi4.default.string().required()
|
|
1322
1662
|
}).required()
|
|
1323
1663
|
).min(1).unique("unit", { ignoreUndefined: true }).optional().messages({
|
|
1324
1664
|
"array.unique": "Duplicate area units are not allowed"
|
|
@@ -1326,8 +1666,8 @@ function useAreaController() {
|
|
|
1326
1666
|
});
|
|
1327
1667
|
const { error } = schema.validate(payload);
|
|
1328
1668
|
if (error) {
|
|
1329
|
-
|
|
1330
|
-
next(new
|
|
1669
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1670
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1331
1671
|
return;
|
|
1332
1672
|
}
|
|
1333
1673
|
try {
|
|
@@ -1336,286 +1676,135 @@ function useAreaController() {
|
|
|
1336
1676
|
res.json({ message: "Area updated successfully." });
|
|
1337
1677
|
return;
|
|
1338
1678
|
} catch (error2) {
|
|
1339
|
-
|
|
1679
|
+
import_node_server_utils9.logger.log({ level: "error", message: error2.message });
|
|
1340
1680
|
next(error2);
|
|
1341
|
-
return;
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
async function deleteArea(req, res, next) {
|
|
1345
|
-
const id = req.params.id;
|
|
1346
|
-
const validation =
|
|
1347
|
-
const { error, value } = validation.validate(id);
|
|
1348
|
-
if (error) {
|
|
1349
|
-
|
|
1350
|
-
next(new
|
|
1351
|
-
return;
|
|
1352
|
-
}
|
|
1353
|
-
try {
|
|
1354
|
-
await _deleteById(value);
|
|
1355
|
-
res.json({ message: "Area deleted successfully." });
|
|
1356
|
-
return;
|
|
1357
|
-
} catch (error2) {
|
|
1358
|
-
import_node_server_utils6.logger.log({ level: "error", message: error2.message });
|
|
1359
|
-
next(error2);
|
|
1360
|
-
return;
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
async function importArea(req, res, next) {
|
|
1364
|
-
if (!req.file) {
|
|
1365
|
-
next(new import_node_server_utils6.BadRequestError("File is required!"));
|
|
1366
|
-
return;
|
|
1367
|
-
}
|
|
1368
|
-
const { site } = req.params;
|
|
1369
|
-
const schema = import_joi3.default.string().hex().required();
|
|
1370
|
-
const { error, value } = schema.validate(site);
|
|
1371
|
-
if (error) {
|
|
1372
|
-
import_node_server_utils6.logger.log({ level: "error", message: error.message });
|
|
1373
|
-
next(new import_node_server_utils6.BadRequestError(error.message));
|
|
1374
|
-
return;
|
|
1375
|
-
}
|
|
1376
|
-
try {
|
|
1377
|
-
const xlsData = await convertBufferFile(req.file.buffer);
|
|
1378
|
-
const dataJson = JSON.stringify(xlsData);
|
|
1379
|
-
const result = await _importArea({ dataJson, site: value });
|
|
1380
|
-
return res.status(201).json(result);
|
|
1381
|
-
} catch (error2) {
|
|
1382
|
-
import_node_server_utils6.logger.log({ level: "error", message: error2.message });
|
|
1383
|
-
next(error2);
|
|
1384
|
-
return;
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
return {
|
|
1388
|
-
createArea,
|
|
1389
|
-
getAreas,
|
|
1390
|
-
getAreaById,
|
|
1391
|
-
updateArea,
|
|
1392
|
-
deleteArea,
|
|
1393
|
-
importArea
|
|
1394
|
-
};
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
// src/models/hygiene-unit.model.ts
|
|
1398
|
-
var import_joi4 = __toESM(require("joi"));
|
|
1399
|
-
var import_mongodb4 = require("mongodb");
|
|
1400
|
-
var import_node_server_utils7 = require("@7365admin1/node-server-utils");
|
|
1401
|
-
var unitSchema = import_joi4.default.object({
|
|
1402
|
-
site: import_joi4.default.string().hex().required(),
|
|
1403
|
-
name: import_joi4.default.string().required()
|
|
1404
|
-
});
|
|
1405
|
-
function MUnit(value) {
|
|
1406
|
-
const { error } = unitSchema.validate(value);
|
|
1407
|
-
if (error) {
|
|
1408
|
-
import_node_server_utils7.logger.info(`Hygiene Unit Model: ${error.message}`);
|
|
1409
|
-
throw new import_node_server_utils7.BadRequestError(error.message);
|
|
1410
|
-
}
|
|
1411
|
-
if (value.site) {
|
|
1412
|
-
try {
|
|
1413
|
-
value.site = new import_mongodb4.ObjectId(value.site);
|
|
1414
|
-
} catch (error2) {
|
|
1415
|
-
throw new import_node_server_utils7.BadRequestError("Invalid site ID format.");
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
return {
|
|
1419
|
-
site: value.site,
|
|
1420
|
-
name: value.name,
|
|
1421
|
-
status: "active",
|
|
1422
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1423
|
-
updatedAt: "",
|
|
1424
|
-
deletedAt: ""
|
|
1425
|
-
};
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
// src/services/hygiene-unit.service.ts
|
|
1429
|
-
var import_node_server_utils9 = require("@7365admin1/node-server-utils");
|
|
1430
|
-
|
|
1431
|
-
// src/repositories/hygiene-unit.repository.ts
|
|
1432
|
-
var import_mongodb5 = require("mongodb");
|
|
1433
|
-
var import_node_server_utils8 = require("@7365admin1/node-server-utils");
|
|
1434
|
-
function useUnitRepository() {
|
|
1435
|
-
const db = import_node_server_utils8.useAtlas.getDb();
|
|
1436
|
-
if (!db) {
|
|
1437
|
-
throw new import_node_server_utils8.InternalServerError("Unable to connect to server.");
|
|
1438
|
-
}
|
|
1439
|
-
const namespace_collection = "site.cleaning.area.unit";
|
|
1440
|
-
const collection = db.collection(namespace_collection);
|
|
1441
|
-
const { delNamespace, setCache, getCache } = (0, import_node_server_utils8.useCache)(namespace_collection);
|
|
1442
|
-
async function createIndex() {
|
|
1443
|
-
try {
|
|
1444
|
-
await collection.createIndexes([
|
|
1445
|
-
{ key: { site: 1 } },
|
|
1446
|
-
{ key: { status: 1 } }
|
|
1447
|
-
]);
|
|
1448
|
-
} catch (error) {
|
|
1449
|
-
throw new import_node_server_utils8.InternalServerError("Failed to create index on hygiene unit.");
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
async function createTextIndex() {
|
|
1453
|
-
try {
|
|
1454
|
-
await collection.createIndex({ name: "text" });
|
|
1455
|
-
} catch (error) {
|
|
1456
|
-
throw new import_node_server_utils8.InternalServerError(
|
|
1457
|
-
"Failed to create text index on hygiene unit."
|
|
1458
|
-
);
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
async function createUniqueIndex() {
|
|
1462
|
-
try {
|
|
1463
|
-
await collection.createIndex(
|
|
1464
|
-
{ site: 1, name: 1, deletedAt: 1 },
|
|
1465
|
-
{ unique: true }
|
|
1466
|
-
);
|
|
1467
|
-
} catch (error) {
|
|
1468
|
-
throw new import_node_server_utils8.InternalServerError(
|
|
1469
|
-
"Failed to create unique index on hygiene unit."
|
|
1470
|
-
);
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
async function createUnit(value, session) {
|
|
1474
|
-
try {
|
|
1475
|
-
value = MUnit(value);
|
|
1476
|
-
const res = await collection.insertOne(value, { session });
|
|
1477
|
-
delNamespace().then(() => {
|
|
1478
|
-
import_node_server_utils8.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1479
|
-
}).catch((err) => {
|
|
1480
|
-
import_node_server_utils8.logger.error(
|
|
1481
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1482
|
-
err
|
|
1483
|
-
);
|
|
1484
|
-
});
|
|
1485
|
-
return res.insertedId;
|
|
1486
|
-
} catch (error) {
|
|
1487
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
1488
|
-
if (isDuplicated) {
|
|
1489
|
-
throw new import_node_server_utils8.BadRequestError("Unit already exists.");
|
|
1490
|
-
}
|
|
1491
|
-
throw error;
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
async function getUnits({
|
|
1495
|
-
page = 1,
|
|
1496
|
-
limit = 10,
|
|
1497
|
-
search = "",
|
|
1498
|
-
site
|
|
1499
|
-
}) {
|
|
1500
|
-
page = page > 0 ? page - 1 : 0;
|
|
1501
|
-
const query = {
|
|
1502
|
-
status: { $ne: "deleted" }
|
|
1503
|
-
};
|
|
1504
|
-
const cacheOptions = {
|
|
1505
|
-
page,
|
|
1506
|
-
limit
|
|
1507
|
-
};
|
|
1508
|
-
try {
|
|
1509
|
-
site = new import_mongodb5.ObjectId(site);
|
|
1510
|
-
query.site = site;
|
|
1511
|
-
cacheOptions.site = site.toString();
|
|
1512
|
-
} catch (error) {
|
|
1513
|
-
throw new import_node_server_utils8.BadRequestError("Invalid site ID format.");
|
|
1514
|
-
}
|
|
1515
|
-
if (search) {
|
|
1516
|
-
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
1517
|
-
cacheOptions.search = search;
|
|
1518
|
-
}
|
|
1519
|
-
const cacheKey = (0, import_node_server_utils8.makeCacheKey)(namespace_collection, cacheOptions);
|
|
1520
|
-
const cachedData = await getCache(cacheKey);
|
|
1521
|
-
if (cachedData) {
|
|
1522
|
-
import_node_server_utils8.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1523
|
-
return cachedData;
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
async function deleteArea(req, res, next) {
|
|
1685
|
+
const id = req.params.id;
|
|
1686
|
+
const validation = import_joi4.default.string().hex().required();
|
|
1687
|
+
const { error, value } = validation.validate(id);
|
|
1688
|
+
if (error) {
|
|
1689
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1690
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1691
|
+
return;
|
|
1524
1692
|
}
|
|
1525
1693
|
try {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
const length = await collection.countDocuments(query);
|
|
1534
|
-
const data = (0, import_node_server_utils8.paginate)(items, page, limit, length);
|
|
1535
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
1536
|
-
import_node_server_utils8.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1537
|
-
}).catch((err) => {
|
|
1538
|
-
import_node_server_utils8.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1539
|
-
});
|
|
1540
|
-
return data;
|
|
1541
|
-
} catch (error) {
|
|
1542
|
-
throw error;
|
|
1694
|
+
await _deleteById(value);
|
|
1695
|
+
res.json({ message: "Area deleted successfully." });
|
|
1696
|
+
return;
|
|
1697
|
+
} catch (error2) {
|
|
1698
|
+
import_node_server_utils9.logger.log({ level: "error", message: error2.message });
|
|
1699
|
+
next(error2);
|
|
1700
|
+
return;
|
|
1543
1701
|
}
|
|
1544
1702
|
}
|
|
1545
|
-
async function
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1703
|
+
async function importArea(req, res, next) {
|
|
1704
|
+
if (!req.file) {
|
|
1705
|
+
next(new import_node_server_utils9.BadRequestError("File is required!"));
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
const { site } = req.params;
|
|
1709
|
+
const schema = import_joi4.default.string().hex().required();
|
|
1710
|
+
const { error, value } = schema.validate(site);
|
|
1711
|
+
if (error) {
|
|
1712
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1713
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1714
|
+
return;
|
|
1550
1715
|
}
|
|
1551
1716
|
try {
|
|
1552
|
-
const
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
);
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
}
|
|
1561
|
-
delNamespace().then(() => {
|
|
1562
|
-
import_node_server_utils8.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1563
|
-
}).catch((err) => {
|
|
1564
|
-
import_node_server_utils8.logger.error(
|
|
1565
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1566
|
-
err
|
|
1567
|
-
);
|
|
1568
|
-
});
|
|
1569
|
-
return res.modifiedCount;
|
|
1570
|
-
} catch (error) {
|
|
1571
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
1572
|
-
if (isDuplicated) {
|
|
1573
|
-
throw new import_node_server_utils8.BadRequestError("Area already exists.");
|
|
1574
|
-
}
|
|
1575
|
-
throw error;
|
|
1717
|
+
const xlsData = await convertBufferFile(req.file.buffer);
|
|
1718
|
+
const dataJson = JSON.stringify(xlsData);
|
|
1719
|
+
const result = await _importArea({ dataJson, site: value });
|
|
1720
|
+
return res.status(201).json(result);
|
|
1721
|
+
} catch (error2) {
|
|
1722
|
+
import_node_server_utils9.logger.log({ level: "error", message: error2.message });
|
|
1723
|
+
next(error2);
|
|
1724
|
+
return;
|
|
1576
1725
|
}
|
|
1577
1726
|
}
|
|
1578
|
-
async function
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1727
|
+
async function exportAreas(req, res, next) {
|
|
1728
|
+
const { site } = req.params;
|
|
1729
|
+
const validation = import_joi4.default.string().hex().required();
|
|
1730
|
+
const { error, value } = validation.validate(site);
|
|
1731
|
+
if (error) {
|
|
1732
|
+
import_node_server_utils9.logger.log({ level: "error", message: error.message });
|
|
1733
|
+
next(new import_node_server_utils9.BadRequestError(error.message));
|
|
1734
|
+
return;
|
|
1583
1735
|
}
|
|
1584
1736
|
try {
|
|
1585
|
-
const
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1737
|
+
const excelBuffer = await _exportAreas(value);
|
|
1738
|
+
const date = /* @__PURE__ */ new Date();
|
|
1739
|
+
const formattedDate = `${String(date.getMonth() + 1).padStart(
|
|
1740
|
+
2,
|
|
1741
|
+
"0"
|
|
1742
|
+
)}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
|
|
1743
|
+
res.setHeader(
|
|
1744
|
+
"Content-Type",
|
|
1745
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
1594
1746
|
);
|
|
1595
|
-
|
|
1596
|
-
|
|
1747
|
+
res.setHeader(
|
|
1748
|
+
"Content-Disposition",
|
|
1749
|
+
`attachment; filename="areas-${formattedDate}.xlsx"`
|
|
1750
|
+
);
|
|
1751
|
+
res.setHeader("Content-Length", excelBuffer.length);
|
|
1752
|
+
res.end(excelBuffer);
|
|
1753
|
+
return;
|
|
1754
|
+
} catch (error2) {
|
|
1755
|
+
import_node_server_utils9.logger.log({ level: "error", message: error2.message });
|
|
1756
|
+
next(error2);
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return {
|
|
1761
|
+
createArea,
|
|
1762
|
+
getAreas,
|
|
1763
|
+
getAreaById,
|
|
1764
|
+
updateArea,
|
|
1765
|
+
deleteArea,
|
|
1766
|
+
importArea,
|
|
1767
|
+
exportAreas
|
|
1768
|
+
};
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
// src/services/hygiene-unit.service.ts
|
|
1772
|
+
var import_node_server_utils11 = require("@7365admin1/node-server-utils");
|
|
1773
|
+
|
|
1774
|
+
// src/services/hygiene-unit-export.service.ts
|
|
1775
|
+
var import_node_server_utils10 = require("@7365admin1/node-server-utils");
|
|
1776
|
+
var xlsx3 = __toESM(require("xlsx"));
|
|
1777
|
+
function useUnitExportService() {
|
|
1778
|
+
async function generateUnitExcel(units) {
|
|
1779
|
+
try {
|
|
1780
|
+
const rows = [];
|
|
1781
|
+
rows.push(["UNIT"]);
|
|
1782
|
+
for (const unit of units) {
|
|
1783
|
+
const unitName = unit.name || "";
|
|
1784
|
+
rows.push([unitName]);
|
|
1597
1785
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1786
|
+
const workbook = xlsx3.utils.book_new();
|
|
1787
|
+
const worksheet = xlsx3.utils.aoa_to_sheet(rows);
|
|
1788
|
+
worksheet["!cols"] = [
|
|
1789
|
+
{ width: 25 }
|
|
1790
|
+
// UNIT
|
|
1791
|
+
];
|
|
1792
|
+
xlsx3.utils.book_append_sheet(workbook, worksheet, "Units");
|
|
1793
|
+
const excelBuffer = xlsx3.write(workbook, {
|
|
1794
|
+
type: "buffer",
|
|
1795
|
+
bookType: "xlsx"
|
|
1605
1796
|
});
|
|
1606
|
-
return
|
|
1797
|
+
return excelBuffer;
|
|
1607
1798
|
} catch (error) {
|
|
1799
|
+
import_node_server_utils10.logger.log({
|
|
1800
|
+
level: "error",
|
|
1801
|
+
message: `Failed to generate unit Excel: ${error.message}`
|
|
1802
|
+
});
|
|
1608
1803
|
throw error;
|
|
1609
1804
|
}
|
|
1610
1805
|
}
|
|
1611
1806
|
return {
|
|
1612
|
-
|
|
1613
|
-
createTextIndex,
|
|
1614
|
-
createUniqueIndex,
|
|
1615
|
-
createUnit,
|
|
1616
|
-
getUnits,
|
|
1617
|
-
updateUnit,
|
|
1618
|
-
deleteUnit
|
|
1807
|
+
generateUnitExcel
|
|
1619
1808
|
};
|
|
1620
1809
|
}
|
|
1621
1810
|
|
|
@@ -1635,10 +1824,10 @@ function useUnitService() {
|
|
|
1635
1824
|
try {
|
|
1636
1825
|
dataArray = JSON.parse(dataJson);
|
|
1637
1826
|
} catch (error) {
|
|
1638
|
-
throw new
|
|
1827
|
+
throw new import_node_server_utils11.BadRequestError("Invalid JSON format for data in excel");
|
|
1639
1828
|
}
|
|
1640
1829
|
if (!dataArray || dataArray.length === 0) {
|
|
1641
|
-
throw new
|
|
1830
|
+
throw new import_node_server_utils11.NotFoundError("No data found in the uploaded file");
|
|
1642
1831
|
}
|
|
1643
1832
|
const insertedUnitIds = [];
|
|
1644
1833
|
const duplicateUnits = [];
|
|
@@ -1648,18 +1837,18 @@ function useUnitService() {
|
|
|
1648
1837
|
for (let i = 0; i < dataArray.length; i++) {
|
|
1649
1838
|
const row = dataArray[i];
|
|
1650
1839
|
if (!row?.UNIT) {
|
|
1651
|
-
|
|
1840
|
+
import_node_server_utils11.logger.warn(`Skipping row ${i + 1} with missing UNIT:`, row);
|
|
1652
1841
|
skippedRows.push(i + 1);
|
|
1653
1842
|
continue;
|
|
1654
1843
|
}
|
|
1655
1844
|
const unitName = String(row.UNIT).trim();
|
|
1656
1845
|
if (!unitName) {
|
|
1657
|
-
|
|
1846
|
+
import_node_server_utils11.logger.warn(`Skipping row ${i + 1} with empty unit name`);
|
|
1658
1847
|
skippedRows.push(i + 1);
|
|
1659
1848
|
continue;
|
|
1660
1849
|
}
|
|
1661
1850
|
if (unitName.startsWith("Sample:")) {
|
|
1662
|
-
|
|
1851
|
+
import_node_server_utils11.logger.warn(`Skipping row ${i + 1} with sample unit: ${unitName}`);
|
|
1663
1852
|
skippedRows.push(i + 1);
|
|
1664
1853
|
continue;
|
|
1665
1854
|
}
|
|
@@ -1669,9 +1858,9 @@ function useUnitService() {
|
|
|
1669
1858
|
site
|
|
1670
1859
|
});
|
|
1671
1860
|
insertedUnitIds.push(insertedId);
|
|
1672
|
-
|
|
1861
|
+
import_node_server_utils11.logger.info(`Successfully created unit: ${unitName}`);
|
|
1673
1862
|
} catch (error) {
|
|
1674
|
-
|
|
1863
|
+
import_node_server_utils11.logger.error(`Error creating unit "${unitName}": ${error.message}`);
|
|
1675
1864
|
if (error.message.includes("Unit already exists")) {
|
|
1676
1865
|
duplicateUnits.push(unitName);
|
|
1677
1866
|
} else {
|
|
@@ -1689,44 +1878,44 @@ function useUnitService() {
|
|
|
1689
1878
|
if (skippedRows.length > 0) {
|
|
1690
1879
|
message += `, ${skippedRows.length} rows skipped (invalid data)`;
|
|
1691
1880
|
}
|
|
1692
|
-
|
|
1881
|
+
import_node_server_utils11.logger.info(message);
|
|
1693
1882
|
if (insertedUnitIds.length === 0) {
|
|
1694
1883
|
if (duplicateUnits.length > 0 && failedUnits.length === 0) {
|
|
1695
|
-
throw new
|
|
1884
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1696
1885
|
`No new units were created. All ${duplicateUnits.length} units already exist in the system: ${duplicateUnits.join(", ")}`
|
|
1697
1886
|
);
|
|
1698
1887
|
} else if (failedUnits.length > 0) {
|
|
1699
|
-
throw new
|
|
1888
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1700
1889
|
`No units were created. Please check your data format and ensure unit names are valid.`
|
|
1701
1890
|
);
|
|
1702
1891
|
} else if (skippedRows.length > 0) {
|
|
1703
|
-
throw new
|
|
1892
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1704
1893
|
`No units were created. All rows contained invalid or missing unit names.`
|
|
1705
1894
|
);
|
|
1706
1895
|
}
|
|
1707
1896
|
}
|
|
1708
1897
|
return { message };
|
|
1709
1898
|
} catch (error) {
|
|
1710
|
-
|
|
1711
|
-
if (error instanceof
|
|
1899
|
+
import_node_server_utils11.logger.error("Error while uploading unit information", error);
|
|
1900
|
+
if (error instanceof import_node_server_utils11.BadRequestError) {
|
|
1712
1901
|
throw error;
|
|
1713
1902
|
} else if (error.message.includes("duplicate")) {
|
|
1714
|
-
throw new
|
|
1903
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1715
1904
|
"Upload failed due to duplicate unit names. Please ensure all unit names are unique."
|
|
1716
1905
|
);
|
|
1717
1906
|
} else if (error.message.includes("validation")) {
|
|
1718
|
-
throw new
|
|
1907
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1719
1908
|
"Upload failed due to invalid data format. Please check that all required fields are properly filled."
|
|
1720
1909
|
);
|
|
1721
1910
|
} else {
|
|
1722
|
-
throw new
|
|
1911
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1723
1912
|
`Upload failed: ${error.message || "Please check your data format and try again."}`
|
|
1724
1913
|
);
|
|
1725
1914
|
}
|
|
1726
1915
|
}
|
|
1727
1916
|
}
|
|
1728
1917
|
async function updateUnit(_id, value) {
|
|
1729
|
-
const session =
|
|
1918
|
+
const session = import_node_server_utils11.useAtlas.getClient()?.startSession();
|
|
1730
1919
|
try {
|
|
1731
1920
|
session?.startTransaction();
|
|
1732
1921
|
const result = await _updateUnit(_id, value, session);
|
|
@@ -1737,7 +1926,7 @@ function useUnitService() {
|
|
|
1737
1926
|
await session?.commitTransaction();
|
|
1738
1927
|
return result;
|
|
1739
1928
|
} catch (error) {
|
|
1740
|
-
|
|
1929
|
+
import_node_server_utils11.logger.error(`Error updating unit and associated areas:`, error);
|
|
1741
1930
|
if (session?.inTransaction()) {
|
|
1742
1931
|
await session?.abortTransaction();
|
|
1743
1932
|
}
|
|
@@ -1747,18 +1936,18 @@ function useUnitService() {
|
|
|
1747
1936
|
}
|
|
1748
1937
|
}
|
|
1749
1938
|
async function deleteUnit(_id) {
|
|
1750
|
-
const session =
|
|
1939
|
+
const session = import_node_server_utils11.useAtlas.getClient()?.startSession();
|
|
1751
1940
|
try {
|
|
1752
1941
|
session?.startTransaction();
|
|
1753
1942
|
const isExistingArea = await verifyAreaByUnitId(_id);
|
|
1754
1943
|
if (isExistingArea) {
|
|
1755
|
-
throw new
|
|
1944
|
+
throw new import_node_server_utils11.BadRequestError("Failed to delete unit, unit is in use.");
|
|
1756
1945
|
}
|
|
1757
1946
|
const result = await _deleteUnit(_id, session);
|
|
1758
1947
|
await session?.commitTransaction();
|
|
1759
1948
|
return result;
|
|
1760
1949
|
} catch (error) {
|
|
1761
|
-
|
|
1950
|
+
import_node_server_utils11.logger.error(`Error deleting unit:`, error);
|
|
1762
1951
|
if (session?.inTransaction()) {
|
|
1763
1952
|
await session?.abortTransaction();
|
|
1764
1953
|
}
|
|
@@ -1767,25 +1956,49 @@ function useUnitService() {
|
|
|
1767
1956
|
session?.endSession();
|
|
1768
1957
|
}
|
|
1769
1958
|
}
|
|
1770
|
-
|
|
1959
|
+
async function exportUnits(site) {
|
|
1960
|
+
const { generateUnitExcel: _generateUnitExcel } = useUnitExportService();
|
|
1961
|
+
const { getUnits: _getUnits } = useUnitRepository();
|
|
1962
|
+
try {
|
|
1963
|
+
const data = await _getUnits({
|
|
1964
|
+
page: 1,
|
|
1965
|
+
limit: 999999,
|
|
1966
|
+
search: "",
|
|
1967
|
+
site
|
|
1968
|
+
});
|
|
1969
|
+
if (!data || !data.items || data.items.length === 0) {
|
|
1970
|
+
throw new import_node_server_utils11.BadRequestError("No data found to export");
|
|
1971
|
+
}
|
|
1972
|
+
const excelBuffer = await _generateUnitExcel(data.items);
|
|
1973
|
+
if (!excelBuffer || excelBuffer.length === 0) {
|
|
1974
|
+
throw new Error("Generated Excel file is empty or invalid.");
|
|
1975
|
+
}
|
|
1976
|
+
return excelBuffer;
|
|
1977
|
+
} catch (error) {
|
|
1978
|
+
import_node_server_utils11.logger.error(`Error downloading units: ${error.message}`);
|
|
1979
|
+
throw error;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return { importUnit, updateUnit, deleteUnit, exportUnits };
|
|
1771
1983
|
}
|
|
1772
1984
|
|
|
1773
1985
|
// src/controllers/hygiene-unit.controller.ts
|
|
1774
1986
|
var import_joi5 = __toESM(require("joi"));
|
|
1775
|
-
var
|
|
1987
|
+
var import_node_server_utils12 = require("@7365admin1/node-server-utils");
|
|
1776
1988
|
function useUnitController() {
|
|
1777
1989
|
const { createUnit: _createUnit, getUnits: _getUnits } = useUnitRepository();
|
|
1778
1990
|
const {
|
|
1779
1991
|
updateUnit: _updateUnit,
|
|
1780
1992
|
deleteUnit: _deleteUnit,
|
|
1781
|
-
importUnit: _importUnit
|
|
1993
|
+
importUnit: _importUnit,
|
|
1994
|
+
exportUnits: _exportUnits
|
|
1782
1995
|
} = useUnitService();
|
|
1783
1996
|
async function createUnit(req, res, next) {
|
|
1784
1997
|
const payload = { ...req.body, ...req.params };
|
|
1785
1998
|
const { error } = unitSchema.validate(payload);
|
|
1786
1999
|
if (error) {
|
|
1787
|
-
|
|
1788
|
-
next(new
|
|
2000
|
+
import_node_server_utils12.logger.log({ level: "error", message: error.message });
|
|
2001
|
+
next(new import_node_server_utils12.BadRequestError(error.message));
|
|
1789
2002
|
return;
|
|
1790
2003
|
}
|
|
1791
2004
|
try {
|
|
@@ -1793,7 +2006,7 @@ function useUnitController() {
|
|
|
1793
2006
|
res.status(201).json({ message: "Unit created successfully.", id });
|
|
1794
2007
|
return;
|
|
1795
2008
|
} catch (error2) {
|
|
1796
|
-
|
|
2009
|
+
import_node_server_utils12.logger.log({ level: "error", message: error2.message });
|
|
1797
2010
|
next(error2);
|
|
1798
2011
|
return;
|
|
1799
2012
|
}
|
|
@@ -1808,8 +2021,8 @@ function useUnitController() {
|
|
|
1808
2021
|
});
|
|
1809
2022
|
const { error } = validation.validate(query);
|
|
1810
2023
|
if (error) {
|
|
1811
|
-
|
|
1812
|
-
next(new
|
|
2024
|
+
import_node_server_utils12.logger.log({ level: "error", message: error.message });
|
|
2025
|
+
next(new import_node_server_utils12.BadRequestError(error.message));
|
|
1813
2026
|
return;
|
|
1814
2027
|
}
|
|
1815
2028
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -1826,7 +2039,7 @@ function useUnitController() {
|
|
|
1826
2039
|
res.json(data);
|
|
1827
2040
|
return;
|
|
1828
2041
|
} catch (error2) {
|
|
1829
|
-
|
|
2042
|
+
import_node_server_utils12.logger.log({ level: "error", message: error2.message });
|
|
1830
2043
|
next(error2);
|
|
1831
2044
|
return;
|
|
1832
2045
|
}
|
|
@@ -1839,8 +2052,8 @@ function useUnitController() {
|
|
|
1839
2052
|
});
|
|
1840
2053
|
const { error } = validation.validate(payload);
|
|
1841
2054
|
if (error) {
|
|
1842
|
-
|
|
1843
|
-
next(new
|
|
2055
|
+
import_node_server_utils12.logger.log({ level: "error", message: error.message });
|
|
2056
|
+
next(new import_node_server_utils12.BadRequestError(error.message));
|
|
1844
2057
|
return;
|
|
1845
2058
|
}
|
|
1846
2059
|
try {
|
|
@@ -1849,7 +2062,7 @@ function useUnitController() {
|
|
|
1849
2062
|
res.json({ message: "Unit updated successfully." });
|
|
1850
2063
|
return;
|
|
1851
2064
|
} catch (error2) {
|
|
1852
|
-
|
|
2065
|
+
import_node_server_utils12.logger.log({ level: "error", message: error2.message });
|
|
1853
2066
|
next(error2);
|
|
1854
2067
|
return;
|
|
1855
2068
|
}
|
|
@@ -1861,8 +2074,8 @@ function useUnitController() {
|
|
|
1861
2074
|
});
|
|
1862
2075
|
const { error, value } = validation.validate({ id });
|
|
1863
2076
|
if (error) {
|
|
1864
|
-
|
|
1865
|
-
next(new
|
|
2077
|
+
import_node_server_utils12.logger.log({ level: "error", message: error.message });
|
|
2078
|
+
next(new import_node_server_utils12.BadRequestError(error.message));
|
|
1866
2079
|
return;
|
|
1867
2080
|
}
|
|
1868
2081
|
try {
|
|
@@ -1870,22 +2083,22 @@ function useUnitController() {
|
|
|
1870
2083
|
res.json({ message: "Unit deleted successfully." });
|
|
1871
2084
|
return;
|
|
1872
2085
|
} catch (error2) {
|
|
1873
|
-
|
|
2086
|
+
import_node_server_utils12.logger.log({ level: "error", message: error2.message });
|
|
1874
2087
|
next(error2);
|
|
1875
2088
|
return;
|
|
1876
2089
|
}
|
|
1877
2090
|
}
|
|
1878
2091
|
async function importUnit(req, res, next) {
|
|
1879
2092
|
if (!req.file) {
|
|
1880
|
-
next(new
|
|
2093
|
+
next(new import_node_server_utils12.BadRequestError("File is required!"));
|
|
1881
2094
|
return;
|
|
1882
2095
|
}
|
|
1883
2096
|
const { site } = req.params;
|
|
1884
2097
|
const validation = import_joi5.default.string().hex().required();
|
|
1885
2098
|
const { error, value } = validation.validate(site);
|
|
1886
2099
|
if (error) {
|
|
1887
|
-
|
|
1888
|
-
next(new
|
|
2100
|
+
import_node_server_utils12.logger.log({ level: "error", message: error.message });
|
|
2101
|
+
next(new import_node_server_utils12.BadRequestError(error.message));
|
|
1889
2102
|
return;
|
|
1890
2103
|
}
|
|
1891
2104
|
try {
|
|
@@ -1894,7 +2107,40 @@ function useUnitController() {
|
|
|
1894
2107
|
const result = await _importUnit({ dataJson, site: value });
|
|
1895
2108
|
return res.status(201).json(result);
|
|
1896
2109
|
} catch (error2) {
|
|
1897
|
-
|
|
2110
|
+
import_node_server_utils12.logger.log({ level: "error", message: error2.message });
|
|
2111
|
+
next(error2);
|
|
2112
|
+
return;
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
async function exportUnits(req, res, next) {
|
|
2116
|
+
const { site } = req.params;
|
|
2117
|
+
const validation = import_joi5.default.string().hex().required();
|
|
2118
|
+
const { error, value } = validation.validate(site);
|
|
2119
|
+
if (error) {
|
|
2120
|
+
import_node_server_utils12.logger.log({ level: "error", message: error.message });
|
|
2121
|
+
next(new import_node_server_utils12.BadRequestError(error.message));
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
try {
|
|
2125
|
+
const excelBuffer = await _exportUnits(value);
|
|
2126
|
+
const date = /* @__PURE__ */ new Date();
|
|
2127
|
+
const formattedDate = `${String(date.getMonth() + 1).padStart(
|
|
2128
|
+
2,
|
|
2129
|
+
"0"
|
|
2130
|
+
)}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
|
|
2131
|
+
res.setHeader(
|
|
2132
|
+
"Content-Type",
|
|
2133
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
2134
|
+
);
|
|
2135
|
+
res.setHeader(
|
|
2136
|
+
"Content-Disposition",
|
|
2137
|
+
`attachment; filename="units-${formattedDate}.xlsx"`
|
|
2138
|
+
);
|
|
2139
|
+
res.setHeader("Content-Length", excelBuffer.length);
|
|
2140
|
+
res.end(excelBuffer);
|
|
2141
|
+
return;
|
|
2142
|
+
} catch (error2) {
|
|
2143
|
+
import_node_server_utils12.logger.log({ level: "error", message: error2.message });
|
|
1898
2144
|
next(error2);
|
|
1899
2145
|
return;
|
|
1900
2146
|
}
|
|
@@ -1904,14 +2150,15 @@ function useUnitController() {
|
|
|
1904
2150
|
getUnits,
|
|
1905
2151
|
updateUnit,
|
|
1906
2152
|
deleteUnit,
|
|
1907
|
-
importUnit
|
|
2153
|
+
importUnit,
|
|
2154
|
+
exportUnits
|
|
1908
2155
|
};
|
|
1909
2156
|
}
|
|
1910
2157
|
|
|
1911
2158
|
// src/models/hygiene-parent-checklist.model.ts
|
|
1912
2159
|
var import_joi6 = __toESM(require("joi"));
|
|
1913
2160
|
var import_mongodb6 = require("mongodb");
|
|
1914
|
-
var
|
|
2161
|
+
var import_node_server_utils13 = require("@7365admin1/node-server-utils");
|
|
1915
2162
|
var parentChecklistSchema = import_joi6.default.object({
|
|
1916
2163
|
createdAt: import_joi6.default.alternatives().try(import_joi6.default.date(), import_joi6.default.string()).optional().allow("", null),
|
|
1917
2164
|
site: import_joi6.default.string().hex().required()
|
|
@@ -1919,14 +2166,14 @@ var parentChecklistSchema = import_joi6.default.object({
|
|
|
1919
2166
|
function MParentChecklist(value) {
|
|
1920
2167
|
const { error } = parentChecklistSchema.validate(value);
|
|
1921
2168
|
if (error) {
|
|
1922
|
-
|
|
1923
|
-
throw new
|
|
2169
|
+
import_node_server_utils13.logger.info(`Hygiene Parent Checklist Model: ${error.message}`);
|
|
2170
|
+
throw new import_node_server_utils13.BadRequestError(error.message);
|
|
1924
2171
|
}
|
|
1925
2172
|
if (value.site) {
|
|
1926
2173
|
try {
|
|
1927
2174
|
value.site = new import_mongodb6.ObjectId(value.site);
|
|
1928
2175
|
} catch (error2) {
|
|
1929
|
-
throw new
|
|
2176
|
+
throw new import_node_server_utils13.BadRequestError(`Invalid site ID format: ${value.site}`);
|
|
1930
2177
|
}
|
|
1931
2178
|
}
|
|
1932
2179
|
return {
|
|
@@ -1939,17 +2186,17 @@ function MParentChecklist(value) {
|
|
|
1939
2186
|
|
|
1940
2187
|
// src/repositories/hygiene-parent-checklist.repository.ts
|
|
1941
2188
|
var import_mongodb7 = require("mongodb");
|
|
1942
|
-
var
|
|
2189
|
+
var import_node_server_utils14 = require("@7365admin1/node-server-utils");
|
|
1943
2190
|
function useParentChecklistRepo() {
|
|
1944
|
-
const db =
|
|
2191
|
+
const db = import_node_server_utils14.useAtlas.getDb();
|
|
1945
2192
|
if (!db) {
|
|
1946
|
-
throw new
|
|
2193
|
+
throw new import_node_server_utils14.InternalServerError("Unable to connect to server.");
|
|
1947
2194
|
}
|
|
1948
2195
|
const namespace_collection = "site.cleaning.schedules";
|
|
1949
2196
|
const site_collection = "sites";
|
|
1950
2197
|
const collection = db.collection(namespace_collection);
|
|
1951
2198
|
const siteCollection = db.collection(site_collection);
|
|
1952
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
2199
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils14.useCache)(namespace_collection);
|
|
1953
2200
|
async function createIndex() {
|
|
1954
2201
|
try {
|
|
1955
2202
|
await collection.createIndexes([
|
|
@@ -1958,7 +2205,7 @@ function useParentChecklistRepo() {
|
|
|
1958
2205
|
{ key: { status: 1 } }
|
|
1959
2206
|
]);
|
|
1960
2207
|
} catch (error) {
|
|
1961
|
-
throw new
|
|
2208
|
+
throw new import_node_server_utils14.InternalServerError(
|
|
1962
2209
|
"Failed to create index on hygiene parent checklist."
|
|
1963
2210
|
);
|
|
1964
2211
|
}
|
|
@@ -1979,16 +2226,16 @@ function useParentChecklistRepo() {
|
|
|
1979
2226
|
if (value.site) {
|
|
1980
2227
|
try {
|
|
1981
2228
|
existingQuery.site = new import_mongodb7.ObjectId(value.site);
|
|
1982
|
-
|
|
2229
|
+
import_node_server_utils14.logger.info(
|
|
1983
2230
|
`createParentChecklist: Looking for existing checklist with query: ${JSON.stringify(
|
|
1984
2231
|
{ ...existingQuery, site: value.site }
|
|
1985
2232
|
)}`
|
|
1986
2233
|
);
|
|
1987
2234
|
} catch (error) {
|
|
1988
|
-
throw new
|
|
2235
|
+
throw new import_node_server_utils14.BadRequestError("Invalid site ID format.");
|
|
1989
2236
|
}
|
|
1990
2237
|
} else {
|
|
1991
|
-
|
|
2238
|
+
import_node_server_utils14.logger.info(
|
|
1992
2239
|
`createParentChecklist: Looking for existing checklist with query (no site filter): ${JSON.stringify(
|
|
1993
2240
|
existingQuery
|
|
1994
2241
|
)}`
|
|
@@ -1997,7 +2244,7 @@ function useParentChecklistRepo() {
|
|
|
1997
2244
|
const existingChecklist = await collection.findOne(existingQuery);
|
|
1998
2245
|
if (existingChecklist) {
|
|
1999
2246
|
const dateStr2 = currentDate.toISOString().split("T")[0];
|
|
2000
|
-
|
|
2247
|
+
import_node_server_utils14.logger.info(
|
|
2001
2248
|
`Parent checklist already exists for ${value.site ? `site ${value.site} on` : ""} today: ${dateStr2}. Found checklist: ${JSON.stringify({
|
|
2002
2249
|
_id: existingChecklist._id,
|
|
2003
2250
|
site: existingChecklist.site
|
|
@@ -2012,27 +2259,27 @@ function useParentChecklistRepo() {
|
|
|
2012
2259
|
});
|
|
2013
2260
|
const result2 = await collection.insertOne(checklistDoc, { session });
|
|
2014
2261
|
delNamespace().then(() => {
|
|
2015
|
-
|
|
2262
|
+
import_node_server_utils14.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2016
2263
|
}).catch((err) => {
|
|
2017
|
-
|
|
2264
|
+
import_node_server_utils14.logger.error(
|
|
2018
2265
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2019
2266
|
err
|
|
2020
2267
|
);
|
|
2021
2268
|
});
|
|
2022
2269
|
const dateStr2 = currentDate.toISOString().split("T")[0];
|
|
2023
|
-
|
|
2270
|
+
import_node_server_utils14.logger.info(
|
|
2024
2271
|
`Created parent checklist for site ${value.site} for today: ${dateStr2}`
|
|
2025
2272
|
);
|
|
2026
2273
|
return result2.insertedId;
|
|
2027
2274
|
}
|
|
2028
2275
|
const siteIds = await getHygieneSiteIds();
|
|
2029
2276
|
if (!Array.isArray(siteIds)) {
|
|
2030
|
-
|
|
2031
|
-
throw new
|
|
2277
|
+
import_node_server_utils14.logger.error("getHygieneSiteIds returned non-array value:", siteIds);
|
|
2278
|
+
throw new import_node_server_utils14.InternalServerError("Failed to retrieve site IDs");
|
|
2032
2279
|
}
|
|
2033
2280
|
if (siteIds.length === 0) {
|
|
2034
|
-
|
|
2035
|
-
throw new
|
|
2281
|
+
import_node_server_utils14.logger.warn("No sites found for creating parent checklist");
|
|
2282
|
+
throw new import_node_server_utils14.BadRequestError("No sites available for checklist creation");
|
|
2036
2283
|
}
|
|
2037
2284
|
const checklistDocs = [];
|
|
2038
2285
|
for (const site of siteIds) {
|
|
@@ -2045,20 +2292,20 @@ function useParentChecklistRepo() {
|
|
|
2045
2292
|
}
|
|
2046
2293
|
const result = await collection.insertMany(checklistDocs, { session });
|
|
2047
2294
|
delNamespace().then(() => {
|
|
2048
|
-
|
|
2295
|
+
import_node_server_utils14.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2049
2296
|
}).catch((err) => {
|
|
2050
|
-
|
|
2297
|
+
import_node_server_utils14.logger.error(
|
|
2051
2298
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2052
2299
|
err
|
|
2053
2300
|
);
|
|
2054
2301
|
});
|
|
2055
2302
|
const dateStr = currentDate.toISOString().split("T")[0];
|
|
2056
|
-
|
|
2303
|
+
import_node_server_utils14.logger.info(
|
|
2057
2304
|
`Created ${Object.keys(result.insertedIds).length} parent checklists for today: ${dateStr}`
|
|
2058
2305
|
);
|
|
2059
2306
|
return Object.values(result.insertedIds);
|
|
2060
2307
|
} catch (error) {
|
|
2061
|
-
|
|
2308
|
+
import_node_server_utils14.logger.error("Failed to create daily parent checklist", error);
|
|
2062
2309
|
throw error;
|
|
2063
2310
|
}
|
|
2064
2311
|
}
|
|
@@ -2082,7 +2329,7 @@ function useParentChecklistRepo() {
|
|
|
2082
2329
|
query.site = site;
|
|
2083
2330
|
cacheOptions.site = site.toString();
|
|
2084
2331
|
} catch (error) {
|
|
2085
|
-
throw new
|
|
2332
|
+
throw new import_node_server_utils14.BadRequestError("Invalid site ID format.");
|
|
2086
2333
|
}
|
|
2087
2334
|
if (search) {
|
|
2088
2335
|
query.$text = { $search: search };
|
|
@@ -2106,10 +2353,10 @@ function useParentChecklistRepo() {
|
|
|
2106
2353
|
query.status = status;
|
|
2107
2354
|
cacheOptions.status = status;
|
|
2108
2355
|
}
|
|
2109
|
-
const cacheKey = (0,
|
|
2356
|
+
const cacheKey = (0, import_node_server_utils14.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2110
2357
|
const cachedData = await getCache(cacheKey);
|
|
2111
2358
|
if (cachedData) {
|
|
2112
|
-
|
|
2359
|
+
import_node_server_utils14.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2113
2360
|
return cachedData;
|
|
2114
2361
|
}
|
|
2115
2362
|
try {
|
|
@@ -2142,11 +2389,11 @@ function useParentChecklistRepo() {
|
|
|
2142
2389
|
);
|
|
2143
2390
|
const items = await collection.aggregate(pipeline).toArray();
|
|
2144
2391
|
const length = await collection.countDocuments(query);
|
|
2145
|
-
const data = (0,
|
|
2392
|
+
const data = (0, import_node_server_utils14.paginate)(items, page, limit, length);
|
|
2146
2393
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2147
|
-
|
|
2394
|
+
import_node_server_utils14.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2148
2395
|
}).catch((err) => {
|
|
2149
|
-
|
|
2396
|
+
import_node_server_utils14.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2150
2397
|
});
|
|
2151
2398
|
return data;
|
|
2152
2399
|
} catch (error) {
|
|
@@ -2157,7 +2404,7 @@ function useParentChecklistRepo() {
|
|
|
2157
2404
|
try {
|
|
2158
2405
|
_id = new import_mongodb7.ObjectId(_id);
|
|
2159
2406
|
} catch (error) {
|
|
2160
|
-
throw new
|
|
2407
|
+
throw new import_node_server_utils14.BadRequestError("Invalid parent checklist ID format.");
|
|
2161
2408
|
}
|
|
2162
2409
|
try {
|
|
2163
2410
|
const updateValue = {
|
|
@@ -2173,14 +2420,14 @@ function useParentChecklistRepo() {
|
|
|
2173
2420
|
{ session }
|
|
2174
2421
|
);
|
|
2175
2422
|
if (res.modifiedCount === 0) {
|
|
2176
|
-
throw new
|
|
2423
|
+
throw new import_node_server_utils14.InternalServerError(
|
|
2177
2424
|
"Unable to update parent checklist status."
|
|
2178
2425
|
);
|
|
2179
2426
|
}
|
|
2180
2427
|
delNamespace().then(() => {
|
|
2181
|
-
|
|
2428
|
+
import_node_server_utils14.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2182
2429
|
}).catch((err) => {
|
|
2183
|
-
|
|
2430
|
+
import_node_server_utils14.logger.error(
|
|
2184
2431
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2185
2432
|
err
|
|
2186
2433
|
);
|
|
@@ -2194,10 +2441,10 @@ function useParentChecklistRepo() {
|
|
|
2194
2441
|
const query = {
|
|
2195
2442
|
status: { $ne: "deleted" }
|
|
2196
2443
|
};
|
|
2197
|
-
const cacheKey = (0,
|
|
2444
|
+
const cacheKey = (0, import_node_server_utils14.makeCacheKey)(site_collection, { tag: "site-ids" });
|
|
2198
2445
|
const cachedData = await getCache(cacheKey);
|
|
2199
2446
|
if (cachedData && Array.isArray(cachedData)) {
|
|
2200
|
-
|
|
2447
|
+
import_node_server_utils14.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2201
2448
|
return cachedData;
|
|
2202
2449
|
}
|
|
2203
2450
|
try {
|
|
@@ -2209,14 +2456,14 @@ function useParentChecklistRepo() {
|
|
|
2209
2456
|
const siteIds = items.map((item) => item._id.toString());
|
|
2210
2457
|
if (siteIds.length > 0) {
|
|
2211
2458
|
setCache(cacheKey, siteIds, 15 * 60).then(() => {
|
|
2212
|
-
|
|
2459
|
+
import_node_server_utils14.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2213
2460
|
}).catch((err) => {
|
|
2214
|
-
|
|
2461
|
+
import_node_server_utils14.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2215
2462
|
});
|
|
2216
2463
|
}
|
|
2217
2464
|
return siteIds;
|
|
2218
2465
|
} catch (error) {
|
|
2219
|
-
|
|
2466
|
+
import_node_server_utils14.logger.error("Failed to get hygiene site IDs", error);
|
|
2220
2467
|
throw error;
|
|
2221
2468
|
}
|
|
2222
2469
|
}
|
|
@@ -2230,7 +2477,7 @@ function useParentChecklistRepo() {
|
|
|
2230
2477
|
|
|
2231
2478
|
// src/controllers/hygiene-parent-checklist.controller.ts
|
|
2232
2479
|
var import_joi7 = __toESM(require("joi"));
|
|
2233
|
-
var
|
|
2480
|
+
var import_node_server_utils15 = require("@7365admin1/node-server-utils");
|
|
2234
2481
|
function useParentChecklistController() {
|
|
2235
2482
|
const {
|
|
2236
2483
|
createParentChecklist: _createParentChecklist,
|
|
@@ -2240,8 +2487,8 @@ function useParentChecklistController() {
|
|
|
2240
2487
|
const payload = req.body;
|
|
2241
2488
|
const { error } = parentChecklistSchema.validate(payload);
|
|
2242
2489
|
if (error) {
|
|
2243
|
-
|
|
2244
|
-
next(new
|
|
2490
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2491
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2245
2492
|
return;
|
|
2246
2493
|
}
|
|
2247
2494
|
try {
|
|
@@ -2249,7 +2496,7 @@ function useParentChecklistController() {
|
|
|
2249
2496
|
res.status(201).json({ message: "Parent checklist created successfully.", id });
|
|
2250
2497
|
return;
|
|
2251
2498
|
} catch (error2) {
|
|
2252
|
-
|
|
2499
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2253
2500
|
next(error2);
|
|
2254
2501
|
return;
|
|
2255
2502
|
}
|
|
@@ -2267,8 +2514,8 @@ function useParentChecklistController() {
|
|
|
2267
2514
|
});
|
|
2268
2515
|
const { error } = validation.validate(query);
|
|
2269
2516
|
if (error) {
|
|
2270
|
-
|
|
2271
|
-
next(new
|
|
2517
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2518
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2272
2519
|
return;
|
|
2273
2520
|
}
|
|
2274
2521
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -2291,7 +2538,7 @@ function useParentChecklistController() {
|
|
|
2291
2538
|
res.json(data);
|
|
2292
2539
|
return;
|
|
2293
2540
|
} catch (error2) {
|
|
2294
|
-
|
|
2541
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2295
2542
|
next(error2);
|
|
2296
2543
|
return;
|
|
2297
2544
|
}
|
|
@@ -2305,7 +2552,7 @@ function useParentChecklistController() {
|
|
|
2305
2552
|
// src/models/hygiene-area-checklist.model.ts
|
|
2306
2553
|
var import_joi8 = __toESM(require("joi"));
|
|
2307
2554
|
var import_mongodb8 = require("mongodb");
|
|
2308
|
-
var
|
|
2555
|
+
var import_node_server_utils16 = require("@7365admin1/node-server-utils");
|
|
2309
2556
|
var allowedChecklistStatus = ["ready", "completed"];
|
|
2310
2557
|
var areaChecklistSchema = import_joi8.default.object({
|
|
2311
2558
|
schedule: import_joi8.default.string().hex().required(),
|
|
@@ -2328,21 +2575,21 @@ var areaChecklistSchema = import_joi8.default.object({
|
|
|
2328
2575
|
function MAreaChecklist(value) {
|
|
2329
2576
|
const { error } = areaChecklistSchema.validate(value);
|
|
2330
2577
|
if (error) {
|
|
2331
|
-
|
|
2332
|
-
throw new
|
|
2578
|
+
import_node_server_utils16.logger.info(`Hygiene Checklist Area Model: ${error.message}`);
|
|
2579
|
+
throw new import_node_server_utils16.BadRequestError(error.message);
|
|
2333
2580
|
}
|
|
2334
2581
|
if (value.schedule) {
|
|
2335
2582
|
try {
|
|
2336
2583
|
value.schedule = new import_mongodb8.ObjectId(value.schedule);
|
|
2337
2584
|
} catch (error2) {
|
|
2338
|
-
throw new
|
|
2585
|
+
throw new import_node_server_utils16.BadRequestError("Invalid schedule ID format.");
|
|
2339
2586
|
}
|
|
2340
2587
|
}
|
|
2341
2588
|
if (value.area) {
|
|
2342
2589
|
try {
|
|
2343
2590
|
value.area = new import_mongodb8.ObjectId(value.area);
|
|
2344
2591
|
} catch (error2) {
|
|
2345
|
-
throw new
|
|
2592
|
+
throw new import_node_server_utils16.BadRequestError("Invalid area ID format.");
|
|
2346
2593
|
}
|
|
2347
2594
|
}
|
|
2348
2595
|
if (value.checklist && Array.isArray(value.checklist)) {
|
|
@@ -2364,7 +2611,7 @@ function MAreaChecklist(value) {
|
|
|
2364
2611
|
try {
|
|
2365
2612
|
value.createdBy = new import_mongodb8.ObjectId(value.createdBy);
|
|
2366
2613
|
} catch (error2) {
|
|
2367
|
-
throw new
|
|
2614
|
+
throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
|
|
2368
2615
|
}
|
|
2369
2616
|
}
|
|
2370
2617
|
return {
|
|
@@ -2382,19 +2629,19 @@ function MAreaChecklist(value) {
|
|
|
2382
2629
|
}
|
|
2383
2630
|
|
|
2384
2631
|
// src/services/hygiene-area-checklist.service.ts
|
|
2385
|
-
var
|
|
2632
|
+
var import_node_server_utils18 = require("@7365admin1/node-server-utils");
|
|
2386
2633
|
|
|
2387
2634
|
// src/repositories/hygiene-area-checklist.repository.ts
|
|
2388
2635
|
var import_mongodb9 = require("mongodb");
|
|
2389
|
-
var
|
|
2636
|
+
var import_node_server_utils17 = require("@7365admin1/node-server-utils");
|
|
2390
2637
|
function useAreaChecklistRepo() {
|
|
2391
|
-
const db =
|
|
2638
|
+
const db = import_node_server_utils17.useAtlas.getDb();
|
|
2392
2639
|
if (!db) {
|
|
2393
|
-
throw new
|
|
2640
|
+
throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
|
|
2394
2641
|
}
|
|
2395
2642
|
const namespace_collection = "site.cleaning.schedule.areas";
|
|
2396
2643
|
const collection = db.collection(namespace_collection);
|
|
2397
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
2644
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
|
|
2398
2645
|
async function createIndex() {
|
|
2399
2646
|
try {
|
|
2400
2647
|
await collection.createIndexes([
|
|
@@ -2406,7 +2653,7 @@ function useAreaChecklistRepo() {
|
|
|
2406
2653
|
{ key: { "checklist.units.status": 1 } }
|
|
2407
2654
|
]);
|
|
2408
2655
|
} catch (error) {
|
|
2409
|
-
throw new
|
|
2656
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
2410
2657
|
"Failed to create index on hygiene checklist area."
|
|
2411
2658
|
);
|
|
2412
2659
|
}
|
|
@@ -2419,7 +2666,7 @@ function useAreaChecklistRepo() {
|
|
|
2419
2666
|
"checklist.units.remarks": "text"
|
|
2420
2667
|
});
|
|
2421
2668
|
} catch (error) {
|
|
2422
|
-
throw new
|
|
2669
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
2423
2670
|
"Failed to create text index on hygiene checklist area."
|
|
2424
2671
|
);
|
|
2425
2672
|
}
|
|
@@ -2442,7 +2689,7 @@ function useAreaChecklistRepo() {
|
|
|
2442
2689
|
}
|
|
2443
2690
|
});
|
|
2444
2691
|
if (existingChecklist) {
|
|
2445
|
-
|
|
2692
|
+
import_node_server_utils17.logger.info(
|
|
2446
2693
|
`Area checklist already exists for area ${value.name} on ${currentDate.toISOString().split("T")[0]}`
|
|
2447
2694
|
);
|
|
2448
2695
|
return existingChecklist._id;
|
|
@@ -2450,9 +2697,9 @@ function useAreaChecklistRepo() {
|
|
|
2450
2697
|
const processedValue = MAreaChecklist(value);
|
|
2451
2698
|
const result = await collection.insertOne(processedValue, { session });
|
|
2452
2699
|
delNamespace().then(() => {
|
|
2453
|
-
|
|
2700
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2454
2701
|
}).catch((err) => {
|
|
2455
|
-
|
|
2702
|
+
import_node_server_utils17.logger.error(
|
|
2456
2703
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2457
2704
|
err
|
|
2458
2705
|
);
|
|
@@ -2480,7 +2727,7 @@ function useAreaChecklistRepo() {
|
|
|
2480
2727
|
query.schedule = new import_mongodb9.ObjectId(schedule);
|
|
2481
2728
|
cacheOptions.schedule = schedule.toString();
|
|
2482
2729
|
} catch (error) {
|
|
2483
|
-
throw new
|
|
2730
|
+
throw new import_node_server_utils17.BadRequestError("Invalid parent checklist ID format.");
|
|
2484
2731
|
}
|
|
2485
2732
|
if (type && type !== "all") {
|
|
2486
2733
|
query.type = type;
|
|
@@ -2494,11 +2741,11 @@ function useAreaChecklistRepo() {
|
|
|
2494
2741
|
query.$text = { $search: search };
|
|
2495
2742
|
cacheOptions.search = search;
|
|
2496
2743
|
}
|
|
2497
|
-
const cacheKey = (0,
|
|
2744
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2498
2745
|
if (!session) {
|
|
2499
2746
|
const cachedData = await getCache(cacheKey);
|
|
2500
2747
|
if (cachedData) {
|
|
2501
|
-
|
|
2748
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2502
2749
|
return cachedData;
|
|
2503
2750
|
}
|
|
2504
2751
|
}
|
|
@@ -2572,11 +2819,11 @@ function useAreaChecklistRepo() {
|
|
|
2572
2819
|
];
|
|
2573
2820
|
const items = await collection.aggregate(pipeline, { session }).toArray();
|
|
2574
2821
|
const length = await collection.countDocuments(query, { session });
|
|
2575
|
-
const data = (0,
|
|
2822
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2576
2823
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2577
|
-
|
|
2824
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2578
2825
|
}).catch((err) => {
|
|
2579
|
-
|
|
2826
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2580
2827
|
});
|
|
2581
2828
|
return data;
|
|
2582
2829
|
} catch (error) {
|
|
@@ -2602,7 +2849,7 @@ function useAreaChecklistRepo() {
|
|
|
2602
2849
|
query.schedule = new import_mongodb9.ObjectId(schedule);
|
|
2603
2850
|
cacheOptions.schedule = schedule.toString();
|
|
2604
2851
|
} catch (error) {
|
|
2605
|
-
throw new
|
|
2852
|
+
throw new import_node_server_utils17.BadRequestError("Invalid parent checklist ID format.");
|
|
2606
2853
|
}
|
|
2607
2854
|
if (type) {
|
|
2608
2855
|
query.type = type;
|
|
@@ -2625,10 +2872,10 @@ function useAreaChecklistRepo() {
|
|
|
2625
2872
|
} else {
|
|
2626
2873
|
query.status = { $in: ["ongoing", "completed"] };
|
|
2627
2874
|
}
|
|
2628
|
-
const cacheKey = (0,
|
|
2875
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2629
2876
|
const cachedData = await getCache(cacheKey);
|
|
2630
2877
|
if (cachedData) {
|
|
2631
|
-
|
|
2878
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2632
2879
|
return cachedData;
|
|
2633
2880
|
}
|
|
2634
2881
|
try {
|
|
@@ -2676,11 +2923,11 @@ function useAreaChecklistRepo() {
|
|
|
2676
2923
|
];
|
|
2677
2924
|
const items = await collection.aggregate(pipeline).toArray();
|
|
2678
2925
|
const length = await collection.countDocuments(query);
|
|
2679
|
-
const data = (0,
|
|
2926
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2680
2927
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2681
|
-
|
|
2928
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2682
2929
|
}).catch((err) => {
|
|
2683
|
-
|
|
2930
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2684
2931
|
});
|
|
2685
2932
|
return data;
|
|
2686
2933
|
} catch (error) {
|
|
@@ -2691,14 +2938,14 @@ function useAreaChecklistRepo() {
|
|
|
2691
2938
|
try {
|
|
2692
2939
|
_id = new import_mongodb9.ObjectId(_id);
|
|
2693
2940
|
} catch (error) {
|
|
2694
|
-
throw new
|
|
2941
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2695
2942
|
}
|
|
2696
|
-
const cacheKey = (0,
|
|
2943
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, {
|
|
2697
2944
|
_id: _id.toString()
|
|
2698
2945
|
});
|
|
2699
2946
|
const cachedData = await getCache(cacheKey);
|
|
2700
2947
|
if (cachedData) {
|
|
2701
|
-
|
|
2948
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2702
2949
|
return cachedData;
|
|
2703
2950
|
}
|
|
2704
2951
|
try {
|
|
@@ -2821,16 +3068,16 @@ function useAreaChecklistRepo() {
|
|
|
2821
3068
|
collection.aggregate(unitPipeline).toArray()
|
|
2822
3069
|
]);
|
|
2823
3070
|
if (!area.length) {
|
|
2824
|
-
throw new
|
|
3071
|
+
throw new import_node_server_utils17.BadRequestError("Area checklist not found.");
|
|
2825
3072
|
}
|
|
2826
3073
|
const items = {
|
|
2827
3074
|
area: area[0],
|
|
2828
3075
|
units
|
|
2829
3076
|
};
|
|
2830
3077
|
setCache(cacheKey, items, 15 * 60).then(() => {
|
|
2831
|
-
|
|
3078
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2832
3079
|
}).catch((err) => {
|
|
2833
|
-
|
|
3080
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2834
3081
|
});
|
|
2835
3082
|
return items;
|
|
2836
3083
|
} catch (error) {
|
|
@@ -2853,17 +3100,17 @@ function useAreaChecklistRepo() {
|
|
|
2853
3100
|
query._id = new import_mongodb9.ObjectId(_id);
|
|
2854
3101
|
cacheOptions._id = _id.toString();
|
|
2855
3102
|
} catch (error) {
|
|
2856
|
-
throw new
|
|
3103
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2857
3104
|
}
|
|
2858
3105
|
if (search) {
|
|
2859
3106
|
query.$text = { $search: search };
|
|
2860
3107
|
cacheOptions.search = search;
|
|
2861
3108
|
}
|
|
2862
|
-
const cacheKey = (0,
|
|
3109
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2863
3110
|
if (!session) {
|
|
2864
3111
|
const cachedData = await getCache(cacheKey);
|
|
2865
3112
|
if (cachedData) {
|
|
2866
|
-
|
|
3113
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2867
3114
|
return cachedData;
|
|
2868
3115
|
}
|
|
2869
3116
|
}
|
|
@@ -2951,11 +3198,11 @@ function useAreaChecklistRepo() {
|
|
|
2951
3198
|
collection.aggregate(countPipeline, { session }).toArray()
|
|
2952
3199
|
]);
|
|
2953
3200
|
const length = countResult.length > 0 ? countResult[0].total : 0;
|
|
2954
|
-
const data = (0,
|
|
3201
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2955
3202
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2956
|
-
|
|
3203
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2957
3204
|
}).catch((err) => {
|
|
2958
|
-
|
|
3205
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2959
3206
|
});
|
|
2960
3207
|
return data;
|
|
2961
3208
|
} catch (error) {
|
|
@@ -2966,7 +3213,7 @@ function useAreaChecklistRepo() {
|
|
|
2966
3213
|
try {
|
|
2967
3214
|
_id = new import_mongodb9.ObjectId(_id);
|
|
2968
3215
|
} catch (error) {
|
|
2969
|
-
throw new
|
|
3216
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2970
3217
|
}
|
|
2971
3218
|
try {
|
|
2972
3219
|
const area = await collection.findOne(
|
|
@@ -2974,7 +3221,7 @@ function useAreaChecklistRepo() {
|
|
|
2974
3221
|
{ projection: { schedule: 1, name: 1, type: 1, status: 1 }, session }
|
|
2975
3222
|
);
|
|
2976
3223
|
if (!area) {
|
|
2977
|
-
throw new
|
|
3224
|
+
throw new import_node_server_utils17.BadRequestError("Area checklist not found.");
|
|
2978
3225
|
}
|
|
2979
3226
|
return area;
|
|
2980
3227
|
} catch (error) {
|
|
@@ -2986,12 +3233,12 @@ function useAreaChecklistRepo() {
|
|
|
2986
3233
|
schedule = new import_mongodb9.ObjectId(schedule);
|
|
2987
3234
|
area = new import_mongodb9.ObjectId(area);
|
|
2988
3235
|
} catch (error) {
|
|
2989
|
-
throw new
|
|
3236
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2990
3237
|
}
|
|
2991
3238
|
try {
|
|
2992
3239
|
const data = await collection.findOne({ schedule, area }, { session });
|
|
2993
3240
|
if (!data) {
|
|
2994
|
-
throw new
|
|
3241
|
+
throw new import_node_server_utils17.BadRequestError("Area checklist not found.");
|
|
2995
3242
|
}
|
|
2996
3243
|
return data;
|
|
2997
3244
|
} catch (error) {
|
|
@@ -3002,12 +3249,12 @@ function useAreaChecklistRepo() {
|
|
|
3002
3249
|
try {
|
|
3003
3250
|
_id = new import_mongodb9.ObjectId(_id);
|
|
3004
3251
|
} catch (error) {
|
|
3005
|
-
throw new
|
|
3252
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
3006
3253
|
}
|
|
3007
3254
|
try {
|
|
3008
3255
|
unitId = new import_mongodb9.ObjectId(unitId);
|
|
3009
3256
|
} catch (error) {
|
|
3010
|
-
throw new
|
|
3257
|
+
throw new import_node_server_utils17.BadRequestError("Invalid unit checklist ID format.");
|
|
3011
3258
|
}
|
|
3012
3259
|
try {
|
|
3013
3260
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -3032,19 +3279,19 @@ function useAreaChecklistRepo() {
|
|
|
3032
3279
|
{ arrayFilters, session }
|
|
3033
3280
|
);
|
|
3034
3281
|
if (res.modifiedCount === 0) {
|
|
3035
|
-
throw new
|
|
3282
|
+
throw new import_node_server_utils17.InternalServerError("Unable to update area checklist unit.");
|
|
3036
3283
|
}
|
|
3037
3284
|
delNamespace().then(() => {
|
|
3038
|
-
|
|
3285
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3039
3286
|
}).catch((err) => {
|
|
3040
|
-
|
|
3287
|
+
import_node_server_utils17.logger.error(
|
|
3041
3288
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3042
3289
|
err
|
|
3043
3290
|
);
|
|
3044
3291
|
});
|
|
3045
3292
|
return res.modifiedCount;
|
|
3046
3293
|
} catch (error) {
|
|
3047
|
-
|
|
3294
|
+
import_node_server_utils17.logger.error("Error updating area checklist unit:", error.message);
|
|
3048
3295
|
throw error;
|
|
3049
3296
|
}
|
|
3050
3297
|
}
|
|
@@ -3052,7 +3299,7 @@ function useAreaChecklistRepo() {
|
|
|
3052
3299
|
try {
|
|
3053
3300
|
_id = new import_mongodb9.ObjectId(_id);
|
|
3054
3301
|
} catch (error) {
|
|
3055
|
-
throw new
|
|
3302
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
3056
3303
|
}
|
|
3057
3304
|
try {
|
|
3058
3305
|
const updateValue = {
|
|
@@ -3065,12 +3312,12 @@ function useAreaChecklistRepo() {
|
|
|
3065
3312
|
{ session }
|
|
3066
3313
|
);
|
|
3067
3314
|
if (res.modifiedCount === 0) {
|
|
3068
|
-
throw new
|
|
3315
|
+
throw new import_node_server_utils17.InternalServerError("Unable to update area checklist.");
|
|
3069
3316
|
}
|
|
3070
3317
|
delNamespace().then(() => {
|
|
3071
|
-
|
|
3318
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3072
3319
|
}).catch((err) => {
|
|
3073
|
-
|
|
3320
|
+
import_node_server_utils17.logger.error(
|
|
3074
3321
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3075
3322
|
err
|
|
3076
3323
|
);
|
|
@@ -3084,7 +3331,7 @@ function useAreaChecklistRepo() {
|
|
|
3084
3331
|
try {
|
|
3085
3332
|
_id = new import_mongodb9.ObjectId(_id);
|
|
3086
3333
|
} catch (error) {
|
|
3087
|
-
throw new
|
|
3334
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
3088
3335
|
}
|
|
3089
3336
|
try {
|
|
3090
3337
|
const updateValue = {
|
|
@@ -3100,14 +3347,14 @@ function useAreaChecklistRepo() {
|
|
|
3100
3347
|
{ session }
|
|
3101
3348
|
);
|
|
3102
3349
|
if (res.modifiedCount === 0) {
|
|
3103
|
-
throw new
|
|
3350
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
3104
3351
|
"Unable to update area checklist status."
|
|
3105
3352
|
);
|
|
3106
3353
|
}
|
|
3107
3354
|
delNamespace().then(() => {
|
|
3108
|
-
|
|
3355
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3109
3356
|
}).catch((err) => {
|
|
3110
|
-
|
|
3357
|
+
import_node_server_utils17.logger.error(
|
|
3111
3358
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3112
3359
|
err
|
|
3113
3360
|
);
|
|
@@ -3130,7 +3377,7 @@ function useAreaChecklistRepo() {
|
|
|
3130
3377
|
).toArray();
|
|
3131
3378
|
return result.length > 0 && result[0].maxSet ? result[0].maxSet : 0;
|
|
3132
3379
|
} catch (error) {
|
|
3133
|
-
|
|
3380
|
+
import_node_server_utils17.logger.error(`Error getting max set number for area ${areaId}:`, error);
|
|
3134
3381
|
return 0;
|
|
3135
3382
|
}
|
|
3136
3383
|
}
|
|
@@ -3165,7 +3412,7 @@ function useAreaChecklistService() {
|
|
|
3165
3412
|
} = useAreaChecklistRepo();
|
|
3166
3413
|
const { updateParentChecklistStatuses } = useParentChecklistRepo();
|
|
3167
3414
|
async function createAreaChecklist(value) {
|
|
3168
|
-
const session =
|
|
3415
|
+
const session = import_node_server_utils18.useAtlas.getClient()?.startSession();
|
|
3169
3416
|
try {
|
|
3170
3417
|
session?.startTransaction();
|
|
3171
3418
|
const results = [];
|
|
@@ -3178,7 +3425,7 @@ function useAreaChecklistService() {
|
|
|
3178
3425
|
const batch = areas.slice(i, i + BATCH_SIZE);
|
|
3179
3426
|
const batchPromises = batch.map(async (area) => {
|
|
3180
3427
|
if (!area.units || area.units.length === 0) {
|
|
3181
|
-
|
|
3428
|
+
import_node_server_utils18.logger.warn(
|
|
3182
3429
|
`Skipping area ${area.name} (${area._id}): No units defined`
|
|
3183
3430
|
);
|
|
3184
3431
|
return null;
|
|
@@ -3209,19 +3456,19 @@ function useAreaChecklistService() {
|
|
|
3209
3456
|
const batchResults = await Promise.all(batchPromises);
|
|
3210
3457
|
results.push(...batchResults.filter((id) => id !== null));
|
|
3211
3458
|
}
|
|
3212
|
-
|
|
3459
|
+
import_node_server_utils18.logger.info(
|
|
3213
3460
|
`Created ${totalChecklistsCreated} area checklists out of ${areas.length} areas for site: ${value.site}`
|
|
3214
3461
|
);
|
|
3215
3462
|
} else {
|
|
3216
|
-
|
|
3463
|
+
import_node_server_utils18.logger.warn(`No common areas found for site: ${value.site}`);
|
|
3217
3464
|
}
|
|
3218
3465
|
await session?.commitTransaction();
|
|
3219
|
-
|
|
3466
|
+
import_node_server_utils18.logger.info(
|
|
3220
3467
|
`Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
|
|
3221
3468
|
);
|
|
3222
3469
|
return results;
|
|
3223
3470
|
} catch (error) {
|
|
3224
|
-
|
|
3471
|
+
import_node_server_utils18.logger.error(`Error generating area checklists:`, error);
|
|
3225
3472
|
if (session?.inTransaction()) {
|
|
3226
3473
|
await session?.abortTransaction();
|
|
3227
3474
|
}
|
|
@@ -3231,7 +3478,7 @@ function useAreaChecklistService() {
|
|
|
3231
3478
|
}
|
|
3232
3479
|
}
|
|
3233
3480
|
async function completeAreaChecklistUnits(_id, set, unitId, value) {
|
|
3234
|
-
const session =
|
|
3481
|
+
const session = import_node_server_utils18.useAtlas.getClient()?.startSession();
|
|
3235
3482
|
try {
|
|
3236
3483
|
session?.startTransaction();
|
|
3237
3484
|
await _completeAreaChecklistUnits(_id, set, unitId, value, session);
|
|
@@ -3297,7 +3544,7 @@ function useAreaChecklistService() {
|
|
|
3297
3544
|
session
|
|
3298
3545
|
);
|
|
3299
3546
|
} else {
|
|
3300
|
-
|
|
3547
|
+
import_node_server_utils18.logger.info(
|
|
3301
3548
|
"No area checklists found, keeping parent status as ready"
|
|
3302
3549
|
);
|
|
3303
3550
|
}
|
|
@@ -3305,7 +3552,7 @@ function useAreaChecklistService() {
|
|
|
3305
3552
|
await session?.commitTransaction();
|
|
3306
3553
|
return;
|
|
3307
3554
|
} catch (error) {
|
|
3308
|
-
|
|
3555
|
+
import_node_server_utils18.logger.error(`Error updating area checklist unit and statuses:`, error);
|
|
3309
3556
|
if (session?.inTransaction()) {
|
|
3310
3557
|
await session?.abortTransaction();
|
|
3311
3558
|
}
|
|
@@ -3319,7 +3566,7 @@ function useAreaChecklistService() {
|
|
|
3319
3566
|
|
|
3320
3567
|
// src/controllers/hygiene-area-checklist.controller.ts
|
|
3321
3568
|
var import_joi9 = __toESM(require("joi"));
|
|
3322
|
-
var
|
|
3569
|
+
var import_node_server_utils19 = require("@7365admin1/node-server-utils");
|
|
3323
3570
|
function useAreaChecklistController() {
|
|
3324
3571
|
const {
|
|
3325
3572
|
getAllAreaChecklist: _getAllAreaChecklist,
|
|
@@ -3349,8 +3596,8 @@ function useAreaChecklistController() {
|
|
|
3349
3596
|
});
|
|
3350
3597
|
const { error, value } = validation.validate(payload);
|
|
3351
3598
|
if (error) {
|
|
3352
|
-
|
|
3353
|
-
next(new
|
|
3599
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3600
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3354
3601
|
return;
|
|
3355
3602
|
}
|
|
3356
3603
|
try {
|
|
@@ -3358,7 +3605,7 @@ function useAreaChecklistController() {
|
|
|
3358
3605
|
res.status(201).json({ message: "Area checklist generated successfully." });
|
|
3359
3606
|
return;
|
|
3360
3607
|
} catch (error2) {
|
|
3361
|
-
|
|
3608
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3362
3609
|
next(error2);
|
|
3363
3610
|
return;
|
|
3364
3611
|
}
|
|
@@ -3375,8 +3622,8 @@ function useAreaChecklistController() {
|
|
|
3375
3622
|
});
|
|
3376
3623
|
const { error } = validation.validate(query);
|
|
3377
3624
|
if (error) {
|
|
3378
|
-
|
|
3379
|
-
next(new
|
|
3625
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3626
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3380
3627
|
return;
|
|
3381
3628
|
}
|
|
3382
3629
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3397,7 +3644,7 @@ function useAreaChecklistController() {
|
|
|
3397
3644
|
res.json(data);
|
|
3398
3645
|
return;
|
|
3399
3646
|
} catch (error2) {
|
|
3400
|
-
|
|
3647
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3401
3648
|
next(error2);
|
|
3402
3649
|
return;
|
|
3403
3650
|
}
|
|
@@ -3415,8 +3662,8 @@ function useAreaChecklistController() {
|
|
|
3415
3662
|
});
|
|
3416
3663
|
const { error } = validation.validate(query);
|
|
3417
3664
|
if (error) {
|
|
3418
|
-
|
|
3419
|
-
next(new
|
|
3665
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3666
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3420
3667
|
return;
|
|
3421
3668
|
}
|
|
3422
3669
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3439,7 +3686,7 @@ function useAreaChecklistController() {
|
|
|
3439
3686
|
res.json(data);
|
|
3440
3687
|
return;
|
|
3441
3688
|
} catch (error2) {
|
|
3442
|
-
|
|
3689
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3443
3690
|
next(error2);
|
|
3444
3691
|
return;
|
|
3445
3692
|
}
|
|
@@ -3449,8 +3696,8 @@ function useAreaChecklistController() {
|
|
|
3449
3696
|
const _id = req.params.id;
|
|
3450
3697
|
const { error, value } = validation.validate(_id);
|
|
3451
3698
|
if (error) {
|
|
3452
|
-
|
|
3453
|
-
next(new
|
|
3699
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3700
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3454
3701
|
return;
|
|
3455
3702
|
}
|
|
3456
3703
|
try {
|
|
@@ -3458,7 +3705,7 @@ function useAreaChecklistController() {
|
|
|
3458
3705
|
res.json(data);
|
|
3459
3706
|
return;
|
|
3460
3707
|
} catch (error2) {
|
|
3461
|
-
|
|
3708
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3462
3709
|
next(error2);
|
|
3463
3710
|
return;
|
|
3464
3711
|
}
|
|
@@ -3473,8 +3720,8 @@ function useAreaChecklistController() {
|
|
|
3473
3720
|
});
|
|
3474
3721
|
const { error } = validation.validate(query);
|
|
3475
3722
|
if (error) {
|
|
3476
|
-
|
|
3477
|
-
next(new
|
|
3723
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3724
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3478
3725
|
return;
|
|
3479
3726
|
}
|
|
3480
3727
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3491,7 +3738,7 @@ function useAreaChecklistController() {
|
|
|
3491
3738
|
res.json(data);
|
|
3492
3739
|
return;
|
|
3493
3740
|
} catch (error2) {
|
|
3494
|
-
|
|
3741
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3495
3742
|
next(error2);
|
|
3496
3743
|
return;
|
|
3497
3744
|
}
|
|
@@ -3516,8 +3763,8 @@ function useAreaChecklistController() {
|
|
|
3516
3763
|
});
|
|
3517
3764
|
const { error } = validation.validate(payload);
|
|
3518
3765
|
if (error) {
|
|
3519
|
-
|
|
3520
|
-
next(new
|
|
3766
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3767
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3521
3768
|
return;
|
|
3522
3769
|
}
|
|
3523
3770
|
try {
|
|
@@ -3531,7 +3778,7 @@ function useAreaChecklistController() {
|
|
|
3531
3778
|
res.json({ message: "Area checklist updated successfully." });
|
|
3532
3779
|
return;
|
|
3533
3780
|
} catch (error2) {
|
|
3534
|
-
|
|
3781
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3535
3782
|
next(error2);
|
|
3536
3783
|
return;
|
|
3537
3784
|
}
|
|
@@ -3549,7 +3796,7 @@ function useAreaChecklistController() {
|
|
|
3549
3796
|
// src/models/hygiene-supply.model.ts
|
|
3550
3797
|
var import_joi10 = __toESM(require("joi"));
|
|
3551
3798
|
var import_mongodb10 = require("mongodb");
|
|
3552
|
-
var
|
|
3799
|
+
var import_node_server_utils20 = require("@7365admin1/node-server-utils");
|
|
3553
3800
|
var supplySchema = import_joi10.default.object({
|
|
3554
3801
|
site: import_joi10.default.string().hex().required(),
|
|
3555
3802
|
name: import_joi10.default.string().required(),
|
|
@@ -3558,14 +3805,14 @@ var supplySchema = import_joi10.default.object({
|
|
|
3558
3805
|
function MSupply(value) {
|
|
3559
3806
|
const { error } = supplySchema.validate(value);
|
|
3560
3807
|
if (error) {
|
|
3561
|
-
|
|
3562
|
-
throw new
|
|
3808
|
+
import_node_server_utils20.logger.info(`Hygiene Supply Model: ${error.message}`);
|
|
3809
|
+
throw new import_node_server_utils20.BadRequestError(error.message);
|
|
3563
3810
|
}
|
|
3564
3811
|
if (value.site) {
|
|
3565
3812
|
try {
|
|
3566
3813
|
value.site = new import_mongodb10.ObjectId(value.site);
|
|
3567
3814
|
} catch (error2) {
|
|
3568
|
-
throw new
|
|
3815
|
+
throw new import_node_server_utils20.BadRequestError("Invalid site ID format.");
|
|
3569
3816
|
}
|
|
3570
3817
|
}
|
|
3571
3818
|
return {
|
|
@@ -3582,20 +3829,20 @@ function MSupply(value) {
|
|
|
3582
3829
|
|
|
3583
3830
|
// src/repositories/hygiene-supply.repository.ts
|
|
3584
3831
|
var import_mongodb11 = require("mongodb");
|
|
3585
|
-
var
|
|
3832
|
+
var import_node_server_utils21 = require("@7365admin1/node-server-utils");
|
|
3586
3833
|
function useSupplyRepository() {
|
|
3587
|
-
const db =
|
|
3834
|
+
const db = import_node_server_utils21.useAtlas.getDb();
|
|
3588
3835
|
if (!db) {
|
|
3589
|
-
throw new
|
|
3836
|
+
throw new import_node_server_utils21.InternalServerError("Unable to connect to server.");
|
|
3590
3837
|
}
|
|
3591
3838
|
const namespace_collection = "site.supplies";
|
|
3592
3839
|
const collection = db.collection(namespace_collection);
|
|
3593
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
3840
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils21.useCache)(namespace_collection);
|
|
3594
3841
|
async function createIndex() {
|
|
3595
3842
|
try {
|
|
3596
3843
|
await collection.createIndexes([{ key: { site: 1 } }]);
|
|
3597
3844
|
} catch (error) {
|
|
3598
|
-
throw new
|
|
3845
|
+
throw new import_node_server_utils21.InternalServerError(
|
|
3599
3846
|
"Failed to create index on hygiene supply."
|
|
3600
3847
|
);
|
|
3601
3848
|
}
|
|
@@ -3604,7 +3851,7 @@ function useSupplyRepository() {
|
|
|
3604
3851
|
try {
|
|
3605
3852
|
await collection.createIndex({ name: "text" });
|
|
3606
3853
|
} catch (error) {
|
|
3607
|
-
throw new
|
|
3854
|
+
throw new import_node_server_utils21.InternalServerError(
|
|
3608
3855
|
"Failed to create text index on hygiene supply."
|
|
3609
3856
|
);
|
|
3610
3857
|
}
|
|
@@ -3616,7 +3863,7 @@ function useSupplyRepository() {
|
|
|
3616
3863
|
{ unique: true }
|
|
3617
3864
|
);
|
|
3618
3865
|
} catch (error) {
|
|
3619
|
-
throw new
|
|
3866
|
+
throw new import_node_server_utils21.InternalServerError(
|
|
3620
3867
|
"Failed to create unique index on hygiene supply."
|
|
3621
3868
|
);
|
|
3622
3869
|
}
|
|
@@ -3626,9 +3873,9 @@ function useSupplyRepository() {
|
|
|
3626
3873
|
value = MSupply(value);
|
|
3627
3874
|
const res = await collection.insertOne(value, { session });
|
|
3628
3875
|
delNamespace().then(() => {
|
|
3629
|
-
|
|
3876
|
+
import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3630
3877
|
}).catch((err) => {
|
|
3631
|
-
|
|
3878
|
+
import_node_server_utils21.logger.error(
|
|
3632
3879
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3633
3880
|
err
|
|
3634
3881
|
);
|
|
@@ -3637,7 +3884,7 @@ function useSupplyRepository() {
|
|
|
3637
3884
|
} catch (error) {
|
|
3638
3885
|
const isDuplicated = error.message.includes("duplicate");
|
|
3639
3886
|
if (isDuplicated) {
|
|
3640
|
-
throw new
|
|
3887
|
+
throw new import_node_server_utils21.BadRequestError("Supply already exists.");
|
|
3641
3888
|
}
|
|
3642
3889
|
throw error;
|
|
3643
3890
|
}
|
|
@@ -3661,16 +3908,16 @@ function useSupplyRepository() {
|
|
|
3661
3908
|
query.site = site;
|
|
3662
3909
|
cacheOptions.site = site.toString();
|
|
3663
3910
|
} catch (error) {
|
|
3664
|
-
throw new
|
|
3911
|
+
throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
|
|
3665
3912
|
}
|
|
3666
3913
|
if (search) {
|
|
3667
3914
|
query.$text = { $search: search };
|
|
3668
3915
|
cacheOptions.search = search;
|
|
3669
3916
|
}
|
|
3670
|
-
const cacheKey = (0,
|
|
3917
|
+
const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3671
3918
|
const cachedData = await getCache(cacheKey);
|
|
3672
3919
|
if (cachedData) {
|
|
3673
|
-
|
|
3920
|
+
import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3674
3921
|
return cachedData;
|
|
3675
3922
|
}
|
|
3676
3923
|
try {
|
|
@@ -3688,11 +3935,11 @@ function useSupplyRepository() {
|
|
|
3688
3935
|
{ $limit: limit }
|
|
3689
3936
|
]).toArray();
|
|
3690
3937
|
const length = await collection.countDocuments(query);
|
|
3691
|
-
const data = (0,
|
|
3938
|
+
const data = (0, import_node_server_utils21.paginate)(items, page, limit, length);
|
|
3692
3939
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3693
|
-
|
|
3940
|
+
import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3694
3941
|
}).catch((err) => {
|
|
3695
|
-
|
|
3942
|
+
import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3696
3943
|
});
|
|
3697
3944
|
return data;
|
|
3698
3945
|
} catch (error) {
|
|
@@ -3703,23 +3950,23 @@ function useSupplyRepository() {
|
|
|
3703
3950
|
try {
|
|
3704
3951
|
_id = new import_mongodb11.ObjectId(_id);
|
|
3705
3952
|
} catch (error) {
|
|
3706
|
-
throw new
|
|
3953
|
+
throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
|
|
3707
3954
|
}
|
|
3708
3955
|
const query = {
|
|
3709
3956
|
_id,
|
|
3710
3957
|
status: { $ne: "deleted" }
|
|
3711
3958
|
};
|
|
3712
|
-
const cacheKey = (0,
|
|
3959
|
+
const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, {
|
|
3713
3960
|
_id: _id.toString()
|
|
3714
3961
|
});
|
|
3715
3962
|
if (!session) {
|
|
3716
3963
|
const cachedData = await getCache(cacheKey);
|
|
3717
3964
|
if (cachedData) {
|
|
3718
|
-
|
|
3965
|
+
import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3719
3966
|
return cachedData;
|
|
3720
3967
|
}
|
|
3721
3968
|
} else {
|
|
3722
|
-
|
|
3969
|
+
import_node_server_utils21.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
3723
3970
|
}
|
|
3724
3971
|
try {
|
|
3725
3972
|
const data = await collection.aggregate([
|
|
@@ -3733,12 +3980,12 @@ function useSupplyRepository() {
|
|
|
3733
3980
|
}
|
|
3734
3981
|
]).toArray();
|
|
3735
3982
|
if (!data || data.length === 0) {
|
|
3736
|
-
throw new
|
|
3983
|
+
throw new import_node_server_utils21.NotFoundError("Supply not found.");
|
|
3737
3984
|
}
|
|
3738
3985
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
3739
|
-
|
|
3986
|
+
import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3740
3987
|
}).catch((err) => {
|
|
3741
|
-
|
|
3988
|
+
import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3742
3989
|
});
|
|
3743
3990
|
return data[0];
|
|
3744
3991
|
} catch (error) {
|
|
@@ -3749,7 +3996,7 @@ function useSupplyRepository() {
|
|
|
3749
3996
|
try {
|
|
3750
3997
|
_id = new import_mongodb11.ObjectId(_id);
|
|
3751
3998
|
} catch (error) {
|
|
3752
|
-
throw new
|
|
3999
|
+
throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
|
|
3753
4000
|
}
|
|
3754
4001
|
try {
|
|
3755
4002
|
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
@@ -3759,12 +4006,12 @@ function useSupplyRepository() {
|
|
|
3759
4006
|
{ session }
|
|
3760
4007
|
);
|
|
3761
4008
|
if (res.modifiedCount === 0) {
|
|
3762
|
-
throw new
|
|
4009
|
+
throw new import_node_server_utils21.InternalServerError("Unable to update cleaning supply.");
|
|
3763
4010
|
}
|
|
3764
4011
|
delNamespace().then(() => {
|
|
3765
|
-
|
|
4012
|
+
import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3766
4013
|
}).catch((err) => {
|
|
3767
|
-
|
|
4014
|
+
import_node_server_utils21.logger.error(
|
|
3768
4015
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3769
4016
|
err
|
|
3770
4017
|
);
|
|
@@ -3773,7 +4020,7 @@ function useSupplyRepository() {
|
|
|
3773
4020
|
} catch (error) {
|
|
3774
4021
|
const isDuplicated = error.message.includes("duplicate");
|
|
3775
4022
|
if (isDuplicated) {
|
|
3776
|
-
throw new
|
|
4023
|
+
throw new import_node_server_utils21.BadRequestError("Supply already exists.");
|
|
3777
4024
|
}
|
|
3778
4025
|
throw error;
|
|
3779
4026
|
}
|
|
@@ -3782,7 +4029,7 @@ function useSupplyRepository() {
|
|
|
3782
4029
|
try {
|
|
3783
4030
|
_id = new import_mongodb11.ObjectId(_id);
|
|
3784
4031
|
} catch (error) {
|
|
3785
|
-
throw new
|
|
4032
|
+
throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
|
|
3786
4033
|
}
|
|
3787
4034
|
try {
|
|
3788
4035
|
const updateValue = {
|
|
@@ -3796,12 +4043,12 @@ function useSupplyRepository() {
|
|
|
3796
4043
|
{ session }
|
|
3797
4044
|
);
|
|
3798
4045
|
if (res.modifiedCount === 0) {
|
|
3799
|
-
throw new
|
|
4046
|
+
throw new import_node_server_utils21.InternalServerError("Unable to delete supply.");
|
|
3800
4047
|
}
|
|
3801
4048
|
delNamespace().then(() => {
|
|
3802
|
-
|
|
4049
|
+
import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3803
4050
|
}).catch((err) => {
|
|
3804
|
-
|
|
4051
|
+
import_node_server_utils21.logger.error(
|
|
3805
4052
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3806
4053
|
err
|
|
3807
4054
|
);
|
|
@@ -3825,7 +4072,7 @@ function useSupplyRepository() {
|
|
|
3825
4072
|
|
|
3826
4073
|
// src/controllers/hygiene-supply.controller.ts
|
|
3827
4074
|
var import_joi11 = __toESM(require("joi"));
|
|
3828
|
-
var
|
|
4075
|
+
var import_node_server_utils22 = require("@7365admin1/node-server-utils");
|
|
3829
4076
|
function useSupplyController() {
|
|
3830
4077
|
const {
|
|
3831
4078
|
createSupply: _createSupply,
|
|
@@ -3838,8 +4085,8 @@ function useSupplyController() {
|
|
|
3838
4085
|
const payload = { ...req.body, ...req.params };
|
|
3839
4086
|
const { error } = supplySchema.validate(payload);
|
|
3840
4087
|
if (error) {
|
|
3841
|
-
|
|
3842
|
-
next(new
|
|
4088
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4089
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3843
4090
|
return;
|
|
3844
4091
|
}
|
|
3845
4092
|
try {
|
|
@@ -3847,7 +4094,7 @@ function useSupplyController() {
|
|
|
3847
4094
|
res.status(201).json({ message: "Supply created successfully.", id });
|
|
3848
4095
|
return;
|
|
3849
4096
|
} catch (error2) {
|
|
3850
|
-
|
|
4097
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3851
4098
|
next(error2);
|
|
3852
4099
|
return;
|
|
3853
4100
|
}
|
|
@@ -3862,8 +4109,8 @@ function useSupplyController() {
|
|
|
3862
4109
|
});
|
|
3863
4110
|
const { error } = validation.validate(query);
|
|
3864
4111
|
if (error) {
|
|
3865
|
-
|
|
3866
|
-
next(new
|
|
4112
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4113
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3867
4114
|
return;
|
|
3868
4115
|
}
|
|
3869
4116
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3880,7 +4127,7 @@ function useSupplyController() {
|
|
|
3880
4127
|
res.json(data);
|
|
3881
4128
|
return;
|
|
3882
4129
|
} catch (error2) {
|
|
3883
|
-
|
|
4130
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3884
4131
|
next(error2);
|
|
3885
4132
|
return;
|
|
3886
4133
|
}
|
|
@@ -3890,8 +4137,8 @@ function useSupplyController() {
|
|
|
3890
4137
|
const _id = req.params.id;
|
|
3891
4138
|
const { error, value } = validation.validate(_id);
|
|
3892
4139
|
if (error) {
|
|
3893
|
-
|
|
3894
|
-
next(new
|
|
4140
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4141
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3895
4142
|
return;
|
|
3896
4143
|
}
|
|
3897
4144
|
try {
|
|
@@ -3899,7 +4146,7 @@ function useSupplyController() {
|
|
|
3899
4146
|
res.json(data);
|
|
3900
4147
|
return;
|
|
3901
4148
|
} catch (error2) {
|
|
3902
|
-
|
|
4149
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3903
4150
|
next(error2);
|
|
3904
4151
|
return;
|
|
3905
4152
|
}
|
|
@@ -3914,8 +4161,8 @@ function useSupplyController() {
|
|
|
3914
4161
|
});
|
|
3915
4162
|
const { error } = validation.validate(payload);
|
|
3916
4163
|
if (error) {
|
|
3917
|
-
|
|
3918
|
-
next(new
|
|
4164
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4165
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3919
4166
|
return;
|
|
3920
4167
|
}
|
|
3921
4168
|
try {
|
|
@@ -3924,7 +4171,7 @@ function useSupplyController() {
|
|
|
3924
4171
|
res.json({ message: "Supply updated successfully." });
|
|
3925
4172
|
return;
|
|
3926
4173
|
} catch (error2) {
|
|
3927
|
-
|
|
4174
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3928
4175
|
next(error2);
|
|
3929
4176
|
return;
|
|
3930
4177
|
}
|
|
@@ -3936,8 +4183,8 @@ function useSupplyController() {
|
|
|
3936
4183
|
});
|
|
3937
4184
|
const { error, value } = validation.validate({ id });
|
|
3938
4185
|
if (error) {
|
|
3939
|
-
|
|
3940
|
-
next(new
|
|
4186
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4187
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3941
4188
|
return;
|
|
3942
4189
|
}
|
|
3943
4190
|
try {
|
|
@@ -3945,7 +4192,7 @@ function useSupplyController() {
|
|
|
3945
4192
|
res.json({ message: "Supply deleted successfully." });
|
|
3946
4193
|
return;
|
|
3947
4194
|
} catch (error2) {
|
|
3948
|
-
|
|
4195
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3949
4196
|
next(error2);
|
|
3950
4197
|
return;
|
|
3951
4198
|
}
|
|
@@ -3962,7 +4209,7 @@ function useSupplyController() {
|
|
|
3962
4209
|
// src/models/hygiene-stock.model.ts
|
|
3963
4210
|
var import_joi12 = __toESM(require("joi"));
|
|
3964
4211
|
var import_mongodb12 = require("mongodb");
|
|
3965
|
-
var
|
|
4212
|
+
var import_node_server_utils23 = require("@7365admin1/node-server-utils");
|
|
3966
4213
|
var stockSchema = import_joi12.default.object({
|
|
3967
4214
|
site: import_joi12.default.string().hex().required(),
|
|
3968
4215
|
supply: import_joi12.default.string().hex().required(),
|
|
@@ -3974,21 +4221,21 @@ var stockSchema = import_joi12.default.object({
|
|
|
3974
4221
|
function MStock(value) {
|
|
3975
4222
|
const { error } = stockSchema.validate(value);
|
|
3976
4223
|
if (error) {
|
|
3977
|
-
|
|
3978
|
-
throw new
|
|
4224
|
+
import_node_server_utils23.logger.info(`Hygiene Stock Model: ${error.message}`);
|
|
4225
|
+
throw new import_node_server_utils23.BadRequestError(error.message);
|
|
3979
4226
|
}
|
|
3980
4227
|
if (value.site) {
|
|
3981
4228
|
try {
|
|
3982
4229
|
value.site = new import_mongodb12.ObjectId(value.site);
|
|
3983
4230
|
} catch (error2) {
|
|
3984
|
-
throw new
|
|
4231
|
+
throw new import_node_server_utils23.BadRequestError("Invalid site ID format.");
|
|
3985
4232
|
}
|
|
3986
4233
|
}
|
|
3987
4234
|
if (value.supply) {
|
|
3988
4235
|
try {
|
|
3989
4236
|
value.supply = new import_mongodb12.ObjectId(value.supply);
|
|
3990
4237
|
} catch (error2) {
|
|
3991
|
-
throw new
|
|
4238
|
+
throw new import_node_server_utils23.BadRequestError("Invalid supply ID format.");
|
|
3992
4239
|
}
|
|
3993
4240
|
}
|
|
3994
4241
|
return {
|
|
@@ -4007,17 +4254,17 @@ function MStock(value) {
|
|
|
4007
4254
|
|
|
4008
4255
|
// src/repositories/hygiene-stock.repository.ts
|
|
4009
4256
|
var import_mongodb13 = require("mongodb");
|
|
4010
|
-
var
|
|
4257
|
+
var import_node_server_utils24 = require("@7365admin1/node-server-utils");
|
|
4011
4258
|
function useStockRepository() {
|
|
4012
|
-
const db =
|
|
4259
|
+
const db = import_node_server_utils24.useAtlas.getDb();
|
|
4013
4260
|
if (!db) {
|
|
4014
|
-
throw new
|
|
4261
|
+
throw new import_node_server_utils24.InternalServerError("Unable to connect to server.");
|
|
4015
4262
|
}
|
|
4016
4263
|
const namespace_collection = "site.supply.stocks";
|
|
4017
4264
|
const supply_collection = "site.supplies";
|
|
4018
4265
|
const collection = db.collection(namespace_collection);
|
|
4019
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4020
|
-
const { delNamespace: delSupplyNamespace } = (0,
|
|
4266
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils24.useCache)(namespace_collection);
|
|
4267
|
+
const { delNamespace: delSupplyNamespace } = (0, import_node_server_utils24.useCache)(supply_collection);
|
|
4021
4268
|
async function createIndex() {
|
|
4022
4269
|
try {
|
|
4023
4270
|
await collection.createIndexes([
|
|
@@ -4027,7 +4274,7 @@ function useStockRepository() {
|
|
|
4027
4274
|
{ key: { status: 1 } }
|
|
4028
4275
|
]);
|
|
4029
4276
|
} catch (error) {
|
|
4030
|
-
throw new
|
|
4277
|
+
throw new import_node_server_utils24.InternalServerError("Failed to create index on hygiene stock.");
|
|
4031
4278
|
}
|
|
4032
4279
|
}
|
|
4033
4280
|
async function createStock(value, session) {
|
|
@@ -4035,17 +4282,17 @@ function useStockRepository() {
|
|
|
4035
4282
|
value = MStock(value);
|
|
4036
4283
|
const res = await collection.insertOne(value, { session });
|
|
4037
4284
|
delNamespace().then(() => {
|
|
4038
|
-
|
|
4285
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4039
4286
|
}).catch((err) => {
|
|
4040
|
-
|
|
4287
|
+
import_node_server_utils24.logger.error(
|
|
4041
4288
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4042
4289
|
err
|
|
4043
4290
|
);
|
|
4044
4291
|
});
|
|
4045
4292
|
delSupplyNamespace().then(() => {
|
|
4046
|
-
|
|
4293
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${supply_collection}`);
|
|
4047
4294
|
}).catch((err) => {
|
|
4048
|
-
|
|
4295
|
+
import_node_server_utils24.logger.error(
|
|
4049
4296
|
`Failed to clear cache for namespace: ${supply_collection}`,
|
|
4050
4297
|
err
|
|
4051
4298
|
);
|
|
@@ -4075,23 +4322,23 @@ function useStockRepository() {
|
|
|
4075
4322
|
query.site = site;
|
|
4076
4323
|
cacheOptions.site = site.toString();
|
|
4077
4324
|
} catch (error) {
|
|
4078
|
-
throw new
|
|
4325
|
+
throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
|
|
4079
4326
|
}
|
|
4080
4327
|
try {
|
|
4081
4328
|
supply = new import_mongodb13.ObjectId(supply);
|
|
4082
4329
|
query.supply = supply;
|
|
4083
4330
|
cacheOptions.supply = supply.toString();
|
|
4084
4331
|
} catch (error) {
|
|
4085
|
-
throw new
|
|
4332
|
+
throw new import_node_server_utils24.BadRequestError("Invalid supply ID format.");
|
|
4086
4333
|
}
|
|
4087
4334
|
if (search) {
|
|
4088
4335
|
query.$text = { $search: search };
|
|
4089
4336
|
cacheOptions.search = search;
|
|
4090
4337
|
}
|
|
4091
|
-
const cacheKey = (0,
|
|
4338
|
+
const cacheKey = (0, import_node_server_utils24.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4092
4339
|
const cachedData = await getCache(cacheKey);
|
|
4093
4340
|
if (cachedData) {
|
|
4094
|
-
|
|
4341
|
+
import_node_server_utils24.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4095
4342
|
return cachedData;
|
|
4096
4343
|
}
|
|
4097
4344
|
try {
|
|
@@ -4110,11 +4357,11 @@ function useStockRepository() {
|
|
|
4110
4357
|
{ $limit: limit }
|
|
4111
4358
|
]).toArray();
|
|
4112
4359
|
const length = await collection.countDocuments(query);
|
|
4113
|
-
const data = (0,
|
|
4360
|
+
const data = (0, import_node_server_utils24.paginate)(items, page, limit, length);
|
|
4114
4361
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4115
|
-
|
|
4362
|
+
import_node_server_utils24.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4116
4363
|
}).catch((err) => {
|
|
4117
|
-
|
|
4364
|
+
import_node_server_utils24.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4118
4365
|
});
|
|
4119
4366
|
return data;
|
|
4120
4367
|
} catch (error) {
|
|
@@ -4129,14 +4376,14 @@ function useStockRepository() {
|
|
|
4129
4376
|
}
|
|
4130
4377
|
|
|
4131
4378
|
// src/services/hygiene-stock.service.ts
|
|
4132
|
-
var
|
|
4379
|
+
var import_node_server_utils25 = require("@7365admin1/node-server-utils");
|
|
4133
4380
|
function useStockService() {
|
|
4134
4381
|
const { createStock: _createStock } = useStockRepository();
|
|
4135
4382
|
const { getSupplyById, updateSupply } = useSupplyRepository();
|
|
4136
4383
|
async function createStock(value, out = false, session) {
|
|
4137
4384
|
let ownSession = false;
|
|
4138
4385
|
if (!session) {
|
|
4139
|
-
session =
|
|
4386
|
+
session = import_node_server_utils25.useAtlas.getClient()?.startSession();
|
|
4140
4387
|
ownSession = true;
|
|
4141
4388
|
}
|
|
4142
4389
|
try {
|
|
@@ -4145,11 +4392,11 @@ function useStockService() {
|
|
|
4145
4392
|
const { qty, ...stockData } = value;
|
|
4146
4393
|
const supply = await getSupplyById(value.supply, session);
|
|
4147
4394
|
if (!supply || supply.qty === void 0) {
|
|
4148
|
-
throw new
|
|
4395
|
+
throw new import_node_server_utils25.NotFoundError("Supply not found.");
|
|
4149
4396
|
}
|
|
4150
4397
|
const newSupplyQty = out ? supply.qty - qty : supply.qty + qty;
|
|
4151
4398
|
if (out && newSupplyQty < 0) {
|
|
4152
|
-
throw new
|
|
4399
|
+
throw new import_node_server_utils25.BadRequestError(
|
|
4153
4400
|
`Insufficient stock. Available: ${supply.qty}, Requested: ${qty}`
|
|
4154
4401
|
);
|
|
4155
4402
|
}
|
|
@@ -4180,7 +4427,7 @@ function useStockService() {
|
|
|
4180
4427
|
|
|
4181
4428
|
// src/controllers/hygiene-stock.controller.ts
|
|
4182
4429
|
var import_joi13 = __toESM(require("joi"));
|
|
4183
|
-
var
|
|
4430
|
+
var import_node_server_utils26 = require("@7365admin1/node-server-utils");
|
|
4184
4431
|
function useStockController() {
|
|
4185
4432
|
const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
|
|
4186
4433
|
const { createStock: _createStock } = useStockService();
|
|
@@ -4194,8 +4441,8 @@ function useStockController() {
|
|
|
4194
4441
|
});
|
|
4195
4442
|
const { error } = validation.validate(payload);
|
|
4196
4443
|
if (error) {
|
|
4197
|
-
|
|
4198
|
-
next(new
|
|
4444
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4445
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4199
4446
|
return;
|
|
4200
4447
|
}
|
|
4201
4448
|
try {
|
|
@@ -4203,7 +4450,7 @@ function useStockController() {
|
|
|
4203
4450
|
res.status(201).json({ message: "Stock created successfully.", id });
|
|
4204
4451
|
return;
|
|
4205
4452
|
} catch (error2) {
|
|
4206
|
-
|
|
4453
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4207
4454
|
next(error2);
|
|
4208
4455
|
return;
|
|
4209
4456
|
}
|
|
@@ -4219,8 +4466,8 @@ function useStockController() {
|
|
|
4219
4466
|
});
|
|
4220
4467
|
const { error } = validation.validate(query);
|
|
4221
4468
|
if (error) {
|
|
4222
|
-
|
|
4223
|
-
next(new
|
|
4469
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4470
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4224
4471
|
return;
|
|
4225
4472
|
}
|
|
4226
4473
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4239,7 +4486,7 @@ function useStockController() {
|
|
|
4239
4486
|
res.json(data);
|
|
4240
4487
|
return;
|
|
4241
4488
|
} catch (error2) {
|
|
4242
|
-
|
|
4489
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4243
4490
|
next(error2);
|
|
4244
4491
|
return;
|
|
4245
4492
|
}
|
|
@@ -4253,7 +4500,7 @@ function useStockController() {
|
|
|
4253
4500
|
// src/models/hygiene-checkout-item.model.ts
|
|
4254
4501
|
var import_joi14 = __toESM(require("joi"));
|
|
4255
4502
|
var import_mongodb14 = require("mongodb");
|
|
4256
|
-
var
|
|
4503
|
+
var import_node_server_utils27 = require("@7365admin1/node-server-utils");
|
|
4257
4504
|
var allowedCheckOutItemStatus = ["pending", "completed"];
|
|
4258
4505
|
var checkOutItemSchema = import_joi14.default.object({
|
|
4259
4506
|
site: import_joi14.default.string().hex().required(),
|
|
@@ -4267,21 +4514,21 @@ var checkOutItemSchema = import_joi14.default.object({
|
|
|
4267
4514
|
function MCheckOutItem(value) {
|
|
4268
4515
|
const { error } = checkOutItemSchema.validate(value);
|
|
4269
4516
|
if (error) {
|
|
4270
|
-
|
|
4271
|
-
throw new
|
|
4517
|
+
import_node_server_utils27.logger.info(`Hygiene Check Out Item Model: ${error.message}`);
|
|
4518
|
+
throw new import_node_server_utils27.BadRequestError(error.message);
|
|
4272
4519
|
}
|
|
4273
4520
|
if (value.site) {
|
|
4274
4521
|
try {
|
|
4275
4522
|
value.site = new import_mongodb14.ObjectId(value.site);
|
|
4276
4523
|
} catch (error2) {
|
|
4277
|
-
throw new
|
|
4524
|
+
throw new import_node_server_utils27.BadRequestError("Invalid site ID format.");
|
|
4278
4525
|
}
|
|
4279
4526
|
}
|
|
4280
4527
|
if (value.supply) {
|
|
4281
4528
|
try {
|
|
4282
4529
|
value.supply = new import_mongodb14.ObjectId(value.supply);
|
|
4283
4530
|
} catch (error2) {
|
|
4284
|
-
throw new
|
|
4531
|
+
throw new import_node_server_utils27.BadRequestError("Invalid supply ID format.");
|
|
4285
4532
|
}
|
|
4286
4533
|
}
|
|
4287
4534
|
return {
|
|
@@ -4301,15 +4548,15 @@ function MCheckOutItem(value) {
|
|
|
4301
4548
|
|
|
4302
4549
|
// src/repositories/hygiene-checkout-item.repository.ts
|
|
4303
4550
|
var import_mongodb15 = require("mongodb");
|
|
4304
|
-
var
|
|
4551
|
+
var import_node_server_utils28 = require("@7365admin1/node-server-utils");
|
|
4305
4552
|
function useCheckOutItemRepository() {
|
|
4306
|
-
const db =
|
|
4553
|
+
const db = import_node_server_utils28.useAtlas.getDb();
|
|
4307
4554
|
if (!db) {
|
|
4308
|
-
throw new
|
|
4555
|
+
throw new import_node_server_utils28.InternalServerError("Unable to connect to server.");
|
|
4309
4556
|
}
|
|
4310
4557
|
const namespace_collection = "site.supply.checkouts";
|
|
4311
4558
|
const collection = db.collection(namespace_collection);
|
|
4312
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4559
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils28.useCache)(namespace_collection);
|
|
4313
4560
|
async function createIndex() {
|
|
4314
4561
|
try {
|
|
4315
4562
|
await collection.createIndexes([
|
|
@@ -4318,7 +4565,7 @@ function useCheckOutItemRepository() {
|
|
|
4318
4565
|
{ key: { status: 1 } }
|
|
4319
4566
|
]);
|
|
4320
4567
|
} catch (error) {
|
|
4321
|
-
throw new
|
|
4568
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4322
4569
|
"Failed to create index on hygiene check out item."
|
|
4323
4570
|
);
|
|
4324
4571
|
}
|
|
@@ -4327,7 +4574,7 @@ function useCheckOutItemRepository() {
|
|
|
4327
4574
|
try {
|
|
4328
4575
|
await collection.createIndex({ supplyName: "text" });
|
|
4329
4576
|
} catch (error) {
|
|
4330
|
-
throw new
|
|
4577
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4331
4578
|
"Failed to create text index on hygiene supply."
|
|
4332
4579
|
);
|
|
4333
4580
|
}
|
|
@@ -4337,9 +4584,9 @@ function useCheckOutItemRepository() {
|
|
|
4337
4584
|
value = MCheckOutItem(value);
|
|
4338
4585
|
const res = await collection.insertOne(value, { session });
|
|
4339
4586
|
delNamespace().then(() => {
|
|
4340
|
-
|
|
4587
|
+
import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4341
4588
|
}).catch((err) => {
|
|
4342
|
-
|
|
4589
|
+
import_node_server_utils28.logger.error(
|
|
4343
4590
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4344
4591
|
err
|
|
4345
4592
|
);
|
|
@@ -4368,16 +4615,16 @@ function useCheckOutItemRepository() {
|
|
|
4368
4615
|
query.site = site;
|
|
4369
4616
|
cacheOptions.site = site.toString();
|
|
4370
4617
|
} catch (error) {
|
|
4371
|
-
throw new
|
|
4618
|
+
throw new import_node_server_utils28.BadRequestError("Invalid site ID format.");
|
|
4372
4619
|
}
|
|
4373
4620
|
if (search) {
|
|
4374
4621
|
query.$text = { $search: search };
|
|
4375
4622
|
cacheOptions.search = search;
|
|
4376
4623
|
}
|
|
4377
|
-
const cacheKey = (0,
|
|
4624
|
+
const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4378
4625
|
const cachedData = await getCache(cacheKey);
|
|
4379
4626
|
if (cachedData) {
|
|
4380
|
-
|
|
4627
|
+
import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4381
4628
|
return cachedData;
|
|
4382
4629
|
}
|
|
4383
4630
|
try {
|
|
@@ -4424,11 +4671,11 @@ function useCheckOutItemRepository() {
|
|
|
4424
4671
|
{ $limit: limit }
|
|
4425
4672
|
]).toArray();
|
|
4426
4673
|
const length = await collection.countDocuments(query);
|
|
4427
|
-
const data = (0,
|
|
4674
|
+
const data = (0, import_node_server_utils28.paginate)(items, page, limit, length);
|
|
4428
4675
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4429
|
-
|
|
4676
|
+
import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4430
4677
|
}).catch((err) => {
|
|
4431
|
-
|
|
4678
|
+
import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4432
4679
|
});
|
|
4433
4680
|
return data;
|
|
4434
4681
|
} catch (error) {
|
|
@@ -4439,20 +4686,20 @@ function useCheckOutItemRepository() {
|
|
|
4439
4686
|
try {
|
|
4440
4687
|
_id = new import_mongodb15.ObjectId(_id);
|
|
4441
4688
|
} catch (error) {
|
|
4442
|
-
throw new
|
|
4689
|
+
throw new import_node_server_utils28.BadRequestError("Invalid check out item ID format.");
|
|
4443
4690
|
}
|
|
4444
4691
|
const query = { _id };
|
|
4445
|
-
const cacheKey = (0,
|
|
4692
|
+
const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, {
|
|
4446
4693
|
_id: _id.toString()
|
|
4447
4694
|
});
|
|
4448
4695
|
if (!session) {
|
|
4449
4696
|
const cachedData = await getCache(cacheKey);
|
|
4450
4697
|
if (cachedData) {
|
|
4451
|
-
|
|
4698
|
+
import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4452
4699
|
return cachedData;
|
|
4453
4700
|
}
|
|
4454
4701
|
} else {
|
|
4455
|
-
|
|
4702
|
+
import_node_server_utils28.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
4456
4703
|
}
|
|
4457
4704
|
try {
|
|
4458
4705
|
const data = await collection.aggregate(
|
|
@@ -4487,12 +4734,12 @@ function useCheckOutItemRepository() {
|
|
|
4487
4734
|
session ? { session } : void 0
|
|
4488
4735
|
).toArray();
|
|
4489
4736
|
if (!data || data.length === 0) {
|
|
4490
|
-
throw new
|
|
4737
|
+
throw new import_node_server_utils28.NotFoundError("Check out item not found.");
|
|
4491
4738
|
}
|
|
4492
4739
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
4493
|
-
|
|
4740
|
+
import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4494
4741
|
}).catch((err) => {
|
|
4495
|
-
|
|
4742
|
+
import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4496
4743
|
});
|
|
4497
4744
|
return data[0];
|
|
4498
4745
|
} catch (error) {
|
|
@@ -4503,7 +4750,7 @@ function useCheckOutItemRepository() {
|
|
|
4503
4750
|
try {
|
|
4504
4751
|
_id = new import_mongodb15.ObjectId(_id);
|
|
4505
4752
|
} catch (error) {
|
|
4506
|
-
throw new
|
|
4753
|
+
throw new import_node_server_utils28.BadRequestError("Invalid check out item ID format.");
|
|
4507
4754
|
}
|
|
4508
4755
|
try {
|
|
4509
4756
|
const updateValue = {
|
|
@@ -4516,12 +4763,12 @@ function useCheckOutItemRepository() {
|
|
|
4516
4763
|
{ session }
|
|
4517
4764
|
);
|
|
4518
4765
|
if (res.modifiedCount === 0) {
|
|
4519
|
-
throw new
|
|
4766
|
+
throw new import_node_server_utils28.InternalServerError("Unable to complete check out item.");
|
|
4520
4767
|
}
|
|
4521
4768
|
delNamespace().then(() => {
|
|
4522
|
-
|
|
4769
|
+
import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4523
4770
|
}).catch((err) => {
|
|
4524
|
-
|
|
4771
|
+
import_node_server_utils28.logger.error(
|
|
4525
4772
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4526
4773
|
err
|
|
4527
4774
|
);
|
|
@@ -4543,7 +4790,7 @@ function useCheckOutItemRepository() {
|
|
|
4543
4790
|
|
|
4544
4791
|
// src/services/hygiene-checkout-item.service.ts
|
|
4545
4792
|
var import_core = require("@7365admin1/core");
|
|
4546
|
-
var
|
|
4793
|
+
var import_node_server_utils29 = require("@7365admin1/node-server-utils");
|
|
4547
4794
|
function useCheckOutItemService() {
|
|
4548
4795
|
const {
|
|
4549
4796
|
createCheckOutItem: _createCheckOutItem,
|
|
@@ -4554,7 +4801,7 @@ function useCheckOutItemService() {
|
|
|
4554
4801
|
const { getUserById } = (0, import_core.useUserRepo)();
|
|
4555
4802
|
const { createStock } = useStockService();
|
|
4556
4803
|
async function createCheckOutItem(value) {
|
|
4557
|
-
const session =
|
|
4804
|
+
const session = import_node_server_utils29.useAtlas.getClient()?.startSession();
|
|
4558
4805
|
try {
|
|
4559
4806
|
session?.startTransaction();
|
|
4560
4807
|
const supplyData = await getSupplyById(value.supply);
|
|
@@ -4572,7 +4819,7 @@ function useCheckOutItemService() {
|
|
|
4572
4819
|
session
|
|
4573
4820
|
);
|
|
4574
4821
|
if (!checkOutItem) {
|
|
4575
|
-
throw new
|
|
4822
|
+
throw new import_node_server_utils29.BadRequestError("Failed to create check out item.");
|
|
4576
4823
|
}
|
|
4577
4824
|
const createdStocks = await createStock(
|
|
4578
4825
|
{
|
|
@@ -4594,7 +4841,7 @@ function useCheckOutItemService() {
|
|
|
4594
4841
|
}
|
|
4595
4842
|
}
|
|
4596
4843
|
async function createCheckOutItemByBatch(value) {
|
|
4597
|
-
const session =
|
|
4844
|
+
const session = import_node_server_utils29.useAtlas.getClient()?.startSession();
|
|
4598
4845
|
try {
|
|
4599
4846
|
session?.startTransaction();
|
|
4600
4847
|
const { site, attachment, createdBy, items } = value;
|
|
@@ -4642,7 +4889,7 @@ function useCheckOutItemService() {
|
|
|
4642
4889
|
|
|
4643
4890
|
// src/controllers/hygiene-checkout-item.controller.ts
|
|
4644
4891
|
var import_joi15 = __toESM(require("joi"));
|
|
4645
|
-
var
|
|
4892
|
+
var import_node_server_utils30 = require("@7365admin1/node-server-utils");
|
|
4646
4893
|
function useCheckOutItemController() {
|
|
4647
4894
|
const {
|
|
4648
4895
|
getCheckOutItems: _getCheckOutItems,
|
|
@@ -4672,8 +4919,8 @@ function useCheckOutItemController() {
|
|
|
4672
4919
|
});
|
|
4673
4920
|
const { error } = validation.validate(payload);
|
|
4674
4921
|
if (error) {
|
|
4675
|
-
|
|
4676
|
-
next(new
|
|
4922
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
4923
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4677
4924
|
return;
|
|
4678
4925
|
}
|
|
4679
4926
|
try {
|
|
@@ -4681,7 +4928,7 @@ function useCheckOutItemController() {
|
|
|
4681
4928
|
res.status(201).json({ message: "Check out item created successfully.", id });
|
|
4682
4929
|
return;
|
|
4683
4930
|
} catch (error2) {
|
|
4684
|
-
|
|
4931
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4685
4932
|
next(error2);
|
|
4686
4933
|
return;
|
|
4687
4934
|
}
|
|
@@ -4710,8 +4957,8 @@ function useCheckOutItemController() {
|
|
|
4710
4957
|
});
|
|
4711
4958
|
const { error } = validation.validate(payload);
|
|
4712
4959
|
if (error) {
|
|
4713
|
-
|
|
4714
|
-
next(new
|
|
4960
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
4961
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4715
4962
|
return;
|
|
4716
4963
|
}
|
|
4717
4964
|
try {
|
|
@@ -4719,7 +4966,7 @@ function useCheckOutItemController() {
|
|
|
4719
4966
|
res.status(201).json({ message: "Check out items created successfully." });
|
|
4720
4967
|
return;
|
|
4721
4968
|
} catch (error2) {
|
|
4722
|
-
|
|
4969
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4723
4970
|
next(error2);
|
|
4724
4971
|
return;
|
|
4725
4972
|
}
|
|
@@ -4734,8 +4981,8 @@ function useCheckOutItemController() {
|
|
|
4734
4981
|
});
|
|
4735
4982
|
const { error } = validation.validate(query);
|
|
4736
4983
|
if (error) {
|
|
4737
|
-
|
|
4738
|
-
next(new
|
|
4984
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
4985
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4739
4986
|
return;
|
|
4740
4987
|
}
|
|
4741
4988
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4752,7 +4999,7 @@ function useCheckOutItemController() {
|
|
|
4752
4999
|
res.json(data);
|
|
4753
5000
|
return;
|
|
4754
5001
|
} catch (error2) {
|
|
4755
|
-
|
|
5002
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4756
5003
|
next(error2);
|
|
4757
5004
|
return;
|
|
4758
5005
|
}
|
|
@@ -4762,8 +5009,8 @@ function useCheckOutItemController() {
|
|
|
4762
5009
|
const _id = req.params.id;
|
|
4763
5010
|
const { error, value } = validation.validate(_id);
|
|
4764
5011
|
if (error) {
|
|
4765
|
-
|
|
4766
|
-
next(new
|
|
5012
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
5013
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4767
5014
|
return;
|
|
4768
5015
|
}
|
|
4769
5016
|
try {
|
|
@@ -4771,7 +5018,7 @@ function useCheckOutItemController() {
|
|
|
4771
5018
|
res.json(data);
|
|
4772
5019
|
return;
|
|
4773
5020
|
} catch (error2) {
|
|
4774
|
-
|
|
5021
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4775
5022
|
next(error2);
|
|
4776
5023
|
return;
|
|
4777
5024
|
}
|
|
@@ -4785,7 +5032,7 @@ function useCheckOutItemController() {
|
|
|
4785
5032
|
}
|
|
4786
5033
|
|
|
4787
5034
|
// src/models/hygiene-schedule-task.model.ts
|
|
4788
|
-
var
|
|
5035
|
+
var import_node_server_utils31 = require("@7365admin1/node-server-utils");
|
|
4789
5036
|
var import_joi16 = __toESM(require("joi"));
|
|
4790
5037
|
var import_mongodb16 = require("mongodb");
|
|
4791
5038
|
var scheduleTaskSchema = import_joi16.default.object({
|
|
@@ -4806,14 +5053,14 @@ var scheduleTaskSchema = import_joi16.default.object({
|
|
|
4806
5053
|
function MScheduleTask(value) {
|
|
4807
5054
|
const { error } = scheduleTaskSchema.validate(value);
|
|
4808
5055
|
if (error) {
|
|
4809
|
-
|
|
4810
|
-
throw new
|
|
5056
|
+
import_node_server_utils31.logger.info(`Hygiene Schedule Task Model: ${error.message}`);
|
|
5057
|
+
throw new import_node_server_utils31.BadRequestError(error.message);
|
|
4811
5058
|
}
|
|
4812
5059
|
if (value.site) {
|
|
4813
5060
|
try {
|
|
4814
5061
|
value.site = new import_mongodb16.ObjectId(value.site);
|
|
4815
5062
|
} catch (error2) {
|
|
4816
|
-
throw new
|
|
5063
|
+
throw new import_node_server_utils31.BadRequestError("Invalid site ID format.");
|
|
4817
5064
|
}
|
|
4818
5065
|
}
|
|
4819
5066
|
if (value.areas && Array.isArray(value.areas)) {
|
|
@@ -4824,7 +5071,7 @@ function MScheduleTask(value) {
|
|
|
4824
5071
|
value: new import_mongodb16.ObjectId(area.value.toString())
|
|
4825
5072
|
};
|
|
4826
5073
|
} catch (error2) {
|
|
4827
|
-
throw new
|
|
5074
|
+
throw new import_node_server_utils31.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
4828
5075
|
}
|
|
4829
5076
|
});
|
|
4830
5077
|
}
|
|
@@ -4832,7 +5079,7 @@ function MScheduleTask(value) {
|
|
|
4832
5079
|
try {
|
|
4833
5080
|
value.createdBy = new import_mongodb16.ObjectId(value.createdBy);
|
|
4834
5081
|
} catch (error2) {
|
|
4835
|
-
throw new
|
|
5082
|
+
throw new import_node_server_utils31.BadRequestError("Invalid createdBy ID format.");
|
|
4836
5083
|
}
|
|
4837
5084
|
}
|
|
4838
5085
|
return {
|
|
@@ -4853,15 +5100,15 @@ function MScheduleTask(value) {
|
|
|
4853
5100
|
|
|
4854
5101
|
// src/repositories/hygiene-schedule-task.repository.ts
|
|
4855
5102
|
var import_mongodb17 = require("mongodb");
|
|
4856
|
-
var
|
|
5103
|
+
var import_node_server_utils32 = require("@7365admin1/node-server-utils");
|
|
4857
5104
|
function useScheduleTaskRepository() {
|
|
4858
|
-
const db =
|
|
5105
|
+
const db = import_node_server_utils32.useAtlas.getDb();
|
|
4859
5106
|
if (!db) {
|
|
4860
|
-
throw new
|
|
5107
|
+
throw new import_node_server_utils32.InternalServerError("Unable to connect to server.");
|
|
4861
5108
|
}
|
|
4862
5109
|
const namespace_collection = "site.schedule-tasks";
|
|
4863
5110
|
const collection = db.collection(namespace_collection);
|
|
4864
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
5111
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils32.useCache)(namespace_collection);
|
|
4865
5112
|
async function createIndex() {
|
|
4866
5113
|
try {
|
|
4867
5114
|
await collection.createIndexes([
|
|
@@ -4869,7 +5116,7 @@ function useScheduleTaskRepository() {
|
|
|
4869
5116
|
{ key: { status: 1 } }
|
|
4870
5117
|
]);
|
|
4871
5118
|
} catch (error) {
|
|
4872
|
-
throw new
|
|
5119
|
+
throw new import_node_server_utils32.InternalServerError(
|
|
4873
5120
|
"Failed to create index on hygiene schedule task."
|
|
4874
5121
|
);
|
|
4875
5122
|
}
|
|
@@ -4878,7 +5125,7 @@ function useScheduleTaskRepository() {
|
|
|
4878
5125
|
try {
|
|
4879
5126
|
await collection.createIndex({ title: "text", description: "text" });
|
|
4880
5127
|
} catch (error) {
|
|
4881
|
-
throw new
|
|
5128
|
+
throw new import_node_server_utils32.InternalServerError(
|
|
4882
5129
|
"Failed to create text index on hygiene schedule task."
|
|
4883
5130
|
);
|
|
4884
5131
|
}
|
|
@@ -4888,9 +5135,9 @@ function useScheduleTaskRepository() {
|
|
|
4888
5135
|
value = MScheduleTask(value);
|
|
4889
5136
|
const res = await collection.insertOne(value, { session });
|
|
4890
5137
|
delNamespace().then(() => {
|
|
4891
|
-
|
|
5138
|
+
import_node_server_utils32.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4892
5139
|
}).catch((err) => {
|
|
4893
|
-
|
|
5140
|
+
import_node_server_utils32.logger.error(
|
|
4894
5141
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4895
5142
|
err
|
|
4896
5143
|
);
|
|
@@ -4919,16 +5166,16 @@ function useScheduleTaskRepository() {
|
|
|
4919
5166
|
query.site = site;
|
|
4920
5167
|
cacheOptions.site = site.toString();
|
|
4921
5168
|
} catch (error) {
|
|
4922
|
-
throw new
|
|
5169
|
+
throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
|
|
4923
5170
|
}
|
|
4924
5171
|
if (search) {
|
|
4925
5172
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
4926
5173
|
cacheOptions.search = search;
|
|
4927
5174
|
}
|
|
4928
|
-
const cacheKey = (0,
|
|
5175
|
+
const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4929
5176
|
const cachedData = await getCache(cacheKey);
|
|
4930
5177
|
if (cachedData) {
|
|
4931
|
-
|
|
5178
|
+
import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4932
5179
|
return cachedData;
|
|
4933
5180
|
}
|
|
4934
5181
|
try {
|
|
@@ -4946,11 +5193,11 @@ function useScheduleTaskRepository() {
|
|
|
4946
5193
|
{ $limit: limit }
|
|
4947
5194
|
]).toArray();
|
|
4948
5195
|
const length = await collection.countDocuments(query);
|
|
4949
|
-
const data = (0,
|
|
5196
|
+
const data = (0, import_node_server_utils32.paginate)(items, page, limit, length);
|
|
4950
5197
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4951
|
-
|
|
5198
|
+
import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4952
5199
|
}).catch((err) => {
|
|
4953
|
-
|
|
5200
|
+
import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4954
5201
|
});
|
|
4955
5202
|
return data;
|
|
4956
5203
|
} catch (error) {
|
|
@@ -4987,16 +5234,16 @@ function useScheduleTaskRepository() {
|
|
|
4987
5234
|
query.site = site;
|
|
4988
5235
|
cacheOptions.site = site.toString();
|
|
4989
5236
|
} catch (error) {
|
|
4990
|
-
throw new
|
|
5237
|
+
throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
|
|
4991
5238
|
}
|
|
4992
5239
|
if (search) {
|
|
4993
5240
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
4994
5241
|
cacheOptions.search = search;
|
|
4995
5242
|
}
|
|
4996
|
-
const cacheKey = (0,
|
|
5243
|
+
const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4997
5244
|
const cachedData = await getCache(cacheKey);
|
|
4998
5245
|
if (cachedData) {
|
|
4999
|
-
|
|
5246
|
+
import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5000
5247
|
return cachedData;
|
|
5001
5248
|
}
|
|
5002
5249
|
try {
|
|
@@ -5013,11 +5260,11 @@ function useScheduleTaskRepository() {
|
|
|
5013
5260
|
{ $limit: limit }
|
|
5014
5261
|
]).toArray();
|
|
5015
5262
|
const length = await collection.countDocuments(query);
|
|
5016
|
-
const data = (0,
|
|
5263
|
+
const data = (0, import_node_server_utils32.paginate)(items, page, limit, length);
|
|
5017
5264
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
5018
|
-
|
|
5265
|
+
import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5019
5266
|
}).catch((err) => {
|
|
5020
|
-
|
|
5267
|
+
import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5021
5268
|
});
|
|
5022
5269
|
return data;
|
|
5023
5270
|
} catch (error) {
|
|
@@ -5028,23 +5275,23 @@ function useScheduleTaskRepository() {
|
|
|
5028
5275
|
try {
|
|
5029
5276
|
_id = new import_mongodb17.ObjectId(_id);
|
|
5030
5277
|
} catch (error) {
|
|
5031
|
-
throw new
|
|
5278
|
+
throw new import_node_server_utils32.BadRequestError("Invalid schedule task ID format.");
|
|
5032
5279
|
}
|
|
5033
5280
|
const query = {
|
|
5034
5281
|
_id,
|
|
5035
5282
|
status: { $ne: "deleted" }
|
|
5036
5283
|
};
|
|
5037
|
-
const cacheKey = (0,
|
|
5284
|
+
const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, {
|
|
5038
5285
|
_id: _id.toString()
|
|
5039
5286
|
});
|
|
5040
5287
|
if (!session) {
|
|
5041
5288
|
const cachedData = await getCache(cacheKey);
|
|
5042
5289
|
if (cachedData) {
|
|
5043
|
-
|
|
5290
|
+
import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5044
5291
|
return cachedData;
|
|
5045
5292
|
}
|
|
5046
5293
|
} else {
|
|
5047
|
-
|
|
5294
|
+
import_node_server_utils32.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
5048
5295
|
}
|
|
5049
5296
|
try {
|
|
5050
5297
|
const data = await collection.aggregate([
|
|
@@ -5063,12 +5310,12 @@ function useScheduleTaskRepository() {
|
|
|
5063
5310
|
}
|
|
5064
5311
|
]).toArray();
|
|
5065
5312
|
if (!data || data.length === 0) {
|
|
5066
|
-
throw new
|
|
5313
|
+
throw new import_node_server_utils32.NotFoundError("Schedule task not found.");
|
|
5067
5314
|
}
|
|
5068
5315
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
5069
|
-
|
|
5316
|
+
import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5070
5317
|
}).catch((err) => {
|
|
5071
|
-
|
|
5318
|
+
import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5072
5319
|
});
|
|
5073
5320
|
return data[0];
|
|
5074
5321
|
} catch (error) {
|
|
@@ -5079,7 +5326,7 @@ function useScheduleTaskRepository() {
|
|
|
5079
5326
|
try {
|
|
5080
5327
|
_id = new import_mongodb17.ObjectId(_id);
|
|
5081
5328
|
} catch (error) {
|
|
5082
|
-
throw new
|
|
5329
|
+
throw new import_node_server_utils32.BadRequestError("Invalid schedule task ID format.");
|
|
5083
5330
|
}
|
|
5084
5331
|
if (value.areas && Array.isArray(value.areas)) {
|
|
5085
5332
|
value.areas = value.areas.map((area) => {
|
|
@@ -5089,7 +5336,7 @@ function useScheduleTaskRepository() {
|
|
|
5089
5336
|
value: new import_mongodb17.ObjectId(area.value.toString())
|
|
5090
5337
|
};
|
|
5091
5338
|
} catch (error) {
|
|
5092
|
-
throw new
|
|
5339
|
+
throw new import_node_server_utils32.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
5093
5340
|
}
|
|
5094
5341
|
});
|
|
5095
5342
|
}
|
|
@@ -5101,14 +5348,14 @@ function useScheduleTaskRepository() {
|
|
|
5101
5348
|
{ session }
|
|
5102
5349
|
);
|
|
5103
5350
|
if (res.modifiedCount === 0) {
|
|
5104
|
-
throw new
|
|
5351
|
+
throw new import_node_server_utils32.InternalServerError(
|
|
5105
5352
|
"Unable to update hygiene schedule task."
|
|
5106
5353
|
);
|
|
5107
5354
|
}
|
|
5108
5355
|
delNamespace().then(() => {
|
|
5109
|
-
|
|
5356
|
+
import_node_server_utils32.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
5110
5357
|
}).catch((err) => {
|
|
5111
|
-
|
|
5358
|
+
import_node_server_utils32.logger.error(
|
|
5112
5359
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
5113
5360
|
err
|
|
5114
5361
|
);
|
|
@@ -5131,7 +5378,7 @@ function useScheduleTaskRepository() {
|
|
|
5131
5378
|
}
|
|
5132
5379
|
|
|
5133
5380
|
// src/services/hygiene-schedule-task.service.ts
|
|
5134
|
-
var
|
|
5381
|
+
var import_node_server_utils33 = require("@7365admin1/node-server-utils");
|
|
5135
5382
|
function useScheduleTaskService() {
|
|
5136
5383
|
const { createParentChecklist } = useParentChecklistRepo();
|
|
5137
5384
|
const { getAllScheduleTask } = useScheduleTaskRepository();
|
|
@@ -5154,13 +5401,13 @@ function useScheduleTaskService() {
|
|
|
5154
5401
|
const currentDateString = now.toLocaleDateString("en-US", {
|
|
5155
5402
|
timeZone: "Asia/Singapore"
|
|
5156
5403
|
});
|
|
5157
|
-
|
|
5404
|
+
import_node_server_utils33.logger.info(
|
|
5158
5405
|
`Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Current date ${currentDateString}, Schedule time ${schedule.time}, Start date ${schedule.startDate}, End date ${schedule.endDate}`
|
|
5159
5406
|
);
|
|
5160
5407
|
const startDate = /* @__PURE__ */ new Date(schedule.startDate + "T00:00:00");
|
|
5161
5408
|
const currentDateOnly = /* @__PURE__ */ new Date(currentDateString + "T00:00:00");
|
|
5162
5409
|
if (currentDateOnly < startDate) {
|
|
5163
|
-
|
|
5410
|
+
import_node_server_utils33.logger.info(
|
|
5164
5411
|
`Schedule ${schedule._id}: Current date ${currentDateString} is before start date ${schedule.startDate}`
|
|
5165
5412
|
);
|
|
5166
5413
|
return false;
|
|
@@ -5168,7 +5415,7 @@ function useScheduleTaskService() {
|
|
|
5168
5415
|
if (schedule.endDate) {
|
|
5169
5416
|
const endDate = /* @__PURE__ */ new Date(schedule.endDate + "T00:00:00");
|
|
5170
5417
|
if (currentDateOnly > endDate) {
|
|
5171
|
-
|
|
5418
|
+
import_node_server_utils33.logger.info(
|
|
5172
5419
|
`Schedule ${schedule._id}: Current date ${currentDateString} is after end date ${schedule.endDate}`
|
|
5173
5420
|
);
|
|
5174
5421
|
return false;
|
|
@@ -5177,17 +5424,17 @@ function useScheduleTaskService() {
|
|
|
5177
5424
|
const [scheduleHour, scheduleMinute] = schedule.time.split(":").map(Number);
|
|
5178
5425
|
const timeMatches = currentHour === scheduleHour && currentMinute === scheduleMinute;
|
|
5179
5426
|
if (!timeMatches) {
|
|
5180
|
-
|
|
5427
|
+
import_node_server_utils33.logger.info(
|
|
5181
5428
|
`Schedule ${schedule._id}: Time does not match. Current: ${currentHour}:${currentMinute}, Expected: ${scheduleHour}:${scheduleMinute}`
|
|
5182
5429
|
);
|
|
5183
5430
|
return false;
|
|
5184
5431
|
}
|
|
5185
|
-
|
|
5432
|
+
import_node_server_utils33.logger.info(
|
|
5186
5433
|
`Schedule ${schedule._id}: All conditions matched - Date is within range and time matches`
|
|
5187
5434
|
);
|
|
5188
5435
|
return true;
|
|
5189
5436
|
} catch (error) {
|
|
5190
|
-
|
|
5437
|
+
import_node_server_utils33.logger.error(
|
|
5191
5438
|
`Error checking schedule conditions for ${schedule._id}:`,
|
|
5192
5439
|
error
|
|
5193
5440
|
);
|
|
@@ -5196,40 +5443,40 @@ function useScheduleTaskService() {
|
|
|
5196
5443
|
}
|
|
5197
5444
|
async function processScheduledTasks(currentDate) {
|
|
5198
5445
|
try {
|
|
5199
|
-
|
|
5446
|
+
import_node_server_utils33.logger.info("Starting scheduled task processing...");
|
|
5200
5447
|
const scheduleTasks = await getAllScheduleTask();
|
|
5201
5448
|
if (!scheduleTasks || scheduleTasks.length === 0) {
|
|
5202
|
-
|
|
5449
|
+
import_node_server_utils33.logger.info("No schedule tasks found to process");
|
|
5203
5450
|
return { processed: 0, validated: 0 };
|
|
5204
5451
|
}
|
|
5205
|
-
|
|
5452
|
+
import_node_server_utils33.logger.info(`Found ${scheduleTasks.length} schedule tasks to check`);
|
|
5206
5453
|
let processedCount = 0;
|
|
5207
5454
|
let validatedCount = 0;
|
|
5208
5455
|
const validatedTasks = [];
|
|
5209
5456
|
for (const scheduleTask of scheduleTasks) {
|
|
5210
5457
|
try {
|
|
5211
|
-
|
|
5458
|
+
import_node_server_utils33.logger.info(
|
|
5212
5459
|
`Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, startDate=${scheduleTask.startDate}, endDate=${scheduleTask.endDate}`
|
|
5213
5460
|
);
|
|
5214
5461
|
const shouldRun = checkScheduleConditions(scheduleTask, currentDate);
|
|
5215
5462
|
if (!shouldRun) {
|
|
5216
|
-
|
|
5463
|
+
import_node_server_utils33.logger.info(
|
|
5217
5464
|
`Schedule ${scheduleTask._id} conditions not met, skipping`
|
|
5218
5465
|
);
|
|
5219
5466
|
continue;
|
|
5220
5467
|
}
|
|
5221
|
-
|
|
5468
|
+
import_node_server_utils33.logger.info(
|
|
5222
5469
|
`Schedule ${scheduleTask._id} conditions validated, creating area checklists`
|
|
5223
5470
|
);
|
|
5224
5471
|
if (!scheduleTask._id) {
|
|
5225
|
-
|
|
5472
|
+
import_node_server_utils33.logger.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
|
|
5226
5473
|
continue;
|
|
5227
5474
|
}
|
|
5228
5475
|
if (!scheduleTask.site) {
|
|
5229
|
-
|
|
5476
|
+
import_node_server_utils33.logger.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
|
|
5230
5477
|
continue;
|
|
5231
5478
|
}
|
|
5232
|
-
|
|
5479
|
+
import_node_server_utils33.logger.info(
|
|
5233
5480
|
`Getting or creating parent checklist for schedule ${scheduleTask._id} in site ${scheduleTask.site}`
|
|
5234
5481
|
);
|
|
5235
5482
|
const parentChecklistIds = await createParentChecklist({
|
|
@@ -5237,7 +5484,7 @@ function useScheduleTaskService() {
|
|
|
5237
5484
|
createdAt: /* @__PURE__ */ new Date()
|
|
5238
5485
|
});
|
|
5239
5486
|
const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
|
|
5240
|
-
|
|
5487
|
+
import_node_server_utils33.logger.info(
|
|
5241
5488
|
`Using parent checklist ${parentChecklistId}, now creating/updating area checklists`
|
|
5242
5489
|
);
|
|
5243
5490
|
for (const area of scheduleTask.areas) {
|
|
@@ -5250,14 +5497,14 @@ function useScheduleTaskService() {
|
|
|
5250
5497
|
unit: unit.unit.toString(),
|
|
5251
5498
|
name: unit.name
|
|
5252
5499
|
}));
|
|
5253
|
-
|
|
5500
|
+
import_node_server_utils33.logger.info(
|
|
5254
5501
|
`Area ${area.name} (${areaId}): Using units from area details: ${JSON.stringify(
|
|
5255
5502
|
units
|
|
5256
5503
|
)}`
|
|
5257
5504
|
);
|
|
5258
5505
|
}
|
|
5259
5506
|
if (units.length === 0) {
|
|
5260
|
-
|
|
5507
|
+
import_node_server_utils33.logger.warn(
|
|
5261
5508
|
`Area ${area.name} (${areaId}): No units found, skipping area.`
|
|
5262
5509
|
);
|
|
5263
5510
|
continue;
|
|
@@ -5268,11 +5515,11 @@ function useScheduleTaskService() {
|
|
|
5268
5515
|
parentChecklistId.toString(),
|
|
5269
5516
|
areaId
|
|
5270
5517
|
);
|
|
5271
|
-
|
|
5518
|
+
import_node_server_utils33.logger.info(
|
|
5272
5519
|
`Area ${area.name} (${areaId}): Existing area checklist found: ${existingAreaChecklist ? "Yes" : "No"}`
|
|
5273
5520
|
);
|
|
5274
5521
|
if (existingAreaChecklist) {
|
|
5275
|
-
|
|
5522
|
+
import_node_server_utils33.logger.info(
|
|
5276
5523
|
`Area ${area.name} (${areaId}): Existing checklist content: ${JSON.stringify(
|
|
5277
5524
|
existingAreaChecklist.checklist
|
|
5278
5525
|
)}`
|
|
@@ -5280,7 +5527,7 @@ function useScheduleTaskService() {
|
|
|
5280
5527
|
}
|
|
5281
5528
|
} catch (error) {
|
|
5282
5529
|
existingAreaChecklist = null;
|
|
5283
|
-
|
|
5530
|
+
import_node_server_utils33.logger.info(
|
|
5284
5531
|
`Area ${area.name} (${areaId}): No existing area checklist found (exception).`
|
|
5285
5532
|
);
|
|
5286
5533
|
}
|
|
@@ -5294,7 +5541,7 @@ function useScheduleTaskService() {
|
|
|
5294
5541
|
...existingAreaChecklist.checklist || [],
|
|
5295
5542
|
newSet
|
|
5296
5543
|
];
|
|
5297
|
-
|
|
5544
|
+
import_node_server_utils33.logger.info(
|
|
5298
5545
|
`Area ${area.name} (${areaId}): Appending new set ${newSet.set} to checklist. Updated checklist: ${JSON.stringify(
|
|
5299
5546
|
updatedChecklist
|
|
5300
5547
|
)}`
|
|
@@ -5302,7 +5549,7 @@ function useScheduleTaskService() {
|
|
|
5302
5549
|
await updateAreaChecklist(existingAreaChecklist._id, {
|
|
5303
5550
|
checklist: updatedChecklist
|
|
5304
5551
|
});
|
|
5305
|
-
|
|
5552
|
+
import_node_server_utils33.logger.info(
|
|
5306
5553
|
`Appended set ${newSet.set} to area checklist for area ${area.name}`
|
|
5307
5554
|
);
|
|
5308
5555
|
try {
|
|
@@ -5310,13 +5557,13 @@ function useScheduleTaskService() {
|
|
|
5310
5557
|
parentChecklistId.toString(),
|
|
5311
5558
|
areaId
|
|
5312
5559
|
);
|
|
5313
|
-
|
|
5560
|
+
import_node_server_utils33.logger.info(
|
|
5314
5561
|
`Area ${area.name} (${areaId}): Checklist after update: ${JSON.stringify(
|
|
5315
5562
|
verifyChecklist.checklist
|
|
5316
5563
|
)}`
|
|
5317
5564
|
);
|
|
5318
5565
|
} catch (verifyError) {
|
|
5319
|
-
|
|
5566
|
+
import_node_server_utils33.logger.warn(
|
|
5320
5567
|
`Area ${area.name} (${areaId}): Error verifying checklist after update:`,
|
|
5321
5568
|
verifyError
|
|
5322
5569
|
);
|
|
@@ -5335,50 +5582,50 @@ function useScheduleTaskService() {
|
|
|
5335
5582
|
],
|
|
5336
5583
|
createdBy: scheduleTask.createdBy
|
|
5337
5584
|
};
|
|
5338
|
-
|
|
5585
|
+
import_node_server_utils33.logger.info(
|
|
5339
5586
|
`Area ${area.name} (${areaId}): Creating new area checklist with data: ${JSON.stringify(
|
|
5340
5587
|
checklistData
|
|
5341
5588
|
)}`
|
|
5342
5589
|
);
|
|
5343
5590
|
await createAreaChecklist(checklistData);
|
|
5344
|
-
|
|
5591
|
+
import_node_server_utils33.logger.info(`Created new area checklist for area ${area.name}`);
|
|
5345
5592
|
try {
|
|
5346
5593
|
const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
|
|
5347
5594
|
parentChecklistId.toString(),
|
|
5348
5595
|
areaId
|
|
5349
5596
|
);
|
|
5350
|
-
|
|
5597
|
+
import_node_server_utils33.logger.info(
|
|
5351
5598
|
`Area ${area.name} (${areaId}): Checklist after creation: ${JSON.stringify(
|
|
5352
5599
|
verifyChecklist.checklist
|
|
5353
5600
|
)}`
|
|
5354
5601
|
);
|
|
5355
5602
|
} catch (verifyError) {
|
|
5356
|
-
|
|
5603
|
+
import_node_server_utils33.logger.warn(
|
|
5357
5604
|
`Area ${area.name} (${areaId}): Error verifying checklist after creation:`,
|
|
5358
5605
|
verifyError
|
|
5359
5606
|
);
|
|
5360
5607
|
}
|
|
5361
5608
|
}
|
|
5362
5609
|
} catch (error) {
|
|
5363
|
-
|
|
5610
|
+
import_node_server_utils33.logger.error(`Error processing area ${area.name}:`, error);
|
|
5364
5611
|
continue;
|
|
5365
5612
|
}
|
|
5366
5613
|
}
|
|
5367
5614
|
processedCount++;
|
|
5368
5615
|
validatedCount++;
|
|
5369
5616
|
validatedTasks.push(scheduleTask);
|
|
5370
|
-
|
|
5617
|
+
import_node_server_utils33.logger.info(
|
|
5371
5618
|
`Successfully processed schedule ${scheduleTask._id}, created/updated area checklists for all areas.`
|
|
5372
5619
|
);
|
|
5373
5620
|
} catch (error) {
|
|
5374
|
-
|
|
5621
|
+
import_node_server_utils33.logger.error(
|
|
5375
5622
|
`Error processing schedule task ${scheduleTask._id}:`,
|
|
5376
5623
|
error
|
|
5377
5624
|
);
|
|
5378
5625
|
continue;
|
|
5379
5626
|
}
|
|
5380
5627
|
}
|
|
5381
|
-
|
|
5628
|
+
import_node_server_utils33.logger.info(
|
|
5382
5629
|
`Scheduled task processing completed. Processed: ${processedCount}, Validated: ${validatedCount} tasks`
|
|
5383
5630
|
);
|
|
5384
5631
|
return {
|
|
@@ -5387,7 +5634,7 @@ function useScheduleTaskService() {
|
|
|
5387
5634
|
tasks: validatedTasks
|
|
5388
5635
|
};
|
|
5389
5636
|
} catch (error) {
|
|
5390
|
-
|
|
5637
|
+
import_node_server_utils33.logger.error("Error processing scheduled tasks:", error);
|
|
5391
5638
|
throw error;
|
|
5392
5639
|
}
|
|
5393
5640
|
}
|
|
@@ -5396,7 +5643,7 @@ function useScheduleTaskService() {
|
|
|
5396
5643
|
|
|
5397
5644
|
// src/controllers/hygiene-schedule-task.controller.ts
|
|
5398
5645
|
var import_joi17 = __toESM(require("joi"));
|
|
5399
|
-
var
|
|
5646
|
+
var import_node_server_utils34 = require("@7365admin1/node-server-utils");
|
|
5400
5647
|
function useScheduleTaskController() {
|
|
5401
5648
|
const {
|
|
5402
5649
|
createScheduleTask: _createScheduleTask,
|
|
@@ -5414,8 +5661,8 @@ function useScheduleTaskController() {
|
|
|
5414
5661
|
const payload = { ...req.body, ...req.params, createdBy };
|
|
5415
5662
|
const { error } = scheduleTaskSchema.validate(payload);
|
|
5416
5663
|
if (error) {
|
|
5417
|
-
|
|
5418
|
-
next(new
|
|
5664
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5665
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5419
5666
|
return;
|
|
5420
5667
|
}
|
|
5421
5668
|
try {
|
|
@@ -5423,7 +5670,7 @@ function useScheduleTaskController() {
|
|
|
5423
5670
|
res.status(201).json({ message: "Schedule task created successfully.", id });
|
|
5424
5671
|
return;
|
|
5425
5672
|
} catch (error2) {
|
|
5426
|
-
|
|
5673
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5427
5674
|
next(error2);
|
|
5428
5675
|
return;
|
|
5429
5676
|
}
|
|
@@ -5438,8 +5685,8 @@ function useScheduleTaskController() {
|
|
|
5438
5685
|
});
|
|
5439
5686
|
const { error } = validation.validate(query);
|
|
5440
5687
|
if (error) {
|
|
5441
|
-
|
|
5442
|
-
next(new
|
|
5688
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5689
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5443
5690
|
return;
|
|
5444
5691
|
}
|
|
5445
5692
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5456,7 +5703,7 @@ function useScheduleTaskController() {
|
|
|
5456
5703
|
res.json(data);
|
|
5457
5704
|
return;
|
|
5458
5705
|
} catch (error2) {
|
|
5459
|
-
|
|
5706
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5460
5707
|
next(error2);
|
|
5461
5708
|
return;
|
|
5462
5709
|
}
|
|
@@ -5471,8 +5718,8 @@ function useScheduleTaskController() {
|
|
|
5471
5718
|
});
|
|
5472
5719
|
const { error } = validation.validate(query);
|
|
5473
5720
|
if (error) {
|
|
5474
|
-
|
|
5475
|
-
next(new
|
|
5721
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5722
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5476
5723
|
return;
|
|
5477
5724
|
}
|
|
5478
5725
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5489,7 +5736,7 @@ function useScheduleTaskController() {
|
|
|
5489
5736
|
res.json(data);
|
|
5490
5737
|
return;
|
|
5491
5738
|
} catch (error2) {
|
|
5492
|
-
|
|
5739
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5493
5740
|
next(error2);
|
|
5494
5741
|
return;
|
|
5495
5742
|
}
|
|
@@ -5499,8 +5746,8 @@ function useScheduleTaskController() {
|
|
|
5499
5746
|
const _id = req.params.id;
|
|
5500
5747
|
const { error, value } = validation.validate(_id);
|
|
5501
5748
|
if (error) {
|
|
5502
|
-
|
|
5503
|
-
next(new
|
|
5749
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5750
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5504
5751
|
return;
|
|
5505
5752
|
}
|
|
5506
5753
|
try {
|
|
@@ -5508,7 +5755,7 @@ function useScheduleTaskController() {
|
|
|
5508
5755
|
res.json(data);
|
|
5509
5756
|
return;
|
|
5510
5757
|
} catch (error2) {
|
|
5511
|
-
|
|
5758
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5512
5759
|
next(error2);
|
|
5513
5760
|
return;
|
|
5514
5761
|
}
|
|
@@ -5531,8 +5778,8 @@ function useScheduleTaskController() {
|
|
|
5531
5778
|
});
|
|
5532
5779
|
const { error } = validation.validate(payload);
|
|
5533
5780
|
if (error) {
|
|
5534
|
-
|
|
5535
|
-
next(new
|
|
5781
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5782
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5536
5783
|
return;
|
|
5537
5784
|
}
|
|
5538
5785
|
try {
|
|
@@ -5541,7 +5788,7 @@ function useScheduleTaskController() {
|
|
|
5541
5788
|
res.json({ message: "Schedule task updated successfully." });
|
|
5542
5789
|
return;
|
|
5543
5790
|
} catch (error2) {
|
|
5544
|
-
|
|
5791
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5545
5792
|
next(error2);
|
|
5546
5793
|
return;
|
|
5547
5794
|
}
|
|
@@ -5554,6 +5801,275 @@ function useScheduleTaskController() {
|
|
|
5554
5801
|
updateScheduleTask
|
|
5555
5802
|
};
|
|
5556
5803
|
}
|
|
5804
|
+
|
|
5805
|
+
// src/services/hygiene-qr.service.ts
|
|
5806
|
+
var import_node_server_utils35 = require("@7365admin1/node-server-utils");
|
|
5807
|
+
var import_puppeteer = require("puppeteer");
|
|
5808
|
+
var import_qrcode = __toESM(require("qrcode"));
|
|
5809
|
+
function useQRService() {
|
|
5810
|
+
async function generateQRDataUrl(qrUrl) {
|
|
5811
|
+
return import_qrcode.default.toDataURL(qrUrl, {
|
|
5812
|
+
width: 350,
|
|
5813
|
+
margin: 2,
|
|
5814
|
+
errorCorrectionLevel: "M",
|
|
5815
|
+
color: {
|
|
5816
|
+
dark: "#000000",
|
|
5817
|
+
light: "#FFFFFF"
|
|
5818
|
+
}
|
|
5819
|
+
});
|
|
5820
|
+
}
|
|
5821
|
+
async function generateQRImage(qrUrl) {
|
|
5822
|
+
try {
|
|
5823
|
+
const qrDataUrl = await generateQRDataUrl(qrUrl);
|
|
5824
|
+
const browser = await (0, import_puppeteer.launch)({
|
|
5825
|
+
headless: true,
|
|
5826
|
+
executablePath: process.env.CHROME_BINARY,
|
|
5827
|
+
args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
|
|
5828
|
+
});
|
|
5829
|
+
const page = await browser.newPage();
|
|
5830
|
+
await page.setViewport({
|
|
5831
|
+
width: 400,
|
|
5832
|
+
height: 400
|
|
5833
|
+
});
|
|
5834
|
+
const html = `
|
|
5835
|
+
<!DOCTYPE html>
|
|
5836
|
+
<html>
|
|
5837
|
+
<head>
|
|
5838
|
+
<meta charset="UTF-8">
|
|
5839
|
+
<style>
|
|
5840
|
+
body {
|
|
5841
|
+
margin: 0;
|
|
5842
|
+
padding: 20px;
|
|
5843
|
+
display: flex;
|
|
5844
|
+
justify-content: center;
|
|
5845
|
+
align-items: center;
|
|
5846
|
+
background: white;
|
|
5847
|
+
min-height: 100vh;
|
|
5848
|
+
}
|
|
5849
|
+
#qr-image {
|
|
5850
|
+
display: block;
|
|
5851
|
+
width: 350px;
|
|
5852
|
+
height: 350px;
|
|
5853
|
+
}
|
|
5854
|
+
</style>
|
|
5855
|
+
</head>
|
|
5856
|
+
<body>
|
|
5857
|
+
<img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
|
|
5858
|
+
</body>
|
|
5859
|
+
</html>
|
|
5860
|
+
`;
|
|
5861
|
+
await page.setContent(html, {
|
|
5862
|
+
waitUntil: ["load", "networkidle0"]
|
|
5863
|
+
});
|
|
5864
|
+
await page.waitForSelector("#qr-image", { timeout: 1e4 });
|
|
5865
|
+
const imageBuffer = await page.screenshot({
|
|
5866
|
+
type: "png",
|
|
5867
|
+
clip: {
|
|
5868
|
+
x: 0,
|
|
5869
|
+
y: 0,
|
|
5870
|
+
width: 400,
|
|
5871
|
+
height: 400
|
|
5872
|
+
}
|
|
5873
|
+
});
|
|
5874
|
+
await browser.close();
|
|
5875
|
+
return imageBuffer;
|
|
5876
|
+
} catch (error) {
|
|
5877
|
+
import_node_server_utils35.logger.log({
|
|
5878
|
+
level: "error",
|
|
5879
|
+
message: `Failed to generate QR image: ${error.message}`
|
|
5880
|
+
});
|
|
5881
|
+
throw error;
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
async function generateQRPDF(qrUrl, title) {
|
|
5885
|
+
try {
|
|
5886
|
+
const qrDataUrl = await generateQRDataUrl(qrUrl);
|
|
5887
|
+
const browser = await (0, import_puppeteer.launch)({
|
|
5888
|
+
headless: true,
|
|
5889
|
+
executablePath: process.env.CHROME_BINARY,
|
|
5890
|
+
args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
|
|
5891
|
+
});
|
|
5892
|
+
const page = await browser.newPage();
|
|
5893
|
+
await page.setViewport({
|
|
5894
|
+
width: 800,
|
|
5895
|
+
height: 1100
|
|
5896
|
+
});
|
|
5897
|
+
const escapedTitle = (title || "Cleaning Schedule QR Code").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5898
|
+
const html = `
|
|
5899
|
+
<!DOCTYPE html>
|
|
5900
|
+
<html>
|
|
5901
|
+
<head>
|
|
5902
|
+
<meta charset="UTF-8">
|
|
5903
|
+
<style>
|
|
5904
|
+
* {
|
|
5905
|
+
margin: 0;
|
|
5906
|
+
padding: 0;
|
|
5907
|
+
box-sizing: border-box;
|
|
5908
|
+
}
|
|
5909
|
+
body {
|
|
5910
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
5911
|
+
background: white;
|
|
5912
|
+
padding: 60px 40px;
|
|
5913
|
+
display: flex;
|
|
5914
|
+
flex-direction: column;
|
|
5915
|
+
align-items: center;
|
|
5916
|
+
justify-content: center;
|
|
5917
|
+
min-height: 100vh;
|
|
5918
|
+
}
|
|
5919
|
+
.qr-container {
|
|
5920
|
+
text-align: center;
|
|
5921
|
+
background: transparent;
|
|
5922
|
+
padding: 0;
|
|
5923
|
+
}
|
|
5924
|
+
h1 {
|
|
5925
|
+
font-size: 28px;
|
|
5926
|
+
color: #333;
|
|
5927
|
+
margin-bottom: 20px;
|
|
5928
|
+
font-weight: 600;
|
|
5929
|
+
}
|
|
5930
|
+
.qr-wrapper {
|
|
5931
|
+
display: inline-block;
|
|
5932
|
+
padding: 0;
|
|
5933
|
+
background: transparent;
|
|
5934
|
+
border: none;
|
|
5935
|
+
border-radius: 0;
|
|
5936
|
+
margin: 20px 0;
|
|
5937
|
+
}
|
|
5938
|
+
#qr-image {
|
|
5939
|
+
display: block;
|
|
5940
|
+
width: 350px;
|
|
5941
|
+
height: 350px;
|
|
5942
|
+
}
|
|
5943
|
+
.instructions {
|
|
5944
|
+
margin-top: 30px;
|
|
5945
|
+
font-size: 16px;
|
|
5946
|
+
color: #666;
|
|
5947
|
+
line-height: 1.6;
|
|
5948
|
+
}
|
|
5949
|
+
.url-info {
|
|
5950
|
+
margin-top: 20px;
|
|
5951
|
+
padding: 15px;
|
|
5952
|
+
background: #f5f5f5;
|
|
5953
|
+
border-radius: 6px;
|
|
5954
|
+
font-size: 12px;
|
|
5955
|
+
color: #888;
|
|
5956
|
+
word-break: break-all;
|
|
5957
|
+
}
|
|
5958
|
+
</style>
|
|
5959
|
+
</head>
|
|
5960
|
+
<body>
|
|
5961
|
+
<div class="qr-container">
|
|
5962
|
+
<h1>${escapedTitle}</h1>
|
|
5963
|
+
<div class="qr-wrapper">
|
|
5964
|
+
<img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
|
|
5965
|
+
</div>
|
|
5966
|
+
<div class="instructions">
|
|
5967
|
+
<p>Scan this QR code to access the cleaning schedule.</p>
|
|
5968
|
+
</div>
|
|
5969
|
+
<div class="url-info">
|
|
5970
|
+
${qrUrl}
|
|
5971
|
+
</div>
|
|
5972
|
+
</div>
|
|
5973
|
+
</body>
|
|
5974
|
+
</html>
|
|
5975
|
+
`;
|
|
5976
|
+
await page.setContent(html, {
|
|
5977
|
+
waitUntil: ["load", "networkidle0"]
|
|
5978
|
+
});
|
|
5979
|
+
await page.waitForSelector("#qr-image", { timeout: 1e4 });
|
|
5980
|
+
await page.waitForFunction(
|
|
5981
|
+
() => {
|
|
5982
|
+
const img = document.getElementById("qr-image");
|
|
5983
|
+
return img && img.complete && img.naturalWidth > 0;
|
|
5984
|
+
},
|
|
5985
|
+
{ timeout: 1e4 }
|
|
5986
|
+
);
|
|
5987
|
+
const pdfBuffer = await page.pdf({
|
|
5988
|
+
format: "A4",
|
|
5989
|
+
printBackground: true,
|
|
5990
|
+
margin: {
|
|
5991
|
+
top: "20mm",
|
|
5992
|
+
right: "20mm",
|
|
5993
|
+
bottom: "20mm",
|
|
5994
|
+
left: "20mm"
|
|
5995
|
+
}
|
|
5996
|
+
});
|
|
5997
|
+
await browser.close();
|
|
5998
|
+
return pdfBuffer;
|
|
5999
|
+
} catch (error) {
|
|
6000
|
+
import_node_server_utils35.logger.log({
|
|
6001
|
+
level: "error",
|
|
6002
|
+
message: `Failed to generate QR PDF: ${error.message}`
|
|
6003
|
+
});
|
|
6004
|
+
throw error;
|
|
6005
|
+
}
|
|
6006
|
+
}
|
|
6007
|
+
return {
|
|
6008
|
+
generateQRImage,
|
|
6009
|
+
generateQRPDF
|
|
6010
|
+
};
|
|
6011
|
+
}
|
|
6012
|
+
|
|
6013
|
+
// src/controllers/hygiene-qr.controller.ts
|
|
6014
|
+
var import_joi18 = __toESM(require("joi"));
|
|
6015
|
+
var import_node_server_utils36 = require("@7365admin1/node-server-utils");
|
|
6016
|
+
function useQRController() {
|
|
6017
|
+
const { generateQRImage: _generateQRImage, generateQRPDF: _generateQRPDF } = useQRService();
|
|
6018
|
+
async function generateQR(req, res, next) {
|
|
6019
|
+
const validation = import_joi18.default.object({
|
|
6020
|
+
url: import_joi18.default.string().uri().required(),
|
|
6021
|
+
filename: import_joi18.default.string().optional().allow("", null),
|
|
6022
|
+
title: import_joi18.default.string().optional().allow("", null),
|
|
6023
|
+
download: import_joi18.default.boolean().optional().default(false)
|
|
6024
|
+
});
|
|
6025
|
+
const query = { ...req.query };
|
|
6026
|
+
const { error, value } = validation.validate(query);
|
|
6027
|
+
if (error) {
|
|
6028
|
+
import_node_server_utils36.logger.log({ level: "error", message: error.message });
|
|
6029
|
+
next(new import_node_server_utils36.BadRequestError(error.message));
|
|
6030
|
+
return;
|
|
6031
|
+
}
|
|
6032
|
+
try {
|
|
6033
|
+
const { url, filename, title, download } = value;
|
|
6034
|
+
if (download) {
|
|
6035
|
+
const pdfBuffer = await _generateQRPDF(url, title);
|
|
6036
|
+
if (!pdfBuffer || pdfBuffer.length === 0) {
|
|
6037
|
+
throw new Error("Generated QR PDF is empty or invalid.");
|
|
6038
|
+
}
|
|
6039
|
+
const sanitizedFilename = (filename || "qrcode").replace(/['"]/g, "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6040
|
+
const date = /* @__PURE__ */ new Date();
|
|
6041
|
+
const formattedDate = `${String(date.getMonth() + 1).padStart(
|
|
6042
|
+
2,
|
|
6043
|
+
"0"
|
|
6044
|
+
)}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
|
|
6045
|
+
res.setHeader("Content-Type", "application/pdf");
|
|
6046
|
+
res.setHeader(
|
|
6047
|
+
"Content-Disposition",
|
|
6048
|
+
`attachment; filename="${sanitizedFilename}-${formattedDate}.pdf"`
|
|
6049
|
+
);
|
|
6050
|
+
res.setHeader("Content-Length", pdfBuffer.length);
|
|
6051
|
+
res.end(pdfBuffer);
|
|
6052
|
+
} else {
|
|
6053
|
+
const imageBuffer = await _generateQRImage(url);
|
|
6054
|
+
if (!imageBuffer || imageBuffer.length === 0) {
|
|
6055
|
+
throw new Error("Generated QR image is empty or invalid.");
|
|
6056
|
+
}
|
|
6057
|
+
res.setHeader("Content-Type", "image/png");
|
|
6058
|
+
res.setHeader("Cache-Control", "public, max-age=3600");
|
|
6059
|
+
res.setHeader("Content-Length", imageBuffer.length);
|
|
6060
|
+
res.end(imageBuffer);
|
|
6061
|
+
}
|
|
6062
|
+
return;
|
|
6063
|
+
} catch (error2) {
|
|
6064
|
+
import_node_server_utils36.logger.log({ level: "error", message: error2.message });
|
|
6065
|
+
next(error2);
|
|
6066
|
+
return;
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
return {
|
|
6070
|
+
generateQR
|
|
6071
|
+
};
|
|
6072
|
+
}
|
|
5557
6073
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5558
6074
|
0 && (module.exports = {
|
|
5559
6075
|
MArea,
|
|
@@ -5581,6 +6097,7 @@ function useScheduleTaskController() {
|
|
|
5581
6097
|
useAreaChecklistRepo,
|
|
5582
6098
|
useAreaChecklistService,
|
|
5583
6099
|
useAreaController,
|
|
6100
|
+
useAreaExportService,
|
|
5584
6101
|
useAreaRepo,
|
|
5585
6102
|
useAreaService,
|
|
5586
6103
|
useCheckOutItemController,
|
|
@@ -5590,6 +6107,8 @@ function useScheduleTaskController() {
|
|
|
5590
6107
|
useHygieneDashboardRepository,
|
|
5591
6108
|
useParentChecklistController,
|
|
5592
6109
|
useParentChecklistRepo,
|
|
6110
|
+
useQRController,
|
|
6111
|
+
useQRService,
|
|
5593
6112
|
useScheduleTaskController,
|
|
5594
6113
|
useScheduleTaskRepository,
|
|
5595
6114
|
useScheduleTaskService,
|
|
@@ -5599,6 +6118,7 @@ function useScheduleTaskController() {
|
|
|
5599
6118
|
useSupplyController,
|
|
5600
6119
|
useSupplyRepository,
|
|
5601
6120
|
useUnitController,
|
|
6121
|
+
useUnitExportService,
|
|
5602
6122
|
useUnitRepository,
|
|
5603
6123
|
useUnitService
|
|
5604
6124
|
});
|