@7365admin1/core 2.9.0 → 2.11.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/.github/workflows/main.yml +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +71 -2
- package/dist/index.js +1521 -641
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +969 -84
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/public/rsa-keys/new_rsa_512_priv.pem +0 -3
- package/dist/public/rsa-keys/new_rsa_512_pub.pem +0 -3
package/dist/index.mjs
CHANGED
|
@@ -372,7 +372,8 @@ function useFeedbackRepo() {
|
|
|
372
372
|
query.$or = [
|
|
373
373
|
{ subject: { $regex: search, $options: "i" } },
|
|
374
374
|
{ description: { $regex: search, $options: "i" } },
|
|
375
|
-
{ createdByName: { $regex: search, $options: "i" } }
|
|
375
|
+
{ createdByName: { $regex: search, $options: "i" } },
|
|
376
|
+
{ category: { $regex: search, $options: "i" } }
|
|
376
377
|
];
|
|
377
378
|
cacheOptions.search = search;
|
|
378
379
|
}
|
|
@@ -933,6 +934,7 @@ function useWorkOrderRepo() {
|
|
|
933
934
|
}
|
|
934
935
|
}
|
|
935
936
|
const { delNamespace, setCache, getCache, delCache } = useCache3(namespace_collection);
|
|
937
|
+
const { delNamespace: _delDashboardNameSpace } = useCache3("dashboard");
|
|
936
938
|
async function createWorkOrder(value, session) {
|
|
937
939
|
try {
|
|
938
940
|
value = MWorkOrder(value);
|
|
@@ -945,6 +947,11 @@ function useWorkOrderRepo() {
|
|
|
945
947
|
err
|
|
946
948
|
);
|
|
947
949
|
});
|
|
950
|
+
_delDashboardNameSpace().then(() => {
|
|
951
|
+
logger5.info(`Cache cleared for namespace: dashboard`);
|
|
952
|
+
}).catch((err) => {
|
|
953
|
+
logger5.error(`Failed to clear cache for namespace: dashboard`, err);
|
|
954
|
+
});
|
|
948
955
|
return res.insertedId;
|
|
949
956
|
} catch (error) {
|
|
950
957
|
throw error;
|
|
@@ -993,7 +1000,9 @@ function useWorkOrderRepo() {
|
|
|
993
1000
|
if (search) {
|
|
994
1001
|
query.$or = [
|
|
995
1002
|
{ subject: { $regex: search, $options: "i" } },
|
|
996
|
-
{ createdByName: { $regex: search, $options: "i" } }
|
|
1003
|
+
{ createdByName: { $regex: search, $options: "i" } },
|
|
1004
|
+
{ description: { $regex: search, $options: "i" } },
|
|
1005
|
+
{ category: { $regex: search, $options: "i" } }
|
|
997
1006
|
];
|
|
998
1007
|
cacheOptions.search = search;
|
|
999
1008
|
}
|
|
@@ -1179,11 +1188,18 @@ function useWorkOrderRepo() {
|
|
|
1179
1188
|
if (res.modifiedCount === 0) {
|
|
1180
1189
|
throw new InternalServerError3("Unable to update work order.");
|
|
1181
1190
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1191
|
+
delNamespace().then(() => {
|
|
1192
|
+
logger5.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1193
|
+
}).catch((err) => {
|
|
1194
|
+
logger5.error(
|
|
1195
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1196
|
+
err
|
|
1197
|
+
);
|
|
1198
|
+
});
|
|
1199
|
+
_delDashboardNameSpace().then(() => {
|
|
1200
|
+
logger5.info(`Cache cleared for namespace: dashboard`);
|
|
1185
1201
|
}).catch((err) => {
|
|
1186
|
-
logger5.error(`Failed to
|
|
1202
|
+
logger5.error(`Failed to clear cache for namespace: dashboard`, err);
|
|
1187
1203
|
});
|
|
1188
1204
|
return res.modifiedCount;
|
|
1189
1205
|
} catch (error) {
|
|
@@ -1206,11 +1222,18 @@ function useWorkOrderRepo() {
|
|
|
1206
1222
|
if (res.modifiedCount === 0) {
|
|
1207
1223
|
throw new InternalServerError3("Unable to update work order status.");
|
|
1208
1224
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1225
|
+
delNamespace().then(() => {
|
|
1226
|
+
logger5.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1227
|
+
}).catch((err) => {
|
|
1228
|
+
logger5.error(
|
|
1229
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1230
|
+
err
|
|
1231
|
+
);
|
|
1232
|
+
});
|
|
1233
|
+
_delDashboardNameSpace().then(() => {
|
|
1234
|
+
logger5.info(`Cache cleared for namespace: dashboard`);
|
|
1212
1235
|
}).catch((err) => {
|
|
1213
|
-
logger5.error(`Failed to
|
|
1236
|
+
logger5.error(`Failed to clear cache for namespace: dashboard`, err);
|
|
1214
1237
|
});
|
|
1215
1238
|
return res.modifiedCount;
|
|
1216
1239
|
} catch (error) {
|
|
@@ -1228,11 +1251,18 @@ function useWorkOrderRepo() {
|
|
|
1228
1251
|
{ $set: updateValue },
|
|
1229
1252
|
session
|
|
1230
1253
|
);
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
logger5.info(`Cache deleted for key: ${cacheKey}`);
|
|
1254
|
+
delNamespace().then(() => {
|
|
1255
|
+
logger5.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1234
1256
|
}).catch((err) => {
|
|
1235
|
-
logger5.error(
|
|
1257
|
+
logger5.error(
|
|
1258
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1259
|
+
err
|
|
1260
|
+
);
|
|
1261
|
+
});
|
|
1262
|
+
_delDashboardNameSpace().then(() => {
|
|
1263
|
+
logger5.info(`Cache cleared for namespace: dashboard`);
|
|
1264
|
+
}).catch((err) => {
|
|
1265
|
+
logger5.error(`Failed to clear cache for namespace: dashboard`, err);
|
|
1236
1266
|
});
|
|
1237
1267
|
return res.modifiedCount;
|
|
1238
1268
|
} catch (error) {
|
|
@@ -1262,11 +1292,18 @@ function useWorkOrderRepo() {
|
|
|
1262
1292
|
"Unable to mark work order as completed."
|
|
1263
1293
|
);
|
|
1264
1294
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1295
|
+
delNamespace().then(() => {
|
|
1296
|
+
logger5.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1297
|
+
}).catch((err) => {
|
|
1298
|
+
logger5.error(
|
|
1299
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1300
|
+
err
|
|
1301
|
+
);
|
|
1302
|
+
});
|
|
1303
|
+
_delDashboardNameSpace().then(() => {
|
|
1304
|
+
logger5.info(`Cache cleared for namespace: dashboard`);
|
|
1268
1305
|
}).catch((err) => {
|
|
1269
|
-
logger5.error(`Failed to
|
|
1306
|
+
logger5.error(`Failed to clear cache for namespace: dashboard`, err);
|
|
1270
1307
|
});
|
|
1271
1308
|
return res.modifiedCount;
|
|
1272
1309
|
} catch (error) {
|
|
@@ -1293,11 +1330,18 @@ function useWorkOrderRepo() {
|
|
|
1293
1330
|
if (res.modifiedCount === 0) {
|
|
1294
1331
|
throw new InternalServerError3("Unable to delete work order.");
|
|
1295
1332
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
logger5.info(`Cache deleted for key: ${cacheKey}`);
|
|
1333
|
+
delNamespace().then(() => {
|
|
1334
|
+
logger5.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1299
1335
|
}).catch((err) => {
|
|
1300
|
-
logger5.error(
|
|
1336
|
+
logger5.error(
|
|
1337
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1338
|
+
err
|
|
1339
|
+
);
|
|
1340
|
+
});
|
|
1341
|
+
_delDashboardNameSpace().then(() => {
|
|
1342
|
+
logger5.info(`Cache cleared for namespace: dashboard`);
|
|
1343
|
+
}).catch((err) => {
|
|
1344
|
+
logger5.error(`Failed to clear cache for namespace: dashboard`, err);
|
|
1301
1345
|
});
|
|
1302
1346
|
return res.modifiedCount;
|
|
1303
1347
|
} catch (error) {
|
|
@@ -2855,6 +2899,14 @@ function useVerificationRepo() {
|
|
|
2855
2899
|
throw new InternalServerError7("Error updating verification status.");
|
|
2856
2900
|
}
|
|
2857
2901
|
}
|
|
2902
|
+
async function getByStatus(status) {
|
|
2903
|
+
try {
|
|
2904
|
+
const data = await collection.find({ status }).toArray();
|
|
2905
|
+
return data;
|
|
2906
|
+
} catch (error) {
|
|
2907
|
+
return Promise.reject(error);
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2858
2910
|
return {
|
|
2859
2911
|
createIndex,
|
|
2860
2912
|
createTextIndex,
|
|
@@ -2862,7 +2914,8 @@ function useVerificationRepo() {
|
|
|
2862
2914
|
getById,
|
|
2863
2915
|
getVerifications,
|
|
2864
2916
|
getByIdByType,
|
|
2865
|
-
updateStatusById
|
|
2917
|
+
updateStatusById,
|
|
2918
|
+
getByStatus
|
|
2866
2919
|
};
|
|
2867
2920
|
}
|
|
2868
2921
|
|
|
@@ -3226,7 +3279,8 @@ var allowedFieldsSite = [
|
|
|
3226
3279
|
"metadata.block",
|
|
3227
3280
|
"metadata.guardPosts",
|
|
3228
3281
|
"metadata.gracePeriod",
|
|
3229
|
-
"metadata.incidentCounter"
|
|
3282
|
+
"metadata.incidentCounter",
|
|
3283
|
+
"metadata.incidentLogo"
|
|
3230
3284
|
];
|
|
3231
3285
|
var siteSchema = Joi8.object({
|
|
3232
3286
|
name: Joi8.string().required(),
|
|
@@ -4115,7 +4169,8 @@ function useVerificationService() {
|
|
|
4115
4169
|
const {
|
|
4116
4170
|
add,
|
|
4117
4171
|
getById: _getById,
|
|
4118
|
-
updateStatusById: _updateStatusById
|
|
4172
|
+
updateStatusById: _updateStatusById,
|
|
4173
|
+
getByStatus: _getByStatus
|
|
4119
4174
|
} = useVerificationRepo();
|
|
4120
4175
|
const { getUserByEmail } = useUserRepo();
|
|
4121
4176
|
const { getById: getOrgById, getByEmail: getOrgByEmail } = useOrgRepo();
|
|
@@ -4361,7 +4416,6 @@ function useVerificationService() {
|
|
|
4361
4416
|
}
|
|
4362
4417
|
async function cancelUserInvitation(id) {
|
|
4363
4418
|
try {
|
|
4364
|
-
await verify(id);
|
|
4365
4419
|
await updateStatusById(id, "cancelled");
|
|
4366
4420
|
} catch (error) {
|
|
4367
4421
|
throw new InternalServerError11(
|
|
@@ -4423,6 +4477,30 @@ function useVerificationService() {
|
|
|
4423
4477
|
throw error;
|
|
4424
4478
|
}
|
|
4425
4479
|
}
|
|
4480
|
+
async function checkExpiredInvitation() {
|
|
4481
|
+
const session = useAtlas10.getClient()?.startSession();
|
|
4482
|
+
session?.startTransaction();
|
|
4483
|
+
try {
|
|
4484
|
+
const verifications = await _getByStatus("pending");
|
|
4485
|
+
for (const verification of verifications) {
|
|
4486
|
+
const expiration = new Date(verification.expireAt).getTime();
|
|
4487
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
4488
|
+
if (now > expiration) {
|
|
4489
|
+
await _updateStatusById(verification._id.toString(), "expired");
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
return "Successfully checked for expired invitations.";
|
|
4493
|
+
} catch (error) {
|
|
4494
|
+
await session?.abortTransaction();
|
|
4495
|
+
logger14.log({
|
|
4496
|
+
level: "info",
|
|
4497
|
+
message: `Error checking expired user invitation: ${error}`
|
|
4498
|
+
});
|
|
4499
|
+
throw error;
|
|
4500
|
+
} finally {
|
|
4501
|
+
session?.endSession();
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4426
4504
|
return {
|
|
4427
4505
|
createUserInvite,
|
|
4428
4506
|
createForgetPassword,
|
|
@@ -4431,7 +4509,8 @@ function useVerificationService() {
|
|
|
4431
4509
|
verify,
|
|
4432
4510
|
cancelUserInvitation,
|
|
4433
4511
|
updateStatusById,
|
|
4434
|
-
signUp
|
|
4512
|
+
signUp,
|
|
4513
|
+
checkExpiredInvitation
|
|
4435
4514
|
};
|
|
4436
4515
|
}
|
|
4437
4516
|
|
|
@@ -5641,6 +5720,16 @@ function useFileRepo() {
|
|
|
5641
5720
|
const namespace_collection = "files";
|
|
5642
5721
|
const collection = db.collection(namespace_collection);
|
|
5643
5722
|
const { delNamespace, getCache, setCache } = useCache13(namespace_collection);
|
|
5723
|
+
async function createIndex() {
|
|
5724
|
+
try {
|
|
5725
|
+
await collection.createIndexes([
|
|
5726
|
+
{ key: { createdAt: 1 } },
|
|
5727
|
+
{ key: { status: 1 } }
|
|
5728
|
+
]);
|
|
5729
|
+
} catch (error) {
|
|
5730
|
+
throw new InternalServerError14("Failed to create index on feedback.");
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5644
5733
|
async function createFile(value, session) {
|
|
5645
5734
|
try {
|
|
5646
5735
|
value = new MFile(value);
|
|
@@ -5769,7 +5858,8 @@ function useFileRepo() {
|
|
|
5769
5858
|
deleteFileById,
|
|
5770
5859
|
getAllDraftedFiles,
|
|
5771
5860
|
updateStatusById,
|
|
5772
|
-
getFileById
|
|
5861
|
+
getFileById,
|
|
5862
|
+
createIndex
|
|
5773
5863
|
};
|
|
5774
5864
|
}
|
|
5775
5865
|
|
|
@@ -10802,7 +10892,8 @@ function useFeedbackController() {
|
|
|
10802
10892
|
}
|
|
10803
10893
|
async function deleteFeedback(req, res, next) {
|
|
10804
10894
|
const validation = Joi28.string().hex().required();
|
|
10805
|
-
const _id = req.
|
|
10895
|
+
const _id = req.query.id;
|
|
10896
|
+
console.log(_id);
|
|
10806
10897
|
const { error } = validation.validate(_id);
|
|
10807
10898
|
if (error) {
|
|
10808
10899
|
logger39.log({ level: "error", message: error.message });
|
|
@@ -11166,7 +11257,8 @@ function useWorkOrderController() {
|
|
|
11166
11257
|
}
|
|
11167
11258
|
async function deleteWorkOrder(req, res, next) {
|
|
11168
11259
|
const validation = Joi29.string().hex().required();
|
|
11169
|
-
const _id = req.
|
|
11260
|
+
const _id = req.query.id;
|
|
11261
|
+
console.log(_id);
|
|
11170
11262
|
const { error } = validation.validate(_id);
|
|
11171
11263
|
if (error) {
|
|
11172
11264
|
logger40.log({ level: "error", message: error.message });
|
|
@@ -12706,7 +12798,7 @@ function useSiteController() {
|
|
|
12706
12798
|
const validation = Joi36.object({
|
|
12707
12799
|
_id: Joi36.string().hex().required(),
|
|
12708
12800
|
field: Joi36.string().valid(...allowedFieldsSite).required(),
|
|
12709
|
-
value: Joi36.number().integer().min(0).required()
|
|
12801
|
+
value: Joi36.alternatives().try(Joi36.number().integer().min(0), Joi36.string().hex().length(24)).required()
|
|
12710
12802
|
});
|
|
12711
12803
|
const _id = req.params.id ?? "";
|
|
12712
12804
|
const field = req.body.field ?? "";
|
|
@@ -27207,11 +27299,11 @@ var EAccessCardTypes = /* @__PURE__ */ ((EAccessCardTypes2) => {
|
|
|
27207
27299
|
EAccessCardTypes2["QR"] = "QRCODE";
|
|
27208
27300
|
return EAccessCardTypes2;
|
|
27209
27301
|
})(EAccessCardTypes || {});
|
|
27210
|
-
var EAccessCardUserTypes = /* @__PURE__ */ ((
|
|
27211
|
-
|
|
27212
|
-
|
|
27213
|
-
|
|
27214
|
-
return
|
|
27302
|
+
var EAccessCardUserTypes = /* @__PURE__ */ ((EAccessCardUserTypes4) => {
|
|
27303
|
+
EAccessCardUserTypes4["RESIDENT"] = "Resident/Tenant";
|
|
27304
|
+
EAccessCardUserTypes4["CONTRACTOR"] = "Contractor";
|
|
27305
|
+
EAccessCardUserTypes4["VISITOR"] = "Visitor";
|
|
27306
|
+
return EAccessCardUserTypes4;
|
|
27215
27307
|
})(EAccessCardUserTypes || {});
|
|
27216
27308
|
var AccessTypeProps = /* @__PURE__ */ ((AccessTypeProps2) => {
|
|
27217
27309
|
AccessTypeProps2["NORMAL"] = "Normal";
|
|
@@ -27273,7 +27365,8 @@ var MAccessCard = class {
|
|
|
27273
27365
|
doorName,
|
|
27274
27366
|
liftName,
|
|
27275
27367
|
replacementStatus,
|
|
27276
|
-
vmsRemarks
|
|
27368
|
+
vmsRemarks,
|
|
27369
|
+
isWinsland = false
|
|
27277
27370
|
} = {}) {
|
|
27278
27371
|
this._id = _id;
|
|
27279
27372
|
this.userId = userId;
|
|
@@ -27300,12 +27393,14 @@ var MAccessCard = class {
|
|
|
27300
27393
|
this.liftName = liftName;
|
|
27301
27394
|
this.replacementStatus = replacementStatus;
|
|
27302
27395
|
this.vmsRemarks = vmsRemarks;
|
|
27396
|
+
this.isWinsland = isWinsland;
|
|
27303
27397
|
}
|
|
27304
27398
|
};
|
|
27305
27399
|
|
|
27306
27400
|
// src/repositories/access-management.repo.ts
|
|
27307
27401
|
import {
|
|
27308
27402
|
InternalServerError as InternalServerError47,
|
|
27403
|
+
paginate as paginate38,
|
|
27309
27404
|
useAtlas as useAtlas74
|
|
27310
27405
|
} from "@7365admin1/node-server-utils";
|
|
27311
27406
|
import { ObjectId as ObjectId83 } from "mongodb";
|
|
@@ -27352,6 +27447,15 @@ function UseAccessManagementRepo() {
|
|
|
27352
27447
|
return Promise.reject("Failed to create Access cards indexes.");
|
|
27353
27448
|
}
|
|
27354
27449
|
}
|
|
27450
|
+
async function createIndexForEntrypass() {
|
|
27451
|
+
try {
|
|
27452
|
+
const entrypass = collectionName("entrypass-settings");
|
|
27453
|
+
await Promise.all([entrypass.createIndex({ site: 1 })]);
|
|
27454
|
+
return Promise.resolve("Access cards indexes created.");
|
|
27455
|
+
} catch (error) {
|
|
27456
|
+
return Promise.reject("Failed to create Access cards indexes.");
|
|
27457
|
+
}
|
|
27458
|
+
}
|
|
27355
27459
|
async function addPhysicalCardRepo({
|
|
27356
27460
|
payload
|
|
27357
27461
|
}) {
|
|
@@ -27442,7 +27546,8 @@ function UseAccessManagementRepo() {
|
|
|
27442
27546
|
liftName: params.liftName,
|
|
27443
27547
|
assignedUnit: new ObjectId83(units[i]),
|
|
27444
27548
|
createdAt: new Date(params.createdAt),
|
|
27445
|
-
updatedAt: new Date(params.updatedAt)
|
|
27549
|
+
updatedAt: new Date(params.updatedAt),
|
|
27550
|
+
isWinsland: params.isWinsland
|
|
27446
27551
|
});
|
|
27447
27552
|
try {
|
|
27448
27553
|
const result = await collection().insertOne(newCard);
|
|
@@ -27494,7 +27599,8 @@ function UseAccessManagementRepo() {
|
|
|
27494
27599
|
liftName: params.liftName,
|
|
27495
27600
|
assignedUnit: null,
|
|
27496
27601
|
createdAt: new Date(params.createdAt),
|
|
27497
|
-
updatedAt: new Date(params.updatedAt)
|
|
27602
|
+
updatedAt: new Date(params.updatedAt),
|
|
27603
|
+
isWinsland: params.isWinsland
|
|
27498
27604
|
});
|
|
27499
27605
|
try {
|
|
27500
27606
|
const result = await collection().insertOne(newCard);
|
|
@@ -27526,10 +27632,538 @@ function UseAccessManagementRepo() {
|
|
|
27526
27632
|
throw new Error(error.message);
|
|
27527
27633
|
}
|
|
27528
27634
|
}
|
|
27635
|
+
async function accessManagementSettingsRepo(params) {
|
|
27636
|
+
try {
|
|
27637
|
+
params.site = new ObjectId83(params.site);
|
|
27638
|
+
const result = collectionName("entrypass-settings").updateOne(
|
|
27639
|
+
{ site: params.site },
|
|
27640
|
+
{
|
|
27641
|
+
$set: {
|
|
27642
|
+
...params,
|
|
27643
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
27644
|
+
},
|
|
27645
|
+
$setOnInsert: {
|
|
27646
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
27647
|
+
}
|
|
27648
|
+
},
|
|
27649
|
+
{ upsert: true }
|
|
27650
|
+
);
|
|
27651
|
+
await createIndexForEntrypass();
|
|
27652
|
+
return result;
|
|
27653
|
+
} catch (error) {
|
|
27654
|
+
throw new Error(error.message);
|
|
27655
|
+
}
|
|
27656
|
+
}
|
|
27657
|
+
async function allAccessCardsCountsRepo(params) {
|
|
27658
|
+
try {
|
|
27659
|
+
const site = new ObjectId83(params.site);
|
|
27660
|
+
const userType = params.userType;
|
|
27661
|
+
const result = await collection().aggregate([
|
|
27662
|
+
{
|
|
27663
|
+
$match: { site, userType }
|
|
27664
|
+
},
|
|
27665
|
+
{
|
|
27666
|
+
$facet: {
|
|
27667
|
+
available_physical: [{ $match: { assignedUnit: { $eq: null }, type: "NFC" /* NFC */ } }, { $count: "count" }],
|
|
27668
|
+
available_non_physical: [{ $match: { assignedUnit: { $eq: null }, type: "QRCODE" /* QR */ } }, { $count: "count" }],
|
|
27669
|
+
assigned_physical: [{ $match: { assignedUnit: { $ne: null }, type: "NFC" /* NFC */ } }, { $count: "count" }],
|
|
27670
|
+
assigned_non_physical: [{ $match: { assignedUnit: { $ne: null }, type: "QRCODE" /* QR */ } }, { $count: "count" }]
|
|
27671
|
+
}
|
|
27672
|
+
}
|
|
27673
|
+
]).toArray();
|
|
27674
|
+
const totalCardCount = {
|
|
27675
|
+
available_physical: result[0].available_physical[0] ? result[0].available_physical[0].count : 0,
|
|
27676
|
+
available_non_physical: result[0].available_non_physical[0] ? result[0].available_non_physical[0].count : 0,
|
|
27677
|
+
assigned_physical: result[0].assigned_physical[0] ? result[0].assigned_physical[0].count : 0,
|
|
27678
|
+
assigned_non_physical: result[0].assigned_non_physical[0] ? result[0].assigned_non_physical[0].count : 0
|
|
27679
|
+
};
|
|
27680
|
+
return totalCardCount;
|
|
27681
|
+
} catch (error) {
|
|
27682
|
+
throw new Error(error.message);
|
|
27683
|
+
}
|
|
27684
|
+
}
|
|
27685
|
+
async function availableAccessCardsRepo(params) {
|
|
27686
|
+
try {
|
|
27687
|
+
const site = new ObjectId83(params.site);
|
|
27688
|
+
const userType = params.userType;
|
|
27689
|
+
const type = params.type;
|
|
27690
|
+
const query = {
|
|
27691
|
+
site: { $in: [site] },
|
|
27692
|
+
userType,
|
|
27693
|
+
assignedUnit: null,
|
|
27694
|
+
type,
|
|
27695
|
+
isActivated: true
|
|
27696
|
+
};
|
|
27697
|
+
const result = await collection().aggregate([
|
|
27698
|
+
{
|
|
27699
|
+
$match: { ...query }
|
|
27700
|
+
},
|
|
27701
|
+
{
|
|
27702
|
+
$project: {
|
|
27703
|
+
accessLevel: 1,
|
|
27704
|
+
liftAccessLevel: 1,
|
|
27705
|
+
doorName: 1,
|
|
27706
|
+
liftName: 1
|
|
27707
|
+
}
|
|
27708
|
+
},
|
|
27709
|
+
{
|
|
27710
|
+
$group: {
|
|
27711
|
+
_id: {
|
|
27712
|
+
accessLevel: "$accessLevel",
|
|
27713
|
+
liftAccessLevel: "$liftAccessLevel",
|
|
27714
|
+
doorName: "$doorName",
|
|
27715
|
+
liftName: "$liftName"
|
|
27716
|
+
},
|
|
27717
|
+
count: { $sum: 1 }
|
|
27718
|
+
}
|
|
27719
|
+
},
|
|
27720
|
+
{
|
|
27721
|
+
$project: {
|
|
27722
|
+
_id: 0,
|
|
27723
|
+
accessLevel: "$_id.accessLevel",
|
|
27724
|
+
liftAccessLevel: "$_id.liftAccessLevel",
|
|
27725
|
+
doorName: "$_id.doorName",
|
|
27726
|
+
liftName: "$_id.liftName",
|
|
27727
|
+
count: 1
|
|
27728
|
+
}
|
|
27729
|
+
}
|
|
27730
|
+
]).toArray();
|
|
27731
|
+
return result;
|
|
27732
|
+
} catch (error) {
|
|
27733
|
+
throw new Error(error.message);
|
|
27734
|
+
}
|
|
27735
|
+
}
|
|
27736
|
+
function getAfterSecondSlash(term) {
|
|
27737
|
+
const first = term.indexOf("/");
|
|
27738
|
+
if (first === -1)
|
|
27739
|
+
return "";
|
|
27740
|
+
const second = term.indexOf("/", first + 1);
|
|
27741
|
+
if (second === -1)
|
|
27742
|
+
return "";
|
|
27743
|
+
return term.substring(second + 1).toLowerCase();
|
|
27744
|
+
}
|
|
27745
|
+
function buildSearchQuery(search) {
|
|
27746
|
+
if (!search) {
|
|
27747
|
+
return {};
|
|
27748
|
+
}
|
|
27749
|
+
const terms = search.split("/").map((s) => s.trim()).filter(Boolean);
|
|
27750
|
+
if (search.includes("/")) {
|
|
27751
|
+
switch (true) {
|
|
27752
|
+
case terms.length >= 3:
|
|
27753
|
+
return {
|
|
27754
|
+
$and: [
|
|
27755
|
+
{ $expr: { $eq: [{ $toLower: "$name" }, terms[0].toLowerCase()] } },
|
|
27756
|
+
{ $expr: { $eq: [{ $toLower: "$level.level" }, terms[1].toLowerCase()] } },
|
|
27757
|
+
{ $expr: { $eq: [{ $toLower: "$level.units.name" }, getAfterSecondSlash(search)] } }
|
|
27758
|
+
]
|
|
27759
|
+
};
|
|
27760
|
+
case terms.length === 2:
|
|
27761
|
+
return {
|
|
27762
|
+
$and: [
|
|
27763
|
+
{ $expr: { $eq: [{ $toLower: "$name" }, terms[0].toLowerCase()] } },
|
|
27764
|
+
{ $expr: { $eq: [{ $toLower: "$level.level" }, terms[1].toLowerCase()] } }
|
|
27765
|
+
]
|
|
27766
|
+
};
|
|
27767
|
+
default:
|
|
27768
|
+
return {
|
|
27769
|
+
$expr: { $eq: [{ $toLower: "$name" }, terms[0].toLowerCase()] }
|
|
27770
|
+
};
|
|
27771
|
+
}
|
|
27772
|
+
}
|
|
27773
|
+
return {
|
|
27774
|
+
$or: [
|
|
27775
|
+
{ name: { $regex: search.trim(), $options: "i" } },
|
|
27776
|
+
{ "level.level": { $regex: search.trim(), $options: "i" } },
|
|
27777
|
+
{ "level.units.name": { $regex: search.trim(), $options: "i" } }
|
|
27778
|
+
]
|
|
27779
|
+
};
|
|
27780
|
+
}
|
|
27781
|
+
async function userTypeAccessCardsRepo(params) {
|
|
27782
|
+
try {
|
|
27783
|
+
const site = new ObjectId83(params.site);
|
|
27784
|
+
const userType = params.userType;
|
|
27785
|
+
const page = params.page ? Number(params.page) - 1 : 0;
|
|
27786
|
+
const limit = Number(params.limit) || 10;
|
|
27787
|
+
const search = params.search;
|
|
27788
|
+
const defaultQuery = {
|
|
27789
|
+
site
|
|
27790
|
+
};
|
|
27791
|
+
const searchQuery = buildSearchQuery(search);
|
|
27792
|
+
const result = await collectionName("buildings").aggregate([
|
|
27793
|
+
// ✅ Match early with index-friendly query
|
|
27794
|
+
{
|
|
27795
|
+
$match: {
|
|
27796
|
+
...defaultQuery,
|
|
27797
|
+
status: { $ne: "deleted" }
|
|
27798
|
+
}
|
|
27799
|
+
},
|
|
27800
|
+
// ✅ Only project needed fields before heavy lookups
|
|
27801
|
+
{
|
|
27802
|
+
$project: {
|
|
27803
|
+
_id: 1,
|
|
27804
|
+
name: 1,
|
|
27805
|
+
site: 1
|
|
27806
|
+
}
|
|
27807
|
+
},
|
|
27808
|
+
// ✅ Use localField/foreignField for better index usage
|
|
27809
|
+
{
|
|
27810
|
+
$lookup: {
|
|
27811
|
+
from: "building-levels",
|
|
27812
|
+
localField: "_id",
|
|
27813
|
+
foreignField: "block",
|
|
27814
|
+
pipeline: [
|
|
27815
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
27816
|
+
{
|
|
27817
|
+
$lookup: {
|
|
27818
|
+
from: "building-units",
|
|
27819
|
+
localField: "_id",
|
|
27820
|
+
foreignField: "level",
|
|
27821
|
+
pipeline: [
|
|
27822
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
27823
|
+
{ $project: { _id: 1, name: 1 } }
|
|
27824
|
+
],
|
|
27825
|
+
as: "units"
|
|
27826
|
+
}
|
|
27827
|
+
},
|
|
27828
|
+
{
|
|
27829
|
+
$match: { "units.0": { $exists: true } }
|
|
27830
|
+
},
|
|
27831
|
+
{
|
|
27832
|
+
$project: {
|
|
27833
|
+
_id: 1,
|
|
27834
|
+
level: 1,
|
|
27835
|
+
units: 1
|
|
27836
|
+
}
|
|
27837
|
+
}
|
|
27838
|
+
],
|
|
27839
|
+
as: "level"
|
|
27840
|
+
}
|
|
27841
|
+
},
|
|
27842
|
+
// ✅ Filter out buildings with no levels early
|
|
27843
|
+
{
|
|
27844
|
+
$match: { "level.0": { $exists: true } }
|
|
27845
|
+
},
|
|
27846
|
+
// ✅ Unwind to flatten the hierarchy
|
|
27847
|
+
{
|
|
27848
|
+
$unwind: {
|
|
27849
|
+
path: "$level",
|
|
27850
|
+
preserveNullAndEmptyArrays: false
|
|
27851
|
+
}
|
|
27852
|
+
},
|
|
27853
|
+
{
|
|
27854
|
+
$unwind: {
|
|
27855
|
+
path: "$level.units",
|
|
27856
|
+
preserveNullAndEmptyArrays: false
|
|
27857
|
+
}
|
|
27858
|
+
},
|
|
27859
|
+
// Groups by unit _id and keeps only the first occurrence
|
|
27860
|
+
{
|
|
27861
|
+
$group: {
|
|
27862
|
+
_id: "$level.units._id",
|
|
27863
|
+
doc: { $first: "$$ROOT" }
|
|
27864
|
+
}
|
|
27865
|
+
},
|
|
27866
|
+
{
|
|
27867
|
+
$replaceRoot: { newRoot: "$doc" }
|
|
27868
|
+
},
|
|
27869
|
+
// ✅ Apply search filter
|
|
27870
|
+
{
|
|
27871
|
+
$match: {
|
|
27872
|
+
...searchQuery
|
|
27873
|
+
}
|
|
27874
|
+
},
|
|
27875
|
+
{
|
|
27876
|
+
$facet: {
|
|
27877
|
+
totalCount: [{ $count: "count" }],
|
|
27878
|
+
items: [
|
|
27879
|
+
// ✅ Sort BEFORE skip/limit for correct pagination
|
|
27880
|
+
{ $sort: { _id: -1 } },
|
|
27881
|
+
{ $skip: page * limit },
|
|
27882
|
+
{ $limit: limit },
|
|
27883
|
+
// ✅ Users lookup - optimized with index hint
|
|
27884
|
+
{
|
|
27885
|
+
$lookup: {
|
|
27886
|
+
from: "users",
|
|
27887
|
+
let: { unit: "$level.units._id" },
|
|
27888
|
+
pipeline: [
|
|
27889
|
+
{
|
|
27890
|
+
$match: {
|
|
27891
|
+
$expr: { $eq: ["$unitNumber", "$$unit"] },
|
|
27892
|
+
residentType: "House/Unit Owner"
|
|
27893
|
+
}
|
|
27894
|
+
},
|
|
27895
|
+
{ $limit: 1 },
|
|
27896
|
+
{ $project: { _id: 1, givenName: 1, surname: 1 } }
|
|
27897
|
+
],
|
|
27898
|
+
as: "unitOwner"
|
|
27899
|
+
}
|
|
27900
|
+
},
|
|
27901
|
+
// ✅ Access card lookup - optimized query
|
|
27902
|
+
{
|
|
27903
|
+
$lookup: {
|
|
27904
|
+
from: "access-cards",
|
|
27905
|
+
let: { unit: "$level.units._id" },
|
|
27906
|
+
pipeline: [
|
|
27907
|
+
{
|
|
27908
|
+
$match: {
|
|
27909
|
+
$expr: {
|
|
27910
|
+
$in: [
|
|
27911
|
+
"$$unit",
|
|
27912
|
+
{ $cond: [{ $isArray: "$assignedUnit" }, "$assignedUnit", ["$assignedUnit"]] }
|
|
27913
|
+
]
|
|
27914
|
+
},
|
|
27915
|
+
userType
|
|
27916
|
+
}
|
|
27917
|
+
},
|
|
27918
|
+
{ $project: { _id: 1, userId: 1, type: 1, cardNo: 1, isActivated: 1 } }
|
|
27919
|
+
],
|
|
27920
|
+
as: "accessCards"
|
|
27921
|
+
}
|
|
27922
|
+
},
|
|
27923
|
+
// ✅ Compute all card categorization and counts in ONE stage
|
|
27924
|
+
{
|
|
27925
|
+
$addFields: {
|
|
27926
|
+
f_Available: {
|
|
27927
|
+
$filter: {
|
|
27928
|
+
input: "$accessCards",
|
|
27929
|
+
as: "card",
|
|
27930
|
+
cond: { $and: [{ $eq: ["$$card.userId", null] }, { $eq: ["$$card.isActivated", true] }] }
|
|
27931
|
+
}
|
|
27932
|
+
},
|
|
27933
|
+
f_Assigned: {
|
|
27934
|
+
$filter: {
|
|
27935
|
+
input: "$accessCards",
|
|
27936
|
+
as: "card",
|
|
27937
|
+
cond: { $ne: ["$$card.userId", null] }
|
|
27938
|
+
}
|
|
27939
|
+
}
|
|
27940
|
+
}
|
|
27941
|
+
},
|
|
27942
|
+
// ✅ Final projection with all computed fields
|
|
27943
|
+
{
|
|
27944
|
+
$project: {
|
|
27945
|
+
_id: "$level.units._id",
|
|
27946
|
+
name: "$level.units.name",
|
|
27947
|
+
level: { _id: "$level._id", level: "$level.level" },
|
|
27948
|
+
block: { _id: "$_id", name: "$name" },
|
|
27949
|
+
site: "$site",
|
|
27950
|
+
unit_owner: { $arrayElemAt: ["$unitOwner", 0] },
|
|
27951
|
+
available: {
|
|
27952
|
+
physical: { $filter: { input: "$f_Available", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
27953
|
+
non_physical: { $filter: { input: "$f_Available", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
27954
|
+
},
|
|
27955
|
+
assigned: {
|
|
27956
|
+
physical: { $filter: { input: "$f_Assigned", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
27957
|
+
non_physical: { $filter: { input: "$f_Assigned", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
27958
|
+
},
|
|
27959
|
+
cardCounts: {
|
|
27960
|
+
available: {
|
|
27961
|
+
physical: { $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
27962
|
+
non_physical: { $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } }
|
|
27963
|
+
},
|
|
27964
|
+
assigned: {
|
|
27965
|
+
physical: { $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
27966
|
+
non_physical: { $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } }
|
|
27967
|
+
}
|
|
27968
|
+
},
|
|
27969
|
+
totalCardCount: {
|
|
27970
|
+
$add: [
|
|
27971
|
+
{ $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
27972
|
+
{ $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } },
|
|
27973
|
+
{ $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
27974
|
+
{ $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } }
|
|
27975
|
+
]
|
|
27976
|
+
}
|
|
27977
|
+
}
|
|
27978
|
+
}
|
|
27979
|
+
]
|
|
27980
|
+
}
|
|
27981
|
+
}
|
|
27982
|
+
], { allowDiskUse: true }).toArray();
|
|
27983
|
+
const totalCount = result[0]?.totalCount?.[0]?.count ?? 0;
|
|
27984
|
+
const items = result[0]?.items ?? [];
|
|
27985
|
+
const paginatedResult = paginate38(items, page, limit, totalCount);
|
|
27986
|
+
return paginatedResult;
|
|
27987
|
+
} catch (error) {
|
|
27988
|
+
throw new Error(error.message);
|
|
27989
|
+
}
|
|
27990
|
+
}
|
|
27991
|
+
async function assignedAccessCardsRepo(params) {
|
|
27992
|
+
try {
|
|
27993
|
+
const site = new ObjectId83(params.site);
|
|
27994
|
+
const userType = params.userType;
|
|
27995
|
+
const type = params.type;
|
|
27996
|
+
const search = params.search;
|
|
27997
|
+
const query = {
|
|
27998
|
+
site: { $in: [site] }
|
|
27999
|
+
};
|
|
28000
|
+
const searchQuery = buildSearchQuery(search);
|
|
28001
|
+
const result = await collectionName("buildings").aggregate([
|
|
28002
|
+
// ✅ Match early with index-friendly query
|
|
28003
|
+
{
|
|
28004
|
+
$match: {
|
|
28005
|
+
...query,
|
|
28006
|
+
status: { $ne: "deleted" }
|
|
28007
|
+
}
|
|
28008
|
+
},
|
|
28009
|
+
// ✅ Only project needed fields before heavy lookups
|
|
28010
|
+
{
|
|
28011
|
+
$project: {
|
|
28012
|
+
_id: 1,
|
|
28013
|
+
name: 1,
|
|
28014
|
+
site: 1
|
|
28015
|
+
}
|
|
28016
|
+
},
|
|
28017
|
+
// ✅ Use localField/foreignField for better index usage
|
|
28018
|
+
{
|
|
28019
|
+
$lookup: {
|
|
28020
|
+
from: "building-levels",
|
|
28021
|
+
localField: "_id",
|
|
28022
|
+
foreignField: "block",
|
|
28023
|
+
pipeline: [
|
|
28024
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
28025
|
+
{
|
|
28026
|
+
$lookup: {
|
|
28027
|
+
from: "building-units",
|
|
28028
|
+
localField: "_id",
|
|
28029
|
+
foreignField: "level",
|
|
28030
|
+
pipeline: [
|
|
28031
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
28032
|
+
{ $project: { _id: 1, name: 1 } },
|
|
28033
|
+
{
|
|
28034
|
+
$lookup: {
|
|
28035
|
+
from: "access-cards",
|
|
28036
|
+
localField: "_id",
|
|
28037
|
+
foreignField: "assignedUnit",
|
|
28038
|
+
pipeline: [
|
|
28039
|
+
{
|
|
28040
|
+
$match: {
|
|
28041
|
+
isActivated: true,
|
|
28042
|
+
userType,
|
|
28043
|
+
type
|
|
28044
|
+
}
|
|
28045
|
+
},
|
|
28046
|
+
{
|
|
28047
|
+
$group: {
|
|
28048
|
+
_id: null,
|
|
28049
|
+
accessLevels: { $addToSet: "$accessLevel" },
|
|
28050
|
+
liftAccessLevels: { $addToSet: "$liftAccessLevel" },
|
|
28051
|
+
doorNames: { $addToSet: "$doorName" },
|
|
28052
|
+
liftNames: { $addToSet: "$liftName" },
|
|
28053
|
+
cards: {
|
|
28054
|
+
$push: {
|
|
28055
|
+
_id: "$_id",
|
|
28056
|
+
cardNo: "$cardNo",
|
|
28057
|
+
accessLevel: "$accessLevel",
|
|
28058
|
+
liftAccessLevel: "$liftAccessLevel",
|
|
28059
|
+
doorName: "$doorName",
|
|
28060
|
+
liftName: "$liftName"
|
|
28061
|
+
}
|
|
28062
|
+
}
|
|
28063
|
+
}
|
|
28064
|
+
},
|
|
28065
|
+
{
|
|
28066
|
+
$project: {
|
|
28067
|
+
_id: 0,
|
|
28068
|
+
accessCardCount: {
|
|
28069
|
+
$size: "$cards"
|
|
28070
|
+
},
|
|
28071
|
+
accessLevels: 1,
|
|
28072
|
+
liftAccessLevels: 1,
|
|
28073
|
+
doorNames: 1,
|
|
28074
|
+
liftNames: 1
|
|
28075
|
+
}
|
|
28076
|
+
}
|
|
28077
|
+
],
|
|
28078
|
+
as: "fAccessCards"
|
|
28079
|
+
}
|
|
28080
|
+
},
|
|
28081
|
+
{
|
|
28082
|
+
$match: {
|
|
28083
|
+
"fAccessCards.0": { $exists: true }
|
|
28084
|
+
}
|
|
28085
|
+
}
|
|
28086
|
+
],
|
|
28087
|
+
as: "units"
|
|
28088
|
+
}
|
|
28089
|
+
},
|
|
28090
|
+
{
|
|
28091
|
+
$match: { "units.0": { $exists: true } }
|
|
28092
|
+
},
|
|
28093
|
+
{
|
|
28094
|
+
$project: {
|
|
28095
|
+
_id: 1,
|
|
28096
|
+
level: 1,
|
|
28097
|
+
units: 1
|
|
28098
|
+
}
|
|
28099
|
+
}
|
|
28100
|
+
],
|
|
28101
|
+
as: "level"
|
|
28102
|
+
}
|
|
28103
|
+
},
|
|
28104
|
+
// ✅ Filter out buildings with no levels early
|
|
28105
|
+
{
|
|
28106
|
+
$match: { "level.0": { $exists: true } }
|
|
28107
|
+
},
|
|
28108
|
+
// ✅ Unwind to flatten the hierarchy
|
|
28109
|
+
{
|
|
28110
|
+
$unwind: {
|
|
28111
|
+
path: "$level",
|
|
28112
|
+
preserveNullAndEmptyArrays: false
|
|
28113
|
+
}
|
|
28114
|
+
},
|
|
28115
|
+
{
|
|
28116
|
+
$unwind: {
|
|
28117
|
+
path: "$level.units",
|
|
28118
|
+
preserveNullAndEmptyArrays: false
|
|
28119
|
+
}
|
|
28120
|
+
},
|
|
28121
|
+
{
|
|
28122
|
+
$unwind: {
|
|
28123
|
+
path: "$level.units.fAccessCards",
|
|
28124
|
+
preserveNullAndEmptyArrays: false
|
|
28125
|
+
}
|
|
28126
|
+
},
|
|
28127
|
+
// // Groups by unit _id and keeps only the first occurrence
|
|
28128
|
+
{
|
|
28129
|
+
$group: {
|
|
28130
|
+
_id: "$level.units._id",
|
|
28131
|
+
doc: { $first: "$$ROOT" }
|
|
28132
|
+
}
|
|
28133
|
+
},
|
|
28134
|
+
{
|
|
28135
|
+
$replaceRoot: { newRoot: "$doc" }
|
|
28136
|
+
},
|
|
28137
|
+
// ✅ Apply search filter
|
|
28138
|
+
{
|
|
28139
|
+
$match: {
|
|
28140
|
+
...searchQuery
|
|
28141
|
+
}
|
|
28142
|
+
},
|
|
28143
|
+
{
|
|
28144
|
+
$project: {
|
|
28145
|
+
name: 1,
|
|
28146
|
+
"level.level": 1,
|
|
28147
|
+
"level.units.name": 1,
|
|
28148
|
+
"level.units.fAccessCards": 1
|
|
28149
|
+
}
|
|
28150
|
+
}
|
|
28151
|
+
], { allowDiskUse: true }).toArray();
|
|
28152
|
+
return result;
|
|
28153
|
+
} catch (error) {
|
|
28154
|
+
throw new Error(error.message);
|
|
28155
|
+
}
|
|
28156
|
+
}
|
|
27529
28157
|
return {
|
|
27530
28158
|
createIndexes,
|
|
28159
|
+
createIndexForEntrypass,
|
|
27531
28160
|
addPhysicalCardRepo,
|
|
27532
|
-
addNonPhysicalCardRepo
|
|
28161
|
+
addNonPhysicalCardRepo,
|
|
28162
|
+
accessManagementSettingsRepo,
|
|
28163
|
+
allAccessCardsCountsRepo,
|
|
28164
|
+
availableAccessCardsRepo,
|
|
28165
|
+
userTypeAccessCardsRepo,
|
|
28166
|
+
assignedAccessCardsRepo
|
|
27533
28167
|
};
|
|
27534
28168
|
}
|
|
27535
28169
|
|
|
@@ -27634,8 +28268,18 @@ var formatAccessGroup = (data, search) => {
|
|
|
27634
28268
|
|
|
27635
28269
|
// src/services/access-management.service.ts
|
|
27636
28270
|
import { parseStringPromise } from "xml2js";
|
|
28271
|
+
import { useCache as useCache47 } from "@7365admin1/node-server-utils";
|
|
28272
|
+
var namespace = "cache:acm";
|
|
27637
28273
|
function useAccessManagementSvc() {
|
|
27638
|
-
const {
|
|
28274
|
+
const {
|
|
28275
|
+
addPhysicalCardRepo,
|
|
28276
|
+
addNonPhysicalCardRepo,
|
|
28277
|
+
accessManagementSettingsRepo,
|
|
28278
|
+
allAccessCardsCountsRepo,
|
|
28279
|
+
availableAccessCardsRepo,
|
|
28280
|
+
userTypeAccessCardsRepo,
|
|
28281
|
+
assignedAccessCardsRepo
|
|
28282
|
+
} = UseAccessManagementRepo();
|
|
27639
28283
|
const addPhysicalCardSvc = async (payload) => {
|
|
27640
28284
|
try {
|
|
27641
28285
|
const response = await addPhysicalCardRepo({ payload });
|
|
@@ -27652,12 +28296,34 @@ function useAccessManagementSvc() {
|
|
|
27652
28296
|
throw new Error(err.message);
|
|
27653
28297
|
}
|
|
27654
28298
|
};
|
|
28299
|
+
const setCache = async (params) => {
|
|
28300
|
+
const { key, data, ttlSeconds = 60, redis } = params;
|
|
28301
|
+
const jsonData = JSON.stringify(data);
|
|
28302
|
+
await redis.set(key, jsonData, "EX", ttlSeconds);
|
|
28303
|
+
};
|
|
28304
|
+
const getCache = async (params) => {
|
|
28305
|
+
const { key, redis } = params;
|
|
28306
|
+
const result = await redis.get(key);
|
|
28307
|
+
return result ? JSON.parse(result) : null;
|
|
28308
|
+
};
|
|
27655
28309
|
const doorAccessLevelsSvc = async (params) => {
|
|
27656
28310
|
try {
|
|
28311
|
+
const key = `${namespace}:${params.user}:door-levels`;
|
|
28312
|
+
const listKey = `${namespace}:${params.user}:list`;
|
|
28313
|
+
const { redis } = useCache47(key);
|
|
28314
|
+
const cachedData = await getCache({ key, redis });
|
|
28315
|
+
if (cachedData) {
|
|
28316
|
+
console.log("\u26A1 Cache hit:", key);
|
|
28317
|
+
redis.expire(key, 60).catch(console.error);
|
|
28318
|
+
redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
|
|
28319
|
+
return cachedData;
|
|
28320
|
+
}
|
|
27657
28321
|
const command = readTemplate("door-levels");
|
|
27658
28322
|
const response = await sendCommand(command, params.acm_url);
|
|
27659
28323
|
const res = await parseStringPromise(response, { explicitArray: false });
|
|
27660
28324
|
const format = await formatDoorAccessLevels(res);
|
|
28325
|
+
await setCache({ key, data: format, ttlSeconds: 60, redis });
|
|
28326
|
+
redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
|
|
27661
28327
|
return format;
|
|
27662
28328
|
} catch (err) {
|
|
27663
28329
|
throw new Error(err.message);
|
|
@@ -27665,10 +28331,22 @@ function useAccessManagementSvc() {
|
|
|
27665
28331
|
};
|
|
27666
28332
|
const liftAccessLevelsSvc = async (params) => {
|
|
27667
28333
|
try {
|
|
28334
|
+
const key = `${namespace}:${params.user}:lift-levels`;
|
|
28335
|
+
const listKey = `${namespace}:${params.user}:list`;
|
|
28336
|
+
const { redis } = useCache47(key);
|
|
28337
|
+
const cachedData = await getCache({ key, redis });
|
|
28338
|
+
if (cachedData) {
|
|
28339
|
+
console.log("\u26A1 Cache hit:", key);
|
|
28340
|
+
redis.expire(key, 60).catch(console.error);
|
|
28341
|
+
redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
|
|
28342
|
+
return cachedData;
|
|
28343
|
+
}
|
|
27668
28344
|
const command = readTemplate("lift-levels");
|
|
27669
28345
|
const response = await sendCommand(command, params.acm_url);
|
|
27670
28346
|
const res = await parseStringPromise(response, { explicitArray: false });
|
|
27671
28347
|
const format = await formatLiftAccessLevels(res);
|
|
28348
|
+
await setCache({ key, data: format, ttlSeconds: 60, redis });
|
|
28349
|
+
redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
|
|
27672
28350
|
return format;
|
|
27673
28351
|
} catch (error) {
|
|
27674
28352
|
throw new Error(error.message);
|
|
@@ -27682,7 +28360,47 @@ function useAccessManagementSvc() {
|
|
|
27682
28360
|
const format = await formatAccessGroup(res);
|
|
27683
28361
|
return format;
|
|
27684
28362
|
} catch (err) {
|
|
27685
|
-
|
|
28363
|
+
throw new Error(err.message);
|
|
28364
|
+
}
|
|
28365
|
+
};
|
|
28366
|
+
const accessManagementSettingsSvc = async (settings) => {
|
|
28367
|
+
try {
|
|
28368
|
+
const response = await accessManagementSettingsRepo({ ...settings });
|
|
28369
|
+
return response;
|
|
28370
|
+
} catch (err) {
|
|
28371
|
+
throw new Error(err.message);
|
|
28372
|
+
}
|
|
28373
|
+
};
|
|
28374
|
+
const allAccessCardsCountsSvc = async (params) => {
|
|
28375
|
+
try {
|
|
28376
|
+
const response = await allAccessCardsCountsRepo({ ...params });
|
|
28377
|
+
return response;
|
|
28378
|
+
} catch (err) {
|
|
28379
|
+
throw new Error(err.message);
|
|
28380
|
+
}
|
|
28381
|
+
};
|
|
28382
|
+
const availableAccessCardsSvc = async (params) => {
|
|
28383
|
+
try {
|
|
28384
|
+
const response = await availableAccessCardsRepo({ ...params });
|
|
28385
|
+
return response;
|
|
28386
|
+
} catch (err) {
|
|
28387
|
+
throw new Error(err.message);
|
|
28388
|
+
}
|
|
28389
|
+
};
|
|
28390
|
+
const userTypeAccessCardsSvc = async (params) => {
|
|
28391
|
+
try {
|
|
28392
|
+
const response = await userTypeAccessCardsRepo({ ...params });
|
|
28393
|
+
return response;
|
|
28394
|
+
} catch (err) {
|
|
28395
|
+
throw new Error(err.message);
|
|
28396
|
+
}
|
|
28397
|
+
};
|
|
28398
|
+
const assignedAccessCardsSvc = async (params) => {
|
|
28399
|
+
try {
|
|
28400
|
+
const response = await assignedAccessCardsRepo({ ...params });
|
|
28401
|
+
return response;
|
|
28402
|
+
} catch (err) {
|
|
28403
|
+
throw new Error(err.message);
|
|
27686
28404
|
}
|
|
27687
28405
|
};
|
|
27688
28406
|
return {
|
|
@@ -27690,7 +28408,12 @@ function useAccessManagementSvc() {
|
|
|
27690
28408
|
addNonPhysicalCardSvc,
|
|
27691
28409
|
doorAccessLevelsSvc,
|
|
27692
28410
|
liftAccessLevelsSvc,
|
|
27693
|
-
accessGroupsSvc
|
|
28411
|
+
accessGroupsSvc,
|
|
28412
|
+
accessManagementSettingsSvc,
|
|
28413
|
+
allAccessCardsCountsSvc,
|
|
28414
|
+
availableAccessCardsSvc,
|
|
28415
|
+
userTypeAccessCardsSvc,
|
|
28416
|
+
assignedAccessCardsSvc
|
|
27694
28417
|
};
|
|
27695
28418
|
}
|
|
27696
28419
|
|
|
@@ -27701,7 +28424,12 @@ function useAccessManagementController() {
|
|
|
27701
28424
|
addNonPhysicalCardSvc,
|
|
27702
28425
|
doorAccessLevelsSvc,
|
|
27703
28426
|
liftAccessLevelsSvc,
|
|
27704
|
-
accessGroupsSvc
|
|
28427
|
+
accessGroupsSvc,
|
|
28428
|
+
accessManagementSettingsSvc,
|
|
28429
|
+
allAccessCardsCountsSvc,
|
|
28430
|
+
availableAccessCardsSvc,
|
|
28431
|
+
userTypeAccessCardsSvc,
|
|
28432
|
+
assignedAccessCardsSvc
|
|
27705
28433
|
} = useAccessManagementSvc();
|
|
27706
28434
|
const addPhysicalCard = async (req, res) => {
|
|
27707
28435
|
try {
|
|
@@ -27761,7 +28489,8 @@ function useAccessManagementController() {
|
|
|
27761
28489
|
createdAt,
|
|
27762
28490
|
updatedAt,
|
|
27763
28491
|
startDate,
|
|
27764
|
-
endDate
|
|
28492
|
+
endDate,
|
|
28493
|
+
isWinsland
|
|
27765
28494
|
} = req.body;
|
|
27766
28495
|
const schema2 = Joi85.object({
|
|
27767
28496
|
site: Joi85.string().hex().required(),
|
|
@@ -27777,7 +28506,8 @@ function useAccessManagementController() {
|
|
|
27777
28506
|
startDate: Joi85.date().required(),
|
|
27778
28507
|
endDate: Joi85.date().required(),
|
|
27779
28508
|
createdAt: Joi85.date().required(),
|
|
27780
|
-
updatedAt: Joi85.date().required()
|
|
28509
|
+
updatedAt: Joi85.date().required(),
|
|
28510
|
+
isWinsland: Joi85.boolean().optional().allow(null)
|
|
27781
28511
|
});
|
|
27782
28512
|
const { error } = schema2.validate({
|
|
27783
28513
|
site,
|
|
@@ -27793,7 +28523,8 @@ function useAccessManagementController() {
|
|
|
27793
28523
|
startDate,
|
|
27794
28524
|
endDate,
|
|
27795
28525
|
createdAt,
|
|
27796
|
-
updatedAt
|
|
28526
|
+
updatedAt,
|
|
28527
|
+
isWinsland
|
|
27797
28528
|
});
|
|
27798
28529
|
if (error) {
|
|
27799
28530
|
throw new Error(`${error.message}`);
|
|
@@ -27812,7 +28543,8 @@ function useAccessManagementController() {
|
|
|
27812
28543
|
startDate,
|
|
27813
28544
|
endDate,
|
|
27814
28545
|
createdAt,
|
|
27815
|
-
updatedAt
|
|
28546
|
+
updatedAt,
|
|
28547
|
+
isWinsland
|
|
27816
28548
|
});
|
|
27817
28549
|
return res.status(201).json({
|
|
27818
28550
|
data: result,
|
|
@@ -27828,10 +28560,11 @@ function useAccessManagementController() {
|
|
|
27828
28560
|
const doorAccessLevels = async (req, res) => {
|
|
27829
28561
|
try {
|
|
27830
28562
|
const { acm_url } = req.query;
|
|
28563
|
+
const user = req.cookies?.sid;
|
|
27831
28564
|
if (!acm_url || typeof acm_url !== "string") {
|
|
27832
28565
|
throw new Error("Access Control URL is required");
|
|
27833
28566
|
}
|
|
27834
|
-
const result = await doorAccessLevelsSvc({ acm_url });
|
|
28567
|
+
const result = await doorAccessLevelsSvc({ acm_url, user });
|
|
27835
28568
|
return res.status(200).json({ message: "Success", data: result });
|
|
27836
28569
|
} catch (error) {
|
|
27837
28570
|
return res.status(400).json({
|
|
@@ -27843,10 +28576,11 @@ function useAccessManagementController() {
|
|
|
27843
28576
|
const liftAccessLevels = async (req, res) => {
|
|
27844
28577
|
try {
|
|
27845
28578
|
const { acm_url } = req.query;
|
|
28579
|
+
const user = req.cookies?.sid;
|
|
27846
28580
|
if (!acm_url || typeof acm_url !== "string") {
|
|
27847
28581
|
throw new Error("Access Control URL is required");
|
|
27848
28582
|
}
|
|
27849
|
-
const result = await liftAccessLevelsSvc({ acm_url });
|
|
28583
|
+
const result = await liftAccessLevelsSvc({ acm_url, user });
|
|
27850
28584
|
return res.status(200).json({ message: "Success", data: result });
|
|
27851
28585
|
} catch (error) {
|
|
27852
28586
|
return res.status(400).json({
|
|
@@ -27870,12 +28604,123 @@ function useAccessManagementController() {
|
|
|
27870
28604
|
});
|
|
27871
28605
|
}
|
|
27872
28606
|
};
|
|
28607
|
+
const accessManagementSettings = async (req, res) => {
|
|
28608
|
+
try {
|
|
28609
|
+
const settings = req.body;
|
|
28610
|
+
const result = await accessManagementSettingsSvc(settings);
|
|
28611
|
+
return res.status(201).json({ message: "Success", data: result });
|
|
28612
|
+
} catch (error) {
|
|
28613
|
+
return res.status(400).json({
|
|
28614
|
+
data: null,
|
|
28615
|
+
message: error.message
|
|
28616
|
+
});
|
|
28617
|
+
}
|
|
28618
|
+
};
|
|
28619
|
+
const allAccessCardsCounts = async (req, res) => {
|
|
28620
|
+
try {
|
|
28621
|
+
const { site, userType } = req.query;
|
|
28622
|
+
const schema2 = Joi85.object({
|
|
28623
|
+
site: Joi85.string().hex().required(),
|
|
28624
|
+
userType: Joi85.string().required()
|
|
28625
|
+
});
|
|
28626
|
+
const { error } = schema2.validate({ site, userType });
|
|
28627
|
+
if (error) {
|
|
28628
|
+
throw new Error(`${error.message}`);
|
|
28629
|
+
}
|
|
28630
|
+
const result = await allAccessCardsCountsSvc({ site, userType });
|
|
28631
|
+
return res.status(200).json({ message: "Success", data: result });
|
|
28632
|
+
} catch (error) {
|
|
28633
|
+
return res.status(400).json({
|
|
28634
|
+
data: null,
|
|
28635
|
+
message: error.message
|
|
28636
|
+
});
|
|
28637
|
+
}
|
|
28638
|
+
};
|
|
28639
|
+
const availableAccessCards = async (req, res) => {
|
|
28640
|
+
try {
|
|
28641
|
+
const { site, userType, type } = req.query;
|
|
28642
|
+
const schema2 = Joi85.object({
|
|
28643
|
+
site: Joi85.string().hex().required(),
|
|
28644
|
+
userType: Joi85.string().optional().allow("", null),
|
|
28645
|
+
type: Joi85.string().optional().allow("", null)
|
|
28646
|
+
});
|
|
28647
|
+
const { error } = schema2.validate({ site, userType, type });
|
|
28648
|
+
if (error) {
|
|
28649
|
+
return res.status(400).json({ message: error.message });
|
|
28650
|
+
}
|
|
28651
|
+
const result = await availableAccessCardsSvc({ site, userType, type });
|
|
28652
|
+
return res.status(200).json({ message: "Success", data: result });
|
|
28653
|
+
} catch (error) {
|
|
28654
|
+
return res.status(400).json({
|
|
28655
|
+
data: null,
|
|
28656
|
+
message: error.message
|
|
28657
|
+
});
|
|
28658
|
+
}
|
|
28659
|
+
};
|
|
28660
|
+
const userTypeAccessCards = async (req, res) => {
|
|
28661
|
+
try {
|
|
28662
|
+
const {
|
|
28663
|
+
page = 1,
|
|
28664
|
+
limit = 10,
|
|
28665
|
+
search = "",
|
|
28666
|
+
site,
|
|
28667
|
+
organization,
|
|
28668
|
+
userType
|
|
28669
|
+
} = req.query;
|
|
28670
|
+
const schema2 = Joi85.object({
|
|
28671
|
+
page: Joi85.number().required(),
|
|
28672
|
+
limit: Joi85.number().optional().default(10),
|
|
28673
|
+
site: Joi85.string().hex().required(),
|
|
28674
|
+
organization: Joi85.string().hex().optional().allow("", null),
|
|
28675
|
+
search: Joi85.string().optional().allow("", null),
|
|
28676
|
+
userType: Joi85.string().required()
|
|
28677
|
+
});
|
|
28678
|
+
const { error } = schema2.validate({ page, limit, site, organization, search, userType });
|
|
28679
|
+
if (error) {
|
|
28680
|
+
return res.status(400).json({ message: error.message });
|
|
28681
|
+
}
|
|
28682
|
+
const result = await userTypeAccessCardsSvc({ page, limit, search, site, organization, userType });
|
|
28683
|
+
return res.status(200).json({ message: "Success", data: result });
|
|
28684
|
+
} catch (error) {
|
|
28685
|
+
return res.status(500).json({
|
|
28686
|
+
data: null,
|
|
28687
|
+
message: error.message
|
|
28688
|
+
});
|
|
28689
|
+
}
|
|
28690
|
+
};
|
|
28691
|
+
const assignedAccessCards = async (req, res) => {
|
|
28692
|
+
try {
|
|
28693
|
+
const { site, userType, type, search = "" } = req.query;
|
|
28694
|
+
const schema2 = Joi85.object({
|
|
28695
|
+
site: Joi85.string().hex().required(),
|
|
28696
|
+
userType: Joi85.string().required(),
|
|
28697
|
+
type: Joi85.string().required(),
|
|
28698
|
+
search: Joi85.string().optional().allow("", null)
|
|
28699
|
+
});
|
|
28700
|
+
const { error } = schema2.validate({ site, userType, type, search });
|
|
28701
|
+
if (error) {
|
|
28702
|
+
return res.status(400).json({ message: error.message });
|
|
28703
|
+
}
|
|
28704
|
+
const result = await assignedAccessCardsSvc({ site, userType, type, search });
|
|
28705
|
+
return res.status(200).json({ message: "Success", data: result });
|
|
28706
|
+
} catch (error) {
|
|
28707
|
+
return res.status(500).json({
|
|
28708
|
+
data: null,
|
|
28709
|
+
message: error.message
|
|
28710
|
+
});
|
|
28711
|
+
}
|
|
28712
|
+
};
|
|
27873
28713
|
return {
|
|
27874
28714
|
addPhysicalCard,
|
|
27875
28715
|
addNonPhysicalCard,
|
|
27876
28716
|
doorAccessLevels,
|
|
27877
28717
|
liftAccessLevels,
|
|
27878
|
-
accessGroups
|
|
28718
|
+
accessGroups,
|
|
28719
|
+
accessManagementSettings,
|
|
28720
|
+
allAccessCardsCounts,
|
|
28721
|
+
availableAccessCards,
|
|
28722
|
+
userTypeAccessCards,
|
|
28723
|
+
assignedAccessCards
|
|
27879
28724
|
};
|
|
27880
28725
|
}
|
|
27881
28726
|
|
|
@@ -27945,7 +28790,7 @@ import {
|
|
|
27945
28790
|
makeCacheKey as makeCacheKey45,
|
|
27946
28791
|
paginate as paginate39,
|
|
27947
28792
|
useAtlas as useAtlas75,
|
|
27948
|
-
useCache as
|
|
28793
|
+
useCache as useCache48
|
|
27949
28794
|
} from "@7365admin1/node-server-utils";
|
|
27950
28795
|
import { ObjectId as ObjectId85 } from "mongodb";
|
|
27951
28796
|
function useNfcPatrolTagRepo() {
|
|
@@ -27956,8 +28801,8 @@ function useNfcPatrolTagRepo() {
|
|
|
27956
28801
|
const namespace_collection = "nfc-patrol-tags";
|
|
27957
28802
|
const namespace_collection_nfc_patrol_routes = "nfc-patrol-routes";
|
|
27958
28803
|
const collection = db.collection(namespace_collection);
|
|
27959
|
-
const { delNamespace, getCache, setCache } =
|
|
27960
|
-
const { delNamespace: delNamespaceNfcPatrolRoutes } =
|
|
28804
|
+
const { delNamespace, getCache, setCache } = useCache48(namespace_collection);
|
|
28805
|
+
const { delNamespace: delNamespaceNfcPatrolRoutes } = useCache48(
|
|
27961
28806
|
namespace_collection_nfc_patrol_routes
|
|
27962
28807
|
);
|
|
27963
28808
|
async function createIndexes() {
|
|
@@ -28404,7 +29249,7 @@ import {
|
|
|
28404
29249
|
NotFoundError as NotFoundError37,
|
|
28405
29250
|
paginate as paginate40,
|
|
28406
29251
|
useAtlas as useAtlas77,
|
|
28407
|
-
useCache as
|
|
29252
|
+
useCache as useCache49
|
|
28408
29253
|
} from "@7365admin1/node-server-utils";
|
|
28409
29254
|
import { ObjectId as ObjectId87 } from "mongodb";
|
|
28410
29255
|
function useOccurrenceBookRepo() {
|
|
@@ -28436,7 +29281,7 @@ function useOccurrenceBookRepo() {
|
|
|
28436
29281
|
}
|
|
28437
29282
|
const namespace_collection = "occurrence-books";
|
|
28438
29283
|
const collection = db.collection(namespace_collection);
|
|
28439
|
-
const { delNamespace, getCache, setCache } =
|
|
29284
|
+
const { delNamespace, getCache, setCache } = useCache49(namespace_collection);
|
|
28440
29285
|
async function add(value, session) {
|
|
28441
29286
|
try {
|
|
28442
29287
|
value = MOccurrenceBook(value);
|
|
@@ -29014,7 +29859,7 @@ import {
|
|
|
29014
29859
|
NotFoundError as NotFoundError38,
|
|
29015
29860
|
paginate as paginate41,
|
|
29016
29861
|
useAtlas as useAtlas79,
|
|
29017
|
-
useCache as
|
|
29862
|
+
useCache as useCache50
|
|
29018
29863
|
} from "@7365admin1/node-server-utils";
|
|
29019
29864
|
import { ObjectId as ObjectId89 } from "mongodb";
|
|
29020
29865
|
function useBulletinVideoRepo() {
|
|
@@ -29033,7 +29878,7 @@ function useBulletinVideoRepo() {
|
|
|
29033
29878
|
}
|
|
29034
29879
|
const namespace_collection = "bulletin-videos";
|
|
29035
29880
|
const collection = db.collection(namespace_collection);
|
|
29036
|
-
const { delNamespace, getCache, setCache } =
|
|
29881
|
+
const { delNamespace, getCache, setCache } = useCache50(namespace_collection);
|
|
29037
29882
|
async function add(value, session) {
|
|
29038
29883
|
try {
|
|
29039
29884
|
value = MBulletinVideo(value);
|
|
@@ -29565,7 +30410,7 @@ import {
|
|
|
29565
30410
|
InternalServerError as InternalServerError51,
|
|
29566
30411
|
logger as logger127,
|
|
29567
30412
|
useAtlas as useAtlas81,
|
|
29568
|
-
useCache as
|
|
30413
|
+
useCache as useCache51,
|
|
29569
30414
|
paginate as paginate42,
|
|
29570
30415
|
makeCacheKey as makeCacheKey48
|
|
29571
30416
|
} from "@7365admin1/node-server-utils";
|
|
@@ -29577,7 +30422,7 @@ function useStatementOfAccountRepo() {
|
|
|
29577
30422
|
}
|
|
29578
30423
|
const namespace_collection = "site.statement-of-accounts";
|
|
29579
30424
|
const collection = db.collection(namespace_collection);
|
|
29580
|
-
const { delNamespace, getCache, setCache } =
|
|
30425
|
+
const { delNamespace, getCache, setCache } = useCache51(namespace_collection);
|
|
29581
30426
|
async function createTextIndex() {
|
|
29582
30427
|
try {
|
|
29583
30428
|
await collection.createIndex({
|
|
@@ -30340,7 +31185,7 @@ import {
|
|
|
30340
31185
|
NotFoundError as NotFoundError40,
|
|
30341
31186
|
paginate as paginate43,
|
|
30342
31187
|
useAtlas as useAtlas83,
|
|
30343
|
-
useCache as
|
|
31188
|
+
useCache as useCache52
|
|
30344
31189
|
} from "@7365admin1/node-server-utils";
|
|
30345
31190
|
import { ObjectId as ObjectId93 } from "mongodb";
|
|
30346
31191
|
function useEntryPassSettingsRepo() {
|
|
@@ -30350,7 +31195,7 @@ function useEntryPassSettingsRepo() {
|
|
|
30350
31195
|
}
|
|
30351
31196
|
const namespace_collection = "site.entrypass-settings";
|
|
30352
31197
|
const collection = db.collection(namespace_collection);
|
|
30353
|
-
const { delNamespace, getCache, setCache } =
|
|
31198
|
+
const { delNamespace, getCache, setCache } = useCache52(namespace_collection);
|
|
30354
31199
|
async function createTextIndex() {
|
|
30355
31200
|
try {
|
|
30356
31201
|
await collection.createIndex({
|
|
@@ -30912,7 +31757,7 @@ import {
|
|
|
30912
31757
|
logger as logger133,
|
|
30913
31758
|
makeCacheKey as makeCacheKey50,
|
|
30914
31759
|
useAtlas as useAtlas84,
|
|
30915
|
-
useCache as
|
|
31760
|
+
useCache as useCache53
|
|
30916
31761
|
} from "@7365admin1/node-server-utils";
|
|
30917
31762
|
function useDashboardRepo() {
|
|
30918
31763
|
const db = useAtlas84.getDb();
|
|
@@ -30923,7 +31768,7 @@ function useDashboardRepo() {
|
|
|
30923
31768
|
const work_order_collection = db.collection("work-orders");
|
|
30924
31769
|
const visitor_collection = db.collection("visitor.transactions");
|
|
30925
31770
|
const namespace_collection = "dashboard";
|
|
30926
|
-
const { delNamespace, getCache, setCache } =
|
|
31771
|
+
const { delNamespace, getCache, setCache } = useCache53(namespace_collection);
|
|
30927
31772
|
async function getAll({
|
|
30928
31773
|
site = ""
|
|
30929
31774
|
}, session) {
|
|
@@ -31087,7 +31932,7 @@ import {
|
|
|
31087
31932
|
makeCacheKey as makeCacheKey51,
|
|
31088
31933
|
paginate as paginate44,
|
|
31089
31934
|
useAtlas as useAtlas85,
|
|
31090
|
-
useCache as
|
|
31935
|
+
useCache as useCache54
|
|
31091
31936
|
} from "@7365admin1/node-server-utils";
|
|
31092
31937
|
import { ObjectId as ObjectId95 } from "mongodb";
|
|
31093
31938
|
function useNfcPatrolRouteRepo() {
|
|
@@ -31097,7 +31942,7 @@ function useNfcPatrolRouteRepo() {
|
|
|
31097
31942
|
}
|
|
31098
31943
|
const namespace_collection = "nfc-patrol-routes";
|
|
31099
31944
|
const collection = db.collection(namespace_collection);
|
|
31100
|
-
const { delNamespace, getCache, setCache } =
|
|
31945
|
+
const { delNamespace, getCache, setCache } = useCache54(namespace_collection);
|
|
31101
31946
|
async function createIndexes() {
|
|
31102
31947
|
try {
|
|
31103
31948
|
await collection.createIndexes([
|
|
@@ -31819,7 +32664,11 @@ function MIncidentReport(value) {
|
|
|
31819
32664
|
}
|
|
31820
32665
|
|
|
31821
32666
|
// src/services/incident-report.service.ts
|
|
31822
|
-
import {
|
|
32667
|
+
import {
|
|
32668
|
+
useAtlas as useAtlas88,
|
|
32669
|
+
BadRequestError as BadRequestError160,
|
|
32670
|
+
NotFoundError as NotFoundError44
|
|
32671
|
+
} from "@7365admin1/node-server-utils";
|
|
31823
32672
|
|
|
31824
32673
|
// src/repositories/incident-report.repo.ts
|
|
31825
32674
|
import {
|
|
@@ -31830,7 +32679,7 @@ import {
|
|
|
31830
32679
|
NotFoundError as NotFoundError43,
|
|
31831
32680
|
paginate as paginate45,
|
|
31832
32681
|
useAtlas as useAtlas87,
|
|
31833
|
-
useCache as
|
|
32682
|
+
useCache as useCache55
|
|
31834
32683
|
} from "@7365admin1/node-server-utils";
|
|
31835
32684
|
import { ObjectId as ObjectId97 } from "mongodb";
|
|
31836
32685
|
function useIncidentReportRepo() {
|
|
@@ -31861,7 +32710,7 @@ function useIncidentReportRepo() {
|
|
|
31861
32710
|
}
|
|
31862
32711
|
const namespace_collection = "incident-reports";
|
|
31863
32712
|
const collection = db.collection(namespace_collection);
|
|
31864
|
-
const { delNamespace, getCache, setCache } =
|
|
32713
|
+
const { delNamespace, getCache, setCache } = useCache55(namespace_collection);
|
|
31865
32714
|
async function add(value, session) {
|
|
31866
32715
|
try {
|
|
31867
32716
|
value = MIncidentReport(value);
|
|
@@ -32151,15 +33000,18 @@ function useIncidentReportService() {
|
|
|
32151
33000
|
const {
|
|
32152
33001
|
add: _add,
|
|
32153
33002
|
updateIncidentReportById: _updateIncidentReportById,
|
|
32154
|
-
reviewIncidentReport: _reviewIncidentReport
|
|
33003
|
+
reviewIncidentReport: _reviewIncidentReport,
|
|
33004
|
+
getIncidentReportById: _getIncidentReportById
|
|
32155
33005
|
} = useIncidentReportRepo();
|
|
32156
33006
|
const {
|
|
32157
33007
|
updateSiteIncidentCounter: _updateSiteIncidentCounter,
|
|
32158
33008
|
getSiteById: _getSiteById
|
|
32159
33009
|
} = useSiteRepo();
|
|
33010
|
+
const { updateStatusById } = useFileRepo();
|
|
32160
33011
|
const { getUserById } = useUserRepo();
|
|
32161
33012
|
const { getById: _getUnitById } = useBuildingUnitRepo();
|
|
32162
33013
|
const { getById: _getOrganizationById } = useOrgRepo();
|
|
33014
|
+
const { deleteFile } = useFileService();
|
|
32163
33015
|
async function add(value) {
|
|
32164
33016
|
const session = useAtlas88.getClient()?.startSession();
|
|
32165
33017
|
session?.startTransaction();
|
|
@@ -32177,6 +33029,19 @@ function useIncidentReportService() {
|
|
|
32177
33029
|
);
|
|
32178
33030
|
}
|
|
32179
33031
|
}
|
|
33032
|
+
const incidentAttachments = value?.photos ?? [];
|
|
33033
|
+
if (incidentAttachments.length > 0) {
|
|
33034
|
+
for (const attachment of incidentAttachments) {
|
|
33035
|
+
const file = await updateStatusById(
|
|
33036
|
+
attachment,
|
|
33037
|
+
{ status: "active" },
|
|
33038
|
+
session
|
|
33039
|
+
);
|
|
33040
|
+
if (!file) {
|
|
33041
|
+
throw new NotFoundError44("File not found.");
|
|
33042
|
+
}
|
|
33043
|
+
}
|
|
33044
|
+
}
|
|
32180
33045
|
const result = await _add(value, session);
|
|
32181
33046
|
await session?.commitTransaction();
|
|
32182
33047
|
return result;
|
|
@@ -32191,6 +33056,26 @@ function useIncidentReportService() {
|
|
|
32191
33056
|
const session = useAtlas88.getClient()?.startSession();
|
|
32192
33057
|
session?.startTransaction();
|
|
32193
33058
|
try {
|
|
33059
|
+
const incidentReport = await _getIncidentReportById(id);
|
|
33060
|
+
const dataAttchments = value?.photos || [];
|
|
33061
|
+
const incidentAttachments = incidentReport?.photos || [];
|
|
33062
|
+
const deletedFiles = [];
|
|
33063
|
+
incidentAttachments.forEach((id2) => {
|
|
33064
|
+
if (!dataAttchments.includes(id2)) {
|
|
33065
|
+
deletedFiles.push(id2);
|
|
33066
|
+
}
|
|
33067
|
+
});
|
|
33068
|
+
if (deletedFiles.length > 0) {
|
|
33069
|
+
await Promise.all(
|
|
33070
|
+
deletedFiles.map(async (id2) => {
|
|
33071
|
+
try {
|
|
33072
|
+
await deleteFile(id2);
|
|
33073
|
+
} catch (error) {
|
|
33074
|
+
throw error;
|
|
33075
|
+
}
|
|
33076
|
+
})
|
|
33077
|
+
);
|
|
33078
|
+
}
|
|
32194
33079
|
await _updateIncidentReportById(id, value, session);
|
|
32195
33080
|
await session?.commitTransaction();
|
|
32196
33081
|
return "Successfully updated incident report.";
|
|
@@ -32564,9 +33449,9 @@ import {
|
|
|
32564
33449
|
InternalServerError as InternalServerError56,
|
|
32565
33450
|
logger as logger142,
|
|
32566
33451
|
makeCacheKey as makeCacheKey53,
|
|
32567
|
-
NotFoundError as
|
|
33452
|
+
NotFoundError as NotFoundError45,
|
|
32568
33453
|
useAtlas as useAtlas89,
|
|
32569
|
-
useCache as
|
|
33454
|
+
useCache as useCache56
|
|
32570
33455
|
} from "@7365admin1/node-server-utils";
|
|
32571
33456
|
import { ObjectId as ObjectId99 } from "mongodb";
|
|
32572
33457
|
function useNfcPatrolSettingsRepository() {
|
|
@@ -32576,7 +33461,7 @@ function useNfcPatrolSettingsRepository() {
|
|
|
32576
33461
|
}
|
|
32577
33462
|
const namespace_collection = "site.nfc-patrol-settings";
|
|
32578
33463
|
const collection = db.collection(namespace_collection);
|
|
32579
|
-
const { delNamespace, setCache, getCache } =
|
|
33464
|
+
const { delNamespace, setCache, getCache } = useCache56(namespace_collection);
|
|
32580
33465
|
async function createIndexes() {
|
|
32581
33466
|
try {
|
|
32582
33467
|
await collection.createIndexes([{ key: { site: 1 }, unique: true }]);
|
|
@@ -32654,7 +33539,7 @@ function useNfcPatrolSettingsRepository() {
|
|
|
32654
33539
|
{ session }
|
|
32655
33540
|
);
|
|
32656
33541
|
if (res.matchedCount === 0) {
|
|
32657
|
-
throw new
|
|
33542
|
+
throw new NotFoundError45("NFC patrol settings not found for this site.");
|
|
32658
33543
|
}
|
|
32659
33544
|
delNamespace().then(() => {
|
|
32660
33545
|
logger142.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
@@ -32818,10 +33703,10 @@ import {
|
|
|
32818
33703
|
InternalServerError as InternalServerError57,
|
|
32819
33704
|
logger as logger145,
|
|
32820
33705
|
makeCacheKey as makeCacheKey54,
|
|
32821
|
-
NotFoundError as
|
|
33706
|
+
NotFoundError as NotFoundError46,
|
|
32822
33707
|
paginate as paginate46,
|
|
32823
33708
|
useAtlas as useAtlas91,
|
|
32824
|
-
useCache as
|
|
33709
|
+
useCache as useCache57
|
|
32825
33710
|
} from "@7365admin1/node-server-utils";
|
|
32826
33711
|
|
|
32827
33712
|
// src/models/occurrence-subject.model.ts
|
|
@@ -32898,7 +33783,7 @@ function useOccurrenceSubjectRepo() {
|
|
|
32898
33783
|
}
|
|
32899
33784
|
const namespace_collection = "occurrence-subjects";
|
|
32900
33785
|
const collection = db.collection(namespace_collection);
|
|
32901
|
-
const { delNamespace, getCache, setCache } =
|
|
33786
|
+
const { delNamespace, getCache, setCache } = useCache57(namespace_collection);
|
|
32902
33787
|
async function add(value, session) {
|
|
32903
33788
|
try {
|
|
32904
33789
|
value = MOccurrenceSubject(value);
|
|
@@ -33037,7 +33922,7 @@ function useOccurrenceSubjectRepo() {
|
|
|
33037
33922
|
try {
|
|
33038
33923
|
const data = await collection.findOne({ _id }, { session });
|
|
33039
33924
|
if (!data) {
|
|
33040
|
-
throw new
|
|
33925
|
+
throw new NotFoundError46("Occurrence subject not found.");
|
|
33041
33926
|
}
|
|
33042
33927
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
33043
33928
|
logger145.info(`Cache set for key: ${cacheKey}`);
|
|
@@ -33463,10 +34348,10 @@ import {
|
|
|
33463
34348
|
InternalServerError as InternalServerError58,
|
|
33464
34349
|
logger as logger147,
|
|
33465
34350
|
makeCacheKey as makeCacheKey55,
|
|
33466
|
-
NotFoundError as
|
|
34351
|
+
NotFoundError as NotFoundError47,
|
|
33467
34352
|
paginate as paginate47,
|
|
33468
34353
|
useAtlas as useAtlas93,
|
|
33469
|
-
useCache as
|
|
34354
|
+
useCache as useCache58
|
|
33470
34355
|
} from "@7365admin1/node-server-utils";
|
|
33471
34356
|
import { ObjectId as ObjectId103 } from "mongodb";
|
|
33472
34357
|
function useOnlineFormRepo() {
|
|
@@ -33476,7 +34361,7 @@ function useOnlineFormRepo() {
|
|
|
33476
34361
|
}
|
|
33477
34362
|
const namespace_collection = "online-forms";
|
|
33478
34363
|
const collection = db.collection(namespace_collection);
|
|
33479
|
-
const { delNamespace, getCache, setCache } =
|
|
34364
|
+
const { delNamespace, getCache, setCache } = useCache58(namespace_collection);
|
|
33480
34365
|
async function createTextIndex() {
|
|
33481
34366
|
try {
|
|
33482
34367
|
await collection.createIndex({
|
|
@@ -33599,7 +34484,7 @@ function useOnlineFormRepo() {
|
|
|
33599
34484
|
}
|
|
33600
34485
|
]).toArray();
|
|
33601
34486
|
if (!data || !data.length) {
|
|
33602
|
-
throw new
|
|
34487
|
+
throw new NotFoundError47("Document not found.");
|
|
33603
34488
|
}
|
|
33604
34489
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
33605
34490
|
logger147.info(`Cache set for key: ${cacheKey}`);
|
|
@@ -34212,7 +35097,7 @@ import {
|
|
|
34212
35097
|
makeCacheKey as makeCacheKey56,
|
|
34213
35098
|
paginate as paginate48,
|
|
34214
35099
|
useAtlas as useAtlas95,
|
|
34215
|
-
useCache as
|
|
35100
|
+
useCache as useCache59
|
|
34216
35101
|
} from "@7365admin1/node-server-utils";
|
|
34217
35102
|
import { ObjectId as ObjectId105 } from "mongodb";
|
|
34218
35103
|
function useNfcPatrolLogRepo() {
|
|
@@ -34222,7 +35107,7 @@ function useNfcPatrolLogRepo() {
|
|
|
34222
35107
|
}
|
|
34223
35108
|
const namespace_collection = "nfc-patrol-logs";
|
|
34224
35109
|
const collection = db.collection(namespace_collection);
|
|
34225
|
-
const { delNamespace, getCache, setCache } =
|
|
35110
|
+
const { delNamespace, getCache, setCache } = useCache59(namespace_collection);
|
|
34226
35111
|
async function createIndexes() {
|
|
34227
35112
|
try {
|
|
34228
35113
|
await collection.createIndexes([
|