@7365admin1/core 3.79.1-staging.334 → 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.
@@ -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
- ...toBlocklist ? {} : {
36257
- ...value.block && { block: asId(value.block) },
36258
- ...value.level && { level: asId(value.level) },
36259
- ...value.unit && { unit: asId(value.unit) },
36260
- ...value.peopleId && { peopleId: asId(value.peopleId) }
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