@7365admin1/module-hygiene 4.4.0 → 4.6.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 +12 -0
- package/dist/index.d.ts +49 -5
- package/dist/index.js +1261 -723
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1102 -568
- 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
1681
|
return;
|
|
1342
1682
|
}
|
|
1343
1683
|
}
|
|
1344
1684
|
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;
|
|
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)) {
|
|
@@ -2352,6 +2599,8 @@ function MAreaChecklist(value) {
|
|
|
2352
2599
|
units: checklistItem.units.map((unit) => ({
|
|
2353
2600
|
unit: new import_mongodb8.ObjectId(unit.unit),
|
|
2354
2601
|
name: unit.name,
|
|
2602
|
+
approve: false,
|
|
2603
|
+
reject: false,
|
|
2355
2604
|
status: "ready",
|
|
2356
2605
|
remarks: "",
|
|
2357
2606
|
completedBy: "",
|
|
@@ -2364,7 +2613,7 @@ function MAreaChecklist(value) {
|
|
|
2364
2613
|
try {
|
|
2365
2614
|
value.createdBy = new import_mongodb8.ObjectId(value.createdBy);
|
|
2366
2615
|
} catch (error2) {
|
|
2367
|
-
throw new
|
|
2616
|
+
throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
|
|
2368
2617
|
}
|
|
2369
2618
|
}
|
|
2370
2619
|
return {
|
|
@@ -2382,19 +2631,19 @@ function MAreaChecklist(value) {
|
|
|
2382
2631
|
}
|
|
2383
2632
|
|
|
2384
2633
|
// src/services/hygiene-area-checklist.service.ts
|
|
2385
|
-
var
|
|
2634
|
+
var import_node_server_utils18 = require("@7365admin1/node-server-utils");
|
|
2386
2635
|
|
|
2387
2636
|
// src/repositories/hygiene-area-checklist.repository.ts
|
|
2388
2637
|
var import_mongodb9 = require("mongodb");
|
|
2389
|
-
var
|
|
2638
|
+
var import_node_server_utils17 = require("@7365admin1/node-server-utils");
|
|
2390
2639
|
function useAreaChecklistRepo() {
|
|
2391
|
-
const db =
|
|
2640
|
+
const db = import_node_server_utils17.useAtlas.getDb();
|
|
2392
2641
|
if (!db) {
|
|
2393
|
-
throw new
|
|
2642
|
+
throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
|
|
2394
2643
|
}
|
|
2395
2644
|
const namespace_collection = "site.cleaning.schedule.areas";
|
|
2396
2645
|
const collection = db.collection(namespace_collection);
|
|
2397
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
2646
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
|
|
2398
2647
|
async function createIndex() {
|
|
2399
2648
|
try {
|
|
2400
2649
|
await collection.createIndexes([
|
|
@@ -2406,7 +2655,7 @@ function useAreaChecklistRepo() {
|
|
|
2406
2655
|
{ key: { "checklist.units.status": 1 } }
|
|
2407
2656
|
]);
|
|
2408
2657
|
} catch (error) {
|
|
2409
|
-
throw new
|
|
2658
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
2410
2659
|
"Failed to create index on hygiene checklist area."
|
|
2411
2660
|
);
|
|
2412
2661
|
}
|
|
@@ -2419,7 +2668,7 @@ function useAreaChecklistRepo() {
|
|
|
2419
2668
|
"checklist.units.remarks": "text"
|
|
2420
2669
|
});
|
|
2421
2670
|
} catch (error) {
|
|
2422
|
-
throw new
|
|
2671
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
2423
2672
|
"Failed to create text index on hygiene checklist area."
|
|
2424
2673
|
);
|
|
2425
2674
|
}
|
|
@@ -2442,7 +2691,7 @@ function useAreaChecklistRepo() {
|
|
|
2442
2691
|
}
|
|
2443
2692
|
});
|
|
2444
2693
|
if (existingChecklist) {
|
|
2445
|
-
|
|
2694
|
+
import_node_server_utils17.logger.info(
|
|
2446
2695
|
`Area checklist already exists for area ${value.name} on ${currentDate.toISOString().split("T")[0]}`
|
|
2447
2696
|
);
|
|
2448
2697
|
return existingChecklist._id;
|
|
@@ -2450,9 +2699,9 @@ function useAreaChecklistRepo() {
|
|
|
2450
2699
|
const processedValue = MAreaChecklist(value);
|
|
2451
2700
|
const result = await collection.insertOne(processedValue, { session });
|
|
2452
2701
|
delNamespace().then(() => {
|
|
2453
|
-
|
|
2702
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2454
2703
|
}).catch((err) => {
|
|
2455
|
-
|
|
2704
|
+
import_node_server_utils17.logger.error(
|
|
2456
2705
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2457
2706
|
err
|
|
2458
2707
|
);
|
|
@@ -2480,7 +2729,7 @@ function useAreaChecklistRepo() {
|
|
|
2480
2729
|
query.schedule = new import_mongodb9.ObjectId(schedule);
|
|
2481
2730
|
cacheOptions.schedule = schedule.toString();
|
|
2482
2731
|
} catch (error) {
|
|
2483
|
-
throw new
|
|
2732
|
+
throw new import_node_server_utils17.BadRequestError("Invalid parent checklist ID format.");
|
|
2484
2733
|
}
|
|
2485
2734
|
if (type && type !== "all") {
|
|
2486
2735
|
query.type = type;
|
|
@@ -2494,11 +2743,11 @@ function useAreaChecklistRepo() {
|
|
|
2494
2743
|
query.$text = { $search: search };
|
|
2495
2744
|
cacheOptions.search = search;
|
|
2496
2745
|
}
|
|
2497
|
-
const cacheKey = (0,
|
|
2746
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2498
2747
|
if (!session) {
|
|
2499
2748
|
const cachedData = await getCache(cacheKey);
|
|
2500
2749
|
if (cachedData) {
|
|
2501
|
-
|
|
2750
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2502
2751
|
return cachedData;
|
|
2503
2752
|
}
|
|
2504
2753
|
}
|
|
@@ -2572,11 +2821,11 @@ function useAreaChecklistRepo() {
|
|
|
2572
2821
|
];
|
|
2573
2822
|
const items = await collection.aggregate(pipeline, { session }).toArray();
|
|
2574
2823
|
const length = await collection.countDocuments(query, { session });
|
|
2575
|
-
const data = (0,
|
|
2824
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2576
2825
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2577
|
-
|
|
2826
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2578
2827
|
}).catch((err) => {
|
|
2579
|
-
|
|
2828
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2580
2829
|
});
|
|
2581
2830
|
return data;
|
|
2582
2831
|
} catch (error) {
|
|
@@ -2602,7 +2851,7 @@ function useAreaChecklistRepo() {
|
|
|
2602
2851
|
query.schedule = new import_mongodb9.ObjectId(schedule);
|
|
2603
2852
|
cacheOptions.schedule = schedule.toString();
|
|
2604
2853
|
} catch (error) {
|
|
2605
|
-
throw new
|
|
2854
|
+
throw new import_node_server_utils17.BadRequestError("Invalid parent checklist ID format.");
|
|
2606
2855
|
}
|
|
2607
2856
|
if (type) {
|
|
2608
2857
|
query.type = type;
|
|
@@ -2625,10 +2874,10 @@ function useAreaChecklistRepo() {
|
|
|
2625
2874
|
} else {
|
|
2626
2875
|
query.status = { $in: ["ongoing", "completed"] };
|
|
2627
2876
|
}
|
|
2628
|
-
const cacheKey = (0,
|
|
2877
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2629
2878
|
const cachedData = await getCache(cacheKey);
|
|
2630
2879
|
if (cachedData) {
|
|
2631
|
-
|
|
2880
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2632
2881
|
return cachedData;
|
|
2633
2882
|
}
|
|
2634
2883
|
try {
|
|
@@ -2676,11 +2925,11 @@ function useAreaChecklistRepo() {
|
|
|
2676
2925
|
];
|
|
2677
2926
|
const items = await collection.aggregate(pipeline).toArray();
|
|
2678
2927
|
const length = await collection.countDocuments(query);
|
|
2679
|
-
const data = (0,
|
|
2928
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2680
2929
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2681
|
-
|
|
2930
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2682
2931
|
}).catch((err) => {
|
|
2683
|
-
|
|
2932
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2684
2933
|
});
|
|
2685
2934
|
return data;
|
|
2686
2935
|
} catch (error) {
|
|
@@ -2691,14 +2940,14 @@ function useAreaChecklistRepo() {
|
|
|
2691
2940
|
try {
|
|
2692
2941
|
_id = new import_mongodb9.ObjectId(_id);
|
|
2693
2942
|
} catch (error) {
|
|
2694
|
-
throw new
|
|
2943
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2695
2944
|
}
|
|
2696
|
-
const cacheKey = (0,
|
|
2945
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, {
|
|
2697
2946
|
_id: _id.toString()
|
|
2698
2947
|
});
|
|
2699
2948
|
const cachedData = await getCache(cacheKey);
|
|
2700
2949
|
if (cachedData) {
|
|
2701
|
-
|
|
2950
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2702
2951
|
return cachedData;
|
|
2703
2952
|
}
|
|
2704
2953
|
try {
|
|
@@ -2821,16 +3070,16 @@ function useAreaChecklistRepo() {
|
|
|
2821
3070
|
collection.aggregate(unitPipeline).toArray()
|
|
2822
3071
|
]);
|
|
2823
3072
|
if (!area.length) {
|
|
2824
|
-
throw new
|
|
3073
|
+
throw new import_node_server_utils17.BadRequestError("Area checklist not found.");
|
|
2825
3074
|
}
|
|
2826
3075
|
const items = {
|
|
2827
3076
|
area: area[0],
|
|
2828
3077
|
units
|
|
2829
3078
|
};
|
|
2830
3079
|
setCache(cacheKey, items, 15 * 60).then(() => {
|
|
2831
|
-
|
|
3080
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2832
3081
|
}).catch((err) => {
|
|
2833
|
-
|
|
3082
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2834
3083
|
});
|
|
2835
3084
|
return items;
|
|
2836
3085
|
} catch (error) {
|
|
@@ -2853,17 +3102,17 @@ function useAreaChecklistRepo() {
|
|
|
2853
3102
|
query._id = new import_mongodb9.ObjectId(_id);
|
|
2854
3103
|
cacheOptions._id = _id.toString();
|
|
2855
3104
|
} catch (error) {
|
|
2856
|
-
throw new
|
|
3105
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2857
3106
|
}
|
|
2858
3107
|
if (search) {
|
|
2859
3108
|
query.$text = { $search: search };
|
|
2860
3109
|
cacheOptions.search = search;
|
|
2861
3110
|
}
|
|
2862
|
-
const cacheKey = (0,
|
|
3111
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2863
3112
|
if (!session) {
|
|
2864
3113
|
const cachedData = await getCache(cacheKey);
|
|
2865
3114
|
if (cachedData) {
|
|
2866
|
-
|
|
3115
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2867
3116
|
return cachedData;
|
|
2868
3117
|
}
|
|
2869
3118
|
}
|
|
@@ -2951,11 +3200,11 @@ function useAreaChecklistRepo() {
|
|
|
2951
3200
|
collection.aggregate(countPipeline, { session }).toArray()
|
|
2952
3201
|
]);
|
|
2953
3202
|
const length = countResult.length > 0 ? countResult[0].total : 0;
|
|
2954
|
-
const data = (0,
|
|
3203
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2955
3204
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2956
|
-
|
|
3205
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2957
3206
|
}).catch((err) => {
|
|
2958
|
-
|
|
3207
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2959
3208
|
});
|
|
2960
3209
|
return data;
|
|
2961
3210
|
} catch (error) {
|
|
@@ -2966,7 +3215,7 @@ function useAreaChecklistRepo() {
|
|
|
2966
3215
|
try {
|
|
2967
3216
|
_id = new import_mongodb9.ObjectId(_id);
|
|
2968
3217
|
} catch (error) {
|
|
2969
|
-
throw new
|
|
3218
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2970
3219
|
}
|
|
2971
3220
|
try {
|
|
2972
3221
|
const area = await collection.findOne(
|
|
@@ -2974,7 +3223,7 @@ function useAreaChecklistRepo() {
|
|
|
2974
3223
|
{ projection: { schedule: 1, name: 1, type: 1, status: 1 }, session }
|
|
2975
3224
|
);
|
|
2976
3225
|
if (!area) {
|
|
2977
|
-
throw new
|
|
3226
|
+
throw new import_node_server_utils17.BadRequestError("Area checklist not found.");
|
|
2978
3227
|
}
|
|
2979
3228
|
return area;
|
|
2980
3229
|
} catch (error) {
|
|
@@ -2986,36 +3235,44 @@ function useAreaChecklistRepo() {
|
|
|
2986
3235
|
schedule = new import_mongodb9.ObjectId(schedule);
|
|
2987
3236
|
area = new import_mongodb9.ObjectId(area);
|
|
2988
3237
|
} catch (error) {
|
|
2989
|
-
throw new
|
|
3238
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
2990
3239
|
}
|
|
2991
3240
|
try {
|
|
2992
3241
|
const data = await collection.findOne({ schedule, area }, { session });
|
|
2993
3242
|
if (!data) {
|
|
2994
|
-
throw new
|
|
3243
|
+
throw new import_node_server_utils17.BadRequestError("Area checklist not found.");
|
|
2995
3244
|
}
|
|
2996
3245
|
return data;
|
|
2997
3246
|
} catch (error) {
|
|
2998
3247
|
throw error;
|
|
2999
3248
|
}
|
|
3000
3249
|
}
|
|
3001
|
-
async function
|
|
3250
|
+
async function updateAreaChecklistUnits(_id, set, unitId, value, session) {
|
|
3002
3251
|
try {
|
|
3003
3252
|
_id = new import_mongodb9.ObjectId(_id);
|
|
3004
3253
|
} catch (error) {
|
|
3005
|
-
throw new
|
|
3254
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
3006
3255
|
}
|
|
3007
3256
|
try {
|
|
3008
3257
|
unitId = new import_mongodb9.ObjectId(unitId);
|
|
3009
3258
|
} catch (error) {
|
|
3010
|
-
throw new
|
|
3259
|
+
throw new import_node_server_utils17.BadRequestError("Invalid unit checklist ID format.");
|
|
3011
3260
|
}
|
|
3012
3261
|
try {
|
|
3013
3262
|
const now = /* @__PURE__ */ new Date();
|
|
3014
3263
|
const updateValue = {
|
|
3015
3264
|
"checklist.$[checklist].units.$[unit].timestamp": now,
|
|
3016
|
-
"checklist.$[checklist].units.$[unit].status": "completed",
|
|
3017
3265
|
updatedAt: now
|
|
3018
3266
|
};
|
|
3267
|
+
if (value.approve === true) {
|
|
3268
|
+
updateValue["checklist.$[checklist].units.$[unit].approve"] = true;
|
|
3269
|
+
updateValue["checklist.$[checklist].units.$[unit].reject"] = false;
|
|
3270
|
+
updateValue["checklist.$[checklist].units.$[unit].status"] = "completed";
|
|
3271
|
+
} else if (value.reject === true) {
|
|
3272
|
+
updateValue["checklist.$[checklist].units.$[unit].approve"] = false;
|
|
3273
|
+
updateValue["checklist.$[checklist].units.$[unit].reject"] = true;
|
|
3274
|
+
updateValue["checklist.$[checklist].units.$[unit].status"] = "ready";
|
|
3275
|
+
}
|
|
3019
3276
|
if (value.remarks) {
|
|
3020
3277
|
updateValue["checklist.$[checklist].units.$[unit].remarks"] = value.remarks;
|
|
3021
3278
|
}
|
|
@@ -3032,19 +3289,19 @@ function useAreaChecklistRepo() {
|
|
|
3032
3289
|
{ arrayFilters, session }
|
|
3033
3290
|
);
|
|
3034
3291
|
if (res.modifiedCount === 0) {
|
|
3035
|
-
throw new
|
|
3292
|
+
throw new import_node_server_utils17.InternalServerError("Unable to update area checklist unit.");
|
|
3036
3293
|
}
|
|
3037
3294
|
delNamespace().then(() => {
|
|
3038
|
-
|
|
3295
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3039
3296
|
}).catch((err) => {
|
|
3040
|
-
|
|
3297
|
+
import_node_server_utils17.logger.error(
|
|
3041
3298
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3042
3299
|
err
|
|
3043
3300
|
);
|
|
3044
3301
|
});
|
|
3045
3302
|
return res.modifiedCount;
|
|
3046
3303
|
} catch (error) {
|
|
3047
|
-
|
|
3304
|
+
import_node_server_utils17.logger.error("Error updating area checklist unit:", error.message);
|
|
3048
3305
|
throw error;
|
|
3049
3306
|
}
|
|
3050
3307
|
}
|
|
@@ -3052,7 +3309,7 @@ function useAreaChecklistRepo() {
|
|
|
3052
3309
|
try {
|
|
3053
3310
|
_id = new import_mongodb9.ObjectId(_id);
|
|
3054
3311
|
} catch (error) {
|
|
3055
|
-
throw new
|
|
3312
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
3056
3313
|
}
|
|
3057
3314
|
try {
|
|
3058
3315
|
const updateValue = {
|
|
@@ -3065,12 +3322,12 @@ function useAreaChecklistRepo() {
|
|
|
3065
3322
|
{ session }
|
|
3066
3323
|
);
|
|
3067
3324
|
if (res.modifiedCount === 0) {
|
|
3068
|
-
throw new
|
|
3325
|
+
throw new import_node_server_utils17.InternalServerError("Unable to update area checklist.");
|
|
3069
3326
|
}
|
|
3070
3327
|
delNamespace().then(() => {
|
|
3071
|
-
|
|
3328
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3072
3329
|
}).catch((err) => {
|
|
3073
|
-
|
|
3330
|
+
import_node_server_utils17.logger.error(
|
|
3074
3331
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3075
3332
|
err
|
|
3076
3333
|
);
|
|
@@ -3084,7 +3341,7 @@ function useAreaChecklistRepo() {
|
|
|
3084
3341
|
try {
|
|
3085
3342
|
_id = new import_mongodb9.ObjectId(_id);
|
|
3086
3343
|
} catch (error) {
|
|
3087
|
-
throw new
|
|
3344
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
3088
3345
|
}
|
|
3089
3346
|
try {
|
|
3090
3347
|
const updateValue = {
|
|
@@ -3100,14 +3357,14 @@ function useAreaChecklistRepo() {
|
|
|
3100
3357
|
{ session }
|
|
3101
3358
|
);
|
|
3102
3359
|
if (res.modifiedCount === 0) {
|
|
3103
|
-
throw new
|
|
3360
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
3104
3361
|
"Unable to update area checklist status."
|
|
3105
3362
|
);
|
|
3106
3363
|
}
|
|
3107
3364
|
delNamespace().then(() => {
|
|
3108
|
-
|
|
3365
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3109
3366
|
}).catch((err) => {
|
|
3110
|
-
|
|
3367
|
+
import_node_server_utils17.logger.error(
|
|
3111
3368
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3112
3369
|
err
|
|
3113
3370
|
);
|
|
@@ -3130,7 +3387,7 @@ function useAreaChecklistRepo() {
|
|
|
3130
3387
|
).toArray();
|
|
3131
3388
|
return result.length > 0 && result[0].maxSet ? result[0].maxSet : 0;
|
|
3132
3389
|
} catch (error) {
|
|
3133
|
-
|
|
3390
|
+
import_node_server_utils17.logger.error(`Error getting max set number for area ${areaId}:`, error);
|
|
3134
3391
|
return 0;
|
|
3135
3392
|
}
|
|
3136
3393
|
}
|
|
@@ -3146,7 +3403,7 @@ function useAreaChecklistRepo() {
|
|
|
3146
3403
|
getAreaChecklistByAreaAndSchedule,
|
|
3147
3404
|
updateAreaChecklist,
|
|
3148
3405
|
updateAreaChecklistStatus,
|
|
3149
|
-
|
|
3406
|
+
updateAreaChecklistUnits,
|
|
3150
3407
|
getMaxSetNumberForArea
|
|
3151
3408
|
};
|
|
3152
3409
|
}
|
|
@@ -3159,13 +3416,13 @@ function useAreaChecklistService() {
|
|
|
3159
3416
|
getAllAreaChecklist,
|
|
3160
3417
|
getAreaChecklistUnits,
|
|
3161
3418
|
getAreaChecklistById,
|
|
3162
|
-
|
|
3419
|
+
updateAreaChecklistUnits: _updateAreaChecklistUnits,
|
|
3163
3420
|
updateAreaChecklistStatus,
|
|
3164
3421
|
getMaxSetNumberForArea
|
|
3165
3422
|
} = useAreaChecklistRepo();
|
|
3166
3423
|
const { updateParentChecklistStatuses } = useParentChecklistRepo();
|
|
3167
3424
|
async function createAreaChecklist(value) {
|
|
3168
|
-
const session =
|
|
3425
|
+
const session = import_node_server_utils18.useAtlas.getClient()?.startSession();
|
|
3169
3426
|
try {
|
|
3170
3427
|
session?.startTransaction();
|
|
3171
3428
|
const results = [];
|
|
@@ -3178,7 +3435,7 @@ function useAreaChecklistService() {
|
|
|
3178
3435
|
const batch = areas.slice(i, i + BATCH_SIZE);
|
|
3179
3436
|
const batchPromises = batch.map(async (area) => {
|
|
3180
3437
|
if (!area.units || area.units.length === 0) {
|
|
3181
|
-
|
|
3438
|
+
import_node_server_utils18.logger.warn(
|
|
3182
3439
|
`Skipping area ${area.name} (${area._id}): No units defined`
|
|
3183
3440
|
);
|
|
3184
3441
|
return null;
|
|
@@ -3209,19 +3466,19 @@ function useAreaChecklistService() {
|
|
|
3209
3466
|
const batchResults = await Promise.all(batchPromises);
|
|
3210
3467
|
results.push(...batchResults.filter((id) => id !== null));
|
|
3211
3468
|
}
|
|
3212
|
-
|
|
3469
|
+
import_node_server_utils18.logger.info(
|
|
3213
3470
|
`Created ${totalChecklistsCreated} area checklists out of ${areas.length} areas for site: ${value.site}`
|
|
3214
3471
|
);
|
|
3215
3472
|
} else {
|
|
3216
|
-
|
|
3473
|
+
import_node_server_utils18.logger.warn(`No common areas found for site: ${value.site}`);
|
|
3217
3474
|
}
|
|
3218
3475
|
await session?.commitTransaction();
|
|
3219
|
-
|
|
3476
|
+
import_node_server_utils18.logger.info(
|
|
3220
3477
|
`Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
|
|
3221
3478
|
);
|
|
3222
3479
|
return results;
|
|
3223
3480
|
} catch (error) {
|
|
3224
|
-
|
|
3481
|
+
import_node_server_utils18.logger.error(`Error generating area checklists:`, error);
|
|
3225
3482
|
if (session?.inTransaction()) {
|
|
3226
3483
|
await session?.abortTransaction();
|
|
3227
3484
|
}
|
|
@@ -3230,11 +3487,11 @@ function useAreaChecklistService() {
|
|
|
3230
3487
|
session?.endSession();
|
|
3231
3488
|
}
|
|
3232
3489
|
}
|
|
3233
|
-
async function
|
|
3234
|
-
const session =
|
|
3490
|
+
async function updateAreaChecklistUnits(_id, set, unitId, value) {
|
|
3491
|
+
const session = import_node_server_utils18.useAtlas.getClient()?.startSession();
|
|
3235
3492
|
try {
|
|
3236
3493
|
session?.startTransaction();
|
|
3237
|
-
await
|
|
3494
|
+
await _updateAreaChecklistUnits(_id, set, unitId, value, session);
|
|
3238
3495
|
const allUnitsResult = await getAreaChecklistUnits(
|
|
3239
3496
|
{
|
|
3240
3497
|
page: 1,
|
|
@@ -3297,7 +3554,7 @@ function useAreaChecklistService() {
|
|
|
3297
3554
|
session
|
|
3298
3555
|
);
|
|
3299
3556
|
} else {
|
|
3300
|
-
|
|
3557
|
+
import_node_server_utils18.logger.info(
|
|
3301
3558
|
"No area checklists found, keeping parent status as ready"
|
|
3302
3559
|
);
|
|
3303
3560
|
}
|
|
@@ -3305,7 +3562,7 @@ function useAreaChecklistService() {
|
|
|
3305
3562
|
await session?.commitTransaction();
|
|
3306
3563
|
return;
|
|
3307
3564
|
} catch (error) {
|
|
3308
|
-
|
|
3565
|
+
import_node_server_utils18.logger.error(`Error updating area checklist unit and statuses:`, error);
|
|
3309
3566
|
if (session?.inTransaction()) {
|
|
3310
3567
|
await session?.abortTransaction();
|
|
3311
3568
|
}
|
|
@@ -3314,12 +3571,12 @@ function useAreaChecklistService() {
|
|
|
3314
3571
|
session?.endSession();
|
|
3315
3572
|
}
|
|
3316
3573
|
}
|
|
3317
|
-
return { createAreaChecklist,
|
|
3574
|
+
return { createAreaChecklist, updateAreaChecklistUnits };
|
|
3318
3575
|
}
|
|
3319
3576
|
|
|
3320
3577
|
// src/controllers/hygiene-area-checklist.controller.ts
|
|
3321
3578
|
var import_joi9 = __toESM(require("joi"));
|
|
3322
|
-
var
|
|
3579
|
+
var import_node_server_utils19 = require("@7365admin1/node-server-utils");
|
|
3323
3580
|
function useAreaChecklistController() {
|
|
3324
3581
|
const {
|
|
3325
3582
|
getAllAreaChecklist: _getAllAreaChecklist,
|
|
@@ -3329,7 +3586,7 @@ function useAreaChecklistController() {
|
|
|
3329
3586
|
} = useAreaChecklistRepo();
|
|
3330
3587
|
const {
|
|
3331
3588
|
createAreaChecklist: _createAreaChecklist,
|
|
3332
|
-
|
|
3589
|
+
updateAreaChecklistUnits: _updateAreaChecklistUnits
|
|
3333
3590
|
} = useAreaChecklistService();
|
|
3334
3591
|
async function createAreaChecklist(req, res, next) {
|
|
3335
3592
|
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
@@ -3349,8 +3606,8 @@ function useAreaChecklistController() {
|
|
|
3349
3606
|
});
|
|
3350
3607
|
const { error, value } = validation.validate(payload);
|
|
3351
3608
|
if (error) {
|
|
3352
|
-
|
|
3353
|
-
next(new
|
|
3609
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3610
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3354
3611
|
return;
|
|
3355
3612
|
}
|
|
3356
3613
|
try {
|
|
@@ -3358,7 +3615,7 @@ function useAreaChecklistController() {
|
|
|
3358
3615
|
res.status(201).json({ message: "Area checklist generated successfully." });
|
|
3359
3616
|
return;
|
|
3360
3617
|
} catch (error2) {
|
|
3361
|
-
|
|
3618
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3362
3619
|
next(error2);
|
|
3363
3620
|
return;
|
|
3364
3621
|
}
|
|
@@ -3375,8 +3632,8 @@ function useAreaChecklistController() {
|
|
|
3375
3632
|
});
|
|
3376
3633
|
const { error } = validation.validate(query);
|
|
3377
3634
|
if (error) {
|
|
3378
|
-
|
|
3379
|
-
next(new
|
|
3635
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3636
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3380
3637
|
return;
|
|
3381
3638
|
}
|
|
3382
3639
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3397,7 +3654,7 @@ function useAreaChecklistController() {
|
|
|
3397
3654
|
res.json(data);
|
|
3398
3655
|
return;
|
|
3399
3656
|
} catch (error2) {
|
|
3400
|
-
|
|
3657
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3401
3658
|
next(error2);
|
|
3402
3659
|
return;
|
|
3403
3660
|
}
|
|
@@ -3415,8 +3672,8 @@ function useAreaChecklistController() {
|
|
|
3415
3672
|
});
|
|
3416
3673
|
const { error } = validation.validate(query);
|
|
3417
3674
|
if (error) {
|
|
3418
|
-
|
|
3419
|
-
next(new
|
|
3675
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3676
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3420
3677
|
return;
|
|
3421
3678
|
}
|
|
3422
3679
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3439,7 +3696,7 @@ function useAreaChecklistController() {
|
|
|
3439
3696
|
res.json(data);
|
|
3440
3697
|
return;
|
|
3441
3698
|
} catch (error2) {
|
|
3442
|
-
|
|
3699
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3443
3700
|
next(error2);
|
|
3444
3701
|
return;
|
|
3445
3702
|
}
|
|
@@ -3449,8 +3706,8 @@ function useAreaChecklistController() {
|
|
|
3449
3706
|
const _id = req.params.id;
|
|
3450
3707
|
const { error, value } = validation.validate(_id);
|
|
3451
3708
|
if (error) {
|
|
3452
|
-
|
|
3453
|
-
next(new
|
|
3709
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3710
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3454
3711
|
return;
|
|
3455
3712
|
}
|
|
3456
3713
|
try {
|
|
@@ -3458,7 +3715,7 @@ function useAreaChecklistController() {
|
|
|
3458
3715
|
res.json(data);
|
|
3459
3716
|
return;
|
|
3460
3717
|
} catch (error2) {
|
|
3461
|
-
|
|
3718
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3462
3719
|
next(error2);
|
|
3463
3720
|
return;
|
|
3464
3721
|
}
|
|
@@ -3473,8 +3730,8 @@ function useAreaChecklistController() {
|
|
|
3473
3730
|
});
|
|
3474
3731
|
const { error } = validation.validate(query);
|
|
3475
3732
|
if (error) {
|
|
3476
|
-
|
|
3477
|
-
next(new
|
|
3733
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3734
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3478
3735
|
return;
|
|
3479
3736
|
}
|
|
3480
3737
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3491,47 +3748,55 @@ function useAreaChecklistController() {
|
|
|
3491
3748
|
res.json(data);
|
|
3492
3749
|
return;
|
|
3493
3750
|
} catch (error2) {
|
|
3494
|
-
|
|
3751
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3495
3752
|
next(error2);
|
|
3496
3753
|
return;
|
|
3497
3754
|
}
|
|
3498
3755
|
}
|
|
3499
|
-
async function
|
|
3756
|
+
async function updateAreaChecklistUnits(req, res, next) {
|
|
3500
3757
|
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3501
3758
|
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
3502
3759
|
{}
|
|
3503
3760
|
) : {};
|
|
3504
3761
|
const completedBy = cookies["user"] || "";
|
|
3762
|
+
const decisionMap = {
|
|
3763
|
+
approve: { approve: true, reject: false },
|
|
3764
|
+
reject: { approve: false, reject: true }
|
|
3765
|
+
};
|
|
3766
|
+
const decision = req.params.decision;
|
|
3767
|
+
const decisionValues = decisionMap[decision] || {
|
|
3768
|
+
approve: void 0,
|
|
3769
|
+
reject: void 0
|
|
3770
|
+
};
|
|
3505
3771
|
const payload = {
|
|
3506
3772
|
...req.params,
|
|
3507
3773
|
...req.body,
|
|
3774
|
+
...decisionValues,
|
|
3508
3775
|
completedBy
|
|
3509
3776
|
};
|
|
3510
3777
|
const validation = import_joi9.default.object({
|
|
3511
3778
|
id: import_joi9.default.string().hex().required(),
|
|
3512
3779
|
set: import_joi9.default.number().integer().min(1).required(),
|
|
3513
3780
|
unit: import_joi9.default.string().hex().required(),
|
|
3781
|
+
decision: import_joi9.default.string().valid("approve", "reject").required(),
|
|
3782
|
+
approve: import_joi9.default.boolean().optional(),
|
|
3783
|
+
reject: import_joi9.default.boolean().optional(),
|
|
3514
3784
|
remarks: import_joi9.default.string().optional().allow("", null),
|
|
3515
3785
|
completedBy: import_joi9.default.string().hex().required()
|
|
3516
3786
|
});
|
|
3517
3787
|
const { error } = validation.validate(payload);
|
|
3518
3788
|
if (error) {
|
|
3519
|
-
|
|
3520
|
-
next(new
|
|
3789
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3790
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3521
3791
|
return;
|
|
3522
3792
|
}
|
|
3523
3793
|
try {
|
|
3524
|
-
const { id, set, unit, ...value } = payload;
|
|
3525
|
-
await
|
|
3526
|
-
id,
|
|
3527
|
-
parseInt(set),
|
|
3528
|
-
unit,
|
|
3529
|
-
value
|
|
3530
|
-
);
|
|
3794
|
+
const { id, set, unit, decision: decision2, ...value } = payload;
|
|
3795
|
+
await _updateAreaChecklistUnits(id, parseInt(set), unit, value);
|
|
3531
3796
|
res.json({ message: "Area checklist updated successfully." });
|
|
3532
3797
|
return;
|
|
3533
3798
|
} catch (error2) {
|
|
3534
|
-
|
|
3799
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3535
3800
|
next(error2);
|
|
3536
3801
|
return;
|
|
3537
3802
|
}
|
|
@@ -3542,14 +3807,14 @@ function useAreaChecklistController() {
|
|
|
3542
3807
|
getAreaChecklistHistory,
|
|
3543
3808
|
getAreaChecklistHistoryDetails,
|
|
3544
3809
|
getAreaChecklistUnits,
|
|
3545
|
-
|
|
3810
|
+
updateAreaChecklistUnits
|
|
3546
3811
|
};
|
|
3547
3812
|
}
|
|
3548
3813
|
|
|
3549
3814
|
// src/models/hygiene-supply.model.ts
|
|
3550
3815
|
var import_joi10 = __toESM(require("joi"));
|
|
3551
3816
|
var import_mongodb10 = require("mongodb");
|
|
3552
|
-
var
|
|
3817
|
+
var import_node_server_utils20 = require("@7365admin1/node-server-utils");
|
|
3553
3818
|
var supplySchema = import_joi10.default.object({
|
|
3554
3819
|
site: import_joi10.default.string().hex().required(),
|
|
3555
3820
|
name: import_joi10.default.string().required(),
|
|
@@ -3558,14 +3823,14 @@ var supplySchema = import_joi10.default.object({
|
|
|
3558
3823
|
function MSupply(value) {
|
|
3559
3824
|
const { error } = supplySchema.validate(value);
|
|
3560
3825
|
if (error) {
|
|
3561
|
-
|
|
3562
|
-
throw new
|
|
3826
|
+
import_node_server_utils20.logger.info(`Hygiene Supply Model: ${error.message}`);
|
|
3827
|
+
throw new import_node_server_utils20.BadRequestError(error.message);
|
|
3563
3828
|
}
|
|
3564
3829
|
if (value.site) {
|
|
3565
3830
|
try {
|
|
3566
3831
|
value.site = new import_mongodb10.ObjectId(value.site);
|
|
3567
3832
|
} catch (error2) {
|
|
3568
|
-
throw new
|
|
3833
|
+
throw new import_node_server_utils20.BadRequestError("Invalid site ID format.");
|
|
3569
3834
|
}
|
|
3570
3835
|
}
|
|
3571
3836
|
return {
|
|
@@ -3582,20 +3847,20 @@ function MSupply(value) {
|
|
|
3582
3847
|
|
|
3583
3848
|
// src/repositories/hygiene-supply.repository.ts
|
|
3584
3849
|
var import_mongodb11 = require("mongodb");
|
|
3585
|
-
var
|
|
3850
|
+
var import_node_server_utils21 = require("@7365admin1/node-server-utils");
|
|
3586
3851
|
function useSupplyRepository() {
|
|
3587
|
-
const db =
|
|
3852
|
+
const db = import_node_server_utils21.useAtlas.getDb();
|
|
3588
3853
|
if (!db) {
|
|
3589
|
-
throw new
|
|
3854
|
+
throw new import_node_server_utils21.InternalServerError("Unable to connect to server.");
|
|
3590
3855
|
}
|
|
3591
3856
|
const namespace_collection = "site.supplies";
|
|
3592
3857
|
const collection = db.collection(namespace_collection);
|
|
3593
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
3858
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils21.useCache)(namespace_collection);
|
|
3594
3859
|
async function createIndex() {
|
|
3595
3860
|
try {
|
|
3596
3861
|
await collection.createIndexes([{ key: { site: 1 } }]);
|
|
3597
3862
|
} catch (error) {
|
|
3598
|
-
throw new
|
|
3863
|
+
throw new import_node_server_utils21.InternalServerError(
|
|
3599
3864
|
"Failed to create index on hygiene supply."
|
|
3600
3865
|
);
|
|
3601
3866
|
}
|
|
@@ -3604,7 +3869,7 @@ function useSupplyRepository() {
|
|
|
3604
3869
|
try {
|
|
3605
3870
|
await collection.createIndex({ name: "text" });
|
|
3606
3871
|
} catch (error) {
|
|
3607
|
-
throw new
|
|
3872
|
+
throw new import_node_server_utils21.InternalServerError(
|
|
3608
3873
|
"Failed to create text index on hygiene supply."
|
|
3609
3874
|
);
|
|
3610
3875
|
}
|
|
@@ -3616,7 +3881,7 @@ function useSupplyRepository() {
|
|
|
3616
3881
|
{ unique: true }
|
|
3617
3882
|
);
|
|
3618
3883
|
} catch (error) {
|
|
3619
|
-
throw new
|
|
3884
|
+
throw new import_node_server_utils21.InternalServerError(
|
|
3620
3885
|
"Failed to create unique index on hygiene supply."
|
|
3621
3886
|
);
|
|
3622
3887
|
}
|
|
@@ -3626,9 +3891,9 @@ function useSupplyRepository() {
|
|
|
3626
3891
|
value = MSupply(value);
|
|
3627
3892
|
const res = await collection.insertOne(value, { session });
|
|
3628
3893
|
delNamespace().then(() => {
|
|
3629
|
-
|
|
3894
|
+
import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3630
3895
|
}).catch((err) => {
|
|
3631
|
-
|
|
3896
|
+
import_node_server_utils21.logger.error(
|
|
3632
3897
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3633
3898
|
err
|
|
3634
3899
|
);
|
|
@@ -3637,7 +3902,7 @@ function useSupplyRepository() {
|
|
|
3637
3902
|
} catch (error) {
|
|
3638
3903
|
const isDuplicated = error.message.includes("duplicate");
|
|
3639
3904
|
if (isDuplicated) {
|
|
3640
|
-
throw new
|
|
3905
|
+
throw new import_node_server_utils21.BadRequestError("Supply already exists.");
|
|
3641
3906
|
}
|
|
3642
3907
|
throw error;
|
|
3643
3908
|
}
|
|
@@ -3661,16 +3926,16 @@ function useSupplyRepository() {
|
|
|
3661
3926
|
query.site = site;
|
|
3662
3927
|
cacheOptions.site = site.toString();
|
|
3663
3928
|
} catch (error) {
|
|
3664
|
-
throw new
|
|
3929
|
+
throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
|
|
3665
3930
|
}
|
|
3666
3931
|
if (search) {
|
|
3667
3932
|
query.$text = { $search: search };
|
|
3668
3933
|
cacheOptions.search = search;
|
|
3669
3934
|
}
|
|
3670
|
-
const cacheKey = (0,
|
|
3935
|
+
const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3671
3936
|
const cachedData = await getCache(cacheKey);
|
|
3672
3937
|
if (cachedData) {
|
|
3673
|
-
|
|
3938
|
+
import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3674
3939
|
return cachedData;
|
|
3675
3940
|
}
|
|
3676
3941
|
try {
|
|
@@ -3688,11 +3953,11 @@ function useSupplyRepository() {
|
|
|
3688
3953
|
{ $limit: limit }
|
|
3689
3954
|
]).toArray();
|
|
3690
3955
|
const length = await collection.countDocuments(query);
|
|
3691
|
-
const data = (0,
|
|
3956
|
+
const data = (0, import_node_server_utils21.paginate)(items, page, limit, length);
|
|
3692
3957
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3693
|
-
|
|
3958
|
+
import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3694
3959
|
}).catch((err) => {
|
|
3695
|
-
|
|
3960
|
+
import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3696
3961
|
});
|
|
3697
3962
|
return data;
|
|
3698
3963
|
} catch (error) {
|
|
@@ -3703,23 +3968,23 @@ function useSupplyRepository() {
|
|
|
3703
3968
|
try {
|
|
3704
3969
|
_id = new import_mongodb11.ObjectId(_id);
|
|
3705
3970
|
} catch (error) {
|
|
3706
|
-
throw new
|
|
3971
|
+
throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
|
|
3707
3972
|
}
|
|
3708
3973
|
const query = {
|
|
3709
3974
|
_id,
|
|
3710
3975
|
status: { $ne: "deleted" }
|
|
3711
3976
|
};
|
|
3712
|
-
const cacheKey = (0,
|
|
3977
|
+
const cacheKey = (0, import_node_server_utils21.makeCacheKey)(namespace_collection, {
|
|
3713
3978
|
_id: _id.toString()
|
|
3714
3979
|
});
|
|
3715
3980
|
if (!session) {
|
|
3716
3981
|
const cachedData = await getCache(cacheKey);
|
|
3717
3982
|
if (cachedData) {
|
|
3718
|
-
|
|
3983
|
+
import_node_server_utils21.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3719
3984
|
return cachedData;
|
|
3720
3985
|
}
|
|
3721
3986
|
} else {
|
|
3722
|
-
|
|
3987
|
+
import_node_server_utils21.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
3723
3988
|
}
|
|
3724
3989
|
try {
|
|
3725
3990
|
const data = await collection.aggregate([
|
|
@@ -3733,12 +3998,12 @@ function useSupplyRepository() {
|
|
|
3733
3998
|
}
|
|
3734
3999
|
]).toArray();
|
|
3735
4000
|
if (!data || data.length === 0) {
|
|
3736
|
-
throw new
|
|
4001
|
+
throw new import_node_server_utils21.NotFoundError("Supply not found.");
|
|
3737
4002
|
}
|
|
3738
4003
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
3739
|
-
|
|
4004
|
+
import_node_server_utils21.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3740
4005
|
}).catch((err) => {
|
|
3741
|
-
|
|
4006
|
+
import_node_server_utils21.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3742
4007
|
});
|
|
3743
4008
|
return data[0];
|
|
3744
4009
|
} catch (error) {
|
|
@@ -3749,7 +4014,7 @@ function useSupplyRepository() {
|
|
|
3749
4014
|
try {
|
|
3750
4015
|
_id = new import_mongodb11.ObjectId(_id);
|
|
3751
4016
|
} catch (error) {
|
|
3752
|
-
throw new
|
|
4017
|
+
throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
|
|
3753
4018
|
}
|
|
3754
4019
|
try {
|
|
3755
4020
|
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
@@ -3759,12 +4024,12 @@ function useSupplyRepository() {
|
|
|
3759
4024
|
{ session }
|
|
3760
4025
|
);
|
|
3761
4026
|
if (res.modifiedCount === 0) {
|
|
3762
|
-
throw new
|
|
4027
|
+
throw new import_node_server_utils21.InternalServerError("Unable to update cleaning supply.");
|
|
3763
4028
|
}
|
|
3764
4029
|
delNamespace().then(() => {
|
|
3765
|
-
|
|
4030
|
+
import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3766
4031
|
}).catch((err) => {
|
|
3767
|
-
|
|
4032
|
+
import_node_server_utils21.logger.error(
|
|
3768
4033
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3769
4034
|
err
|
|
3770
4035
|
);
|
|
@@ -3773,7 +4038,7 @@ function useSupplyRepository() {
|
|
|
3773
4038
|
} catch (error) {
|
|
3774
4039
|
const isDuplicated = error.message.includes("duplicate");
|
|
3775
4040
|
if (isDuplicated) {
|
|
3776
|
-
throw new
|
|
4041
|
+
throw new import_node_server_utils21.BadRequestError("Supply already exists.");
|
|
3777
4042
|
}
|
|
3778
4043
|
throw error;
|
|
3779
4044
|
}
|
|
@@ -3782,7 +4047,7 @@ function useSupplyRepository() {
|
|
|
3782
4047
|
try {
|
|
3783
4048
|
_id = new import_mongodb11.ObjectId(_id);
|
|
3784
4049
|
} catch (error) {
|
|
3785
|
-
throw new
|
|
4050
|
+
throw new import_node_server_utils21.BadRequestError("Invalid supply ID format.");
|
|
3786
4051
|
}
|
|
3787
4052
|
try {
|
|
3788
4053
|
const updateValue = {
|
|
@@ -3796,12 +4061,12 @@ function useSupplyRepository() {
|
|
|
3796
4061
|
{ session }
|
|
3797
4062
|
);
|
|
3798
4063
|
if (res.modifiedCount === 0) {
|
|
3799
|
-
throw new
|
|
4064
|
+
throw new import_node_server_utils21.InternalServerError("Unable to delete supply.");
|
|
3800
4065
|
}
|
|
3801
4066
|
delNamespace().then(() => {
|
|
3802
|
-
|
|
4067
|
+
import_node_server_utils21.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3803
4068
|
}).catch((err) => {
|
|
3804
|
-
|
|
4069
|
+
import_node_server_utils21.logger.error(
|
|
3805
4070
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3806
4071
|
err
|
|
3807
4072
|
);
|
|
@@ -3825,7 +4090,7 @@ function useSupplyRepository() {
|
|
|
3825
4090
|
|
|
3826
4091
|
// src/controllers/hygiene-supply.controller.ts
|
|
3827
4092
|
var import_joi11 = __toESM(require("joi"));
|
|
3828
|
-
var
|
|
4093
|
+
var import_node_server_utils22 = require("@7365admin1/node-server-utils");
|
|
3829
4094
|
function useSupplyController() {
|
|
3830
4095
|
const {
|
|
3831
4096
|
createSupply: _createSupply,
|
|
@@ -3838,8 +4103,8 @@ function useSupplyController() {
|
|
|
3838
4103
|
const payload = { ...req.body, ...req.params };
|
|
3839
4104
|
const { error } = supplySchema.validate(payload);
|
|
3840
4105
|
if (error) {
|
|
3841
|
-
|
|
3842
|
-
next(new
|
|
4106
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4107
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3843
4108
|
return;
|
|
3844
4109
|
}
|
|
3845
4110
|
try {
|
|
@@ -3847,7 +4112,7 @@ function useSupplyController() {
|
|
|
3847
4112
|
res.status(201).json({ message: "Supply created successfully.", id });
|
|
3848
4113
|
return;
|
|
3849
4114
|
} catch (error2) {
|
|
3850
|
-
|
|
4115
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3851
4116
|
next(error2);
|
|
3852
4117
|
return;
|
|
3853
4118
|
}
|
|
@@ -3862,8 +4127,8 @@ function useSupplyController() {
|
|
|
3862
4127
|
});
|
|
3863
4128
|
const { error } = validation.validate(query);
|
|
3864
4129
|
if (error) {
|
|
3865
|
-
|
|
3866
|
-
next(new
|
|
4130
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4131
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3867
4132
|
return;
|
|
3868
4133
|
}
|
|
3869
4134
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3880,7 +4145,7 @@ function useSupplyController() {
|
|
|
3880
4145
|
res.json(data);
|
|
3881
4146
|
return;
|
|
3882
4147
|
} catch (error2) {
|
|
3883
|
-
|
|
4148
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3884
4149
|
next(error2);
|
|
3885
4150
|
return;
|
|
3886
4151
|
}
|
|
@@ -3890,8 +4155,8 @@ function useSupplyController() {
|
|
|
3890
4155
|
const _id = req.params.id;
|
|
3891
4156
|
const { error, value } = validation.validate(_id);
|
|
3892
4157
|
if (error) {
|
|
3893
|
-
|
|
3894
|
-
next(new
|
|
4158
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4159
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3895
4160
|
return;
|
|
3896
4161
|
}
|
|
3897
4162
|
try {
|
|
@@ -3899,7 +4164,7 @@ function useSupplyController() {
|
|
|
3899
4164
|
res.json(data);
|
|
3900
4165
|
return;
|
|
3901
4166
|
} catch (error2) {
|
|
3902
|
-
|
|
4167
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3903
4168
|
next(error2);
|
|
3904
4169
|
return;
|
|
3905
4170
|
}
|
|
@@ -3914,8 +4179,8 @@ function useSupplyController() {
|
|
|
3914
4179
|
});
|
|
3915
4180
|
const { error } = validation.validate(payload);
|
|
3916
4181
|
if (error) {
|
|
3917
|
-
|
|
3918
|
-
next(new
|
|
4182
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4183
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3919
4184
|
return;
|
|
3920
4185
|
}
|
|
3921
4186
|
try {
|
|
@@ -3924,7 +4189,7 @@ function useSupplyController() {
|
|
|
3924
4189
|
res.json({ message: "Supply updated successfully." });
|
|
3925
4190
|
return;
|
|
3926
4191
|
} catch (error2) {
|
|
3927
|
-
|
|
4192
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3928
4193
|
next(error2);
|
|
3929
4194
|
return;
|
|
3930
4195
|
}
|
|
@@ -3936,8 +4201,8 @@ function useSupplyController() {
|
|
|
3936
4201
|
});
|
|
3937
4202
|
const { error, value } = validation.validate({ id });
|
|
3938
4203
|
if (error) {
|
|
3939
|
-
|
|
3940
|
-
next(new
|
|
4204
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
4205
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3941
4206
|
return;
|
|
3942
4207
|
}
|
|
3943
4208
|
try {
|
|
@@ -3945,7 +4210,7 @@ function useSupplyController() {
|
|
|
3945
4210
|
res.json({ message: "Supply deleted successfully." });
|
|
3946
4211
|
return;
|
|
3947
4212
|
} catch (error2) {
|
|
3948
|
-
|
|
4213
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3949
4214
|
next(error2);
|
|
3950
4215
|
return;
|
|
3951
4216
|
}
|
|
@@ -3962,7 +4227,7 @@ function useSupplyController() {
|
|
|
3962
4227
|
// src/models/hygiene-stock.model.ts
|
|
3963
4228
|
var import_joi12 = __toESM(require("joi"));
|
|
3964
4229
|
var import_mongodb12 = require("mongodb");
|
|
3965
|
-
var
|
|
4230
|
+
var import_node_server_utils23 = require("@7365admin1/node-server-utils");
|
|
3966
4231
|
var stockSchema = import_joi12.default.object({
|
|
3967
4232
|
site: import_joi12.default.string().hex().required(),
|
|
3968
4233
|
supply: import_joi12.default.string().hex().required(),
|
|
@@ -3974,21 +4239,21 @@ var stockSchema = import_joi12.default.object({
|
|
|
3974
4239
|
function MStock(value) {
|
|
3975
4240
|
const { error } = stockSchema.validate(value);
|
|
3976
4241
|
if (error) {
|
|
3977
|
-
|
|
3978
|
-
throw new
|
|
4242
|
+
import_node_server_utils23.logger.info(`Hygiene Stock Model: ${error.message}`);
|
|
4243
|
+
throw new import_node_server_utils23.BadRequestError(error.message);
|
|
3979
4244
|
}
|
|
3980
4245
|
if (value.site) {
|
|
3981
4246
|
try {
|
|
3982
4247
|
value.site = new import_mongodb12.ObjectId(value.site);
|
|
3983
4248
|
} catch (error2) {
|
|
3984
|
-
throw new
|
|
4249
|
+
throw new import_node_server_utils23.BadRequestError("Invalid site ID format.");
|
|
3985
4250
|
}
|
|
3986
4251
|
}
|
|
3987
4252
|
if (value.supply) {
|
|
3988
4253
|
try {
|
|
3989
4254
|
value.supply = new import_mongodb12.ObjectId(value.supply);
|
|
3990
4255
|
} catch (error2) {
|
|
3991
|
-
throw new
|
|
4256
|
+
throw new import_node_server_utils23.BadRequestError("Invalid supply ID format.");
|
|
3992
4257
|
}
|
|
3993
4258
|
}
|
|
3994
4259
|
return {
|
|
@@ -4007,17 +4272,17 @@ function MStock(value) {
|
|
|
4007
4272
|
|
|
4008
4273
|
// src/repositories/hygiene-stock.repository.ts
|
|
4009
4274
|
var import_mongodb13 = require("mongodb");
|
|
4010
|
-
var
|
|
4275
|
+
var import_node_server_utils24 = require("@7365admin1/node-server-utils");
|
|
4011
4276
|
function useStockRepository() {
|
|
4012
|
-
const db =
|
|
4277
|
+
const db = import_node_server_utils24.useAtlas.getDb();
|
|
4013
4278
|
if (!db) {
|
|
4014
|
-
throw new
|
|
4279
|
+
throw new import_node_server_utils24.InternalServerError("Unable to connect to server.");
|
|
4015
4280
|
}
|
|
4016
4281
|
const namespace_collection = "site.supply.stocks";
|
|
4017
4282
|
const supply_collection = "site.supplies";
|
|
4018
4283
|
const collection = db.collection(namespace_collection);
|
|
4019
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4020
|
-
const { delNamespace: delSupplyNamespace } = (0,
|
|
4284
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils24.useCache)(namespace_collection);
|
|
4285
|
+
const { delNamespace: delSupplyNamespace } = (0, import_node_server_utils24.useCache)(supply_collection);
|
|
4021
4286
|
async function createIndex() {
|
|
4022
4287
|
try {
|
|
4023
4288
|
await collection.createIndexes([
|
|
@@ -4027,7 +4292,7 @@ function useStockRepository() {
|
|
|
4027
4292
|
{ key: { status: 1 } }
|
|
4028
4293
|
]);
|
|
4029
4294
|
} catch (error) {
|
|
4030
|
-
throw new
|
|
4295
|
+
throw new import_node_server_utils24.InternalServerError("Failed to create index on hygiene stock.");
|
|
4031
4296
|
}
|
|
4032
4297
|
}
|
|
4033
4298
|
async function createStock(value, session) {
|
|
@@ -4035,17 +4300,17 @@ function useStockRepository() {
|
|
|
4035
4300
|
value = MStock(value);
|
|
4036
4301
|
const res = await collection.insertOne(value, { session });
|
|
4037
4302
|
delNamespace().then(() => {
|
|
4038
|
-
|
|
4303
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4039
4304
|
}).catch((err) => {
|
|
4040
|
-
|
|
4305
|
+
import_node_server_utils24.logger.error(
|
|
4041
4306
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4042
4307
|
err
|
|
4043
4308
|
);
|
|
4044
4309
|
});
|
|
4045
4310
|
delSupplyNamespace().then(() => {
|
|
4046
|
-
|
|
4311
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${supply_collection}`);
|
|
4047
4312
|
}).catch((err) => {
|
|
4048
|
-
|
|
4313
|
+
import_node_server_utils24.logger.error(
|
|
4049
4314
|
`Failed to clear cache for namespace: ${supply_collection}`,
|
|
4050
4315
|
err
|
|
4051
4316
|
);
|
|
@@ -4075,23 +4340,23 @@ function useStockRepository() {
|
|
|
4075
4340
|
query.site = site;
|
|
4076
4341
|
cacheOptions.site = site.toString();
|
|
4077
4342
|
} catch (error) {
|
|
4078
|
-
throw new
|
|
4343
|
+
throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
|
|
4079
4344
|
}
|
|
4080
4345
|
try {
|
|
4081
4346
|
supply = new import_mongodb13.ObjectId(supply);
|
|
4082
4347
|
query.supply = supply;
|
|
4083
4348
|
cacheOptions.supply = supply.toString();
|
|
4084
4349
|
} catch (error) {
|
|
4085
|
-
throw new
|
|
4350
|
+
throw new import_node_server_utils24.BadRequestError("Invalid supply ID format.");
|
|
4086
4351
|
}
|
|
4087
4352
|
if (search) {
|
|
4088
4353
|
query.$text = { $search: search };
|
|
4089
4354
|
cacheOptions.search = search;
|
|
4090
4355
|
}
|
|
4091
|
-
const cacheKey = (0,
|
|
4356
|
+
const cacheKey = (0, import_node_server_utils24.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4092
4357
|
const cachedData = await getCache(cacheKey);
|
|
4093
4358
|
if (cachedData) {
|
|
4094
|
-
|
|
4359
|
+
import_node_server_utils24.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4095
4360
|
return cachedData;
|
|
4096
4361
|
}
|
|
4097
4362
|
try {
|
|
@@ -4110,11 +4375,11 @@ function useStockRepository() {
|
|
|
4110
4375
|
{ $limit: limit }
|
|
4111
4376
|
]).toArray();
|
|
4112
4377
|
const length = await collection.countDocuments(query);
|
|
4113
|
-
const data = (0,
|
|
4378
|
+
const data = (0, import_node_server_utils24.paginate)(items, page, limit, length);
|
|
4114
4379
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4115
|
-
|
|
4380
|
+
import_node_server_utils24.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4116
4381
|
}).catch((err) => {
|
|
4117
|
-
|
|
4382
|
+
import_node_server_utils24.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4118
4383
|
});
|
|
4119
4384
|
return data;
|
|
4120
4385
|
} catch (error) {
|
|
@@ -4129,14 +4394,14 @@ function useStockRepository() {
|
|
|
4129
4394
|
}
|
|
4130
4395
|
|
|
4131
4396
|
// src/services/hygiene-stock.service.ts
|
|
4132
|
-
var
|
|
4397
|
+
var import_node_server_utils25 = require("@7365admin1/node-server-utils");
|
|
4133
4398
|
function useStockService() {
|
|
4134
4399
|
const { createStock: _createStock } = useStockRepository();
|
|
4135
4400
|
const { getSupplyById, updateSupply } = useSupplyRepository();
|
|
4136
4401
|
async function createStock(value, out = false, session) {
|
|
4137
4402
|
let ownSession = false;
|
|
4138
4403
|
if (!session) {
|
|
4139
|
-
session =
|
|
4404
|
+
session = import_node_server_utils25.useAtlas.getClient()?.startSession();
|
|
4140
4405
|
ownSession = true;
|
|
4141
4406
|
}
|
|
4142
4407
|
try {
|
|
@@ -4145,11 +4410,11 @@ function useStockService() {
|
|
|
4145
4410
|
const { qty, ...stockData } = value;
|
|
4146
4411
|
const supply = await getSupplyById(value.supply, session);
|
|
4147
4412
|
if (!supply || supply.qty === void 0) {
|
|
4148
|
-
throw new
|
|
4413
|
+
throw new import_node_server_utils25.NotFoundError("Supply not found.");
|
|
4149
4414
|
}
|
|
4150
4415
|
const newSupplyQty = out ? supply.qty - qty : supply.qty + qty;
|
|
4151
4416
|
if (out && newSupplyQty < 0) {
|
|
4152
|
-
throw new
|
|
4417
|
+
throw new import_node_server_utils25.BadRequestError(
|
|
4153
4418
|
`Insufficient stock. Available: ${supply.qty}, Requested: ${qty}`
|
|
4154
4419
|
);
|
|
4155
4420
|
}
|
|
@@ -4180,7 +4445,7 @@ function useStockService() {
|
|
|
4180
4445
|
|
|
4181
4446
|
// src/controllers/hygiene-stock.controller.ts
|
|
4182
4447
|
var import_joi13 = __toESM(require("joi"));
|
|
4183
|
-
var
|
|
4448
|
+
var import_node_server_utils26 = require("@7365admin1/node-server-utils");
|
|
4184
4449
|
function useStockController() {
|
|
4185
4450
|
const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
|
|
4186
4451
|
const { createStock: _createStock } = useStockService();
|
|
@@ -4194,8 +4459,8 @@ function useStockController() {
|
|
|
4194
4459
|
});
|
|
4195
4460
|
const { error } = validation.validate(payload);
|
|
4196
4461
|
if (error) {
|
|
4197
|
-
|
|
4198
|
-
next(new
|
|
4462
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4463
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4199
4464
|
return;
|
|
4200
4465
|
}
|
|
4201
4466
|
try {
|
|
@@ -4203,7 +4468,7 @@ function useStockController() {
|
|
|
4203
4468
|
res.status(201).json({ message: "Stock created successfully.", id });
|
|
4204
4469
|
return;
|
|
4205
4470
|
} catch (error2) {
|
|
4206
|
-
|
|
4471
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4207
4472
|
next(error2);
|
|
4208
4473
|
return;
|
|
4209
4474
|
}
|
|
@@ -4219,8 +4484,8 @@ function useStockController() {
|
|
|
4219
4484
|
});
|
|
4220
4485
|
const { error } = validation.validate(query);
|
|
4221
4486
|
if (error) {
|
|
4222
|
-
|
|
4223
|
-
next(new
|
|
4487
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4488
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4224
4489
|
return;
|
|
4225
4490
|
}
|
|
4226
4491
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4239,7 +4504,7 @@ function useStockController() {
|
|
|
4239
4504
|
res.json(data);
|
|
4240
4505
|
return;
|
|
4241
4506
|
} catch (error2) {
|
|
4242
|
-
|
|
4507
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4243
4508
|
next(error2);
|
|
4244
4509
|
return;
|
|
4245
4510
|
}
|
|
@@ -4253,7 +4518,7 @@ function useStockController() {
|
|
|
4253
4518
|
// src/models/hygiene-checkout-item.model.ts
|
|
4254
4519
|
var import_joi14 = __toESM(require("joi"));
|
|
4255
4520
|
var import_mongodb14 = require("mongodb");
|
|
4256
|
-
var
|
|
4521
|
+
var import_node_server_utils27 = require("@7365admin1/node-server-utils");
|
|
4257
4522
|
var allowedCheckOutItemStatus = ["pending", "completed"];
|
|
4258
4523
|
var checkOutItemSchema = import_joi14.default.object({
|
|
4259
4524
|
site: import_joi14.default.string().hex().required(),
|
|
@@ -4267,21 +4532,21 @@ var checkOutItemSchema = import_joi14.default.object({
|
|
|
4267
4532
|
function MCheckOutItem(value) {
|
|
4268
4533
|
const { error } = checkOutItemSchema.validate(value);
|
|
4269
4534
|
if (error) {
|
|
4270
|
-
|
|
4271
|
-
throw new
|
|
4535
|
+
import_node_server_utils27.logger.info(`Hygiene Check Out Item Model: ${error.message}`);
|
|
4536
|
+
throw new import_node_server_utils27.BadRequestError(error.message);
|
|
4272
4537
|
}
|
|
4273
4538
|
if (value.site) {
|
|
4274
4539
|
try {
|
|
4275
4540
|
value.site = new import_mongodb14.ObjectId(value.site);
|
|
4276
4541
|
} catch (error2) {
|
|
4277
|
-
throw new
|
|
4542
|
+
throw new import_node_server_utils27.BadRequestError("Invalid site ID format.");
|
|
4278
4543
|
}
|
|
4279
4544
|
}
|
|
4280
4545
|
if (value.supply) {
|
|
4281
4546
|
try {
|
|
4282
4547
|
value.supply = new import_mongodb14.ObjectId(value.supply);
|
|
4283
4548
|
} catch (error2) {
|
|
4284
|
-
throw new
|
|
4549
|
+
throw new import_node_server_utils27.BadRequestError("Invalid supply ID format.");
|
|
4285
4550
|
}
|
|
4286
4551
|
}
|
|
4287
4552
|
return {
|
|
@@ -4301,15 +4566,15 @@ function MCheckOutItem(value) {
|
|
|
4301
4566
|
|
|
4302
4567
|
// src/repositories/hygiene-checkout-item.repository.ts
|
|
4303
4568
|
var import_mongodb15 = require("mongodb");
|
|
4304
|
-
var
|
|
4569
|
+
var import_node_server_utils28 = require("@7365admin1/node-server-utils");
|
|
4305
4570
|
function useCheckOutItemRepository() {
|
|
4306
|
-
const db =
|
|
4571
|
+
const db = import_node_server_utils28.useAtlas.getDb();
|
|
4307
4572
|
if (!db) {
|
|
4308
|
-
throw new
|
|
4573
|
+
throw new import_node_server_utils28.InternalServerError("Unable to connect to server.");
|
|
4309
4574
|
}
|
|
4310
4575
|
const namespace_collection = "site.supply.checkouts";
|
|
4311
4576
|
const collection = db.collection(namespace_collection);
|
|
4312
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4577
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils28.useCache)(namespace_collection);
|
|
4313
4578
|
async function createIndex() {
|
|
4314
4579
|
try {
|
|
4315
4580
|
await collection.createIndexes([
|
|
@@ -4318,7 +4583,7 @@ function useCheckOutItemRepository() {
|
|
|
4318
4583
|
{ key: { status: 1 } }
|
|
4319
4584
|
]);
|
|
4320
4585
|
} catch (error) {
|
|
4321
|
-
throw new
|
|
4586
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4322
4587
|
"Failed to create index on hygiene check out item."
|
|
4323
4588
|
);
|
|
4324
4589
|
}
|
|
@@ -4327,7 +4592,7 @@ function useCheckOutItemRepository() {
|
|
|
4327
4592
|
try {
|
|
4328
4593
|
await collection.createIndex({ supplyName: "text" });
|
|
4329
4594
|
} catch (error) {
|
|
4330
|
-
throw new
|
|
4595
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4331
4596
|
"Failed to create text index on hygiene supply."
|
|
4332
4597
|
);
|
|
4333
4598
|
}
|
|
@@ -4337,9 +4602,9 @@ function useCheckOutItemRepository() {
|
|
|
4337
4602
|
value = MCheckOutItem(value);
|
|
4338
4603
|
const res = await collection.insertOne(value, { session });
|
|
4339
4604
|
delNamespace().then(() => {
|
|
4340
|
-
|
|
4605
|
+
import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4341
4606
|
}).catch((err) => {
|
|
4342
|
-
|
|
4607
|
+
import_node_server_utils28.logger.error(
|
|
4343
4608
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4344
4609
|
err
|
|
4345
4610
|
);
|
|
@@ -4368,16 +4633,16 @@ function useCheckOutItemRepository() {
|
|
|
4368
4633
|
query.site = site;
|
|
4369
4634
|
cacheOptions.site = site.toString();
|
|
4370
4635
|
} catch (error) {
|
|
4371
|
-
throw new
|
|
4636
|
+
throw new import_node_server_utils28.BadRequestError("Invalid site ID format.");
|
|
4372
4637
|
}
|
|
4373
4638
|
if (search) {
|
|
4374
4639
|
query.$text = { $search: search };
|
|
4375
4640
|
cacheOptions.search = search;
|
|
4376
4641
|
}
|
|
4377
|
-
const cacheKey = (0,
|
|
4642
|
+
const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4378
4643
|
const cachedData = await getCache(cacheKey);
|
|
4379
4644
|
if (cachedData) {
|
|
4380
|
-
|
|
4645
|
+
import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4381
4646
|
return cachedData;
|
|
4382
4647
|
}
|
|
4383
4648
|
try {
|
|
@@ -4424,11 +4689,11 @@ function useCheckOutItemRepository() {
|
|
|
4424
4689
|
{ $limit: limit }
|
|
4425
4690
|
]).toArray();
|
|
4426
4691
|
const length = await collection.countDocuments(query);
|
|
4427
|
-
const data = (0,
|
|
4692
|
+
const data = (0, import_node_server_utils28.paginate)(items, page, limit, length);
|
|
4428
4693
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4429
|
-
|
|
4694
|
+
import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4430
4695
|
}).catch((err) => {
|
|
4431
|
-
|
|
4696
|
+
import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4432
4697
|
});
|
|
4433
4698
|
return data;
|
|
4434
4699
|
} catch (error) {
|
|
@@ -4439,20 +4704,20 @@ function useCheckOutItemRepository() {
|
|
|
4439
4704
|
try {
|
|
4440
4705
|
_id = new import_mongodb15.ObjectId(_id);
|
|
4441
4706
|
} catch (error) {
|
|
4442
|
-
throw new
|
|
4707
|
+
throw new import_node_server_utils28.BadRequestError("Invalid check out item ID format.");
|
|
4443
4708
|
}
|
|
4444
4709
|
const query = { _id };
|
|
4445
|
-
const cacheKey = (0,
|
|
4710
|
+
const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, {
|
|
4446
4711
|
_id: _id.toString()
|
|
4447
4712
|
});
|
|
4448
4713
|
if (!session) {
|
|
4449
4714
|
const cachedData = await getCache(cacheKey);
|
|
4450
4715
|
if (cachedData) {
|
|
4451
|
-
|
|
4716
|
+
import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4452
4717
|
return cachedData;
|
|
4453
4718
|
}
|
|
4454
4719
|
} else {
|
|
4455
|
-
|
|
4720
|
+
import_node_server_utils28.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
4456
4721
|
}
|
|
4457
4722
|
try {
|
|
4458
4723
|
const data = await collection.aggregate(
|
|
@@ -4487,12 +4752,12 @@ function useCheckOutItemRepository() {
|
|
|
4487
4752
|
session ? { session } : void 0
|
|
4488
4753
|
).toArray();
|
|
4489
4754
|
if (!data || data.length === 0) {
|
|
4490
|
-
throw new
|
|
4755
|
+
throw new import_node_server_utils28.NotFoundError("Check out item not found.");
|
|
4491
4756
|
}
|
|
4492
4757
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
4493
|
-
|
|
4758
|
+
import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4494
4759
|
}).catch((err) => {
|
|
4495
|
-
|
|
4760
|
+
import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4496
4761
|
});
|
|
4497
4762
|
return data[0];
|
|
4498
4763
|
} catch (error) {
|
|
@@ -4503,7 +4768,7 @@ function useCheckOutItemRepository() {
|
|
|
4503
4768
|
try {
|
|
4504
4769
|
_id = new import_mongodb15.ObjectId(_id);
|
|
4505
4770
|
} catch (error) {
|
|
4506
|
-
throw new
|
|
4771
|
+
throw new import_node_server_utils28.BadRequestError("Invalid check out item ID format.");
|
|
4507
4772
|
}
|
|
4508
4773
|
try {
|
|
4509
4774
|
const updateValue = {
|
|
@@ -4516,12 +4781,12 @@ function useCheckOutItemRepository() {
|
|
|
4516
4781
|
{ session }
|
|
4517
4782
|
);
|
|
4518
4783
|
if (res.modifiedCount === 0) {
|
|
4519
|
-
throw new
|
|
4784
|
+
throw new import_node_server_utils28.InternalServerError("Unable to complete check out item.");
|
|
4520
4785
|
}
|
|
4521
4786
|
delNamespace().then(() => {
|
|
4522
|
-
|
|
4787
|
+
import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4523
4788
|
}).catch((err) => {
|
|
4524
|
-
|
|
4789
|
+
import_node_server_utils28.logger.error(
|
|
4525
4790
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4526
4791
|
err
|
|
4527
4792
|
);
|
|
@@ -4543,7 +4808,7 @@ function useCheckOutItemRepository() {
|
|
|
4543
4808
|
|
|
4544
4809
|
// src/services/hygiene-checkout-item.service.ts
|
|
4545
4810
|
var import_core = require("@7365admin1/core");
|
|
4546
|
-
var
|
|
4811
|
+
var import_node_server_utils29 = require("@7365admin1/node-server-utils");
|
|
4547
4812
|
function useCheckOutItemService() {
|
|
4548
4813
|
const {
|
|
4549
4814
|
createCheckOutItem: _createCheckOutItem,
|
|
@@ -4554,7 +4819,7 @@ function useCheckOutItemService() {
|
|
|
4554
4819
|
const { getUserById } = (0, import_core.useUserRepo)();
|
|
4555
4820
|
const { createStock } = useStockService();
|
|
4556
4821
|
async function createCheckOutItem(value) {
|
|
4557
|
-
const session =
|
|
4822
|
+
const session = import_node_server_utils29.useAtlas.getClient()?.startSession();
|
|
4558
4823
|
try {
|
|
4559
4824
|
session?.startTransaction();
|
|
4560
4825
|
const supplyData = await getSupplyById(value.supply);
|
|
@@ -4572,7 +4837,7 @@ function useCheckOutItemService() {
|
|
|
4572
4837
|
session
|
|
4573
4838
|
);
|
|
4574
4839
|
if (!checkOutItem) {
|
|
4575
|
-
throw new
|
|
4840
|
+
throw new import_node_server_utils29.BadRequestError("Failed to create check out item.");
|
|
4576
4841
|
}
|
|
4577
4842
|
const createdStocks = await createStock(
|
|
4578
4843
|
{
|
|
@@ -4594,7 +4859,7 @@ function useCheckOutItemService() {
|
|
|
4594
4859
|
}
|
|
4595
4860
|
}
|
|
4596
4861
|
async function createCheckOutItemByBatch(value) {
|
|
4597
|
-
const session =
|
|
4862
|
+
const session = import_node_server_utils29.useAtlas.getClient()?.startSession();
|
|
4598
4863
|
try {
|
|
4599
4864
|
session?.startTransaction();
|
|
4600
4865
|
const { site, attachment, createdBy, items } = value;
|
|
@@ -4642,7 +4907,7 @@ function useCheckOutItemService() {
|
|
|
4642
4907
|
|
|
4643
4908
|
// src/controllers/hygiene-checkout-item.controller.ts
|
|
4644
4909
|
var import_joi15 = __toESM(require("joi"));
|
|
4645
|
-
var
|
|
4910
|
+
var import_node_server_utils30 = require("@7365admin1/node-server-utils");
|
|
4646
4911
|
function useCheckOutItemController() {
|
|
4647
4912
|
const {
|
|
4648
4913
|
getCheckOutItems: _getCheckOutItems,
|
|
@@ -4672,8 +4937,8 @@ function useCheckOutItemController() {
|
|
|
4672
4937
|
});
|
|
4673
4938
|
const { error } = validation.validate(payload);
|
|
4674
4939
|
if (error) {
|
|
4675
|
-
|
|
4676
|
-
next(new
|
|
4940
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
4941
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4677
4942
|
return;
|
|
4678
4943
|
}
|
|
4679
4944
|
try {
|
|
@@ -4681,7 +4946,7 @@ function useCheckOutItemController() {
|
|
|
4681
4946
|
res.status(201).json({ message: "Check out item created successfully.", id });
|
|
4682
4947
|
return;
|
|
4683
4948
|
} catch (error2) {
|
|
4684
|
-
|
|
4949
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4685
4950
|
next(error2);
|
|
4686
4951
|
return;
|
|
4687
4952
|
}
|
|
@@ -4710,8 +4975,8 @@ function useCheckOutItemController() {
|
|
|
4710
4975
|
});
|
|
4711
4976
|
const { error } = validation.validate(payload);
|
|
4712
4977
|
if (error) {
|
|
4713
|
-
|
|
4714
|
-
next(new
|
|
4978
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
4979
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4715
4980
|
return;
|
|
4716
4981
|
}
|
|
4717
4982
|
try {
|
|
@@ -4719,7 +4984,7 @@ function useCheckOutItemController() {
|
|
|
4719
4984
|
res.status(201).json({ message: "Check out items created successfully." });
|
|
4720
4985
|
return;
|
|
4721
4986
|
} catch (error2) {
|
|
4722
|
-
|
|
4987
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4723
4988
|
next(error2);
|
|
4724
4989
|
return;
|
|
4725
4990
|
}
|
|
@@ -4734,8 +4999,8 @@ function useCheckOutItemController() {
|
|
|
4734
4999
|
});
|
|
4735
5000
|
const { error } = validation.validate(query);
|
|
4736
5001
|
if (error) {
|
|
4737
|
-
|
|
4738
|
-
next(new
|
|
5002
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
5003
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4739
5004
|
return;
|
|
4740
5005
|
}
|
|
4741
5006
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4752,7 +5017,7 @@ function useCheckOutItemController() {
|
|
|
4752
5017
|
res.json(data);
|
|
4753
5018
|
return;
|
|
4754
5019
|
} catch (error2) {
|
|
4755
|
-
|
|
5020
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4756
5021
|
next(error2);
|
|
4757
5022
|
return;
|
|
4758
5023
|
}
|
|
@@ -4762,8 +5027,8 @@ function useCheckOutItemController() {
|
|
|
4762
5027
|
const _id = req.params.id;
|
|
4763
5028
|
const { error, value } = validation.validate(_id);
|
|
4764
5029
|
if (error) {
|
|
4765
|
-
|
|
4766
|
-
next(new
|
|
5030
|
+
import_node_server_utils30.logger.log({ level: "error", message: error.message });
|
|
5031
|
+
next(new import_node_server_utils30.BadRequestError(error.message));
|
|
4767
5032
|
return;
|
|
4768
5033
|
}
|
|
4769
5034
|
try {
|
|
@@ -4771,7 +5036,7 @@ function useCheckOutItemController() {
|
|
|
4771
5036
|
res.json(data);
|
|
4772
5037
|
return;
|
|
4773
5038
|
} catch (error2) {
|
|
4774
|
-
|
|
5039
|
+
import_node_server_utils30.logger.log({ level: "error", message: error2.message });
|
|
4775
5040
|
next(error2);
|
|
4776
5041
|
return;
|
|
4777
5042
|
}
|
|
@@ -4785,7 +5050,7 @@ function useCheckOutItemController() {
|
|
|
4785
5050
|
}
|
|
4786
5051
|
|
|
4787
5052
|
// src/models/hygiene-schedule-task.model.ts
|
|
4788
|
-
var
|
|
5053
|
+
var import_node_server_utils31 = require("@7365admin1/node-server-utils");
|
|
4789
5054
|
var import_joi16 = __toESM(require("joi"));
|
|
4790
5055
|
var import_mongodb16 = require("mongodb");
|
|
4791
5056
|
var scheduleTaskSchema = import_joi16.default.object({
|
|
@@ -4806,14 +5071,14 @@ var scheduleTaskSchema = import_joi16.default.object({
|
|
|
4806
5071
|
function MScheduleTask(value) {
|
|
4807
5072
|
const { error } = scheduleTaskSchema.validate(value);
|
|
4808
5073
|
if (error) {
|
|
4809
|
-
|
|
4810
|
-
throw new
|
|
5074
|
+
import_node_server_utils31.logger.info(`Hygiene Schedule Task Model: ${error.message}`);
|
|
5075
|
+
throw new import_node_server_utils31.BadRequestError(error.message);
|
|
4811
5076
|
}
|
|
4812
5077
|
if (value.site) {
|
|
4813
5078
|
try {
|
|
4814
5079
|
value.site = new import_mongodb16.ObjectId(value.site);
|
|
4815
5080
|
} catch (error2) {
|
|
4816
|
-
throw new
|
|
5081
|
+
throw new import_node_server_utils31.BadRequestError("Invalid site ID format.");
|
|
4817
5082
|
}
|
|
4818
5083
|
}
|
|
4819
5084
|
if (value.areas && Array.isArray(value.areas)) {
|
|
@@ -4824,7 +5089,7 @@ function MScheduleTask(value) {
|
|
|
4824
5089
|
value: new import_mongodb16.ObjectId(area.value.toString())
|
|
4825
5090
|
};
|
|
4826
5091
|
} catch (error2) {
|
|
4827
|
-
throw new
|
|
5092
|
+
throw new import_node_server_utils31.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
4828
5093
|
}
|
|
4829
5094
|
});
|
|
4830
5095
|
}
|
|
@@ -4832,7 +5097,7 @@ function MScheduleTask(value) {
|
|
|
4832
5097
|
try {
|
|
4833
5098
|
value.createdBy = new import_mongodb16.ObjectId(value.createdBy);
|
|
4834
5099
|
} catch (error2) {
|
|
4835
|
-
throw new
|
|
5100
|
+
throw new import_node_server_utils31.BadRequestError("Invalid createdBy ID format.");
|
|
4836
5101
|
}
|
|
4837
5102
|
}
|
|
4838
5103
|
return {
|
|
@@ -4853,15 +5118,15 @@ function MScheduleTask(value) {
|
|
|
4853
5118
|
|
|
4854
5119
|
// src/repositories/hygiene-schedule-task.repository.ts
|
|
4855
5120
|
var import_mongodb17 = require("mongodb");
|
|
4856
|
-
var
|
|
5121
|
+
var import_node_server_utils32 = require("@7365admin1/node-server-utils");
|
|
4857
5122
|
function useScheduleTaskRepository() {
|
|
4858
|
-
const db =
|
|
5123
|
+
const db = import_node_server_utils32.useAtlas.getDb();
|
|
4859
5124
|
if (!db) {
|
|
4860
|
-
throw new
|
|
5125
|
+
throw new import_node_server_utils32.InternalServerError("Unable to connect to server.");
|
|
4861
5126
|
}
|
|
4862
5127
|
const namespace_collection = "site.schedule-tasks";
|
|
4863
5128
|
const collection = db.collection(namespace_collection);
|
|
4864
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
5129
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils32.useCache)(namespace_collection);
|
|
4865
5130
|
async function createIndex() {
|
|
4866
5131
|
try {
|
|
4867
5132
|
await collection.createIndexes([
|
|
@@ -4869,7 +5134,7 @@ function useScheduleTaskRepository() {
|
|
|
4869
5134
|
{ key: { status: 1 } }
|
|
4870
5135
|
]);
|
|
4871
5136
|
} catch (error) {
|
|
4872
|
-
throw new
|
|
5137
|
+
throw new import_node_server_utils32.InternalServerError(
|
|
4873
5138
|
"Failed to create index on hygiene schedule task."
|
|
4874
5139
|
);
|
|
4875
5140
|
}
|
|
@@ -4878,7 +5143,7 @@ function useScheduleTaskRepository() {
|
|
|
4878
5143
|
try {
|
|
4879
5144
|
await collection.createIndex({ title: "text", description: "text" });
|
|
4880
5145
|
} catch (error) {
|
|
4881
|
-
throw new
|
|
5146
|
+
throw new import_node_server_utils32.InternalServerError(
|
|
4882
5147
|
"Failed to create text index on hygiene schedule task."
|
|
4883
5148
|
);
|
|
4884
5149
|
}
|
|
@@ -4888,9 +5153,9 @@ function useScheduleTaskRepository() {
|
|
|
4888
5153
|
value = MScheduleTask(value);
|
|
4889
5154
|
const res = await collection.insertOne(value, { session });
|
|
4890
5155
|
delNamespace().then(() => {
|
|
4891
|
-
|
|
5156
|
+
import_node_server_utils32.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4892
5157
|
}).catch((err) => {
|
|
4893
|
-
|
|
5158
|
+
import_node_server_utils32.logger.error(
|
|
4894
5159
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4895
5160
|
err
|
|
4896
5161
|
);
|
|
@@ -4919,16 +5184,16 @@ function useScheduleTaskRepository() {
|
|
|
4919
5184
|
query.site = site;
|
|
4920
5185
|
cacheOptions.site = site.toString();
|
|
4921
5186
|
} catch (error) {
|
|
4922
|
-
throw new
|
|
5187
|
+
throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
|
|
4923
5188
|
}
|
|
4924
5189
|
if (search) {
|
|
4925
5190
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
4926
5191
|
cacheOptions.search = search;
|
|
4927
5192
|
}
|
|
4928
|
-
const cacheKey = (0,
|
|
5193
|
+
const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4929
5194
|
const cachedData = await getCache(cacheKey);
|
|
4930
5195
|
if (cachedData) {
|
|
4931
|
-
|
|
5196
|
+
import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4932
5197
|
return cachedData;
|
|
4933
5198
|
}
|
|
4934
5199
|
try {
|
|
@@ -4946,11 +5211,11 @@ function useScheduleTaskRepository() {
|
|
|
4946
5211
|
{ $limit: limit }
|
|
4947
5212
|
]).toArray();
|
|
4948
5213
|
const length = await collection.countDocuments(query);
|
|
4949
|
-
const data = (0,
|
|
5214
|
+
const data = (0, import_node_server_utils32.paginate)(items, page, limit, length);
|
|
4950
5215
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4951
|
-
|
|
5216
|
+
import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4952
5217
|
}).catch((err) => {
|
|
4953
|
-
|
|
5218
|
+
import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4954
5219
|
});
|
|
4955
5220
|
return data;
|
|
4956
5221
|
} catch (error) {
|
|
@@ -4987,16 +5252,16 @@ function useScheduleTaskRepository() {
|
|
|
4987
5252
|
query.site = site;
|
|
4988
5253
|
cacheOptions.site = site.toString();
|
|
4989
5254
|
} catch (error) {
|
|
4990
|
-
throw new
|
|
5255
|
+
throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
|
|
4991
5256
|
}
|
|
4992
5257
|
if (search) {
|
|
4993
5258
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
4994
5259
|
cacheOptions.search = search;
|
|
4995
5260
|
}
|
|
4996
|
-
const cacheKey = (0,
|
|
5261
|
+
const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4997
5262
|
const cachedData = await getCache(cacheKey);
|
|
4998
5263
|
if (cachedData) {
|
|
4999
|
-
|
|
5264
|
+
import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5000
5265
|
return cachedData;
|
|
5001
5266
|
}
|
|
5002
5267
|
try {
|
|
@@ -5013,11 +5278,11 @@ function useScheduleTaskRepository() {
|
|
|
5013
5278
|
{ $limit: limit }
|
|
5014
5279
|
]).toArray();
|
|
5015
5280
|
const length = await collection.countDocuments(query);
|
|
5016
|
-
const data = (0,
|
|
5281
|
+
const data = (0, import_node_server_utils32.paginate)(items, page, limit, length);
|
|
5017
5282
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
5018
|
-
|
|
5283
|
+
import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5019
5284
|
}).catch((err) => {
|
|
5020
|
-
|
|
5285
|
+
import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5021
5286
|
});
|
|
5022
5287
|
return data;
|
|
5023
5288
|
} catch (error) {
|
|
@@ -5028,23 +5293,23 @@ function useScheduleTaskRepository() {
|
|
|
5028
5293
|
try {
|
|
5029
5294
|
_id = new import_mongodb17.ObjectId(_id);
|
|
5030
5295
|
} catch (error) {
|
|
5031
|
-
throw new
|
|
5296
|
+
throw new import_node_server_utils32.BadRequestError("Invalid schedule task ID format.");
|
|
5032
5297
|
}
|
|
5033
5298
|
const query = {
|
|
5034
5299
|
_id,
|
|
5035
5300
|
status: { $ne: "deleted" }
|
|
5036
5301
|
};
|
|
5037
|
-
const cacheKey = (0,
|
|
5302
|
+
const cacheKey = (0, import_node_server_utils32.makeCacheKey)(namespace_collection, {
|
|
5038
5303
|
_id: _id.toString()
|
|
5039
5304
|
});
|
|
5040
5305
|
if (!session) {
|
|
5041
5306
|
const cachedData = await getCache(cacheKey);
|
|
5042
5307
|
if (cachedData) {
|
|
5043
|
-
|
|
5308
|
+
import_node_server_utils32.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5044
5309
|
return cachedData;
|
|
5045
5310
|
}
|
|
5046
5311
|
} else {
|
|
5047
|
-
|
|
5312
|
+
import_node_server_utils32.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
5048
5313
|
}
|
|
5049
5314
|
try {
|
|
5050
5315
|
const data = await collection.aggregate([
|
|
@@ -5063,12 +5328,12 @@ function useScheduleTaskRepository() {
|
|
|
5063
5328
|
}
|
|
5064
5329
|
]).toArray();
|
|
5065
5330
|
if (!data || data.length === 0) {
|
|
5066
|
-
throw new
|
|
5331
|
+
throw new import_node_server_utils32.NotFoundError("Schedule task not found.");
|
|
5067
5332
|
}
|
|
5068
5333
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
5069
|
-
|
|
5334
|
+
import_node_server_utils32.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5070
5335
|
}).catch((err) => {
|
|
5071
|
-
|
|
5336
|
+
import_node_server_utils32.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5072
5337
|
});
|
|
5073
5338
|
return data[0];
|
|
5074
5339
|
} catch (error) {
|
|
@@ -5079,7 +5344,7 @@ function useScheduleTaskRepository() {
|
|
|
5079
5344
|
try {
|
|
5080
5345
|
_id = new import_mongodb17.ObjectId(_id);
|
|
5081
5346
|
} catch (error) {
|
|
5082
|
-
throw new
|
|
5347
|
+
throw new import_node_server_utils32.BadRequestError("Invalid schedule task ID format.");
|
|
5083
5348
|
}
|
|
5084
5349
|
if (value.areas && Array.isArray(value.areas)) {
|
|
5085
5350
|
value.areas = value.areas.map((area) => {
|
|
@@ -5089,7 +5354,7 @@ function useScheduleTaskRepository() {
|
|
|
5089
5354
|
value: new import_mongodb17.ObjectId(area.value.toString())
|
|
5090
5355
|
};
|
|
5091
5356
|
} catch (error) {
|
|
5092
|
-
throw new
|
|
5357
|
+
throw new import_node_server_utils32.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
5093
5358
|
}
|
|
5094
5359
|
});
|
|
5095
5360
|
}
|
|
@@ -5101,14 +5366,14 @@ function useScheduleTaskRepository() {
|
|
|
5101
5366
|
{ session }
|
|
5102
5367
|
);
|
|
5103
5368
|
if (res.modifiedCount === 0) {
|
|
5104
|
-
throw new
|
|
5369
|
+
throw new import_node_server_utils32.InternalServerError(
|
|
5105
5370
|
"Unable to update hygiene schedule task."
|
|
5106
5371
|
);
|
|
5107
5372
|
}
|
|
5108
5373
|
delNamespace().then(() => {
|
|
5109
|
-
|
|
5374
|
+
import_node_server_utils32.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
5110
5375
|
}).catch((err) => {
|
|
5111
|
-
|
|
5376
|
+
import_node_server_utils32.logger.error(
|
|
5112
5377
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
5113
5378
|
err
|
|
5114
5379
|
);
|
|
@@ -5131,7 +5396,7 @@ function useScheduleTaskRepository() {
|
|
|
5131
5396
|
}
|
|
5132
5397
|
|
|
5133
5398
|
// src/services/hygiene-schedule-task.service.ts
|
|
5134
|
-
var
|
|
5399
|
+
var import_node_server_utils33 = require("@7365admin1/node-server-utils");
|
|
5135
5400
|
function useScheduleTaskService() {
|
|
5136
5401
|
const { createParentChecklist } = useParentChecklistRepo();
|
|
5137
5402
|
const { getAllScheduleTask } = useScheduleTaskRepository();
|
|
@@ -5154,13 +5419,13 @@ function useScheduleTaskService() {
|
|
|
5154
5419
|
const currentDateString = now.toLocaleDateString("en-US", {
|
|
5155
5420
|
timeZone: "Asia/Singapore"
|
|
5156
5421
|
});
|
|
5157
|
-
|
|
5422
|
+
import_node_server_utils33.logger.info(
|
|
5158
5423
|
`Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Current date ${currentDateString}, Schedule time ${schedule.time}, Start date ${schedule.startDate}, End date ${schedule.endDate}`
|
|
5159
5424
|
);
|
|
5160
5425
|
const startDate = /* @__PURE__ */ new Date(schedule.startDate + "T00:00:00");
|
|
5161
5426
|
const currentDateOnly = /* @__PURE__ */ new Date(currentDateString + "T00:00:00");
|
|
5162
5427
|
if (currentDateOnly < startDate) {
|
|
5163
|
-
|
|
5428
|
+
import_node_server_utils33.logger.info(
|
|
5164
5429
|
`Schedule ${schedule._id}: Current date ${currentDateString} is before start date ${schedule.startDate}`
|
|
5165
5430
|
);
|
|
5166
5431
|
return false;
|
|
@@ -5168,7 +5433,7 @@ function useScheduleTaskService() {
|
|
|
5168
5433
|
if (schedule.endDate) {
|
|
5169
5434
|
const endDate = /* @__PURE__ */ new Date(schedule.endDate + "T00:00:00");
|
|
5170
5435
|
if (currentDateOnly > endDate) {
|
|
5171
|
-
|
|
5436
|
+
import_node_server_utils33.logger.info(
|
|
5172
5437
|
`Schedule ${schedule._id}: Current date ${currentDateString} is after end date ${schedule.endDate}`
|
|
5173
5438
|
);
|
|
5174
5439
|
return false;
|
|
@@ -5177,17 +5442,17 @@ function useScheduleTaskService() {
|
|
|
5177
5442
|
const [scheduleHour, scheduleMinute] = schedule.time.split(":").map(Number);
|
|
5178
5443
|
const timeMatches = currentHour === scheduleHour && currentMinute === scheduleMinute;
|
|
5179
5444
|
if (!timeMatches) {
|
|
5180
|
-
|
|
5445
|
+
import_node_server_utils33.logger.info(
|
|
5181
5446
|
`Schedule ${schedule._id}: Time does not match. Current: ${currentHour}:${currentMinute}, Expected: ${scheduleHour}:${scheduleMinute}`
|
|
5182
5447
|
);
|
|
5183
5448
|
return false;
|
|
5184
5449
|
}
|
|
5185
|
-
|
|
5450
|
+
import_node_server_utils33.logger.info(
|
|
5186
5451
|
`Schedule ${schedule._id}: All conditions matched - Date is within range and time matches`
|
|
5187
5452
|
);
|
|
5188
5453
|
return true;
|
|
5189
5454
|
} catch (error) {
|
|
5190
|
-
|
|
5455
|
+
import_node_server_utils33.logger.error(
|
|
5191
5456
|
`Error checking schedule conditions for ${schedule._id}:`,
|
|
5192
5457
|
error
|
|
5193
5458
|
);
|
|
@@ -5196,40 +5461,40 @@ function useScheduleTaskService() {
|
|
|
5196
5461
|
}
|
|
5197
5462
|
async function processScheduledTasks(currentDate) {
|
|
5198
5463
|
try {
|
|
5199
|
-
|
|
5464
|
+
import_node_server_utils33.logger.info("Starting scheduled task processing...");
|
|
5200
5465
|
const scheduleTasks = await getAllScheduleTask();
|
|
5201
5466
|
if (!scheduleTasks || scheduleTasks.length === 0) {
|
|
5202
|
-
|
|
5467
|
+
import_node_server_utils33.logger.info("No schedule tasks found to process");
|
|
5203
5468
|
return { processed: 0, validated: 0 };
|
|
5204
5469
|
}
|
|
5205
|
-
|
|
5470
|
+
import_node_server_utils33.logger.info(`Found ${scheduleTasks.length} schedule tasks to check`);
|
|
5206
5471
|
let processedCount = 0;
|
|
5207
5472
|
let validatedCount = 0;
|
|
5208
5473
|
const validatedTasks = [];
|
|
5209
5474
|
for (const scheduleTask of scheduleTasks) {
|
|
5210
5475
|
try {
|
|
5211
|
-
|
|
5476
|
+
import_node_server_utils33.logger.info(
|
|
5212
5477
|
`Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, startDate=${scheduleTask.startDate}, endDate=${scheduleTask.endDate}`
|
|
5213
5478
|
);
|
|
5214
5479
|
const shouldRun = checkScheduleConditions(scheduleTask, currentDate);
|
|
5215
5480
|
if (!shouldRun) {
|
|
5216
|
-
|
|
5481
|
+
import_node_server_utils33.logger.info(
|
|
5217
5482
|
`Schedule ${scheduleTask._id} conditions not met, skipping`
|
|
5218
5483
|
);
|
|
5219
5484
|
continue;
|
|
5220
5485
|
}
|
|
5221
|
-
|
|
5486
|
+
import_node_server_utils33.logger.info(
|
|
5222
5487
|
`Schedule ${scheduleTask._id} conditions validated, creating area checklists`
|
|
5223
5488
|
);
|
|
5224
5489
|
if (!scheduleTask._id) {
|
|
5225
|
-
|
|
5490
|
+
import_node_server_utils33.logger.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
|
|
5226
5491
|
continue;
|
|
5227
5492
|
}
|
|
5228
5493
|
if (!scheduleTask.site) {
|
|
5229
|
-
|
|
5494
|
+
import_node_server_utils33.logger.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
|
|
5230
5495
|
continue;
|
|
5231
5496
|
}
|
|
5232
|
-
|
|
5497
|
+
import_node_server_utils33.logger.info(
|
|
5233
5498
|
`Getting or creating parent checklist for schedule ${scheduleTask._id} in site ${scheduleTask.site}`
|
|
5234
5499
|
);
|
|
5235
5500
|
const parentChecklistIds = await createParentChecklist({
|
|
@@ -5237,7 +5502,7 @@ function useScheduleTaskService() {
|
|
|
5237
5502
|
createdAt: /* @__PURE__ */ new Date()
|
|
5238
5503
|
});
|
|
5239
5504
|
const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
|
|
5240
|
-
|
|
5505
|
+
import_node_server_utils33.logger.info(
|
|
5241
5506
|
`Using parent checklist ${parentChecklistId}, now creating/updating area checklists`
|
|
5242
5507
|
);
|
|
5243
5508
|
for (const area of scheduleTask.areas) {
|
|
@@ -5250,14 +5515,14 @@ function useScheduleTaskService() {
|
|
|
5250
5515
|
unit: unit.unit.toString(),
|
|
5251
5516
|
name: unit.name
|
|
5252
5517
|
}));
|
|
5253
|
-
|
|
5518
|
+
import_node_server_utils33.logger.info(
|
|
5254
5519
|
`Area ${area.name} (${areaId}): Using units from area details: ${JSON.stringify(
|
|
5255
5520
|
units
|
|
5256
5521
|
)}`
|
|
5257
5522
|
);
|
|
5258
5523
|
}
|
|
5259
5524
|
if (units.length === 0) {
|
|
5260
|
-
|
|
5525
|
+
import_node_server_utils33.logger.warn(
|
|
5261
5526
|
`Area ${area.name} (${areaId}): No units found, skipping area.`
|
|
5262
5527
|
);
|
|
5263
5528
|
continue;
|
|
@@ -5268,11 +5533,11 @@ function useScheduleTaskService() {
|
|
|
5268
5533
|
parentChecklistId.toString(),
|
|
5269
5534
|
areaId
|
|
5270
5535
|
);
|
|
5271
|
-
|
|
5536
|
+
import_node_server_utils33.logger.info(
|
|
5272
5537
|
`Area ${area.name} (${areaId}): Existing area checklist found: ${existingAreaChecklist ? "Yes" : "No"}`
|
|
5273
5538
|
);
|
|
5274
5539
|
if (existingAreaChecklist) {
|
|
5275
|
-
|
|
5540
|
+
import_node_server_utils33.logger.info(
|
|
5276
5541
|
`Area ${area.name} (${areaId}): Existing checklist content: ${JSON.stringify(
|
|
5277
5542
|
existingAreaChecklist.checklist
|
|
5278
5543
|
)}`
|
|
@@ -5280,7 +5545,7 @@ function useScheduleTaskService() {
|
|
|
5280
5545
|
}
|
|
5281
5546
|
} catch (error) {
|
|
5282
5547
|
existingAreaChecklist = null;
|
|
5283
|
-
|
|
5548
|
+
import_node_server_utils33.logger.info(
|
|
5284
5549
|
`Area ${area.name} (${areaId}): No existing area checklist found (exception).`
|
|
5285
5550
|
);
|
|
5286
5551
|
}
|
|
@@ -5294,7 +5559,7 @@ function useScheduleTaskService() {
|
|
|
5294
5559
|
...existingAreaChecklist.checklist || [],
|
|
5295
5560
|
newSet
|
|
5296
5561
|
];
|
|
5297
|
-
|
|
5562
|
+
import_node_server_utils33.logger.info(
|
|
5298
5563
|
`Area ${area.name} (${areaId}): Appending new set ${newSet.set} to checklist. Updated checklist: ${JSON.stringify(
|
|
5299
5564
|
updatedChecklist
|
|
5300
5565
|
)}`
|
|
@@ -5302,7 +5567,7 @@ function useScheduleTaskService() {
|
|
|
5302
5567
|
await updateAreaChecklist(existingAreaChecklist._id, {
|
|
5303
5568
|
checklist: updatedChecklist
|
|
5304
5569
|
});
|
|
5305
|
-
|
|
5570
|
+
import_node_server_utils33.logger.info(
|
|
5306
5571
|
`Appended set ${newSet.set} to area checklist for area ${area.name}`
|
|
5307
5572
|
);
|
|
5308
5573
|
try {
|
|
@@ -5310,13 +5575,13 @@ function useScheduleTaskService() {
|
|
|
5310
5575
|
parentChecklistId.toString(),
|
|
5311
5576
|
areaId
|
|
5312
5577
|
);
|
|
5313
|
-
|
|
5578
|
+
import_node_server_utils33.logger.info(
|
|
5314
5579
|
`Area ${area.name} (${areaId}): Checklist after update: ${JSON.stringify(
|
|
5315
5580
|
verifyChecklist.checklist
|
|
5316
5581
|
)}`
|
|
5317
5582
|
);
|
|
5318
5583
|
} catch (verifyError) {
|
|
5319
|
-
|
|
5584
|
+
import_node_server_utils33.logger.warn(
|
|
5320
5585
|
`Area ${area.name} (${areaId}): Error verifying checklist after update:`,
|
|
5321
5586
|
verifyError
|
|
5322
5587
|
);
|
|
@@ -5335,50 +5600,50 @@ function useScheduleTaskService() {
|
|
|
5335
5600
|
],
|
|
5336
5601
|
createdBy: scheduleTask.createdBy
|
|
5337
5602
|
};
|
|
5338
|
-
|
|
5603
|
+
import_node_server_utils33.logger.info(
|
|
5339
5604
|
`Area ${area.name} (${areaId}): Creating new area checklist with data: ${JSON.stringify(
|
|
5340
5605
|
checklistData
|
|
5341
5606
|
)}`
|
|
5342
5607
|
);
|
|
5343
5608
|
await createAreaChecklist(checklistData);
|
|
5344
|
-
|
|
5609
|
+
import_node_server_utils33.logger.info(`Created new area checklist for area ${area.name}`);
|
|
5345
5610
|
try {
|
|
5346
5611
|
const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
|
|
5347
5612
|
parentChecklistId.toString(),
|
|
5348
5613
|
areaId
|
|
5349
5614
|
);
|
|
5350
|
-
|
|
5615
|
+
import_node_server_utils33.logger.info(
|
|
5351
5616
|
`Area ${area.name} (${areaId}): Checklist after creation: ${JSON.stringify(
|
|
5352
5617
|
verifyChecklist.checklist
|
|
5353
5618
|
)}`
|
|
5354
5619
|
);
|
|
5355
5620
|
} catch (verifyError) {
|
|
5356
|
-
|
|
5621
|
+
import_node_server_utils33.logger.warn(
|
|
5357
5622
|
`Area ${area.name} (${areaId}): Error verifying checklist after creation:`,
|
|
5358
5623
|
verifyError
|
|
5359
5624
|
);
|
|
5360
5625
|
}
|
|
5361
5626
|
}
|
|
5362
5627
|
} catch (error) {
|
|
5363
|
-
|
|
5628
|
+
import_node_server_utils33.logger.error(`Error processing area ${area.name}:`, error);
|
|
5364
5629
|
continue;
|
|
5365
5630
|
}
|
|
5366
5631
|
}
|
|
5367
5632
|
processedCount++;
|
|
5368
5633
|
validatedCount++;
|
|
5369
5634
|
validatedTasks.push(scheduleTask);
|
|
5370
|
-
|
|
5635
|
+
import_node_server_utils33.logger.info(
|
|
5371
5636
|
`Successfully processed schedule ${scheduleTask._id}, created/updated area checklists for all areas.`
|
|
5372
5637
|
);
|
|
5373
5638
|
} catch (error) {
|
|
5374
|
-
|
|
5639
|
+
import_node_server_utils33.logger.error(
|
|
5375
5640
|
`Error processing schedule task ${scheduleTask._id}:`,
|
|
5376
5641
|
error
|
|
5377
5642
|
);
|
|
5378
5643
|
continue;
|
|
5379
5644
|
}
|
|
5380
5645
|
}
|
|
5381
|
-
|
|
5646
|
+
import_node_server_utils33.logger.info(
|
|
5382
5647
|
`Scheduled task processing completed. Processed: ${processedCount}, Validated: ${validatedCount} tasks`
|
|
5383
5648
|
);
|
|
5384
5649
|
return {
|
|
@@ -5387,7 +5652,7 @@ function useScheduleTaskService() {
|
|
|
5387
5652
|
tasks: validatedTasks
|
|
5388
5653
|
};
|
|
5389
5654
|
} catch (error) {
|
|
5390
|
-
|
|
5655
|
+
import_node_server_utils33.logger.error("Error processing scheduled tasks:", error);
|
|
5391
5656
|
throw error;
|
|
5392
5657
|
}
|
|
5393
5658
|
}
|
|
@@ -5396,7 +5661,7 @@ function useScheduleTaskService() {
|
|
|
5396
5661
|
|
|
5397
5662
|
// src/controllers/hygiene-schedule-task.controller.ts
|
|
5398
5663
|
var import_joi17 = __toESM(require("joi"));
|
|
5399
|
-
var
|
|
5664
|
+
var import_node_server_utils34 = require("@7365admin1/node-server-utils");
|
|
5400
5665
|
function useScheduleTaskController() {
|
|
5401
5666
|
const {
|
|
5402
5667
|
createScheduleTask: _createScheduleTask,
|
|
@@ -5414,8 +5679,8 @@ function useScheduleTaskController() {
|
|
|
5414
5679
|
const payload = { ...req.body, ...req.params, createdBy };
|
|
5415
5680
|
const { error } = scheduleTaskSchema.validate(payload);
|
|
5416
5681
|
if (error) {
|
|
5417
|
-
|
|
5418
|
-
next(new
|
|
5682
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5683
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5419
5684
|
return;
|
|
5420
5685
|
}
|
|
5421
5686
|
try {
|
|
@@ -5423,7 +5688,7 @@ function useScheduleTaskController() {
|
|
|
5423
5688
|
res.status(201).json({ message: "Schedule task created successfully.", id });
|
|
5424
5689
|
return;
|
|
5425
5690
|
} catch (error2) {
|
|
5426
|
-
|
|
5691
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5427
5692
|
next(error2);
|
|
5428
5693
|
return;
|
|
5429
5694
|
}
|
|
@@ -5438,8 +5703,8 @@ function useScheduleTaskController() {
|
|
|
5438
5703
|
});
|
|
5439
5704
|
const { error } = validation.validate(query);
|
|
5440
5705
|
if (error) {
|
|
5441
|
-
|
|
5442
|
-
next(new
|
|
5706
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5707
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5443
5708
|
return;
|
|
5444
5709
|
}
|
|
5445
5710
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5456,7 +5721,7 @@ function useScheduleTaskController() {
|
|
|
5456
5721
|
res.json(data);
|
|
5457
5722
|
return;
|
|
5458
5723
|
} catch (error2) {
|
|
5459
|
-
|
|
5724
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5460
5725
|
next(error2);
|
|
5461
5726
|
return;
|
|
5462
5727
|
}
|
|
@@ -5471,8 +5736,8 @@ function useScheduleTaskController() {
|
|
|
5471
5736
|
});
|
|
5472
5737
|
const { error } = validation.validate(query);
|
|
5473
5738
|
if (error) {
|
|
5474
|
-
|
|
5475
|
-
next(new
|
|
5739
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5740
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5476
5741
|
return;
|
|
5477
5742
|
}
|
|
5478
5743
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5489,7 +5754,7 @@ function useScheduleTaskController() {
|
|
|
5489
5754
|
res.json(data);
|
|
5490
5755
|
return;
|
|
5491
5756
|
} catch (error2) {
|
|
5492
|
-
|
|
5757
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5493
5758
|
next(error2);
|
|
5494
5759
|
return;
|
|
5495
5760
|
}
|
|
@@ -5499,8 +5764,8 @@ function useScheduleTaskController() {
|
|
|
5499
5764
|
const _id = req.params.id;
|
|
5500
5765
|
const { error, value } = validation.validate(_id);
|
|
5501
5766
|
if (error) {
|
|
5502
|
-
|
|
5503
|
-
next(new
|
|
5767
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5768
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5504
5769
|
return;
|
|
5505
5770
|
}
|
|
5506
5771
|
try {
|
|
@@ -5508,7 +5773,7 @@ function useScheduleTaskController() {
|
|
|
5508
5773
|
res.json(data);
|
|
5509
5774
|
return;
|
|
5510
5775
|
} catch (error2) {
|
|
5511
|
-
|
|
5776
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5512
5777
|
next(error2);
|
|
5513
5778
|
return;
|
|
5514
5779
|
}
|
|
@@ -5531,8 +5796,8 @@ function useScheduleTaskController() {
|
|
|
5531
5796
|
});
|
|
5532
5797
|
const { error } = validation.validate(payload);
|
|
5533
5798
|
if (error) {
|
|
5534
|
-
|
|
5535
|
-
next(new
|
|
5799
|
+
import_node_server_utils34.logger.log({ level: "error", message: error.message });
|
|
5800
|
+
next(new import_node_server_utils34.BadRequestError(error.message));
|
|
5536
5801
|
return;
|
|
5537
5802
|
}
|
|
5538
5803
|
try {
|
|
@@ -5541,7 +5806,7 @@ function useScheduleTaskController() {
|
|
|
5541
5806
|
res.json({ message: "Schedule task updated successfully." });
|
|
5542
5807
|
return;
|
|
5543
5808
|
} catch (error2) {
|
|
5544
|
-
|
|
5809
|
+
import_node_server_utils34.logger.log({ level: "error", message: error2.message });
|
|
5545
5810
|
next(error2);
|
|
5546
5811
|
return;
|
|
5547
5812
|
}
|
|
@@ -5554,6 +5819,275 @@ function useScheduleTaskController() {
|
|
|
5554
5819
|
updateScheduleTask
|
|
5555
5820
|
};
|
|
5556
5821
|
}
|
|
5822
|
+
|
|
5823
|
+
// src/services/hygiene-qr.service.ts
|
|
5824
|
+
var import_node_server_utils35 = require("@7365admin1/node-server-utils");
|
|
5825
|
+
var import_puppeteer = require("puppeteer");
|
|
5826
|
+
var import_qrcode = __toESM(require("qrcode"));
|
|
5827
|
+
function useQRService() {
|
|
5828
|
+
async function generateQRDataUrl(qrUrl) {
|
|
5829
|
+
return import_qrcode.default.toDataURL(qrUrl, {
|
|
5830
|
+
width: 350,
|
|
5831
|
+
margin: 2,
|
|
5832
|
+
errorCorrectionLevel: "M",
|
|
5833
|
+
color: {
|
|
5834
|
+
dark: "#000000",
|
|
5835
|
+
light: "#FFFFFF"
|
|
5836
|
+
}
|
|
5837
|
+
});
|
|
5838
|
+
}
|
|
5839
|
+
async function generateQRImage(qrUrl) {
|
|
5840
|
+
try {
|
|
5841
|
+
const qrDataUrl = await generateQRDataUrl(qrUrl);
|
|
5842
|
+
const browser = await (0, import_puppeteer.launch)({
|
|
5843
|
+
headless: true,
|
|
5844
|
+
executablePath: process.env.CHROME_BINARY,
|
|
5845
|
+
args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
|
|
5846
|
+
});
|
|
5847
|
+
const page = await browser.newPage();
|
|
5848
|
+
await page.setViewport({
|
|
5849
|
+
width: 400,
|
|
5850
|
+
height: 400
|
|
5851
|
+
});
|
|
5852
|
+
const html = `
|
|
5853
|
+
<!DOCTYPE html>
|
|
5854
|
+
<html>
|
|
5855
|
+
<head>
|
|
5856
|
+
<meta charset="UTF-8">
|
|
5857
|
+
<style>
|
|
5858
|
+
body {
|
|
5859
|
+
margin: 0;
|
|
5860
|
+
padding: 20px;
|
|
5861
|
+
display: flex;
|
|
5862
|
+
justify-content: center;
|
|
5863
|
+
align-items: center;
|
|
5864
|
+
background: white;
|
|
5865
|
+
min-height: 100vh;
|
|
5866
|
+
}
|
|
5867
|
+
#qr-image {
|
|
5868
|
+
display: block;
|
|
5869
|
+
width: 350px;
|
|
5870
|
+
height: 350px;
|
|
5871
|
+
}
|
|
5872
|
+
</style>
|
|
5873
|
+
</head>
|
|
5874
|
+
<body>
|
|
5875
|
+
<img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
|
|
5876
|
+
</body>
|
|
5877
|
+
</html>
|
|
5878
|
+
`;
|
|
5879
|
+
await page.setContent(html, {
|
|
5880
|
+
waitUntil: ["load", "networkidle0"]
|
|
5881
|
+
});
|
|
5882
|
+
await page.waitForSelector("#qr-image", { timeout: 1e4 });
|
|
5883
|
+
const imageBuffer = await page.screenshot({
|
|
5884
|
+
type: "png",
|
|
5885
|
+
clip: {
|
|
5886
|
+
x: 0,
|
|
5887
|
+
y: 0,
|
|
5888
|
+
width: 400,
|
|
5889
|
+
height: 400
|
|
5890
|
+
}
|
|
5891
|
+
});
|
|
5892
|
+
await browser.close();
|
|
5893
|
+
return imageBuffer;
|
|
5894
|
+
} catch (error) {
|
|
5895
|
+
import_node_server_utils35.logger.log({
|
|
5896
|
+
level: "error",
|
|
5897
|
+
message: `Failed to generate QR image: ${error.message}`
|
|
5898
|
+
});
|
|
5899
|
+
throw error;
|
|
5900
|
+
}
|
|
5901
|
+
}
|
|
5902
|
+
async function generateQRPDF(qrUrl, title) {
|
|
5903
|
+
try {
|
|
5904
|
+
const qrDataUrl = await generateQRDataUrl(qrUrl);
|
|
5905
|
+
const browser = await (0, import_puppeteer.launch)({
|
|
5906
|
+
headless: true,
|
|
5907
|
+
executablePath: process.env.CHROME_BINARY,
|
|
5908
|
+
args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
|
|
5909
|
+
});
|
|
5910
|
+
const page = await browser.newPage();
|
|
5911
|
+
await page.setViewport({
|
|
5912
|
+
width: 800,
|
|
5913
|
+
height: 1100
|
|
5914
|
+
});
|
|
5915
|
+
const escapedTitle = (title || "Cleaning Schedule QR Code").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5916
|
+
const html = `
|
|
5917
|
+
<!DOCTYPE html>
|
|
5918
|
+
<html>
|
|
5919
|
+
<head>
|
|
5920
|
+
<meta charset="UTF-8">
|
|
5921
|
+
<style>
|
|
5922
|
+
* {
|
|
5923
|
+
margin: 0;
|
|
5924
|
+
padding: 0;
|
|
5925
|
+
box-sizing: border-box;
|
|
5926
|
+
}
|
|
5927
|
+
body {
|
|
5928
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
5929
|
+
background: white;
|
|
5930
|
+
padding: 60px 40px;
|
|
5931
|
+
display: flex;
|
|
5932
|
+
flex-direction: column;
|
|
5933
|
+
align-items: center;
|
|
5934
|
+
justify-content: center;
|
|
5935
|
+
min-height: 100vh;
|
|
5936
|
+
}
|
|
5937
|
+
.qr-container {
|
|
5938
|
+
text-align: center;
|
|
5939
|
+
background: transparent;
|
|
5940
|
+
padding: 0;
|
|
5941
|
+
}
|
|
5942
|
+
h1 {
|
|
5943
|
+
font-size: 28px;
|
|
5944
|
+
color: #333;
|
|
5945
|
+
margin-bottom: 20px;
|
|
5946
|
+
font-weight: 600;
|
|
5947
|
+
}
|
|
5948
|
+
.qr-wrapper {
|
|
5949
|
+
display: inline-block;
|
|
5950
|
+
padding: 0;
|
|
5951
|
+
background: transparent;
|
|
5952
|
+
border: none;
|
|
5953
|
+
border-radius: 0;
|
|
5954
|
+
margin: 20px 0;
|
|
5955
|
+
}
|
|
5956
|
+
#qr-image {
|
|
5957
|
+
display: block;
|
|
5958
|
+
width: 350px;
|
|
5959
|
+
height: 350px;
|
|
5960
|
+
}
|
|
5961
|
+
.instructions {
|
|
5962
|
+
margin-top: 30px;
|
|
5963
|
+
font-size: 16px;
|
|
5964
|
+
color: #666;
|
|
5965
|
+
line-height: 1.6;
|
|
5966
|
+
}
|
|
5967
|
+
.url-info {
|
|
5968
|
+
margin-top: 20px;
|
|
5969
|
+
padding: 15px;
|
|
5970
|
+
background: #f5f5f5;
|
|
5971
|
+
border-radius: 6px;
|
|
5972
|
+
font-size: 12px;
|
|
5973
|
+
color: #888;
|
|
5974
|
+
word-break: break-all;
|
|
5975
|
+
}
|
|
5976
|
+
</style>
|
|
5977
|
+
</head>
|
|
5978
|
+
<body>
|
|
5979
|
+
<div class="qr-container">
|
|
5980
|
+
<h1>${escapedTitle}</h1>
|
|
5981
|
+
<div class="qr-wrapper">
|
|
5982
|
+
<img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
|
|
5983
|
+
</div>
|
|
5984
|
+
<div class="instructions">
|
|
5985
|
+
<p>Scan this QR code to access the cleaning schedule.</p>
|
|
5986
|
+
</div>
|
|
5987
|
+
<div class="url-info">
|
|
5988
|
+
${qrUrl}
|
|
5989
|
+
</div>
|
|
5990
|
+
</div>
|
|
5991
|
+
</body>
|
|
5992
|
+
</html>
|
|
5993
|
+
`;
|
|
5994
|
+
await page.setContent(html, {
|
|
5995
|
+
waitUntil: ["load", "networkidle0"]
|
|
5996
|
+
});
|
|
5997
|
+
await page.waitForSelector("#qr-image", { timeout: 1e4 });
|
|
5998
|
+
await page.waitForFunction(
|
|
5999
|
+
() => {
|
|
6000
|
+
const img = document.getElementById("qr-image");
|
|
6001
|
+
return img && img.complete && img.naturalWidth > 0;
|
|
6002
|
+
},
|
|
6003
|
+
{ timeout: 1e4 }
|
|
6004
|
+
);
|
|
6005
|
+
const pdfBuffer = await page.pdf({
|
|
6006
|
+
format: "A4",
|
|
6007
|
+
printBackground: true,
|
|
6008
|
+
margin: {
|
|
6009
|
+
top: "20mm",
|
|
6010
|
+
right: "20mm",
|
|
6011
|
+
bottom: "20mm",
|
|
6012
|
+
left: "20mm"
|
|
6013
|
+
}
|
|
6014
|
+
});
|
|
6015
|
+
await browser.close();
|
|
6016
|
+
return pdfBuffer;
|
|
6017
|
+
} catch (error) {
|
|
6018
|
+
import_node_server_utils35.logger.log({
|
|
6019
|
+
level: "error",
|
|
6020
|
+
message: `Failed to generate QR PDF: ${error.message}`
|
|
6021
|
+
});
|
|
6022
|
+
throw error;
|
|
6023
|
+
}
|
|
6024
|
+
}
|
|
6025
|
+
return {
|
|
6026
|
+
generateQRImage,
|
|
6027
|
+
generateQRPDF
|
|
6028
|
+
};
|
|
6029
|
+
}
|
|
6030
|
+
|
|
6031
|
+
// src/controllers/hygiene-qr.controller.ts
|
|
6032
|
+
var import_joi18 = __toESM(require("joi"));
|
|
6033
|
+
var import_node_server_utils36 = require("@7365admin1/node-server-utils");
|
|
6034
|
+
function useQRController() {
|
|
6035
|
+
const { generateQRImage: _generateQRImage, generateQRPDF: _generateQRPDF } = useQRService();
|
|
6036
|
+
async function generateQR(req, res, next) {
|
|
6037
|
+
const validation = import_joi18.default.object({
|
|
6038
|
+
url: import_joi18.default.string().uri().required(),
|
|
6039
|
+
filename: import_joi18.default.string().optional().allow("", null),
|
|
6040
|
+
title: import_joi18.default.string().optional().allow("", null),
|
|
6041
|
+
download: import_joi18.default.boolean().optional().default(false)
|
|
6042
|
+
});
|
|
6043
|
+
const query = { ...req.query };
|
|
6044
|
+
const { error, value } = validation.validate(query);
|
|
6045
|
+
if (error) {
|
|
6046
|
+
import_node_server_utils36.logger.log({ level: "error", message: error.message });
|
|
6047
|
+
next(new import_node_server_utils36.BadRequestError(error.message));
|
|
6048
|
+
return;
|
|
6049
|
+
}
|
|
6050
|
+
try {
|
|
6051
|
+
const { url, filename, title, download } = value;
|
|
6052
|
+
if (download) {
|
|
6053
|
+
const pdfBuffer = await _generateQRPDF(url, title);
|
|
6054
|
+
if (!pdfBuffer || pdfBuffer.length === 0) {
|
|
6055
|
+
throw new Error("Generated QR PDF is empty or invalid.");
|
|
6056
|
+
}
|
|
6057
|
+
const sanitizedFilename = (filename || "qrcode").replace(/['"]/g, "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6058
|
+
const date = /* @__PURE__ */ new Date();
|
|
6059
|
+
const formattedDate = `${String(date.getMonth() + 1).padStart(
|
|
6060
|
+
2,
|
|
6061
|
+
"0"
|
|
6062
|
+
)}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;
|
|
6063
|
+
res.setHeader("Content-Type", "application/pdf");
|
|
6064
|
+
res.setHeader(
|
|
6065
|
+
"Content-Disposition",
|
|
6066
|
+
`attachment; filename="${sanitizedFilename}-${formattedDate}.pdf"`
|
|
6067
|
+
);
|
|
6068
|
+
res.setHeader("Content-Length", pdfBuffer.length);
|
|
6069
|
+
res.end(pdfBuffer);
|
|
6070
|
+
} else {
|
|
6071
|
+
const imageBuffer = await _generateQRImage(url);
|
|
6072
|
+
if (!imageBuffer || imageBuffer.length === 0) {
|
|
6073
|
+
throw new Error("Generated QR image is empty or invalid.");
|
|
6074
|
+
}
|
|
6075
|
+
res.setHeader("Content-Type", "image/png");
|
|
6076
|
+
res.setHeader("Cache-Control", "public, max-age=3600");
|
|
6077
|
+
res.setHeader("Content-Length", imageBuffer.length);
|
|
6078
|
+
res.end(imageBuffer);
|
|
6079
|
+
}
|
|
6080
|
+
return;
|
|
6081
|
+
} catch (error2) {
|
|
6082
|
+
import_node_server_utils36.logger.log({ level: "error", message: error2.message });
|
|
6083
|
+
next(error2);
|
|
6084
|
+
return;
|
|
6085
|
+
}
|
|
6086
|
+
}
|
|
6087
|
+
return {
|
|
6088
|
+
generateQR
|
|
6089
|
+
};
|
|
6090
|
+
}
|
|
5557
6091
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5558
6092
|
0 && (module.exports = {
|
|
5559
6093
|
MArea,
|
|
@@ -5581,6 +6115,7 @@ function useScheduleTaskController() {
|
|
|
5581
6115
|
useAreaChecklistRepo,
|
|
5582
6116
|
useAreaChecklistService,
|
|
5583
6117
|
useAreaController,
|
|
6118
|
+
useAreaExportService,
|
|
5584
6119
|
useAreaRepo,
|
|
5585
6120
|
useAreaService,
|
|
5586
6121
|
useCheckOutItemController,
|
|
@@ -5590,6 +6125,8 @@ function useScheduleTaskController() {
|
|
|
5590
6125
|
useHygieneDashboardRepository,
|
|
5591
6126
|
useParentChecklistController,
|
|
5592
6127
|
useParentChecklistRepo,
|
|
6128
|
+
useQRController,
|
|
6129
|
+
useQRService,
|
|
5593
6130
|
useScheduleTaskController,
|
|
5594
6131
|
useScheduleTaskRepository,
|
|
5595
6132
|
useScheduleTaskService,
|
|
@@ -5599,6 +6136,7 @@ function useScheduleTaskController() {
|
|
|
5599
6136
|
useSupplyController,
|
|
5600
6137
|
useSupplyRepository,
|
|
5601
6138
|
useUnitController,
|
|
6139
|
+
useUnitExportService,
|
|
5602
6140
|
useUnitRepository,
|
|
5603
6141
|
useUnitService
|
|
5604
6142
|
});
|