@7365admin1/core 3.79.1-staging.335 → 3.79.1-staging.336
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/vehicle-one-plate-per-site.md +6 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +124 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +124 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -35,6 +35,12 @@ and moves it to the form's tab (off every camera list, onto the list of its new
|
|
|
35
35
|
kind; pending for a security agency without the approve permission). Its
|
|
36
36
|
history records "moved".
|
|
37
37
|
|
|
38
|
+
**Sync.** `syncVehicleToCameras` puts a live vehicle's plate on every active
|
|
39
|
+
camera of its list that lacks it (a plate saved while its cameras were
|
|
40
|
+
inactive), camera by camera, and records the cameras that took it;
|
|
41
|
+
`activeCameraCounts` gives the active cameras per list so the screens can offer
|
|
42
|
+
it.
|
|
43
|
+
|
|
38
44
|
**One plate per site.** Adding a plate the site already has - deleted,
|
|
39
45
|
pending, temporary, blocked or unblocked included - is refused with its status
|
|
40
46
|
and "edit the existing vehicle instead" (restore, for a deleted one). The same
|
package/dist/index.d.ts
CHANGED
|
@@ -4123,6 +4123,15 @@ declare function useVehicleService(): {
|
|
|
4123
4123
|
view: string;
|
|
4124
4124
|
}[]>;
|
|
4125
4125
|
moveVehicle: (_id: string, value: TVehicle, user?: string) => Promise<string>;
|
|
4126
|
+
activeCameraCounts: (site: string) => Promise<{
|
|
4127
|
+
allowed: number;
|
|
4128
|
+
blocked: number;
|
|
4129
|
+
}>;
|
|
4130
|
+
syncVehicleToCameras: (_id: string, user?: string) => Promise<{
|
|
4131
|
+
message: string;
|
|
4132
|
+
synced: number;
|
|
4133
|
+
failed: number;
|
|
4134
|
+
}>;
|
|
4126
4135
|
fillCameraLists: (site: unknown, camera: {
|
|
4127
4136
|
id?: string;
|
|
4128
4137
|
host?: string;
|
|
@@ -4188,6 +4197,8 @@ declare function useVehicleController(): {
|
|
|
4188
4197
|
removeFromBlocklist: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
4189
4198
|
existingPlates: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
4190
4199
|
moveVehicle: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
4200
|
+
activeCameraCounts: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
4201
|
+
syncVehicleToCameras: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
4191
4202
|
};
|
|
4192
4203
|
|
|
4193
4204
|
declare function useSiteCameraRepo(): {
|
package/dist/index.js
CHANGED
|
@@ -18525,6 +18525,7 @@ function useVehicleRepo() {
|
|
|
18525
18525
|
seasonPassType: 1,
|
|
18526
18526
|
start: 1,
|
|
18527
18527
|
end: 1,
|
|
18528
|
+
remarks: 1,
|
|
18528
18529
|
nric: 1,
|
|
18529
18530
|
plateNumber: 1,
|
|
18530
18531
|
site: 1,
|
|
@@ -18571,7 +18572,9 @@ function useVehicleRepo() {
|
|
|
18571
18572
|
// A season pass's expiry, shown under its number.
|
|
18572
18573
|
seasonPassType: "$seasonPassType",
|
|
18573
18574
|
start: "$start",
|
|
18574
|
-
end: "$end"
|
|
18575
|
+
end: "$end",
|
|
18576
|
+
// Each record's own remarks (e.g. why it was blocked).
|
|
18577
|
+
remarks: "$remarks"
|
|
18575
18578
|
}
|
|
18576
18579
|
}
|
|
18577
18580
|
}
|
|
@@ -36128,6 +36131,76 @@ function useVehicleService() {
|
|
|
36128
36131
|
throw error;
|
|
36129
36132
|
}
|
|
36130
36133
|
}
|
|
36134
|
+
async function activeCameraCounts(site) {
|
|
36135
|
+
const [allowed, blocked] = await Promise.all([
|
|
36136
|
+
allowCamerasAt(site),
|
|
36137
|
+
blockCamerasAt(site)
|
|
36138
|
+
]);
|
|
36139
|
+
return { allowed: allowed.length, blocked: blocked.length };
|
|
36140
|
+
}
|
|
36141
|
+
async function syncVehicleToCameras(_id, user) {
|
|
36142
|
+
const vehicle = await findOne({ _id: new import_mongodb76.ObjectId(_id) });
|
|
36143
|
+
if (!vehicle)
|
|
36144
|
+
throw new import_node_server_utils109.NotFoundError("Vehicle not found.");
|
|
36145
|
+
if (!isLiveVehicleStatus(vehicle.status)) {
|
|
36146
|
+
throw new import_node_server_utils109.BadRequestError(
|
|
36147
|
+
`This vehicle is ${String(vehicle.status || "not live")}, so it is not put on any camera.`
|
|
36148
|
+
);
|
|
36149
|
+
}
|
|
36150
|
+
const blocked = vehicle.type === "blocklist" /* BLOCKLIST */;
|
|
36151
|
+
const cameras = blocked ? await blockCamerasAt(vehicle.site) : await allowCamerasAt(vehicle.site);
|
|
36152
|
+
if (!cameras.length) {
|
|
36153
|
+
throw new import_node_server_utils109.BadRequestError(
|
|
36154
|
+
"There is no active ANPR camera to sync to. Switch a camera on first."
|
|
36155
|
+
);
|
|
36156
|
+
}
|
|
36157
|
+
const plateNumber = String(vehicle.plateNumber ?? "");
|
|
36158
|
+
const write = {
|
|
36159
|
+
plateNumber,
|
|
36160
|
+
mode: blocked ? "TrafficBlackList" /* TRAFFIC_BLACKLIST */ : "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
36161
|
+
owner: String(vehicle.name ?? ""),
|
|
36162
|
+
...blocked ? blockWindow() : cameraWindow(vehicle.start, vehicle.end)
|
|
36163
|
+
};
|
|
36164
|
+
const journal = cameraJournal();
|
|
36165
|
+
const took = [];
|
|
36166
|
+
const failures = [];
|
|
36167
|
+
for (const camera of cameras) {
|
|
36168
|
+
const result = await writeToCameras([camera], write, journal, {
|
|
36169
|
+
onlyIfMissing: true
|
|
36170
|
+
});
|
|
36171
|
+
if (result.failures.length)
|
|
36172
|
+
failures.push(...result.failures);
|
|
36173
|
+
else
|
|
36174
|
+
took.push(camera);
|
|
36175
|
+
}
|
|
36176
|
+
const hostKey = (value) => String(value ?? "").trim().toLowerCase().replace(/\/+$/, "");
|
|
36177
|
+
const tookHosts = new Set(took.map((camera) => hostKey(camera.host)));
|
|
36178
|
+
const current = Array.isArray(vehicle.anprCameras) ? vehicle.anprCameras : [];
|
|
36179
|
+
try {
|
|
36180
|
+
await _setAnprCameras(_id, [
|
|
36181
|
+
...current.filter((entry) => !tookHosts.has(hostKey(entry.host))),
|
|
36182
|
+
...anprCameraSummary(took, blocked ? "blocked" : "allowed")
|
|
36183
|
+
]);
|
|
36184
|
+
if (took.length) {
|
|
36185
|
+
await _pushHistory(_id, vehicleHistoryEntry("synced", user, ["anprCameras"]));
|
|
36186
|
+
}
|
|
36187
|
+
} catch (error) {
|
|
36188
|
+
import_node_server_utils109.logger.error(`syncVehicleToCameras could not record ${_id}: ${error?.message ?? error}`);
|
|
36189
|
+
}
|
|
36190
|
+
const list = blocked ? "blocklist" : "allowed list";
|
|
36191
|
+
if (!failures.length) {
|
|
36192
|
+
return {
|
|
36193
|
+
message: `Vehicle ${plateNumber} is on the ${list} of all ${took.length} active camera${took.length === 1 ? "" : "s"}.`,
|
|
36194
|
+
synced: took.length,
|
|
36195
|
+
failed: 0
|
|
36196
|
+
};
|
|
36197
|
+
}
|
|
36198
|
+
return {
|
|
36199
|
+
message: `Vehicle ${plateNumber} was synced to ${took.length} of ${cameras.length} active cameras. Not synced: ${failures.map((f) => `${f.camera} (${f.reason})`).join("; ")}.`,
|
|
36200
|
+
synced: took.length,
|
|
36201
|
+
failed: failures.length
|
|
36202
|
+
};
|
|
36203
|
+
}
|
|
36131
36204
|
async function existingPlatesAtSite(site, plateNumbers) {
|
|
36132
36205
|
const seen = /* @__PURE__ */ new Set();
|
|
36133
36206
|
const items = [];
|
|
@@ -36253,12 +36326,12 @@ function useVehicleService() {
|
|
|
36253
36326
|
...value.phoneNumber !== void 0 && { phoneNumber: value.phoneNumber },
|
|
36254
36327
|
...value.nric !== void 0 && { nric: value.nric },
|
|
36255
36328
|
...value.remarks !== void 0 && { remarks: value.remarks },
|
|
36256
|
-
|
|
36257
|
-
|
|
36258
|
-
|
|
36259
|
-
|
|
36260
|
-
|
|
36261
|
-
}
|
|
36329
|
+
// Block / level / unit whenever the form sends them - a Block Listed
|
|
36330
|
+
// vehicle blocked from a visitor transaction brings the visit's.
|
|
36331
|
+
...value.block && { block: asId(value.block) },
|
|
36332
|
+
...value.level && { level: asId(value.level) },
|
|
36333
|
+
...value.unit && { unit: asId(value.unit) },
|
|
36334
|
+
...toBlocklist ? {} : { ...value.peopleId && { peopleId: asId(value.peopleId) } }
|
|
36262
36335
|
};
|
|
36263
36336
|
const changed = changedFields(vehicle, formattedValue);
|
|
36264
36337
|
await _updateVehicleById(_id, formattedValue, session);
|
|
@@ -36564,6 +36637,8 @@ function useVehicleService() {
|
|
|
36564
36637
|
removeFromBlocklist,
|
|
36565
36638
|
existingPlatesAtSite,
|
|
36566
36639
|
moveVehicle,
|
|
36640
|
+
activeCameraCounts,
|
|
36641
|
+
syncVehicleToCameras,
|
|
36567
36642
|
fillCameraLists,
|
|
36568
36643
|
newCameraPlateRows,
|
|
36569
36644
|
writeVehicleToNewCamera
|
|
@@ -40139,7 +40214,9 @@ function useVehicleController() {
|
|
|
40139
40214
|
blocklistVehicles: _blocklistVehicles,
|
|
40140
40215
|
removeFromBlocklist: _removeFromBlocklist,
|
|
40141
40216
|
existingPlatesAtSite: _existingPlatesAtSite,
|
|
40142
|
-
moveVehicle: _moveVehicle
|
|
40217
|
+
moveVehicle: _moveVehicle,
|
|
40218
|
+
activeCameraCounts: _activeCameraCounts,
|
|
40219
|
+
syncVehicleToCameras: _syncVehicleToCameras
|
|
40143
40220
|
} = useVehicleService();
|
|
40144
40221
|
const {
|
|
40145
40222
|
getSeasonPassTypes: _getSeasonPassTypes,
|
|
@@ -40970,6 +41047,42 @@ function useVehicleController() {
|
|
|
40970
41047
|
return;
|
|
40971
41048
|
}
|
|
40972
41049
|
}
|
|
41050
|
+
async function activeCameraCounts(req, res, next) {
|
|
41051
|
+
const { error, value } = import_joi58.default.object({
|
|
41052
|
+
site: import_joi58.default.string().hex().length(24).required()
|
|
41053
|
+
}).validate({ site: req.params.site });
|
|
41054
|
+
if (error) {
|
|
41055
|
+
next(new import_node_server_utils123.BadRequestError(error.message));
|
|
41056
|
+
return;
|
|
41057
|
+
}
|
|
41058
|
+
try {
|
|
41059
|
+
await requireSiteReach(req, value.site, VEHICLE_LIST);
|
|
41060
|
+
res.json(await _activeCameraCounts(value.site));
|
|
41061
|
+
return;
|
|
41062
|
+
} catch (error2) {
|
|
41063
|
+
import_node_server_utils123.logger.log({ level: "error", message: error2.message });
|
|
41064
|
+
next(error2);
|
|
41065
|
+
return;
|
|
41066
|
+
}
|
|
41067
|
+
}
|
|
41068
|
+
async function syncVehicleToCameras(req, res, next) {
|
|
41069
|
+
const { error, value } = import_joi58.default.object({
|
|
41070
|
+
_id: import_joi58.default.string().hex().length(24).required()
|
|
41071
|
+
}).validate({ _id: req.params.id });
|
|
41072
|
+
if (error) {
|
|
41073
|
+
next(new import_node_server_utils123.BadRequestError(error.message));
|
|
41074
|
+
return;
|
|
41075
|
+
}
|
|
41076
|
+
try {
|
|
41077
|
+
await requireVehicleReach(req, value._id, VEHICLE_UPDATE);
|
|
41078
|
+
res.json(await _syncVehicleToCameras(value._id, actingUser(req)));
|
|
41079
|
+
return;
|
|
41080
|
+
} catch (error2) {
|
|
41081
|
+
import_node_server_utils123.logger.log({ level: "error", message: error2.message });
|
|
41082
|
+
next(error2);
|
|
41083
|
+
return;
|
|
41084
|
+
}
|
|
41085
|
+
}
|
|
40973
41086
|
return {
|
|
40974
41087
|
add,
|
|
40975
41088
|
addBulk,
|
|
@@ -40988,7 +41101,9 @@ function useVehicleController() {
|
|
|
40988
41101
|
blocklistVehicles,
|
|
40989
41102
|
removeFromBlocklist,
|
|
40990
41103
|
existingPlates,
|
|
40991
|
-
moveVehicle
|
|
41104
|
+
moveVehicle,
|
|
41105
|
+
activeCameraCounts,
|
|
41106
|
+
syncVehicleToCameras
|
|
40992
41107
|
};
|
|
40993
41108
|
}
|
|
40994
41109
|
|