@7365admin1/core 2.49.0 → 2.51.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 +10 -2
- package/dist/index.js +230 -52
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +230 -52
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4333,6 +4333,9 @@ function useVerificationRepo() {
|
|
|
4333
4333
|
return Promise.reject(error);
|
|
4334
4334
|
}
|
|
4335
4335
|
}
|
|
4336
|
+
async function findOne(query) {
|
|
4337
|
+
return await collection.findOne(query);
|
|
4338
|
+
}
|
|
4336
4339
|
return {
|
|
4337
4340
|
createIndex,
|
|
4338
4341
|
createTextIndex,
|
|
@@ -4341,7 +4344,8 @@ function useVerificationRepo() {
|
|
|
4341
4344
|
getVerifications,
|
|
4342
4345
|
getByIdByType,
|
|
4343
4346
|
updateStatusById,
|
|
4344
|
-
getByStatus
|
|
4347
|
+
getByStatus,
|
|
4348
|
+
findOne
|
|
4345
4349
|
};
|
|
4346
4350
|
}
|
|
4347
4351
|
|
|
@@ -5645,29 +5649,28 @@ function useVerificationService() {
|
|
|
5645
5649
|
throw error;
|
|
5646
5650
|
}
|
|
5647
5651
|
}
|
|
5648
|
-
async function createSimpleUserInvite({
|
|
5649
|
-
email,
|
|
5650
|
-
metadata
|
|
5651
|
-
}) {
|
|
5652
|
+
async function createSimpleUserInvite({ email, metadata }) {
|
|
5652
5653
|
const type = "user-invite";
|
|
5654
|
+
if (metadata?.org)
|
|
5655
|
+
await getOrgById(metadata.org);
|
|
5656
|
+
if (metadata?.siteId)
|
|
5657
|
+
await getSiteById(metadata.siteId);
|
|
5658
|
+
const existing = await useVerificationRepo().findOne({
|
|
5659
|
+
type,
|
|
5660
|
+
email,
|
|
5661
|
+
"metadata.org": metadata?.org,
|
|
5662
|
+
"metadata.siteId": metadata?.siteId
|
|
5663
|
+
});
|
|
5664
|
+
if (existing)
|
|
5665
|
+
return existing._id;
|
|
5653
5666
|
const value = {
|
|
5654
5667
|
type,
|
|
5655
5668
|
email,
|
|
5656
5669
|
metadata,
|
|
5657
|
-
expireAt: new Date(
|
|
5658
|
-
(/* @__PURE__ */ new Date()).getTime() + 72 * 60 * 60 * 1e3
|
|
5659
|
-
).toISOString(),
|
|
5670
|
+
expireAt: new Date(Date.now() + 72 * 60 * 60 * 1e3).toISOString(),
|
|
5660
5671
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5661
5672
|
};
|
|
5662
|
-
if (value.metadata?.org) {
|
|
5663
|
-
await getOrgById(value.metadata?.org);
|
|
5664
|
-
}
|
|
5665
|
-
if (value.metadata?.siteId) {
|
|
5666
|
-
await getSiteById(value.metadata?.siteId);
|
|
5667
|
-
}
|
|
5668
5673
|
const res = await add(value);
|
|
5669
|
-
const dir = __dirname;
|
|
5670
|
-
const filePath = (0, import_node_server_utils21.getDirectory)(dir, "./public/handlebars/user-invite");
|
|
5671
5674
|
const link = `${APP_MAIN}/verify/invitation/${res}`;
|
|
5672
5675
|
const emailContent = (0, import_node_server_utils21.compileHandlebar)({
|
|
5673
5676
|
context: {
|
|
@@ -5675,9 +5678,9 @@ function useVerificationService() {
|
|
|
5675
5678
|
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
5676
5679
|
link
|
|
5677
5680
|
},
|
|
5678
|
-
filePath
|
|
5681
|
+
filePath: (0, import_node_server_utils21.getDirectory)(__dirname, "./public/handlebars/user-invite")
|
|
5679
5682
|
});
|
|
5680
|
-
mailer.sendMail({
|
|
5683
|
+
await mailer.sendMail({
|
|
5681
5684
|
to: email,
|
|
5682
5685
|
subject: "User Invite",
|
|
5683
5686
|
html: emailContent,
|
|
@@ -7504,7 +7507,7 @@ function useMemberService() {
|
|
|
7504
7507
|
getByRoles
|
|
7505
7508
|
} = useMemberRepo();
|
|
7506
7509
|
const { getById: _getVerificationById, updateStatusById } = useVerificationRepo();
|
|
7507
|
-
const { getUserByEmail, updateDefaultOrgByEmail } = useUserRepo();
|
|
7510
|
+
const { getUserByEmail, updateDefaultOrgByEmail, getUserById } = useUserRepo();
|
|
7508
7511
|
const { getById: getOrgById } = useOrgRepo();
|
|
7509
7512
|
const { getSiteById } = useSiteRepo();
|
|
7510
7513
|
const { getOwnerRolesByTypeOrg } = useRoleRepo();
|
|
@@ -7566,6 +7569,52 @@ function useMemberService() {
|
|
|
7566
7569
|
session?.endSession();
|
|
7567
7570
|
}
|
|
7568
7571
|
}
|
|
7572
|
+
async function createMemberDirect({
|
|
7573
|
+
userId,
|
|
7574
|
+
orgId,
|
|
7575
|
+
roleId,
|
|
7576
|
+
app,
|
|
7577
|
+
siteId,
|
|
7578
|
+
siteName
|
|
7579
|
+
}) {
|
|
7580
|
+
const session = import_node_server_utils30.useAtlas.getClient()?.startSession();
|
|
7581
|
+
session?.startTransaction();
|
|
7582
|
+
try {
|
|
7583
|
+
const org = await getOrgById(orgId);
|
|
7584
|
+
if (!org)
|
|
7585
|
+
throw new import_node_server_utils30.BadRequestError("Organization not found.");
|
|
7586
|
+
const user = await getUserById(userId);
|
|
7587
|
+
if (!user)
|
|
7588
|
+
throw new import_node_server_utils30.BadRequestError("User not found.");
|
|
7589
|
+
const member = await addMember(
|
|
7590
|
+
{
|
|
7591
|
+
org: org._id?.toString() || "",
|
|
7592
|
+
orgName: org.name || "",
|
|
7593
|
+
user: user._id?.toString() || "",
|
|
7594
|
+
name: user?.email,
|
|
7595
|
+
role: roleId,
|
|
7596
|
+
type: app,
|
|
7597
|
+
siteId: siteId ?? "",
|
|
7598
|
+
siteName: siteName ?? ""
|
|
7599
|
+
},
|
|
7600
|
+
session
|
|
7601
|
+
);
|
|
7602
|
+
if (!user.defaultOrg) {
|
|
7603
|
+
await updateDefaultOrgByEmail(
|
|
7604
|
+
user.email,
|
|
7605
|
+
org._id?.toString() || "",
|
|
7606
|
+
session
|
|
7607
|
+
);
|
|
7608
|
+
}
|
|
7609
|
+
await session?.commitTransaction();
|
|
7610
|
+
return { member };
|
|
7611
|
+
} catch (error) {
|
|
7612
|
+
await session?.abortTransaction();
|
|
7613
|
+
throw error;
|
|
7614
|
+
} finally {
|
|
7615
|
+
session?.endSession();
|
|
7616
|
+
}
|
|
7617
|
+
}
|
|
7569
7618
|
async function updateRoleById(id, role, type, org) {
|
|
7570
7619
|
const owner = await getOwnerRolesByTypeOrg(type, org);
|
|
7571
7620
|
if (!owner.length) {
|
|
@@ -7593,6 +7642,7 @@ function useMemberService() {
|
|
|
7593
7642
|
}
|
|
7594
7643
|
return {
|
|
7595
7644
|
createMember,
|
|
7645
|
+
createMemberDirect,
|
|
7596
7646
|
updateRoleById
|
|
7597
7647
|
};
|
|
7598
7648
|
}
|
|
@@ -7607,7 +7657,7 @@ function useMemberController() {
|
|
|
7607
7657
|
updateMemberStatus: _updateMemberStatus,
|
|
7608
7658
|
updateStatusByUserId: _updateStatusByUserId
|
|
7609
7659
|
} = useMemberRepo();
|
|
7610
|
-
const { createMember: _createMember, updateRoleById: _updateRoleById } = useMemberService();
|
|
7660
|
+
const { createMember: _createMember, createMemberDirect: _createMemberDirect, updateRoleById: _updateRoleById } = useMemberService();
|
|
7611
7661
|
async function createMember(req, res, next) {
|
|
7612
7662
|
const validation = import_joi15.default.string().hex().required();
|
|
7613
7663
|
const _id = req.params.id;
|
|
@@ -7796,6 +7846,32 @@ function useMemberController() {
|
|
|
7796
7846
|
return;
|
|
7797
7847
|
}
|
|
7798
7848
|
}
|
|
7849
|
+
async function createMemberDirect(req, res, next) {
|
|
7850
|
+
const validation = import_joi15.default.object({
|
|
7851
|
+
userId: import_joi15.default.string().hex().required(),
|
|
7852
|
+
orgId: import_joi15.default.string().hex().required(),
|
|
7853
|
+
roleId: import_joi15.default.string().hex().required(),
|
|
7854
|
+
app: import_joi15.default.string().required(),
|
|
7855
|
+
siteId: import_joi15.default.string().hex().optional().allow("", null),
|
|
7856
|
+
siteName: import_joi15.default.string().optional().allow("", null)
|
|
7857
|
+
});
|
|
7858
|
+
const { error } = validation.validate(req.body);
|
|
7859
|
+
if (error) {
|
|
7860
|
+
import_node_server_utils31.logger.log({ level: "error", message: error.message });
|
|
7861
|
+
next(new import_node_server_utils31.BadRequestError(error.message));
|
|
7862
|
+
return;
|
|
7863
|
+
}
|
|
7864
|
+
const { userId, orgId, roleId, app, siteId, siteName } = req.body;
|
|
7865
|
+
try {
|
|
7866
|
+
const data = await _createMemberDirect({ userId, orgId, roleId, app, siteId, siteName });
|
|
7867
|
+
res.status(201).json(data);
|
|
7868
|
+
return;
|
|
7869
|
+
} catch (error2) {
|
|
7870
|
+
import_node_server_utils31.logger.log({ level: "error", message: error2.message });
|
|
7871
|
+
next(error2);
|
|
7872
|
+
return;
|
|
7873
|
+
}
|
|
7874
|
+
}
|
|
7799
7875
|
return {
|
|
7800
7876
|
createMember,
|
|
7801
7877
|
getByUserId,
|
|
@@ -7803,7 +7879,8 @@ function useMemberController() {
|
|
|
7803
7879
|
getAll,
|
|
7804
7880
|
getOrgsByMembership,
|
|
7805
7881
|
updateMemberStatus,
|
|
7806
|
-
updateRoleById
|
|
7882
|
+
updateRoleById,
|
|
7883
|
+
createMemberDirect
|
|
7807
7884
|
};
|
|
7808
7885
|
}
|
|
7809
7886
|
|
|
@@ -14045,14 +14122,14 @@ function useVisitorTransactionRepo() {
|
|
|
14045
14122
|
);
|
|
14046
14123
|
}
|
|
14047
14124
|
}
|
|
14048
|
-
async function updateById(_id, value, session) {
|
|
14125
|
+
async function updateById(_id, value, session, isNotManualCheckOut = true) {
|
|
14049
14126
|
try {
|
|
14050
14127
|
_id = new import_mongodb40.ObjectId(_id);
|
|
14051
14128
|
} catch (error) {
|
|
14052
14129
|
throw new import_node_server_utils68.BadRequestError("Invalid visitor transaction ID format.");
|
|
14053
14130
|
}
|
|
14054
14131
|
value.updatedAt = /* @__PURE__ */ new Date();
|
|
14055
|
-
if (value.checkOut) {
|
|
14132
|
+
if (value.checkOut && isNotManualCheckOut) {
|
|
14056
14133
|
value.manualCheckout = true;
|
|
14057
14134
|
}
|
|
14058
14135
|
try {
|
|
@@ -14803,6 +14880,22 @@ function useVehicleRepo() {
|
|
|
14803
14880
|
throw error;
|
|
14804
14881
|
}
|
|
14805
14882
|
}
|
|
14883
|
+
async function getSpecificVehicleById(_id) {
|
|
14884
|
+
try {
|
|
14885
|
+
_id = new import_mongodb42.ObjectId(_id);
|
|
14886
|
+
} catch (error) {
|
|
14887
|
+
throw new import_node_server_utils70.BadRequestError("Invalid vehicle ID format.");
|
|
14888
|
+
}
|
|
14889
|
+
try {
|
|
14890
|
+
const result = await collection.findOne({ _id });
|
|
14891
|
+
if (!result) {
|
|
14892
|
+
throw new import_node_server_utils70.NotFoundError("Vehicle not found.");
|
|
14893
|
+
}
|
|
14894
|
+
return result;
|
|
14895
|
+
} catch (error) {
|
|
14896
|
+
throw error;
|
|
14897
|
+
}
|
|
14898
|
+
}
|
|
14806
14899
|
async function getByPlaceNumber(value) {
|
|
14807
14900
|
const { error } = import_joi38.default.string().required().validate(value);
|
|
14808
14901
|
if (error) {
|
|
@@ -15061,7 +15154,8 @@ function useVehicleRepo() {
|
|
|
15061
15154
|
deleteExpiredVehicles,
|
|
15062
15155
|
getAllVehiclesByUnitId,
|
|
15063
15156
|
getAllExpiredVehicles,
|
|
15064
|
-
bulkUpsertVehicles
|
|
15157
|
+
bulkUpsertVehicles,
|
|
15158
|
+
getSpecificVehicleById
|
|
15065
15159
|
};
|
|
15066
15160
|
}
|
|
15067
15161
|
|
|
@@ -17317,6 +17411,7 @@ var loggerDahua = winston.createLogger({
|
|
|
17317
17411
|
|
|
17318
17412
|
// src/services/dahua.service.ts
|
|
17319
17413
|
var cameraRegistry = /* @__PURE__ */ new Map();
|
|
17414
|
+
var _savedOnDetected;
|
|
17320
17415
|
function useDahuaDigest({
|
|
17321
17416
|
host = "",
|
|
17322
17417
|
username = "",
|
|
@@ -17381,7 +17476,7 @@ function useDahuaService() {
|
|
|
17381
17476
|
queue.push(buffer);
|
|
17382
17477
|
if (queue.length >= BACKPRESSURE_THRESHOLD && streamRef && !streamRef.isPaused()) {
|
|
17383
17478
|
loggerDahua.warn(
|
|
17384
|
-
`[${site}][${
|
|
17479
|
+
`[${site}][${host}] Queue at ${queue.length}/${MAX_QUEUE_SIZE}, pausing stream`
|
|
17385
17480
|
);
|
|
17386
17481
|
streamRef.pause();
|
|
17387
17482
|
}
|
|
@@ -17398,7 +17493,7 @@ function useDahuaService() {
|
|
|
17398
17493
|
streamRef.resume();
|
|
17399
17494
|
}
|
|
17400
17495
|
loggerDahua.info(
|
|
17401
|
-
`[${site}][${
|
|
17496
|
+
`[${site}][${host}] BufferQueue destroyed. Processed=${processedChunks}, Dropped=${droppedChunks}`
|
|
17402
17497
|
);
|
|
17403
17498
|
}
|
|
17404
17499
|
async function processNext(onDetected2) {
|
|
@@ -17446,9 +17541,9 @@ function useDahuaService() {
|
|
|
17446
17541
|
const transactionId = existingOpenTransaction?._id?.toString() || "";
|
|
17447
17542
|
if (existingOpenTransaction && !existingOpenTransaction.checkOut && transactionId) {
|
|
17448
17543
|
await updateById(transactionId, {
|
|
17449
|
-
checkOut:
|
|
17450
|
-
updatedAt:
|
|
17451
|
-
});
|
|
17544
|
+
checkOut: /* @__PURE__ */ new Date(),
|
|
17545
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
17546
|
+
}, void 0, false);
|
|
17452
17547
|
}
|
|
17453
17548
|
} catch (error) {
|
|
17454
17549
|
loggerDahua.error(
|
|
@@ -17507,7 +17602,7 @@ function useDahuaService() {
|
|
|
17507
17602
|
currentTransactionId = transactionId?.toString();
|
|
17508
17603
|
currentSnapshotField = "snapshotEntryImage";
|
|
17509
17604
|
if (onDetected2) {
|
|
17510
|
-
onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber });
|
|
17605
|
+
onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber, host, direction });
|
|
17511
17606
|
}
|
|
17512
17607
|
} catch (error) {
|
|
17513
17608
|
console.log("failed to create visitor transaction", error);
|
|
@@ -17516,8 +17611,7 @@ function useDahuaService() {
|
|
|
17516
17611
|
error
|
|
17517
17612
|
);
|
|
17518
17613
|
}
|
|
17519
|
-
}
|
|
17520
|
-
if (["exit", "both"].includes(designation) && direction.toLowerCase() === "leave" && plateNumber) {
|
|
17614
|
+
} else if (["exit", "both"].includes(designation) && direction.toLowerCase() === "leave" && plateNumber) {
|
|
17521
17615
|
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17522
17616
|
const existingOpenTransaction = await getOpenByPlateNumber(
|
|
17523
17617
|
plateNumber,
|
|
@@ -17539,6 +17633,9 @@ function useDahuaService() {
|
|
|
17539
17633
|
await removePlateNumber(dahuaPayload);
|
|
17540
17634
|
}
|
|
17541
17635
|
await closeOpenTransaction(plateNumber);
|
|
17636
|
+
if (onDetected2) {
|
|
17637
|
+
onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
|
|
17638
|
+
}
|
|
17542
17639
|
}
|
|
17543
17640
|
}
|
|
17544
17641
|
}
|
|
@@ -17595,7 +17692,7 @@ function useDahuaService() {
|
|
|
17595
17692
|
try {
|
|
17596
17693
|
await import_fs.promises.mkdir(dir, { recursive: true });
|
|
17597
17694
|
await import_fs.promises.writeFile(snapFolder, accumulatedImageBuffer);
|
|
17598
|
-
loggerDahua.
|
|
17695
|
+
loggerDahua.info(`[${host}] Saved image locally: ${filename}`);
|
|
17599
17696
|
const fileId = await _createFile(
|
|
17600
17697
|
{
|
|
17601
17698
|
originalname: filename,
|
|
@@ -17670,9 +17767,12 @@ function useDahuaService() {
|
|
|
17670
17767
|
}
|
|
17671
17768
|
}
|
|
17672
17769
|
async function listenToCamera(camera, onDetected) {
|
|
17770
|
+
if (onDetected) {
|
|
17771
|
+
_savedOnDetected = onDetected;
|
|
17772
|
+
}
|
|
17673
17773
|
if (!camera?._id) {
|
|
17674
17774
|
loggerDahua.error(`Camera _id is required to listen to camera.`);
|
|
17675
|
-
|
|
17775
|
+
return;
|
|
17676
17776
|
}
|
|
17677
17777
|
const cameraId = camera._id.toString();
|
|
17678
17778
|
if (cameraRegistry.has(cameraId)) {
|
|
@@ -17682,6 +17782,11 @@ function useDahuaService() {
|
|
|
17682
17782
|
}
|
|
17683
17783
|
const controller = new AbortController();
|
|
17684
17784
|
cameraRegistry.set(cameraId, controller);
|
|
17785
|
+
const onDetectedHandler = onDetected || _savedOnDetected;
|
|
17786
|
+
if (!onDetectedHandler) {
|
|
17787
|
+
loggerDahua.error(`No plate detection handler registered for camera ${cameraId}`);
|
|
17788
|
+
return;
|
|
17789
|
+
}
|
|
17685
17790
|
getTrafficJunction(
|
|
17686
17791
|
camera.host,
|
|
17687
17792
|
camera.username,
|
|
@@ -17691,7 +17796,7 @@ function useDahuaService() {
|
|
|
17691
17796
|
camera.direction,
|
|
17692
17797
|
cameraId,
|
|
17693
17798
|
controller.signal,
|
|
17694
|
-
|
|
17799
|
+
onDetectedHandler
|
|
17695
17800
|
);
|
|
17696
17801
|
}
|
|
17697
17802
|
async function getTrafficJunctionOld(host = "", username = "", password = "", site = "", gate = "", designation = "", cameraId, signal, onDetected) {
|
|
@@ -17812,9 +17917,12 @@ function useDahuaService() {
|
|
|
17812
17917
|
timeout: 2e4,
|
|
17813
17918
|
streaming: true
|
|
17814
17919
|
});
|
|
17815
|
-
if (
|
|
17920
|
+
if (response.statusCode === 401) {
|
|
17921
|
+
loggerDahua.error(`[${host}] 401 Unauthorized. Potential handshake or wrong credentials.`);
|
|
17922
|
+
continue;
|
|
17923
|
+
} else if ([400, 401, 403, 500].includes(response.statusCode)) {
|
|
17816
17924
|
loggerDahua.error(`[${host}] Connection error: ${response.statusCode}`);
|
|
17817
|
-
|
|
17925
|
+
return;
|
|
17818
17926
|
}
|
|
17819
17927
|
loggerDahua.info(`[${host}] Successfully connected to ANPR.`);
|
|
17820
17928
|
const contentType = response.res.headers["content-type"];
|
|
@@ -17861,16 +17969,31 @@ function useDahuaService() {
|
|
|
17861
17969
|
});
|
|
17862
17970
|
});
|
|
17863
17971
|
} catch (error) {
|
|
17864
|
-
if (signal.aborted)
|
|
17972
|
+
if (signal.aborted || error.name === "AbortError" || error.code === "UND_ERR_ABORTED") {
|
|
17973
|
+
loggerDahua.info(`[${host}] Connection closed by system (Abort).`);
|
|
17865
17974
|
break;
|
|
17975
|
+
}
|
|
17866
17976
|
loggerDahua.error(
|
|
17867
17977
|
`[${host}] Connection lost or error: ${error.message || error}. Retrying in 5s...`
|
|
17868
17978
|
);
|
|
17869
17979
|
} finally {
|
|
17870
|
-
if (bufferQueue?.destroy)
|
|
17871
|
-
|
|
17872
|
-
|
|
17873
|
-
|
|
17980
|
+
if (bufferQueue?.destroy) {
|
|
17981
|
+
try {
|
|
17982
|
+
bufferQueue.destroy();
|
|
17983
|
+
} catch (e) {
|
|
17984
|
+
loggerDahua.error(`[${host}] Error destroying buffer queue:`, e);
|
|
17985
|
+
}
|
|
17986
|
+
}
|
|
17987
|
+
if (response?.res && typeof response.res.destroy === "function" && !response.res.destroyed) {
|
|
17988
|
+
try {
|
|
17989
|
+
response.res.on("error", () => {
|
|
17990
|
+
loggerDahua.error(`[${host}] Stream error during cleanup, likely already closed.`);
|
|
17991
|
+
});
|
|
17992
|
+
response.res.destroy();
|
|
17993
|
+
} catch (err) {
|
|
17994
|
+
loggerDahua.debug(`Cleanup: stream already closing: ${err?.message}`);
|
|
17995
|
+
}
|
|
17996
|
+
}
|
|
17874
17997
|
}
|
|
17875
17998
|
if (!signal.aborted) {
|
|
17876
17999
|
await new Promise((res) => setTimeout(res, 5e3));
|
|
@@ -18086,6 +18209,8 @@ function useSiteCameraRepo() {
|
|
|
18086
18209
|
try {
|
|
18087
18210
|
value = MSiteCamera(value);
|
|
18088
18211
|
const res = await collection.insertOne(value, { session });
|
|
18212
|
+
const { listenToCamera } = useDahuaService();
|
|
18213
|
+
await listenToCamera({ ...value, _id: res.insertedId });
|
|
18089
18214
|
delCachedData();
|
|
18090
18215
|
return res.insertedId;
|
|
18091
18216
|
} catch (error) {
|
|
@@ -19917,7 +20042,8 @@ function useVehicleController() {
|
|
|
19917
20042
|
getVehicles: _getVehicles,
|
|
19918
20043
|
getVehicleById: _getVehicleById,
|
|
19919
20044
|
getVehiclesByNRIC: _getVehiclesByNRIC,
|
|
19920
|
-
getAllVehiclesByUnitId: _getAllVehiclesByUnitId
|
|
20045
|
+
getAllVehiclesByUnitId: _getAllVehiclesByUnitId,
|
|
20046
|
+
getSpecificVehicleById: _getSpecificVehicleById
|
|
19921
20047
|
} = useVehicleRepo();
|
|
19922
20048
|
function normalizeRow(row) {
|
|
19923
20049
|
return Object.fromEntries(
|
|
@@ -20031,7 +20157,9 @@ function useVehicleController() {
|
|
|
20031
20157
|
return;
|
|
20032
20158
|
}
|
|
20033
20159
|
const headerRow = worksheet.getRow(1);
|
|
20034
|
-
const headers = (headerRow.values || []).slice(1).map(
|
|
20160
|
+
const headers = (headerRow.values || []).slice(1).map(
|
|
20161
|
+
(header) => String(header ?? "").trim().replace(/\(.*\)/, "").trim()
|
|
20162
|
+
);
|
|
20035
20163
|
worksheet.eachRow((row, rowNumber) => {
|
|
20036
20164
|
if (rowNumber === 1)
|
|
20037
20165
|
return;
|
|
@@ -20048,7 +20176,11 @@ function useVehicleController() {
|
|
|
20048
20176
|
} else if (lowerName.endsWith(".csv")) {
|
|
20049
20177
|
rows = await new Promise((resolve, reject) => {
|
|
20050
20178
|
const parsed = [];
|
|
20051
|
-
import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("
|
|
20179
|
+
import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("headers", (headers) => {
|
|
20180
|
+
headers = headers.map(
|
|
20181
|
+
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
20182
|
+
);
|
|
20183
|
+
}).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
|
|
20052
20184
|
});
|
|
20053
20185
|
} else {
|
|
20054
20186
|
next(
|
|
@@ -20213,6 +20345,31 @@ function useVehicleController() {
|
|
|
20213
20345
|
return;
|
|
20214
20346
|
}
|
|
20215
20347
|
}
|
|
20348
|
+
async function getSpecificVehicleById(req, res, next) {
|
|
20349
|
+
const schema2 = import_joi46.default.object({
|
|
20350
|
+
_id: import_joi46.default.string().hex().length(24).required()
|
|
20351
|
+
});
|
|
20352
|
+
const { error, value } = schema2.validate(
|
|
20353
|
+
{ _id: req.params.id },
|
|
20354
|
+
{ abortEarly: false }
|
|
20355
|
+
);
|
|
20356
|
+
if (error) {
|
|
20357
|
+
const messages = error.details.map((d) => d.message).join(", ");
|
|
20358
|
+
import_node_server_utils87.logger.log({ level: "error", message: messages });
|
|
20359
|
+
next(new import_node_server_utils87.BadRequestError(messages));
|
|
20360
|
+
return;
|
|
20361
|
+
}
|
|
20362
|
+
const { _id } = value;
|
|
20363
|
+
try {
|
|
20364
|
+
const site = await _getSpecificVehicleById(_id);
|
|
20365
|
+
res.json(site);
|
|
20366
|
+
return;
|
|
20367
|
+
} catch (error2) {
|
|
20368
|
+
import_node_server_utils87.logger.log({ level: "error", message: error2.message });
|
|
20369
|
+
next(error2);
|
|
20370
|
+
return;
|
|
20371
|
+
}
|
|
20372
|
+
}
|
|
20216
20373
|
async function updateVehicleById(req, res, next) {
|
|
20217
20374
|
try {
|
|
20218
20375
|
const schema2 = import_joi46.default.object({
|
|
@@ -20432,7 +20589,8 @@ function useVehicleController() {
|
|
|
20432
20589
|
getVehiclesByNRIC,
|
|
20433
20590
|
reactivateVehicleById,
|
|
20434
20591
|
getAllVehiclesByUnitId,
|
|
20435
|
-
uploadSpreadsheetVehicles
|
|
20592
|
+
uploadSpreadsheetVehicles,
|
|
20593
|
+
getSpecificVehicleById
|
|
20436
20594
|
};
|
|
20437
20595
|
}
|
|
20438
20596
|
|
|
@@ -23535,6 +23693,12 @@ function useVisitorTransactionService() {
|
|
|
23535
23693
|
const parsed = new Date(value.checkOut);
|
|
23536
23694
|
value.checkOut = isNaN(parsed.getTime()) ? null : parsed;
|
|
23537
23695
|
}
|
|
23696
|
+
if (value.site) {
|
|
23697
|
+
value.site = typeof value.site === "string" ? new import_mongodb59.ObjectId(value.site) : value.site;
|
|
23698
|
+
}
|
|
23699
|
+
if (value.unit) {
|
|
23700
|
+
value.unit = typeof value.unit === "string" ? new import_mongodb59.ObjectId(value.unit) : value.unit;
|
|
23701
|
+
}
|
|
23538
23702
|
await _updateVisitorTansactionById(id, value, session);
|
|
23539
23703
|
await session?.commitTransaction();
|
|
23540
23704
|
return "Successfully updated visitor transaction.";
|
|
@@ -26331,7 +26495,7 @@ function usePatrolRouteRepo() {
|
|
|
26331
26495
|
id: "$_id",
|
|
26332
26496
|
start: startOfDay,
|
|
26333
26497
|
end: endOfDay,
|
|
26334
|
-
site: new import_mongodb67.ObjectId(site)
|
|
26498
|
+
site: import_mongodb67.ObjectId.isValid(site) ? new import_mongodb67.ObjectId(site) : null
|
|
26335
26499
|
},
|
|
26336
26500
|
pipeline: [
|
|
26337
26501
|
{
|
|
@@ -26362,10 +26526,8 @@ function usePatrolRouteRepo() {
|
|
|
26362
26526
|
{ $skip: page * limit },
|
|
26363
26527
|
{ $limit: limit }
|
|
26364
26528
|
];
|
|
26365
|
-
const
|
|
26366
|
-
|
|
26367
|
-
collection.aggregate([{ $match: query }, { $count: "total" }], { session }).toArray()
|
|
26368
|
-
]);
|
|
26529
|
+
const items = await collection.aggregate(basePipeline, { session }).toArray();
|
|
26530
|
+
const countResult = await collection.aggregate([{ $match: query }, { $count: "total" }], { session }).toArray();
|
|
26369
26531
|
const totalCount = countResult[0]?.total || 0;
|
|
26370
26532
|
const data = (0, import_node_server_utils117.paginate)(items, page, limit, totalCount);
|
|
26371
26533
|
setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils117.logger.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
@@ -26373,6 +26535,7 @@ function usePatrolRouteRepo() {
|
|
|
26373
26535
|
);
|
|
26374
26536
|
return data;
|
|
26375
26537
|
} catch (error) {
|
|
26538
|
+
console.error("[getScheduledRoute] ERROR:", error?.message, error?.stack);
|
|
26376
26539
|
throw error;
|
|
26377
26540
|
}
|
|
26378
26541
|
}
|
|
@@ -26659,6 +26822,7 @@ var schemaPatrolLog = import_joi65.default.object({
|
|
|
26659
26822
|
cameras: import_joi65.default.array().items(schemeLogCamera).required(),
|
|
26660
26823
|
status: import_joi65.default.array().items(import_joi65.default.string().valid("complete", "late", "incomplete")).required(),
|
|
26661
26824
|
incidentReport: incidentReportLog,
|
|
26825
|
+
platform: import_joi65.default.string().valid("web", "mobile").optional().allow(null, ""),
|
|
26662
26826
|
createdAt: import_joi65.default.date().optional(),
|
|
26663
26827
|
updatedAt: import_joi65.default.date().optional(),
|
|
26664
26828
|
deletedAt: import_joi65.default.date().optional()
|
|
@@ -26672,7 +26836,8 @@ var schemaUpdatePatrolLog = import_joi65.default.object({
|
|
|
26672
26836
|
end: import_joi65.default.string().optional().allow(null, ""),
|
|
26673
26837
|
cameras: import_joi65.default.array().items(schemeLogCamera).optional().allow(null, ""),
|
|
26674
26838
|
status: import_joi65.default.array().items(import_joi65.default.string().valid("complete", "late", "incomplete")).optional().allow(null, ""),
|
|
26675
|
-
incidentReport: incidentReportLog
|
|
26839
|
+
incidentReport: incidentReportLog,
|
|
26840
|
+
platform: import_joi65.default.string().valid("web", "mobile").optional().allow(null, "")
|
|
26676
26841
|
});
|
|
26677
26842
|
function MPatrolLog(value) {
|
|
26678
26843
|
const { error } = schemaPatrolLog.validate(value);
|
|
@@ -26726,6 +26891,7 @@ function MPatrolLog(value) {
|
|
|
26726
26891
|
status: value.status ?? [],
|
|
26727
26892
|
route: value.route,
|
|
26728
26893
|
incidentReport: value.incidentReport,
|
|
26894
|
+
platForm: value.platform ?? "",
|
|
26729
26895
|
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
26730
26896
|
updatedAt: value.updatedAt ?? "",
|
|
26731
26897
|
deletedAt: value.deletedAt ?? ""
|
|
@@ -27078,6 +27244,7 @@ function usePatrolLogService() {
|
|
|
27078
27244
|
}
|
|
27079
27245
|
}
|
|
27080
27246
|
}
|
|
27247
|
+
value.platform = value.platform === "web" ? "web" : "mobile";
|
|
27081
27248
|
const result = await _add(value, session);
|
|
27082
27249
|
await session.commitTransaction();
|
|
27083
27250
|
return result;
|
|
@@ -41140,6 +41307,7 @@ var schemaIncidentReport = import_joi99.default.object({
|
|
|
41140
41307
|
approvedBy: import_joi99.default.string().hex().allow(null, "").optional(),
|
|
41141
41308
|
approvedByName: import_joi99.default.string().optional().allow("", null),
|
|
41142
41309
|
remarks: import_joi99.default.string().optional().allow("", null),
|
|
41310
|
+
platform: import_joi99.default.string().valid("web", "mobile").optional().allow(null, ""),
|
|
41143
41311
|
status: import_joi99.default.string().valid("pending", "approved", "rejected").default("pending")
|
|
41144
41312
|
});
|
|
41145
41313
|
var schemaUpdateIncidentReport = import_joi99.default.object({
|
|
@@ -41220,6 +41388,7 @@ var schemaUpdateIncidentReport = import_joi99.default.object({
|
|
|
41220
41388
|
approvedBy: import_joi99.default.string().hex().allow(null, "").optional(),
|
|
41221
41389
|
approvedByName: import_joi99.default.string().optional().allow("", null),
|
|
41222
41390
|
remarks: import_joi99.default.string().optional().allow("", null),
|
|
41391
|
+
platform: import_joi99.default.string().valid("web", "mobile").optional().allow(null, ""),
|
|
41223
41392
|
status: import_joi99.default.string().valid("pending", "approved", "rejected").default("pending")
|
|
41224
41393
|
});
|
|
41225
41394
|
function MIncidentReport(value) {
|
|
@@ -41281,6 +41450,7 @@ function MIncidentReport(value) {
|
|
|
41281
41450
|
approvedByName: value.approvedByName ?? "",
|
|
41282
41451
|
remarks: value.remarks ?? null,
|
|
41283
41452
|
status: value.status ?? "pending",
|
|
41453
|
+
platForm: value.platform ?? "",
|
|
41284
41454
|
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
41285
41455
|
updatedAt: value.updatedAt,
|
|
41286
41456
|
deletedAt: value.deletedAt
|
|
@@ -41746,6 +41916,7 @@ function useIncidentReportService() {
|
|
|
41746
41916
|
}
|
|
41747
41917
|
}
|
|
41748
41918
|
}
|
|
41919
|
+
value.platform = value.platform === "web" ? "web" : "mobile";
|
|
41749
41920
|
const result = await _add(value, session);
|
|
41750
41921
|
await session?.commitTransaction();
|
|
41751
41922
|
return result;
|
|
@@ -42818,6 +42989,11 @@ function useOccurrenceEntryService() {
|
|
|
42818
42989
|
if (!occurrenceEntry) {
|
|
42819
42990
|
throw new Error("Occurrence entry not found.");
|
|
42820
42991
|
}
|
|
42992
|
+
if (value.incidentReportId) {
|
|
42993
|
+
await _updateOccurrenceEntryById(id, value, session);
|
|
42994
|
+
await session?.commitTransaction();
|
|
42995
|
+
return "Successfully updated occurrence entry (incident report).";
|
|
42996
|
+
}
|
|
42821
42997
|
const entryCount = await _getLatestSerialNumberInGroup(
|
|
42822
42998
|
occurrenceEntry.dailyOccurrenceBookId,
|
|
42823
42999
|
Number(occurrenceEntry.serialNumber)
|
|
@@ -42850,6 +43026,8 @@ function useOccurrenceEntryService() {
|
|
|
42850
43026
|
value.date = value.date ? value.date : occurrenceEntry.date;
|
|
42851
43027
|
value.userName = value.userName ? value.userName : occurrenceEntry.signature.name;
|
|
42852
43028
|
value.createdByName = value.createdByName ? value.createdByName : occurrenceEntry.createdByName;
|
|
43029
|
+
if (occurrenceEntry.incidentReportId)
|
|
43030
|
+
value.incidentReportId = occurrenceEntry.incidentReportId;
|
|
42853
43031
|
await _updateOccurrenceBookById(dobId, {
|
|
42854
43032
|
totalInput: book.totalInput + 1
|
|
42855
43033
|
});
|