@7365admin1/core 3.52.2 → 3.52.3-staging.242
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/.changeset/camera-error-wording-and-plate-cleanup.md +11 -0
- package/.changeset/plate-lookup-hides-deleted-plates.md +9 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +278 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +278 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/anpr-revoke.test.mjs +124 -5
- package/test/e2e/vehicle-plate-read-paths.e2e.test.mjs +357 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Write camera failures in words an operator can act on, and stop offering plates whose vehicle has been deleted.
|
|
6
|
+
|
|
7
|
+
Camera failure messages no longer carry a camera's `_id`, its host, an IP, a port or a raw driver error. A camera is named by its display name and direction ("North Gate (entry)", or "the entry camera" when it has no name), and the reason is plain language ("the camera could not be reached"). The full technical detail — record id, host, and the device's or driver's own text — goes to the server log instead. The same treatment is applied to create, approve, restore, block, unblock, edit and delete; `blocklistVehicles`, `removeFromBlocklist` and `reactivateVehicleById` previously said only "Failed to delete/update/add plate number to ANPR", which named no camera and said nothing about what happened to the record. Blocking now states the opposite consequence to saving, because a failed blacklist write leaves the car able to get in.
|
|
8
|
+
|
|
9
|
+
`site.people.plates[]` no longer keeps a plate after its vehicle is deleted. The pull matched on `recNo`, which Dahua numbers per device, so the copy on the vehicle and the copy on the person diverged and the update silently matched nothing; it now matches on the plate number, and leaves the plate alone when a second live vehicle still holds it. Unblocking, which soft-deletes the record, now pulls the plate too. `GET /api/people/unit/:unit` and `GET /api/people` also drop any plate whose vehicle records are all deleted, so rows that had already drifted are not offered either. A plate the resident merely declared, with no vehicle record at all, is unchanged.
|
|
10
|
+
|
|
11
|
+
Unblocking a vehicle at a site with no ANPR camera now succeeds instead of failing with "No site cameras found." — there is nothing to revoke, which is the state the unblock is trying to reach. Approve, Restore, Block and Edit still refuse in that state, now saying why and what did not happen.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
`GET /api/people/plateNumber/:plateNumber` now hides plates whose vehicle has been deleted, like the other person reads.
|
|
6
|
+
|
|
7
|
+
Its own filter is `status: { $ne: "deleted" }` on the **person**, which is unrelated to the vehicle — reading that line as "deleted plates are excluded" is why this endpoint was missed when the other two were fixed. It has no caller in the estate today, but it is routed and behind `requireAuth`, so an authenticated caller gets the resident's whole `plates[]` array back. The filter runs on read, after the cache, because whether a plate's vehicle is deleted can change inside the 15-minute TTL.
|
|
8
|
+
|
|
9
|
+
`getPersonByPlateNumber` (no caller, no route) and `getApprovedPersonByPlateNumber` (a record-matching path inside `person.service.ts`, not a display path) are deliberately left alone.
|
package/dist/index.d.ts
CHANGED
|
@@ -2528,6 +2528,14 @@ type AnprRevokeOutcome = {
|
|
|
2528
2528
|
statusCode?: number;
|
|
2529
2529
|
/** Why it failed, in words an operator can act on. Empty when `ok`. */
|
|
2530
2530
|
reason: string;
|
|
2531
|
+
/**
|
|
2532
|
+
* The technical cause, for the SERVER LOG only. Never rendered.
|
|
2533
|
+
*
|
|
2534
|
+
* `reason` used to BE this string, so a driver error went straight to the
|
|
2535
|
+
* browser: "connect EHOSTUNREACH 129.126.212.21:8081" put an internal IP and
|
|
2536
|
+
* port in front of a condo manager, who can do nothing with either.
|
|
2537
|
+
*/
|
|
2538
|
+
detail?: string;
|
|
2531
2539
|
};
|
|
2532
2540
|
|
|
2533
2541
|
declare enum CameraType {
|
package/dist/index.js
CHANGED
|
@@ -17573,9 +17573,39 @@ function usePersonRepo() {
|
|
|
17573
17573
|
throw new import_node_server_utils41.InternalServerError("Unable to connect to server.");
|
|
17574
17574
|
}
|
|
17575
17575
|
const collection = db2.collection(site_people_namespace_collection);
|
|
17576
|
+
const vehiclesCollection = db2.collection("vehicles");
|
|
17576
17577
|
const { delNamespace, getCache, setCache } = (0, import_node_server_utils41.useCache)(
|
|
17577
17578
|
site_people_namespace_collection
|
|
17578
17579
|
);
|
|
17580
|
+
async function withoutDeletedPlates(people) {
|
|
17581
|
+
const numbers = Array.from(
|
|
17582
|
+
new Set(
|
|
17583
|
+
people.flatMap(
|
|
17584
|
+
(person) => (Array.isArray(person?.plates) ? person.plates : []).map((plate) => plate?.plateNumber).filter((value) => typeof value === "string" && !!value)
|
|
17585
|
+
)
|
|
17586
|
+
)
|
|
17587
|
+
);
|
|
17588
|
+
if (!numbers.length)
|
|
17589
|
+
return people;
|
|
17590
|
+
const records = await vehiclesCollection.find(
|
|
17591
|
+
{ plateNumber: { $in: numbers } },
|
|
17592
|
+
{ projection: { plateNumber: 1, status: 1, site: 1 } }
|
|
17593
|
+
).toArray();
|
|
17594
|
+
const live = /* @__PURE__ */ new Map();
|
|
17595
|
+
for (const record of records) {
|
|
17596
|
+
const key = `${String(record.site)}|${record.plateNumber}`;
|
|
17597
|
+
live.set(key, live.get(key) === true || record.status !== "deleted");
|
|
17598
|
+
}
|
|
17599
|
+
return people.map((person) => {
|
|
17600
|
+
if (!Array.isArray(person?.plates) || !person.plates.length)
|
|
17601
|
+
return person;
|
|
17602
|
+
const plates = person.plates.filter((plate) => {
|
|
17603
|
+
const key = `${String(person.site)}|${plate?.plateNumber}`;
|
|
17604
|
+
return !live.has(key) || live.get(key) === true;
|
|
17605
|
+
});
|
|
17606
|
+
return plates.length === person.plates.length ? person : { ...person, plates };
|
|
17607
|
+
});
|
|
17608
|
+
}
|
|
17579
17609
|
async function createIndexes() {
|
|
17580
17610
|
try {
|
|
17581
17611
|
await collection.createIndexes([
|
|
@@ -17751,7 +17781,12 @@ function usePersonRepo() {
|
|
|
17751
17781
|
collection.aggregate([{ $match: query2 }, { $count: "total" }], { session }).toArray()
|
|
17752
17782
|
]);
|
|
17753
17783
|
const totalCount = countResult[0]?.total || 0;
|
|
17754
|
-
const data = (0, import_node_server_utils41.paginate)(
|
|
17784
|
+
const data = (0, import_node_server_utils41.paginate)(
|
|
17785
|
+
await withoutDeletedPlates(items),
|
|
17786
|
+
page,
|
|
17787
|
+
limit,
|
|
17788
|
+
totalCount
|
|
17789
|
+
);
|
|
17755
17790
|
return data;
|
|
17756
17791
|
} catch (error) {
|
|
17757
17792
|
throw error;
|
|
@@ -18004,7 +18039,7 @@ function usePersonRepo() {
|
|
|
18004
18039
|
},
|
|
18005
18040
|
{ $unwind: { path: "$unit", preserveNullAndEmptyArrays: true } }
|
|
18006
18041
|
]).toArray();
|
|
18007
|
-
return data;
|
|
18042
|
+
return await withoutDeletedPlates(data);
|
|
18008
18043
|
} catch (error) {
|
|
18009
18044
|
throw new import_node_server_utils41.InternalServerError(
|
|
18010
18045
|
"Failed to fetch people type residents by unit."
|
|
@@ -18095,7 +18130,7 @@ function usePersonRepo() {
|
|
|
18095
18130
|
const cacheData = await getCache(cacheKey);
|
|
18096
18131
|
if (cacheData) {
|
|
18097
18132
|
import_node_server_utils41.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
18098
|
-
return cacheData;
|
|
18133
|
+
return await withoutDeletedPlates(cacheData);
|
|
18099
18134
|
}
|
|
18100
18135
|
const data = await collection.find(
|
|
18101
18136
|
{ "plates.plateNumber": plateNumber, status: { $ne: "deleted" } },
|
|
@@ -18106,7 +18141,7 @@ function usePersonRepo() {
|
|
|
18106
18141
|
}).catch((err) => {
|
|
18107
18142
|
import_node_server_utils41.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
18108
18143
|
});
|
|
18109
|
-
return data;
|
|
18144
|
+
return await withoutDeletedPlates(data);
|
|
18110
18145
|
} catch (error) {
|
|
18111
18146
|
throw new import_node_server_utils41.InternalServerError("Failed to fetch people by plate number.");
|
|
18112
18147
|
}
|
|
@@ -18203,10 +18238,22 @@ function usePersonRepo() {
|
|
|
18203
18238
|
"Cannot remove a vehicle plate without a person or a site."
|
|
18204
18239
|
);
|
|
18205
18240
|
}
|
|
18206
|
-
const match =
|
|
18241
|
+
const match = scope?.plateNumber ? { plateNumber: scope.plateNumber } : recNo ? { recNo } : {};
|
|
18207
18242
|
if (!Object.keys(match).length)
|
|
18208
18243
|
return;
|
|
18209
18244
|
const matchKey = Object.keys(match)[0];
|
|
18245
|
+
if (matchKey === "plateNumber" && site) {
|
|
18246
|
+
const survivor = await vehiclesCollection.findOne(
|
|
18247
|
+
{
|
|
18248
|
+
site,
|
|
18249
|
+
plateNumber: scope.plateNumber,
|
|
18250
|
+
status: { $ne: "deleted" }
|
|
18251
|
+
},
|
|
18252
|
+
{ projection: { _id: 1 }, session }
|
|
18253
|
+
);
|
|
18254
|
+
if (survivor)
|
|
18255
|
+
return;
|
|
18256
|
+
}
|
|
18210
18257
|
const filter = {
|
|
18211
18258
|
[`plates.${matchKey}`]: match[matchKey]
|
|
18212
18259
|
};
|
|
@@ -22443,34 +22490,119 @@ function anprRevokeOutcome(response) {
|
|
|
22443
22490
|
if (statusCode === 200)
|
|
22444
22491
|
return { ok: true, statusCode, reason: "" };
|
|
22445
22492
|
if (statusCode === void 0) {
|
|
22446
|
-
return {
|
|
22493
|
+
return {
|
|
22494
|
+
ok: false,
|
|
22495
|
+
reason: CAMERA_FAILURE_REASONS.transient,
|
|
22496
|
+
detail: "the device reply carried no status code"
|
|
22497
|
+
};
|
|
22447
22498
|
}
|
|
22448
|
-
return {
|
|
22499
|
+
return {
|
|
22500
|
+
ok: false,
|
|
22501
|
+
statusCode,
|
|
22502
|
+
reason: reasonForStatus(statusCode),
|
|
22503
|
+
detail: `the camera answered HTTP ${statusCode}`
|
|
22504
|
+
};
|
|
22449
22505
|
}
|
|
22450
22506
|
function anprRevokeThrew(error) {
|
|
22451
|
-
const message = error?.message ??
|
|
22452
|
-
return {
|
|
22507
|
+
const message = String(error?.message ?? error ?? "");
|
|
22508
|
+
return {
|
|
22509
|
+
ok: false,
|
|
22510
|
+
reason: cameraFailureReason(message),
|
|
22511
|
+
detail: message || "the request threw with no message"
|
|
22512
|
+
};
|
|
22513
|
+
}
|
|
22514
|
+
function cameraFailureSentence(options) {
|
|
22515
|
+
const { failures, operation, outcome, consequence } = options;
|
|
22516
|
+
return `The plate number could not be ${operation} ${cameraCount(failures.length)}: ${cameraDetail(failures)}. The vehicle has NOT been ${outcome} \u2014 ${consequence}. Please check the ${failures.length === 1 ? "camera" : "cameras"} and try again.`;
|
|
22453
22517
|
}
|
|
22454
22518
|
function anprRevokeFailureMessage(failures, action = "deleted") {
|
|
22455
|
-
|
|
22456
|
-
|
|
22519
|
+
return cameraFailureSentence({
|
|
22520
|
+
failures,
|
|
22521
|
+
operation: "removed from",
|
|
22522
|
+
outcome: action,
|
|
22523
|
+
consequence: "it would still open the barrier"
|
|
22524
|
+
});
|
|
22457
22525
|
}
|
|
22458
|
-
|
|
22526
|
+
function anprRestoreFailureMessage(failures) {
|
|
22527
|
+
return cameraFailureSentence({
|
|
22528
|
+
failures,
|
|
22529
|
+
operation: "added to",
|
|
22530
|
+
outcome: "restored",
|
|
22531
|
+
consequence: "it would not open the barrier"
|
|
22532
|
+
});
|
|
22533
|
+
}
|
|
22534
|
+
function anprBlockFailureMessage(failures) {
|
|
22535
|
+
return cameraFailureSentence({
|
|
22536
|
+
failures,
|
|
22537
|
+
operation: "added to",
|
|
22538
|
+
outcome: "blocked",
|
|
22539
|
+
consequence: "it would still open the barrier"
|
|
22540
|
+
});
|
|
22541
|
+
}
|
|
22542
|
+
function anprUnblockFailureMessage(failures) {
|
|
22543
|
+
return cameraFailureSentence({
|
|
22544
|
+
failures,
|
|
22545
|
+
operation: "removed from",
|
|
22546
|
+
outcome: "unblocked",
|
|
22547
|
+
consequence: "it would still be turned away at the barrier"
|
|
22548
|
+
});
|
|
22549
|
+
}
|
|
22550
|
+
var CAMERA_FAILURE_REASONS = {
|
|
22459
22551
|
challenge: "the camera refused the login saved for it (its username or password is wrong, or the account is temporarily locked after failed logins)",
|
|
22460
22552
|
rejected: "the camera rejected the request \u2014 its account is not allowed to change the plate list",
|
|
22461
22553
|
transient: "the camera could not be reached"
|
|
22462
22554
|
};
|
|
22463
|
-
function
|
|
22555
|
+
function cameraFailureReason(detail) {
|
|
22464
22556
|
const message = detail?.message ?? String(detail ?? "");
|
|
22465
|
-
return
|
|
22557
|
+
return CAMERA_FAILURE_REASONS[classifyDahuaFailure(message)];
|
|
22558
|
+
}
|
|
22559
|
+
function reasonForStatus(statusCode) {
|
|
22560
|
+
if (statusCode === 401)
|
|
22561
|
+
return CAMERA_FAILURE_REASONS.challenge;
|
|
22562
|
+
if (statusCode === 403)
|
|
22563
|
+
return CAMERA_FAILURE_REASONS.rejected;
|
|
22564
|
+
return "the camera answered with an error";
|
|
22466
22565
|
}
|
|
22566
|
+
var DIRECTION_WORDS2 = {
|
|
22567
|
+
entry: "entry",
|
|
22568
|
+
exit: "exit",
|
|
22569
|
+
both: "entry/exit",
|
|
22570
|
+
visitors: "visitor lane",
|
|
22571
|
+
residents: "resident lane"
|
|
22572
|
+
};
|
|
22573
|
+
function cameraLabel(camera) {
|
|
22574
|
+
const name = String(camera?.name ?? "").trim();
|
|
22575
|
+
const direction = DIRECTION_WORDS2[String(camera?.direction ?? "").trim().toLowerCase()];
|
|
22576
|
+
if (name && direction)
|
|
22577
|
+
return `${name} (${direction})`;
|
|
22578
|
+
if (name)
|
|
22579
|
+
return name;
|
|
22580
|
+
if (direction)
|
|
22581
|
+
return `the ${direction} camera`;
|
|
22582
|
+
return "an ANPR camera";
|
|
22583
|
+
}
|
|
22584
|
+
function cameraCount(total) {
|
|
22585
|
+
return total === 1 ? "1 ANPR camera" : `${total} ANPR cameras`;
|
|
22586
|
+
}
|
|
22587
|
+
function cameraDetail(failures) {
|
|
22588
|
+
const parts = failures.map((f) => `${f.camera} \u2014 ${f.reason}`);
|
|
22589
|
+
return Array.from(new Set(parts)).join("; ");
|
|
22590
|
+
}
|
|
22591
|
+
var anprWriteReason = cameraFailureReason;
|
|
22467
22592
|
function anprWriteFailureMessage(failures, action = "added") {
|
|
22468
|
-
|
|
22469
|
-
|
|
22593
|
+
return cameraFailureSentence({
|
|
22594
|
+
failures,
|
|
22595
|
+
operation: "added to",
|
|
22596
|
+
outcome: action === "added" ? "saved" : action,
|
|
22597
|
+
consequence: "it would not open the barrier"
|
|
22598
|
+
});
|
|
22470
22599
|
}
|
|
22471
22600
|
function anprNoCameraMessage(type) {
|
|
22472
22601
|
return `Vehicle saved to the ${type} record. There is no active ANPR camera at this site, so the plate has NOT been registered on a barrier yet and the gate will not open for it. It will need to be added once a camera is set up and switched on.`;
|
|
22473
22602
|
}
|
|
22603
|
+
function anprNoCameraRefusal(outcome) {
|
|
22604
|
+
return `There is no ANPR camera set up at this site, so the plate cannot be registered on a barrier. The vehicle has NOT been ${outcome}. Add a camera in Settings first, then try again.`;
|
|
22605
|
+
}
|
|
22474
22606
|
|
|
22475
22607
|
// src/services/dahua.service.ts
|
|
22476
22608
|
function notifyCameraFault(camera, message) {
|
|
@@ -35188,8 +35320,11 @@ function parseDahuaFind(text2) {
|
|
|
35188
35320
|
plateNumber: text2.match(/records\[0\]\.PlateNumber=(.*)/)?.[1]?.trim()
|
|
35189
35321
|
};
|
|
35190
35322
|
}
|
|
35191
|
-
function
|
|
35192
|
-
|
|
35323
|
+
function logCameraFailure(where, camera, detail) {
|
|
35324
|
+
const raw = String(detail?.message ?? detail ?? "");
|
|
35325
|
+
import_node_server_utils99.logger.error(
|
|
35326
|
+
`${where}: ANPR camera ${String(camera?._id ?? "unknown id")} host ${String(camera?.host ?? "unknown host")} name ${JSON.stringify(String(camera?.name ?? ""))} direction ${JSON.stringify(String(camera?.direction ?? ""))} failed: ${raw || "no detail"}`
|
|
35327
|
+
);
|
|
35193
35328
|
}
|
|
35194
35329
|
function useVehicleService() {
|
|
35195
35330
|
const {
|
|
@@ -35336,9 +35471,7 @@ function useVehicleService() {
|
|
|
35336
35471
|
for (const camera of siteCameras) {
|
|
35337
35472
|
const { host, username, password } = camera;
|
|
35338
35473
|
const plateNumber2 = vehicleValue.plateNumber;
|
|
35339
|
-
const label =
|
|
35340
|
-
camera?.name || camera?._id || "ANPR camera"
|
|
35341
|
-
);
|
|
35474
|
+
const label = cameraLabel(camera);
|
|
35342
35475
|
const dahuaPayload = {
|
|
35343
35476
|
host,
|
|
35344
35477
|
username,
|
|
@@ -35354,6 +35487,11 @@ function useVehicleService() {
|
|
|
35354
35487
|
const responseStatus = dahuaResponse?.statusCode || dahuaResponse?.status || dahuaResponse?.res?.status || "unknown";
|
|
35355
35488
|
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
35356
35489
|
if (responseStatus !== 200) {
|
|
35490
|
+
logCameraFailure(
|
|
35491
|
+
"add",
|
|
35492
|
+
camera,
|
|
35493
|
+
`HTTP ${responseStatus}: ${responseData.slice(0, 500)}`
|
|
35494
|
+
);
|
|
35357
35495
|
failures.push({
|
|
35358
35496
|
camera: label,
|
|
35359
35497
|
reason: anprWriteReason(`HTTP ${responseStatus}`)
|
|
@@ -35375,6 +35513,7 @@ function useVehicleService() {
|
|
|
35375
35513
|
);
|
|
35376
35514
|
}
|
|
35377
35515
|
} catch (error) {
|
|
35516
|
+
logCameraFailure("add", camera, error);
|
|
35378
35517
|
failures.push({ camera: label, reason: anprWriteReason(error) });
|
|
35379
35518
|
}
|
|
35380
35519
|
}
|
|
@@ -35452,9 +35591,7 @@ function useVehicleService() {
|
|
|
35452
35591
|
const host = camera.host;
|
|
35453
35592
|
const username = camera.username;
|
|
35454
35593
|
const password = camera.password;
|
|
35455
|
-
const label =
|
|
35456
|
-
camera?.name || camera?._id || "ANPR camera"
|
|
35457
|
-
);
|
|
35594
|
+
const label = cameraLabel(camera);
|
|
35458
35595
|
let recnoForCamera = recno;
|
|
35459
35596
|
if (plateNumber) {
|
|
35460
35597
|
try {
|
|
@@ -35473,10 +35610,9 @@ function useVehicleService() {
|
|
|
35473
35610
|
if (found.recNo)
|
|
35474
35611
|
recnoForCamera = found.recNo;
|
|
35475
35612
|
} catch (error) {
|
|
35476
|
-
|
|
35477
|
-
|
|
35478
|
-
|
|
35479
|
-
});
|
|
35613
|
+
const outcome2 = anprRevokeThrew(error);
|
|
35614
|
+
logCameraFailure("deleteVehicle lookup", camera, outcome2.detail);
|
|
35615
|
+
failures.push({ camera: label, reason: outcome2.reason });
|
|
35480
35616
|
continue;
|
|
35481
35617
|
}
|
|
35482
35618
|
}
|
|
@@ -35490,9 +35626,14 @@ function useVehicleService() {
|
|
|
35490
35626
|
mode: _mode
|
|
35491
35627
|
});
|
|
35492
35628
|
if (!outcome?.ok) {
|
|
35629
|
+
logCameraFailure(
|
|
35630
|
+
"deleteVehicle revoke",
|
|
35631
|
+
camera,
|
|
35632
|
+
outcome?.detail ?? "no outcome returned"
|
|
35633
|
+
);
|
|
35493
35634
|
failures.push({
|
|
35494
35635
|
camera: label,
|
|
35495
|
-
reason: outcome?.reason || "the camera
|
|
35636
|
+
reason: outcome?.reason || "the camera could not be reached"
|
|
35496
35637
|
});
|
|
35497
35638
|
}
|
|
35498
35639
|
}
|
|
@@ -35572,7 +35713,7 @@ function useVehicleService() {
|
|
|
35572
35713
|
page++;
|
|
35573
35714
|
} while (page <= pages);
|
|
35574
35715
|
if (!siteCameras.length) {
|
|
35575
|
-
throw new import_node_server_utils99.BadRequestError("
|
|
35716
|
+
throw new import_node_server_utils99.BadRequestError(anprNoCameraRefusal("approved"));
|
|
35576
35717
|
}
|
|
35577
35718
|
for (const camera of siteCameras) {
|
|
35578
35719
|
const { host, username, password } = camera;
|
|
@@ -35588,6 +35729,11 @@ function useVehicleService() {
|
|
|
35588
35729
|
};
|
|
35589
35730
|
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
35590
35731
|
if (dahuaResponse?.statusCode != 200) {
|
|
35732
|
+
logCameraFailure(
|
|
35733
|
+
"approveVehicleById",
|
|
35734
|
+
camera,
|
|
35735
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
35736
|
+
);
|
|
35591
35737
|
throw new import_node_server_utils99.BadRequestError(
|
|
35592
35738
|
anprWriteFailureMessage([
|
|
35593
35739
|
{
|
|
@@ -35735,7 +35881,7 @@ function useVehicleService() {
|
|
|
35735
35881
|
page++;
|
|
35736
35882
|
} while (page <= pages);
|
|
35737
35883
|
if (!siteCameras.length) {
|
|
35738
|
-
throw new import_node_server_utils99.BadRequestError("
|
|
35884
|
+
throw new import_node_server_utils99.BadRequestError(anprNoCameraRefusal("restored"));
|
|
35739
35885
|
}
|
|
35740
35886
|
for (const camera of siteCameras) {
|
|
35741
35887
|
const { host, username, password } = camera;
|
|
@@ -35751,7 +35897,21 @@ function useVehicleService() {
|
|
|
35751
35897
|
};
|
|
35752
35898
|
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
35753
35899
|
if (dahuaResponse?.statusCode !== 200) {
|
|
35754
|
-
|
|
35900
|
+
logCameraFailure(
|
|
35901
|
+
"reactivateVehicleById",
|
|
35902
|
+
camera,
|
|
35903
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
35904
|
+
);
|
|
35905
|
+
throw new import_node_server_utils99.BadRequestError(
|
|
35906
|
+
anprRestoreFailureMessage([
|
|
35907
|
+
{
|
|
35908
|
+
camera: cameraLabel(camera),
|
|
35909
|
+
reason: anprWriteReason(
|
|
35910
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
35911
|
+
)
|
|
35912
|
+
}
|
|
35913
|
+
])
|
|
35914
|
+
);
|
|
35755
35915
|
}
|
|
35756
35916
|
const responseData = dahuaResponse?.data.toString("utf-8");
|
|
35757
35917
|
value.recNo = responseData.split("=")[1]?.trim();
|
|
@@ -35835,7 +35995,7 @@ function useVehicleService() {
|
|
|
35835
35995
|
page++;
|
|
35836
35996
|
} while (page <= pages);
|
|
35837
35997
|
if (!siteCameras.length) {
|
|
35838
|
-
throw new import_node_server_utils99.BadRequestError("
|
|
35998
|
+
throw new import_node_server_utils99.BadRequestError(anprNoCameraRefusal("updated"));
|
|
35839
35999
|
}
|
|
35840
36000
|
for (const camera of siteCameras) {
|
|
35841
36001
|
const { host, username, password } = camera;
|
|
@@ -35852,12 +36012,17 @@ function useVehicleService() {
|
|
|
35852
36012
|
removePlateNumber
|
|
35853
36013
|
);
|
|
35854
36014
|
if (!responseForDeletion?.ok) {
|
|
36015
|
+
logCameraFailure(
|
|
36016
|
+
"updateVehicleById revoke",
|
|
36017
|
+
camera,
|
|
36018
|
+
responseForDeletion?.detail ?? "no outcome returned"
|
|
36019
|
+
);
|
|
35855
36020
|
throw new import_node_server_utils99.BadRequestError(
|
|
35856
36021
|
anprRevokeFailureMessage(
|
|
35857
36022
|
[
|
|
35858
36023
|
{
|
|
35859
36024
|
camera: cameraLabel(camera),
|
|
35860
|
-
reason: responseForDeletion?.reason || "the camera
|
|
36025
|
+
reason: responseForDeletion?.reason || "the camera could not be reached"
|
|
35861
36026
|
}
|
|
35862
36027
|
],
|
|
35863
36028
|
"updated"
|
|
@@ -35879,6 +36044,7 @@ function useVehicleService() {
|
|
|
35879
36044
|
try {
|
|
35880
36045
|
dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
35881
36046
|
} catch (error) {
|
|
36047
|
+
logCameraFailure("updateVehicleById write", camera, error);
|
|
35882
36048
|
const restored = await restorePlateOnCamera({
|
|
35883
36049
|
...removePlateNumber,
|
|
35884
36050
|
plateNumber: _plateNumber,
|
|
@@ -35894,6 +36060,11 @@ function useVehicleService() {
|
|
|
35894
36060
|
);
|
|
35895
36061
|
}
|
|
35896
36062
|
if (dahuaResponse?.statusCode !== 200) {
|
|
36063
|
+
logCameraFailure(
|
|
36064
|
+
"updateVehicleById write",
|
|
36065
|
+
camera,
|
|
36066
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
36067
|
+
);
|
|
35897
36068
|
throw new import_node_server_utils99.BadRequestError(
|
|
35898
36069
|
anprWriteFailureMessage(
|
|
35899
36070
|
[
|
|
@@ -35940,11 +36111,16 @@ function useVehicleService() {
|
|
|
35940
36111
|
recno: existing.recNo || _recNo
|
|
35941
36112
|
});
|
|
35942
36113
|
if (!outcome?.ok) {
|
|
36114
|
+
logCameraFailure(
|
|
36115
|
+
"updateVehicleById revoke",
|
|
36116
|
+
camera,
|
|
36117
|
+
outcome?.detail ?? "no outcome returned"
|
|
36118
|
+
);
|
|
35943
36119
|
throw new import_node_server_utils99.BadRequestError(
|
|
35944
36120
|
anprRevokeFailureMessage([
|
|
35945
36121
|
{
|
|
35946
36122
|
camera: cameraLabel(camera),
|
|
35947
|
-
reason: outcome?.reason || "the camera
|
|
36123
|
+
reason: outcome?.reason || "the camera could not be reached"
|
|
35948
36124
|
}
|
|
35949
36125
|
], "updated")
|
|
35950
36126
|
);
|
|
@@ -35965,6 +36141,7 @@ function useVehicleService() {
|
|
|
35965
36141
|
try {
|
|
35966
36142
|
dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
35967
36143
|
} catch (error) {
|
|
36144
|
+
logCameraFailure("updateVehicleById write", camera, error);
|
|
35968
36145
|
const restored = existing.exists ? await restorePlateOnCamera({
|
|
35969
36146
|
...dahuaPayload,
|
|
35970
36147
|
owner: _name
|
|
@@ -35977,6 +36154,11 @@ function useVehicleService() {
|
|
|
35977
36154
|
);
|
|
35978
36155
|
}
|
|
35979
36156
|
if (dahuaResponse?.statusCode !== 200) {
|
|
36157
|
+
logCameraFailure(
|
|
36158
|
+
"updateVehicleById write",
|
|
36159
|
+
camera,
|
|
36160
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
36161
|
+
);
|
|
35980
36162
|
throw new import_node_server_utils99.BadRequestError(
|
|
35981
36163
|
anprWriteFailureMessage(
|
|
35982
36164
|
[
|
|
@@ -36157,7 +36339,7 @@ function useVehicleService() {
|
|
|
36157
36339
|
page++;
|
|
36158
36340
|
} while (page <= pages);
|
|
36159
36341
|
if (!siteCameras.length) {
|
|
36160
|
-
throw new import_node_server_utils99.BadRequestError("
|
|
36342
|
+
throw new import_node_server_utils99.BadRequestError(anprNoCameraRefusal("blocked"));
|
|
36161
36343
|
}
|
|
36162
36344
|
for (const camera of siteCameras) {
|
|
36163
36345
|
const { host, username, password } = camera;
|
|
@@ -36171,8 +36353,23 @@ function useVehicleService() {
|
|
|
36171
36353
|
const responseForDeletion = await _removePlateNumber(
|
|
36172
36354
|
removePlateNumber
|
|
36173
36355
|
);
|
|
36174
|
-
if (responseForDeletion?.
|
|
36175
|
-
|
|
36356
|
+
if (!responseForDeletion?.ok) {
|
|
36357
|
+
logCameraFailure(
|
|
36358
|
+
"blocklistVehicles revoke",
|
|
36359
|
+
camera,
|
|
36360
|
+
responseForDeletion?.detail ?? "no outcome returned"
|
|
36361
|
+
);
|
|
36362
|
+
throw new import_node_server_utils99.BadRequestError(
|
|
36363
|
+
anprRevokeFailureMessage(
|
|
36364
|
+
[
|
|
36365
|
+
{
|
|
36366
|
+
camera: cameraLabel(camera),
|
|
36367
|
+
reason: responseForDeletion?.reason || "the camera could not be reached"
|
|
36368
|
+
}
|
|
36369
|
+
],
|
|
36370
|
+
"updated"
|
|
36371
|
+
)
|
|
36372
|
+
);
|
|
36176
36373
|
}
|
|
36177
36374
|
const dahuaPayload = {
|
|
36178
36375
|
host,
|
|
@@ -36186,7 +36383,21 @@ function useVehicleService() {
|
|
|
36186
36383
|
};
|
|
36187
36384
|
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
36188
36385
|
if (dahuaResponse?.statusCode !== 200) {
|
|
36189
|
-
|
|
36386
|
+
logCameraFailure(
|
|
36387
|
+
"blocklistVehicles write",
|
|
36388
|
+
camera,
|
|
36389
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
36390
|
+
);
|
|
36391
|
+
throw new import_node_server_utils99.BadRequestError(
|
|
36392
|
+
anprBlockFailureMessage([
|
|
36393
|
+
{
|
|
36394
|
+
camera: cameraLabel(camera),
|
|
36395
|
+
reason: anprWriteReason(
|
|
36396
|
+
`HTTP ${dahuaResponse?.statusCode ?? "none"}`
|
|
36397
|
+
)
|
|
36398
|
+
}
|
|
36399
|
+
])
|
|
36400
|
+
);
|
|
36190
36401
|
}
|
|
36191
36402
|
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
36192
36403
|
value.recNo = responseData.split("=")[1]?.trim();
|
|
@@ -36248,9 +36459,9 @@ function useVehicleService() {
|
|
|
36248
36459
|
siteCameras.push(...siteCameraReq.items);
|
|
36249
36460
|
page++;
|
|
36250
36461
|
} while (page <= pages);
|
|
36251
|
-
|
|
36252
|
-
|
|
36253
|
-
|
|
36462
|
+
import_node_server_utils99.logger.info(
|
|
36463
|
+
`removeFromBlocklist resolved ${siteCameras.length} ANPR camera(s)`
|
|
36464
|
+
);
|
|
36254
36465
|
for (const camera of siteCameras) {
|
|
36255
36466
|
const { host, username, password } = camera;
|
|
36256
36467
|
const removePlateNumber = {
|
|
@@ -36263,12 +36474,35 @@ function useVehicleService() {
|
|
|
36263
36474
|
const responseForDeletion = await _removePlateNumber(
|
|
36264
36475
|
removePlateNumber
|
|
36265
36476
|
);
|
|
36266
|
-
if (responseForDeletion?.
|
|
36267
|
-
|
|
36477
|
+
if (!responseForDeletion?.ok) {
|
|
36478
|
+
logCameraFailure(
|
|
36479
|
+
"removeFromBlocklist revoke",
|
|
36480
|
+
camera,
|
|
36481
|
+
responseForDeletion?.detail ?? "no outcome returned"
|
|
36482
|
+
);
|
|
36483
|
+
throw new import_node_server_utils99.BadRequestError(
|
|
36484
|
+
anprUnblockFailureMessage([
|
|
36485
|
+
{
|
|
36486
|
+
camera: cameraLabel(camera),
|
|
36487
|
+
reason: responseForDeletion?.reason || "the camera could not be reached"
|
|
36488
|
+
}
|
|
36489
|
+
])
|
|
36490
|
+
);
|
|
36268
36491
|
}
|
|
36269
36492
|
}
|
|
36270
36493
|
}
|
|
36271
36494
|
await _deleteVehicle(_id, session);
|
|
36495
|
+
if ((value.peopleId || site) && (_plateNumber || _recNo)) {
|
|
36496
|
+
await _pullVehicleByRecNo(
|
|
36497
|
+
String(_recNo ?? ""),
|
|
36498
|
+
{
|
|
36499
|
+
peopleId: value.peopleId,
|
|
36500
|
+
site,
|
|
36501
|
+
plateNumber: _plateNumber
|
|
36502
|
+
},
|
|
36503
|
+
session
|
|
36504
|
+
);
|
|
36505
|
+
}
|
|
36272
36506
|
await session.commitTransaction();
|
|
36273
36507
|
} catch (error) {
|
|
36274
36508
|
await session.abortTransaction();
|