@7365admin1/core 3.38.0 → 3.40.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 +9 -4
- package/dist/index.js +247 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +247 -105
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23318,6 +23318,7 @@ function useVehicleRepo() {
|
|
|
23318
23318
|
if (error) {
|
|
23319
23319
|
throw new import_node_server_utils71.BadRequestError(error.details[0].message);
|
|
23320
23320
|
}
|
|
23321
|
+
console.log("getVehicleByPlateNumber plateNumber", plateNumber);
|
|
23321
23322
|
try {
|
|
23322
23323
|
const data = await collection.findOne(
|
|
23323
23324
|
{ plateNumber, status: "active" },
|
|
@@ -23330,6 +23331,14 @@ function useVehicleRepo() {
|
|
|
23330
23331
|
);
|
|
23331
23332
|
}
|
|
23332
23333
|
}
|
|
23334
|
+
async function findOne(query) {
|
|
23335
|
+
try {
|
|
23336
|
+
const data = await collection.findOne(query);
|
|
23337
|
+
return data;
|
|
23338
|
+
} catch (error) {
|
|
23339
|
+
throw new import_node_server_utils71.InternalServerError("Failed to fetch findOne vehicle." + error);
|
|
23340
|
+
}
|
|
23341
|
+
}
|
|
23333
23342
|
async function getVehicleBySiteAndPlateNumber(plateNumber, site, category, status) {
|
|
23334
23343
|
const { error } = import_joi39.default.string().required().validate(plateNumber);
|
|
23335
23344
|
if (error) {
|
|
@@ -23638,7 +23647,8 @@ function useVehicleRepo() {
|
|
|
23638
23647
|
getSpecificVehicleById,
|
|
23639
23648
|
getBlocklistedVehicles,
|
|
23640
23649
|
getVehicleBySiteAndPlateNumber,
|
|
23641
|
-
getBlocklistedVehicleByPlateNumber
|
|
23650
|
+
getBlocklistedVehicleByPlateNumber,
|
|
23651
|
+
findOne
|
|
23642
23652
|
};
|
|
23643
23653
|
}
|
|
23644
23654
|
|
|
@@ -23717,12 +23727,13 @@ async function useDahuaDigestWithRetry({
|
|
|
23717
23727
|
headers = {},
|
|
23718
23728
|
timeout = 1e4,
|
|
23719
23729
|
streaming = false,
|
|
23720
|
-
retries =
|
|
23730
|
+
retries = 10,
|
|
23721
23731
|
retryDelayMs = 0
|
|
23722
23732
|
}) {
|
|
23723
23733
|
let lastError;
|
|
23724
23734
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
23725
23735
|
try {
|
|
23736
|
+
const effectiveTimeout = streaming ? 0 : timeout;
|
|
23726
23737
|
const response = await useDahuaDigest({
|
|
23727
23738
|
host,
|
|
23728
23739
|
username,
|
|
@@ -23730,16 +23741,23 @@ async function useDahuaDigestWithRetry({
|
|
|
23730
23741
|
endpoint,
|
|
23731
23742
|
method,
|
|
23732
23743
|
headers,
|
|
23733
|
-
timeout,
|
|
23744
|
+
timeout: effectiveTimeout,
|
|
23734
23745
|
streaming
|
|
23735
23746
|
});
|
|
23736
|
-
const text = getDahuaResponseText(response);
|
|
23737
23747
|
const statusCode = getDahuaStatusCode(response);
|
|
23738
|
-
|
|
23739
|
-
|
|
23740
|
-
|
|
23748
|
+
if (streaming) {
|
|
23749
|
+
if (statusCode === 200) {
|
|
23750
|
+
return response;
|
|
23751
|
+
}
|
|
23752
|
+
} else {
|
|
23753
|
+
const text = getDahuaResponseText(response);
|
|
23754
|
+
const isOk = statusCode === 200 && text.includes("OK");
|
|
23755
|
+
if (isOk) {
|
|
23756
|
+
return response;
|
|
23757
|
+
}
|
|
23741
23758
|
}
|
|
23742
|
-
const
|
|
23759
|
+
const errorText = streaming ? `HTTP ${statusCode}` : getDahuaResponseText(response);
|
|
23760
|
+
const shouldRetry = isDahuaInvalidAuthority(errorText);
|
|
23743
23761
|
if (shouldRetry && attempt < retries) {
|
|
23744
23762
|
loggerDahua.warn(
|
|
23745
23763
|
`[${host}] Dahua Invalid Authority. Retrying ${attempt}/${retries}`
|
|
@@ -23749,7 +23767,7 @@ async function useDahuaDigestWithRetry({
|
|
|
23749
23767
|
}
|
|
23750
23768
|
continue;
|
|
23751
23769
|
}
|
|
23752
|
-
throw new Error(`Dahua response: ${
|
|
23770
|
+
throw new Error(`Dahua response: ${errorText || `HTTP ${statusCode}`}`);
|
|
23753
23771
|
} catch (error) {
|
|
23754
23772
|
lastError = error;
|
|
23755
23773
|
const message = error?.message || String(error);
|
|
@@ -24132,6 +24150,7 @@ function useDahuaService() {
|
|
|
24132
24150
|
if (camera.status !== "active") {
|
|
24133
24151
|
if (cameraRegistry.has(cameraId)) {
|
|
24134
24152
|
loggerDahua.info(`[${camera?.siteName}-${camera?.direction}] Camera is ${camera.status}. Stopping connection.`);
|
|
24153
|
+
console.log(`[${camera?.siteName}-${camera?.direction}] Camera is ${camera.status}. Stopping connection.`);
|
|
24135
24154
|
cameraRegistry.get(cameraId)?.abort();
|
|
24136
24155
|
cameraRegistry.delete(cameraId);
|
|
24137
24156
|
}
|
|
@@ -24139,6 +24158,7 @@ function useDahuaService() {
|
|
|
24139
24158
|
}
|
|
24140
24159
|
if (cameraRegistry.has(cameraId)) {
|
|
24141
24160
|
loggerDahua.info(`[${camera?.siteName}-${camera?.direction}] Stopping existing connection for update.`);
|
|
24161
|
+
console.log(`[${camera?.siteName}-${camera?.direction}] Stopping existing connection for update.`);
|
|
24142
24162
|
cameraRegistry.get(cameraId)?.abort();
|
|
24143
24163
|
cameraRegistry.delete(cameraId);
|
|
24144
24164
|
}
|
|
@@ -24158,11 +24178,14 @@ function useDahuaService() {
|
|
|
24158
24178
|
}
|
|
24159
24179
|
async function getTrafficJunction(camera, signal, onDetected) {
|
|
24160
24180
|
console.log(`getTrafficJunction camera object`, camera);
|
|
24181
|
+
let authFailureCount = 0;
|
|
24182
|
+
const MAX_AUTH_RETRIES = 10;
|
|
24161
24183
|
while (!signal.aborted) {
|
|
24162
24184
|
let bufferQueue = null;
|
|
24163
24185
|
let response = null;
|
|
24186
|
+
let isAuthFailure = false;
|
|
24164
24187
|
try {
|
|
24165
|
-
response = await
|
|
24188
|
+
response = await useDahuaDigestWithRetry({
|
|
24166
24189
|
host: camera?.host,
|
|
24167
24190
|
username: camera?.username,
|
|
24168
24191
|
password: camera?.password,
|
|
@@ -24170,16 +24193,32 @@ function useDahuaService() {
|
|
|
24170
24193
|
timeout: 2e4,
|
|
24171
24194
|
streaming: true
|
|
24172
24195
|
});
|
|
24173
|
-
|
|
24174
|
-
|
|
24175
|
-
|
|
24176
|
-
|
|
24177
|
-
|
|
24196
|
+
const statusCode = getDahuaStatusCode(response);
|
|
24197
|
+
if (statusCode === 401) {
|
|
24198
|
+
loggerDahua.error(`[${camera?.siteName}-${camera?.direction}] 401 Unauthorized - Handshake or Wrong Credentials`);
|
|
24199
|
+
console.log(`[${camera?.siteName}-${camera?.direction}] 401 Unauthorized - Handshake or Wrong Credentials`);
|
|
24200
|
+
throw new Error("401 Unauthorized - Handshake or Wrong Credentials");
|
|
24201
|
+
} else if (statusCode === 403) {
|
|
24202
|
+
loggerDahua.error(
|
|
24203
|
+
`[${camera?.siteName}-${camera?.direction}] 403 Forbidden. Account locked or invalid permissions.`
|
|
24204
|
+
);
|
|
24178
24205
|
if (onDetected) {
|
|
24179
|
-
onDetected({
|
|
24206
|
+
onDetected({
|
|
24207
|
+
site: camera?.site,
|
|
24208
|
+
direction: camera?.direction,
|
|
24209
|
+
messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Check username and password and try after 10 minutes.`
|
|
24210
|
+
});
|
|
24211
|
+
}
|
|
24212
|
+
return;
|
|
24213
|
+
} else if ([400, 500].includes(statusCode)) {
|
|
24214
|
+
loggerDahua.error(`[${camera?.siteName}-${camera?.direction}] Connection error: ${statusCode}`);
|
|
24215
|
+
if (onDetected) {
|
|
24216
|
+
onDetected({ site: camera?.site, messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Possible Not Authorized.` });
|
|
24180
24217
|
}
|
|
24181
24218
|
return;
|
|
24182
24219
|
}
|
|
24220
|
+
authFailureCount = 0;
|
|
24221
|
+
isAuthFailure = false;
|
|
24183
24222
|
loggerDahua.info(`[${camera?.siteName}-${camera?.direction}] Successfully connected to ANPR.`);
|
|
24184
24223
|
const contentType = response.res.headers["content-type"];
|
|
24185
24224
|
const boundaryMatch = contentType?.match(/boundary=(.*)$/i);
|
|
@@ -24224,15 +24263,53 @@ function useDahuaService() {
|
|
|
24224
24263
|
loggerDahua.info(`[${camera?.siteName}-${camera?.direction}] Connection closed by system (Abort).`);
|
|
24225
24264
|
break;
|
|
24226
24265
|
}
|
|
24227
|
-
|
|
24228
|
-
|
|
24229
|
-
|
|
24230
|
-
|
|
24231
|
-
|
|
24232
|
-
|
|
24233
|
-
|
|
24234
|
-
|
|
24235
|
-
|
|
24266
|
+
const errMsg = String(error?.message || error);
|
|
24267
|
+
if (errMsg.includes("403") || errMsg.includes("Forbidden")) {
|
|
24268
|
+
loggerDahua.error(
|
|
24269
|
+
`[${camera?.siteName}-${camera?.direction}] 403 Forbidden thrown by Dahua client. Account locked or invalid credentials.`
|
|
24270
|
+
);
|
|
24271
|
+
if (onDetected) {
|
|
24272
|
+
onDetected({
|
|
24273
|
+
site: camera?.site,
|
|
24274
|
+
direction: camera?.direction,
|
|
24275
|
+
messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Check username and password and try after 10 minutes.`
|
|
24276
|
+
});
|
|
24277
|
+
}
|
|
24278
|
+
return;
|
|
24279
|
+
}
|
|
24280
|
+
const isAuthError = errMsg.includes("401") || errMsg.includes("Unauthorized") || errMsg.includes("Invalid Authority");
|
|
24281
|
+
if (isAuthError) {
|
|
24282
|
+
authFailureCount++;
|
|
24283
|
+
isAuthFailure = true;
|
|
24284
|
+
loggerDahua.warn(
|
|
24285
|
+
`[${camera?.siteName}-${camera?.direction}] Auth attempt ${authFailureCount}/${MAX_AUTH_RETRIES}`
|
|
24286
|
+
);
|
|
24287
|
+
if (authFailureCount >= MAX_AUTH_RETRIES) {
|
|
24288
|
+
loggerDahua.error(
|
|
24289
|
+
`[${camera?.siteName}-${camera?.direction}] Max auth failures reached (${MAX_AUTH_RETRIES}). Wrong credentials.`
|
|
24290
|
+
);
|
|
24291
|
+
if (onDetected) {
|
|
24292
|
+
onDetected({
|
|
24293
|
+
site: camera?.site,
|
|
24294
|
+
direction: camera?.direction,
|
|
24295
|
+
messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Check username and password.`
|
|
24296
|
+
});
|
|
24297
|
+
}
|
|
24298
|
+
return;
|
|
24299
|
+
}
|
|
24300
|
+
} else {
|
|
24301
|
+
authFailureCount = 0;
|
|
24302
|
+
isAuthFailure = false;
|
|
24303
|
+
loggerDahua.error(
|
|
24304
|
+
`[${camera?.siteName}-${camera?.direction}] Connection lost or error: ${error.message || error}. Retrying in 10 seconds...`
|
|
24305
|
+
);
|
|
24306
|
+
if (onDetected) {
|
|
24307
|
+
onDetected({
|
|
24308
|
+
site: camera?.site,
|
|
24309
|
+
direction: camera?.direction,
|
|
24310
|
+
message: `Camera in [${camera?.siteName}-${camera?.direction}] Connection Lost. Retrying in 10 seconds. Check the camera if this issue persists, Or set the camera to Inactive to stop this notification.`
|
|
24311
|
+
});
|
|
24312
|
+
}
|
|
24236
24313
|
}
|
|
24237
24314
|
} finally {
|
|
24238
24315
|
if (bufferQueue?.destroy) {
|
|
@@ -24254,7 +24331,8 @@ function useDahuaService() {
|
|
|
24254
24331
|
}
|
|
24255
24332
|
}
|
|
24256
24333
|
if (!signal.aborted) {
|
|
24257
|
-
|
|
24334
|
+
const waitMs = isAuthFailure ? 1e3 : 1e4;
|
|
24335
|
+
await new Promise((res) => setTimeout(res, waitMs));
|
|
24258
24336
|
}
|
|
24259
24337
|
}
|
|
24260
24338
|
loggerDahua.info(`[${camera?.siteName}-${camera?.direction}] ANPR Listener stopped.`);
|
|
@@ -24925,7 +25003,8 @@ function useSiteCameraRepo() {
|
|
|
24925
25003
|
throw new import_node_server_utils73.BadRequestError("Site camera not found.");
|
|
24926
25004
|
}
|
|
24927
25005
|
if (result?._id) {
|
|
24928
|
-
const result2 = await findOne({ _id: new import_mongodb44.ObjectId(result._id) });
|
|
25006
|
+
const result2 = await findOne({ _id: new import_mongodb44.ObjectId(result._id) }, void 0, { session });
|
|
25007
|
+
console.log("updateById result2", result2);
|
|
24929
25008
|
if (result2?._id) {
|
|
24930
25009
|
const { listenToCamera } = useDahuaService();
|
|
24931
25010
|
await listenToCamera(result2);
|
|
@@ -24990,6 +25069,9 @@ function useSiteCameraRepo() {
|
|
|
24990
25069
|
throw new import_node_server_utils73.BadRequestError("Invalid site ID format");
|
|
24991
25070
|
}
|
|
24992
25071
|
}
|
|
25072
|
+
if (value.status) {
|
|
25073
|
+
query.status = value.status;
|
|
25074
|
+
}
|
|
24993
25075
|
try {
|
|
24994
25076
|
const items = await collection.aggregate([
|
|
24995
25077
|
{
|
|
@@ -25060,7 +25142,7 @@ function useSiteCameraRepo() {
|
|
|
25060
25142
|
throw new import_node_server_utils73.BadRequestError("Failed to retrieve site cameras.");
|
|
25061
25143
|
}
|
|
25062
25144
|
}
|
|
25063
|
-
async function findOne(query, project = {}) {
|
|
25145
|
+
async function findOne(query, project = {}, options = {}) {
|
|
25064
25146
|
try {
|
|
25065
25147
|
const pipeline = [
|
|
25066
25148
|
{ $match: query },
|
|
@@ -25109,14 +25191,14 @@ function useSiteCameraRepo() {
|
|
|
25109
25191
|
if (Object.keys(project).length > 0) {
|
|
25110
25192
|
pipeline.push({ $project: project });
|
|
25111
25193
|
}
|
|
25112
|
-
const result = await collection.aggregate(pipeline).toArray();
|
|
25194
|
+
const result = await collection.aggregate(pipeline, options).toArray();
|
|
25113
25195
|
return result.length > 0 ? result[0] : null;
|
|
25114
25196
|
} catch (error) {
|
|
25115
25197
|
console.error("Error in findOne aggregation:", error);
|
|
25116
25198
|
throw error;
|
|
25117
25199
|
}
|
|
25118
25200
|
}
|
|
25119
|
-
async function findMany(query, project = {}) {
|
|
25201
|
+
async function findMany(query, project = {}, options = {}) {
|
|
25120
25202
|
try {
|
|
25121
25203
|
const pipeline = [
|
|
25122
25204
|
{ $match: query },
|
|
@@ -25165,10 +25247,10 @@ function useSiteCameraRepo() {
|
|
|
25165
25247
|
if (Object.keys(project).length > 0) {
|
|
25166
25248
|
pipeline.push({ $project: project });
|
|
25167
25249
|
}
|
|
25168
|
-
const result = await collection.aggregate(pipeline).toArray();
|
|
25250
|
+
const result = await collection.aggregate(pipeline, options).toArray();
|
|
25169
25251
|
return result.length > 0 ? result : [];
|
|
25170
25252
|
} catch (error) {
|
|
25171
|
-
console.error("Error in
|
|
25253
|
+
console.error("Error in findMany aggregation:", error);
|
|
25172
25254
|
throw error;
|
|
25173
25255
|
}
|
|
25174
25256
|
}
|
|
@@ -25185,7 +25267,9 @@ function useSiteCameraRepo() {
|
|
|
25185
25267
|
getBySiteGuardPost,
|
|
25186
25268
|
updateById,
|
|
25187
25269
|
deleteById,
|
|
25188
|
-
getAllCameraWithPassword
|
|
25270
|
+
getAllCameraWithPassword,
|
|
25271
|
+
findMany,
|
|
25272
|
+
findOne
|
|
25189
25273
|
};
|
|
25190
25274
|
}
|
|
25191
25275
|
|
|
@@ -25303,9 +25387,9 @@ function usePersonRepo() {
|
|
|
25303
25387
|
{ email: { $regex: search, $options: "i" } },
|
|
25304
25388
|
{ nric: { $regex: search, $options: "i" } },
|
|
25305
25389
|
{ "plates.plateNumber": { $regex: search, $options: "i" } },
|
|
25306
|
-
{ contact: { $regex: makeContainsRegex(
|
|
25307
|
-
{ contacts: { $regex: makeContainsRegex(
|
|
25308
|
-
{ plateNumbers: { $regex: makeContainsRegex(
|
|
25390
|
+
{ contact: { $regex: makeContainsRegex(search) } },
|
|
25391
|
+
{ contacts: { $regex: makeContainsRegex(search) } },
|
|
25392
|
+
{ plateNumbers: { $regex: makeContainsRegex(search) } }
|
|
25309
25393
|
]
|
|
25310
25394
|
},
|
|
25311
25395
|
...import_mongodb45.ObjectId.isValid(org) && { org: new import_mongodb45.ObjectId(org) },
|
|
@@ -27098,7 +27182,8 @@ function useVehicleService() {
|
|
|
27098
27182
|
deleteExpiredVehicles: _deleteExpiredVehicles,
|
|
27099
27183
|
getVehicleByPlateNumber: _getVehicleByPlateNumber,
|
|
27100
27184
|
getAllExpiredVehicles: _getAllExpiredVehicles,
|
|
27101
|
-
bulkUpsertVehicles: _bulkUpsertVehicles
|
|
27185
|
+
bulkUpsertVehicles: _bulkUpsertVehicles,
|
|
27186
|
+
findOne
|
|
27102
27187
|
} = useVehicleRepo();
|
|
27103
27188
|
const {
|
|
27104
27189
|
addPlateNumber: _addPlateNumber,
|
|
@@ -27122,15 +27207,18 @@ function useVehicleService() {
|
|
|
27122
27207
|
throw new Error("Unable to start session for vehicle service.");
|
|
27123
27208
|
}
|
|
27124
27209
|
}
|
|
27210
|
+
console.log("add vehicle service value.plateNumber", value.plateNumber);
|
|
27125
27211
|
const [_vehiclePlateNumber] = value.plateNumber;
|
|
27126
|
-
|
|
27127
|
-
|
|
27212
|
+
console.log("add vehicle service plateNumber", _vehiclePlateNumber);
|
|
27213
|
+
const [
|
|
27214
|
+
// existingPlateNumber,
|
|
27215
|
+
org
|
|
27216
|
+
] = await Promise.all([
|
|
27217
|
+
// _getVehicleByPlateNumber(_vehiclePlateNumber),
|
|
27128
27218
|
_getById(value.org)
|
|
27129
27219
|
]);
|
|
27130
27220
|
if (!org)
|
|
27131
27221
|
throw new import_node_server_utils78.BadRequestError("Org not found");
|
|
27132
|
-
if (existingPlateNumber)
|
|
27133
|
-
throw new import_node_server_utils78.BadRequestError("Vehicle plate number already exists");
|
|
27134
27222
|
if (!Object.values(OrgNature).includes(org.nature)) {
|
|
27135
27223
|
throw new import_node_server_utils78.BadRequestError(
|
|
27136
27224
|
"This organization is not allowed to add vehicles."
|
|
@@ -27143,7 +27231,6 @@ function useVehicleService() {
|
|
|
27143
27231
|
user,
|
|
27144
27232
|
org: value.org
|
|
27145
27233
|
});
|
|
27146
|
-
console.log("userPermissions vehicle.service.ts", userPermissions);
|
|
27147
27234
|
const hasSecurityBypass = addedBySecurity && Array.isArray(userPermissions) && (userPermissions.includes("*") || userPermissions.includes("vehicleManagement:approve-vehicle"));
|
|
27148
27235
|
if (hasSecurityBypass) {
|
|
27149
27236
|
addedByPM = true;
|
|
@@ -27202,17 +27289,16 @@ function useVehicleService() {
|
|
|
27202
27289
|
const siteCameraReq = await _getAllSiteCameras({
|
|
27203
27290
|
site: value.site,
|
|
27204
27291
|
type: "anpr",
|
|
27205
|
-
direction: ["both", "entry"],
|
|
27292
|
+
direction: ["both", "entry", "residents"],
|
|
27206
27293
|
page,
|
|
27207
|
-
limit
|
|
27294
|
+
limit,
|
|
27295
|
+
status: "active"
|
|
27208
27296
|
});
|
|
27209
27297
|
pages = siteCameraReq.pages || 1;
|
|
27210
27298
|
siteCameras.push(...siteCameraReq.items);
|
|
27211
27299
|
page++;
|
|
27212
27300
|
} while (page <= pages);
|
|
27213
|
-
|
|
27214
|
-
throw new import_node_server_utils78.BadRequestError("No site cameras found.");
|
|
27215
|
-
}
|
|
27301
|
+
console.log("add vehicle service siteCameras", siteCameras);
|
|
27216
27302
|
}
|
|
27217
27303
|
for (const plateNumber of plateNumbers) {
|
|
27218
27304
|
const vehicleValue = {
|
|
@@ -31829,6 +31915,7 @@ function useSiteCameraService() {
|
|
|
31829
31915
|
const { add: _add, getAllCameraWithPassword: _getAllCameraWithPassword } = useSiteCameraRepo();
|
|
31830
31916
|
const { updateById: _updateById } = useSiteRepo();
|
|
31831
31917
|
const dahuaService = useDahuaService();
|
|
31918
|
+
const { updateById: _siteCameraUpdateById } = useSiteCameraRepo();
|
|
31832
31919
|
let cleanupTask = null;
|
|
31833
31920
|
async function add(value) {
|
|
31834
31921
|
const { error } = schemaSiteCamera.validate(value);
|
|
@@ -31862,6 +31949,7 @@ function useSiteCameraService() {
|
|
|
31862
31949
|
type: "anpr",
|
|
31863
31950
|
page,
|
|
31864
31951
|
limit
|
|
31952
|
+
// site: "6923d6664150ca6a69b9f2b2"
|
|
31865
31953
|
});
|
|
31866
31954
|
pages = siteCameraReq.pages || 1;
|
|
31867
31955
|
siteCameras.push(...siteCameraReq.items);
|
|
@@ -31877,9 +31965,27 @@ function useSiteCameraService() {
|
|
|
31877
31965
|
}
|
|
31878
31966
|
}
|
|
31879
31967
|
}
|
|
31968
|
+
async function updateById(id, value) {
|
|
31969
|
+
const session = import_node_server_utils93.useAtlas.getClient()?.startSession();
|
|
31970
|
+
if (!session) {
|
|
31971
|
+
throw new Error("Unable to start session for site camera service.");
|
|
31972
|
+
}
|
|
31973
|
+
try {
|
|
31974
|
+
session.startTransaction();
|
|
31975
|
+
const result = await _siteCameraUpdateById(id, value, session);
|
|
31976
|
+
await session.commitTransaction();
|
|
31977
|
+
return result;
|
|
31978
|
+
} catch (error) {
|
|
31979
|
+
await session.abortTransaction();
|
|
31980
|
+
throw error;
|
|
31981
|
+
} finally {
|
|
31982
|
+
session.endSession();
|
|
31983
|
+
}
|
|
31984
|
+
}
|
|
31880
31985
|
return {
|
|
31881
31986
|
add,
|
|
31882
|
-
listenToCapturedPlateNumber
|
|
31987
|
+
listenToCapturedPlateNumber,
|
|
31988
|
+
updateById
|
|
31883
31989
|
};
|
|
31884
31990
|
}
|
|
31885
31991
|
|
|
@@ -31887,10 +31993,9 @@ function useSiteCameraService() {
|
|
|
31887
31993
|
var import_node_server_utils94 = require("@7365admin1/node-server-utils");
|
|
31888
31994
|
var import_joi49 = __toESM(require("joi"));
|
|
31889
31995
|
function useSiteCameraController() {
|
|
31890
|
-
const { add: _add } = useSiteCameraService();
|
|
31996
|
+
const { add: _add, updateById: _updateById } = useSiteCameraService();
|
|
31891
31997
|
const {
|
|
31892
31998
|
getAll: _getAll,
|
|
31893
|
-
updateById: _updateById,
|
|
31894
31999
|
deleteById: _deleteById
|
|
31895
32000
|
} = useSiteCameraRepo();
|
|
31896
32001
|
async function add(req, res, next) {
|
|
@@ -33150,7 +33255,7 @@ function useAttendanceRepository() {
|
|
|
33150
33255
|
localField: "user",
|
|
33151
33256
|
foreignField: "_id",
|
|
33152
33257
|
as: "user",
|
|
33153
|
-
pipeline: [{ $project: { name: 1 } }]
|
|
33258
|
+
pipeline: [{ $project: { name: 1, profile: 1 } }]
|
|
33154
33259
|
}
|
|
33155
33260
|
},
|
|
33156
33261
|
{ $unwind: { path: "$user", preserveNullAndEmptyArrays: true } }
|
|
@@ -33164,6 +33269,7 @@ function useAttendanceRepository() {
|
|
|
33164
33269
|
{
|
|
33165
33270
|
$project: {
|
|
33166
33271
|
userName: "$user.name",
|
|
33272
|
+
userProfile: "$user.profile",
|
|
33167
33273
|
checkInTimestamp: "$checkIn.timestamp",
|
|
33168
33274
|
checkOutTimestamp: "$checkOut.timestamp",
|
|
33169
33275
|
createdAt: 1
|
|
@@ -35636,7 +35742,7 @@ function useVisitorTransactionService() {
|
|
|
35636
35742
|
value.unitName = unit?.name;
|
|
35637
35743
|
}
|
|
35638
35744
|
const { nric = "", name = "", contact = "", plateNumber = "", email = "", site = "", type = "guest", company, createdBy } = value;
|
|
35639
|
-
if (/^(guest|walk-in|contractor|delivery)$/.test(type)) {
|
|
35745
|
+
if (/^(guest|walk-in|contractor|delivery)$/.test(type) && site) {
|
|
35640
35746
|
await addUpdateFromVisitor({
|
|
35641
35747
|
nric,
|
|
35642
35748
|
name,
|
|
@@ -35867,7 +35973,7 @@ function useVisitorTransactionService() {
|
|
|
35867
35973
|
value.checkIn = isNaN(parsed.getTime()) ? null : parsed;
|
|
35868
35974
|
}
|
|
35869
35975
|
const { nric = "", name = "", contact = "", plateNumber = "", email = "", site = "", type = "guest", company, createdBy } = value;
|
|
35870
|
-
if (/^(guest|walk-in|contractor|delivery)$/.test(type) &&
|
|
35976
|
+
if (/^(guest|walk-in|contractor|delivery)$/.test(type) && site) {
|
|
35871
35977
|
await addUpdateFromVisitor({
|
|
35872
35978
|
nric,
|
|
35873
35979
|
name,
|
|
@@ -36051,7 +36157,9 @@ function useVisitorTransactionService() {
|
|
|
36051
36157
|
value.site,
|
|
36052
36158
|
session,
|
|
36053
36159
|
void 0,
|
|
36054
|
-
id
|
|
36160
|
+
id,
|
|
36161
|
+
void 0,
|
|
36162
|
+
true
|
|
36055
36163
|
);
|
|
36056
36164
|
item.receivedDate = /* @__PURE__ */ new Date();
|
|
36057
36165
|
item.status = "Not Returned" /* NOT_RETURNED */;
|
|
@@ -36100,7 +36208,9 @@ function useVisitorTransactionService() {
|
|
|
36100
36208
|
value.site,
|
|
36101
36209
|
session,
|
|
36102
36210
|
void 0,
|
|
36103
|
-
id
|
|
36211
|
+
id,
|
|
36212
|
+
void 0,
|
|
36213
|
+
true
|
|
36104
36214
|
);
|
|
36105
36215
|
item.receivedDate = /* @__PURE__ */ new Date();
|
|
36106
36216
|
item.status = "Not Returned" /* NOT_RETURNED */;
|
|
@@ -55287,8 +55397,11 @@ function useNfcPatrolRouteRepo() {
|
|
|
55287
55397
|
const query = {
|
|
55288
55398
|
site
|
|
55289
55399
|
};
|
|
55290
|
-
if (search) {
|
|
55291
|
-
query
|
|
55400
|
+
if (search?.trim()) {
|
|
55401
|
+
query.name = {
|
|
55402
|
+
$regex: search.trim(),
|
|
55403
|
+
$options: "i"
|
|
55404
|
+
};
|
|
55292
55405
|
}
|
|
55293
55406
|
if (filter === "today" || filter === "notToday") {
|
|
55294
55407
|
const singaporeDateString = (/* @__PURE__ */ new Date()).toLocaleString("en-US", {
|
|
@@ -58651,13 +58764,9 @@ function useNfcPatrolLogRepo() {
|
|
|
58651
58764
|
};
|
|
58652
58765
|
if (date) {
|
|
58653
58766
|
if (type === "month") {
|
|
58654
|
-
const [year, month] = date.split("-").map(Number);
|
|
58655
|
-
const endDay = new Date(year, month, 0).getDate();
|
|
58656
58767
|
query.date = {
|
|
58657
|
-
$gte: `${
|
|
58658
|
-
$lte: `${
|
|
58659
|
-
endDay
|
|
58660
|
-
).padStart(2, "0")}`
|
|
58768
|
+
$gte: `${date}-01-01`,
|
|
58769
|
+
$lte: `${date}-12-31`
|
|
58661
58770
|
};
|
|
58662
58771
|
} else {
|
|
58663
58772
|
query.date = date;
|
|
@@ -58978,47 +59087,52 @@ function useNfcPatrolLogController() {
|
|
|
58978
59087
|
page: import_joi111.default.number().integer().min(1).default(1),
|
|
58979
59088
|
limit: import_joi111.default.number().integer().min(1).max(100).default(10),
|
|
58980
59089
|
site: import_joi111.default.string().length(24).hex().required(),
|
|
58981
|
-
date: import_joi111.default.string().pattern(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])
|
|
58982
|
-
"string.pattern.base": "Date must be
|
|
59090
|
+
date: import_joi111.default.string().pattern(/^\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01]))?)?$/).optional().messages({
|
|
59091
|
+
"string.pattern.base": "Date must be YYYY or YYYY-MM or YYYY-MM-DD"
|
|
58983
59092
|
}),
|
|
58984
59093
|
type: import_joi111.default.string().valid("month").optional(),
|
|
58985
59094
|
route: import_joi111.default.object({
|
|
58986
|
-
_id: import_joi111.default.string().length(24).hex().
|
|
58987
|
-
startTime: import_joi111.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).
|
|
58988
|
-
|
|
59095
|
+
_id: import_joi111.default.string().length(24).hex().optional(),
|
|
59096
|
+
startTime: import_joi111.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().messages({
|
|
59097
|
+
"string.pattern.base": "startTime must be in HH:mm 24-hour format"
|
|
59098
|
+
})
|
|
59099
|
+
}).min(1).optional()
|
|
58989
59100
|
});
|
|
58990
59101
|
const query = {
|
|
59102
|
+
page: req.query.page,
|
|
59103
|
+
limit: req.query.limit,
|
|
58991
59104
|
site: req.query.site,
|
|
58992
59105
|
date: req.query.date,
|
|
58993
|
-
|
|
58994
|
-
|
|
58995
|
-
|
|
58996
|
-
|
|
59106
|
+
type: req.query.type,
|
|
59107
|
+
route: req.query["route._id"] || req.query["route.startTime"] ? {
|
|
59108
|
+
...req.query["route._id"] ? { _id: req.query["route._id"] } : {},
|
|
59109
|
+
...req.query["route.startTime"] ? { startTime: req.query["route.startTime"] } : {}
|
|
59110
|
+
} : void 0
|
|
58997
59111
|
};
|
|
58998
59112
|
const { error, value } = validation.validate(query, {
|
|
58999
|
-
abortEarly: false
|
|
59113
|
+
abortEarly: false,
|
|
59114
|
+
allowUnknown: true,
|
|
59115
|
+
stripUnknown: true
|
|
59000
59116
|
});
|
|
59001
59117
|
if (error) {
|
|
59002
|
-
|
|
59003
|
-
|
|
59004
|
-
|
|
59005
|
-
|
|
59118
|
+
return next(
|
|
59119
|
+
new import_node_server_utils200.BadRequestError(
|
|
59120
|
+
error.details.map((d) => d.message).join(", ")
|
|
59121
|
+
)
|
|
59122
|
+
);
|
|
59006
59123
|
}
|
|
59007
|
-
const { page, limit, site, date, route } = value;
|
|
59008
59124
|
try {
|
|
59009
59125
|
const data = await _getAllBySite({
|
|
59010
|
-
page,
|
|
59011
|
-
limit,
|
|
59012
|
-
site,
|
|
59013
|
-
date,
|
|
59014
|
-
|
|
59126
|
+
page: value.page,
|
|
59127
|
+
limit: value.limit,
|
|
59128
|
+
site: value.site,
|
|
59129
|
+
date: value.date,
|
|
59130
|
+
type: value.type,
|
|
59131
|
+
route: value.route
|
|
59015
59132
|
});
|
|
59016
|
-
res.status(200).json(data);
|
|
59017
|
-
return;
|
|
59133
|
+
return res.status(200).json(data);
|
|
59018
59134
|
} catch (error2) {
|
|
59019
|
-
|
|
59020
|
-
next(error2);
|
|
59021
|
-
return;
|
|
59135
|
+
return next(error2);
|
|
59022
59136
|
}
|
|
59023
59137
|
}
|
|
59024
59138
|
async function completeCheckpoint(req, res, next) {
|
|
@@ -64548,34 +64662,62 @@ var import_axios3 = __toESM(require("axios"));
|
|
|
64548
64662
|
|
|
64549
64663
|
// src/utils/payment-signature.util.ts
|
|
64550
64664
|
var crypto3 = __toESM(require("crypto"));
|
|
64665
|
+
function hasOwn(obj, key) {
|
|
64666
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
64667
|
+
}
|
|
64668
|
+
function sha512(input) {
|
|
64669
|
+
return crypto3.createHash("sha512").update(input).digest("hex");
|
|
64670
|
+
}
|
|
64671
|
+
function assertSecret(secretKey) {
|
|
64672
|
+
if (!secretKey) {
|
|
64673
|
+
throw new Error("Payment signature: missing secret key.");
|
|
64674
|
+
}
|
|
64675
|
+
}
|
|
64551
64676
|
function paymentSignature(params, secretKey) {
|
|
64552
|
-
|
|
64677
|
+
assertSecret(secretKey);
|
|
64678
|
+
const fieldOrder = [
|
|
64679
|
+
"mid",
|
|
64680
|
+
"order_id",
|
|
64681
|
+
"payment_type",
|
|
64682
|
+
"amount",
|
|
64683
|
+
"ccy",
|
|
64684
|
+
"card_no",
|
|
64685
|
+
"exp_date",
|
|
64686
|
+
"cvv2"
|
|
64687
|
+
];
|
|
64553
64688
|
let concatenated = "";
|
|
64554
64689
|
fieldOrder.forEach((v) => {
|
|
64555
|
-
if (!params
|
|
64690
|
+
if (!hasOwn(params, v)) {
|
|
64556
64691
|
return;
|
|
64557
|
-
}
|
|
64558
|
-
|
|
64692
|
+
}
|
|
64693
|
+
const raw = String(params[v] ?? "");
|
|
64694
|
+
if (v === "cvv2") {
|
|
64695
|
+
concatenated += raw.slice(-1);
|
|
64559
64696
|
} else if (v === "card_no") {
|
|
64560
|
-
concatenated +=
|
|
64697
|
+
concatenated += raw.substring(0, 6) + raw.slice(-4);
|
|
64561
64698
|
} else {
|
|
64562
|
-
concatenated +=
|
|
64699
|
+
concatenated += raw;
|
|
64563
64700
|
}
|
|
64564
64701
|
});
|
|
64565
64702
|
concatenated += secretKey;
|
|
64566
|
-
|
|
64567
|
-
return signature;
|
|
64703
|
+
return sha512(concatenated);
|
|
64568
64704
|
}
|
|
64569
64705
|
function genericSignature(params, secretKey) {
|
|
64570
|
-
|
|
64706
|
+
assertSecret(secretKey);
|
|
64707
|
+
const paramsCopy = {
|
|
64708
|
+
...params
|
|
64709
|
+
};
|
|
64571
64710
|
delete paramsCopy["signature"];
|
|
64572
|
-
const
|
|
64573
|
-
|
|
64574
|
-
|
|
64575
|
-
|
|
64576
|
-
|
|
64577
|
-
|
|
64578
|
-
|
|
64711
|
+
const concatenated = Object.keys(paramsCopy).sort().map((key) => {
|
|
64712
|
+
const value = paramsCopy[key];
|
|
64713
|
+
if (value !== null && typeof value === "object") {
|
|
64714
|
+
throw new Error(
|
|
64715
|
+
`Payment signature: non-primitive value for field "${key}".`
|
|
64716
|
+
);
|
|
64717
|
+
}
|
|
64718
|
+
return String(value ?? "");
|
|
64719
|
+
}).join("") + secretKey;
|
|
64720
|
+
return sha512(concatenated);
|
|
64579
64721
|
}
|
|
64580
64722
|
|
|
64581
64723
|
// src/repositories/reddot-payment.repository.ts
|
|
@@ -64998,7 +65140,7 @@ var useRedDotPaymentSvc = () => {
|
|
|
64998
65140
|
};
|
|
64999
65141
|
if (!process.env.MERCHANT_ENQUIRY) {
|
|
65000
65142
|
throw new Error(
|
|
65001
|
-
"
|
|
65143
|
+
"MERCHANT_ENQUIRY environment variable is not defined."
|
|
65002
65144
|
);
|
|
65003
65145
|
}
|
|
65004
65146
|
const url = process.env.MERCHANT_ENQUIRY;
|