@7365admin1/core 3.52.5 → 3.52.6

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/dist/index.mjs CHANGED
@@ -20723,7 +20723,6 @@ function MVehicle(value) {
20723
20723
  const expiredDate = new Date(createdAtDate);
20724
20724
  expiredDate.setFullYear(expiredDate.getFullYear() + 10);
20725
20725
  const createdAt = createdAtDate;
20726
- const expiredAt = value.end ?? expiredDate;
20727
20726
  return {
20728
20727
  plateNumber: value.plateNumber ?? "",
20729
20728
  type: value.type ?? "",
@@ -20740,7 +20739,12 @@ function MVehicle(value) {
20740
20739
  remarks: value.remarks ?? "",
20741
20740
  seasonPassType: value.seasonPassType ?? "",
20742
20741
  start: value.start ? new Date(value.start) : createdAt,
20743
- end: value.end ? new Date(value.end) : expiredAt,
20742
+ // A blank expiry means "no expiry": it takes the createdAt + 10 years
20743
+ // sentinel, the same as a null or absent one. This read `value.end ??
20744
+ // expiredDate`, and `??` only falls through on null/undefined, so an empty
20745
+ // string was stored verbatim as `end: ""` - a String in a Date field. That
20746
+ // is what the expiry sweep then matched instead of the real expiries.
20747
+ end: value.end ? new Date(value.end) : expiredDate,
20744
20748
  status: value.status ?? "active" /* ACTIVE */,
20745
20749
  unitName: value.unitName ?? "",
20746
20750
  peopleId: value.peopleId ?? "",
@@ -20792,6 +20796,12 @@ function MVehicleTransaction(value) {
20792
20796
  category: value.category ?? ""
20793
20797
  };
20794
20798
  }
20799
+ function expiredVehicleSweepFilter(now = /* @__PURE__ */ new Date()) {
20800
+ return {
20801
+ end: { $type: "date", $lte: now },
20802
+ status: { $ne: "deleted" /* DELETED */ }
20803
+ };
20804
+ }
20795
20805
 
20796
20806
  // src/repositories/vehicle.repo.ts
20797
20807
  import { ObjectId as ObjectId42 } from "mongodb";
@@ -21504,18 +21514,22 @@ function useVehicleRepo() {
21504
21514
  }
21505
21515
  async function deleteExpiredVehicles(ids2, session) {
21506
21516
  try {
21507
- const now = (/* @__PURE__ */ new Date()).toISOString();
21517
+ const now = /* @__PURE__ */ new Date();
21508
21518
  const _ids = (ids2 ?? []).map((id) => toObjectId7(id)).filter((id) => Boolean(id));
21509
21519
  if (!_ids.length)
21510
21520
  return 0;
21511
21521
  const res = await collection.updateMany(
21512
21522
  {
21513
21523
  _id: { $in: _ids },
21514
- status: { $ne: "deleted" },
21515
- end: { $exists: true, $lte: now }
21516
- // check only end
21524
+ ...expiredVehicleSweepFilter(now)
21525
+ },
21526
+ {
21527
+ $set: {
21528
+ status: "deleted",
21529
+ deletedAt: now.toISOString(),
21530
+ isDeletedInDahua: true
21531
+ }
21517
21532
  },
21518
- { $set: { status: "deleted", deletedAt: now, isDeletedInDahua: true } },
21519
21533
  { session }
21520
21534
  );
21521
21535
  return res.modifiedCount;
@@ -21556,12 +21570,7 @@ function useVehicleRepo() {
21556
21570
  }
21557
21571
  async function getAllExpiredVehicles() {
21558
21572
  try {
21559
- const now = (/* @__PURE__ */ new Date()).toISOString();
21560
- const query2 = {
21561
- end: { $lte: now },
21562
- status: { $ne: "deleted" }
21563
- };
21564
- const items = await collection.find(query2).toArray();
21573
+ const items = await collection.find(expiredVehicleSweepFilter()).toArray();
21565
21574
  return items;
21566
21575
  } catch (error) {
21567
21576
  throw error;
@@ -35969,34 +35978,99 @@ function useVehicleService() {
35969
35978
  if (!siteCameras.length) {
35970
35979
  throw new Error("No site cameras found.");
35971
35980
  }
35972
- await Promise.all(
35973
- sanitizedValues.map(async (vehicleValue) => {
35974
- const plateNumber = vehicleValue.plateNumber;
35975
- const _mode = vehicleValue.type === "whitelist" /* WHITELIST */ ? "TrafficRedList" /* TRAFFIC_REDLIST */ : "TrafficBlackList" /* TRAFFIC_BLACKLIST */;
35976
- const recNos = await Promise.all(
35977
- siteCameras.map(async (camera) => {
35978
- const { host, username, password } = camera;
35979
- const dahuaPayload = {
35980
- host,
35981
- username,
35982
- password,
35983
- plateNumber,
35984
- mode: _mode,
35985
- ...vehicleValue.start ? { start: String(vehicleValue.start) } : {},
35986
- ...vehicleValue.end ? { end: String(vehicleValue.end) } : {},
35987
- ...vehicleValue.name ? { owner: vehicleValue.name } : {},
35988
- ...vehicleValue.vehicleModel ? { vehicleType: vehicleValue.vehicleModel } : {},
35989
- ...vehicleValue.vehicleColor ? { vehicleColor: vehicleValue.vehicleColor } : {}
35990
- };
35981
+ const written = /* @__PURE__ */ new Map();
35982
+ const sweepRows = sanitizedValues.map((value, index) => ({
35983
+ _id: String(index),
35984
+ site,
35985
+ plateNumber: value.plateNumber
35986
+ }));
35987
+ const { deletableIds: savableIds, skipped } = await sweepExpiredVehicles(
35988
+ sweepRows,
35989
+ {
35990
+ camerasForSite: async () => siteCameras,
35991
+ cameraLabel,
35992
+ revoke: async (camera, row) => {
35993
+ const rowId = String(row._id);
35994
+ const vehicleValue = sanitizedValues[Number(rowId)];
35995
+ const plateNumber = vehicleValue.plateNumber;
35996
+ const { host, username, password } = camera;
35997
+ const dahuaPayload = {
35998
+ host,
35999
+ username,
36000
+ password,
36001
+ plateNumber,
36002
+ mode: vehicleValue.type === "whitelist" /* WHITELIST */ ? "TrafficRedList" /* TRAFFIC_REDLIST */ : "TrafficBlackList" /* TRAFFIC_BLACKLIST */,
36003
+ ...vehicleValue.start ? { start: String(vehicleValue.start) } : {},
36004
+ ...vehicleValue.end ? { end: String(vehicleValue.end) } : {},
36005
+ ...vehicleValue.name ? { owner: vehicleValue.name } : {},
36006
+ ...vehicleValue.vehicleModel ? { vehicleType: vehicleValue.vehicleModel } : {},
36007
+ ...vehicleValue.vehicleColor ? { vehicleColor: vehicleValue.vehicleColor } : {}
36008
+ };
36009
+ try {
35991
36010
  const dahuaResponse = await _bulkInsertPlateNumber(dahuaPayload);
36011
+ const responseStatus = dahuaResponse?.statusCode || dahuaResponse?.status || dahuaResponse?.res?.status || "unknown";
35992
36012
  const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
35993
- return responseData.split("=")[1]?.trim();
35994
- })
36013
+ if (responseStatus !== 200) {
36014
+ logCameraFailure(
36015
+ "bulk add",
36016
+ camera,
36017
+ `HTTP ${responseStatus}: ${responseData.slice(0, 500)}`
36018
+ );
36019
+ return {
36020
+ ok: false,
36021
+ reason: anprWriteReason(`HTTP ${responseStatus}`)
36022
+ };
36023
+ }
36024
+ const recNo = String(responseData.split("=")[1]?.trim() ?? "");
36025
+ if (recNo) {
36026
+ vehicleValue.recNo = vehicleValue.recNo || recNo;
36027
+ const entries = written.get(rowId) ?? [];
36028
+ entries.push({ camera, recno: recNo });
36029
+ written.set(rowId, entries);
36030
+ }
36031
+ return { ok: true, reason: "" };
36032
+ } catch (error) {
36033
+ logCameraFailure("bulk add", camera, error);
36034
+ return { ok: false, reason: anprWriteReason(error) };
36035
+ }
36036
+ }
36037
+ }
36038
+ );
36039
+ const failedRows = [];
36040
+ for (const entry of skipped) {
36041
+ const stranded = [];
36042
+ for (const write of written.get(entry.id) ?? []) {
36043
+ const outcome = await _removePlateNumber({
36044
+ host: write.camera.host,
36045
+ username: write.camera.username,
36046
+ password: write.camera.password,
36047
+ recno: write.recno,
36048
+ mode: sanitizedValues[Number(entry.id)]?.type === "whitelist" /* WHITELIST */ ? "TrafficRedList" /* TRAFFIC_REDLIST */ : "TrafficBlackList" /* TRAFFIC_BLACKLIST */
36049
+ }).catch((removeError) => anprRevokeThrew(removeError));
36050
+ if (!outcome?.ok)
36051
+ stranded.push(cameraLabel(write.camera));
36052
+ }
36053
+ let message = anprWriteFailureMessage(entry.failures);
36054
+ if (stranded.length) {
36055
+ logger63.error(
36056
+ `bulkUpsertVehicles could not take the plate back off: ${stranded.join(", ")} (plate ${JSON.stringify(entry.plateNumber)})`
35995
36057
  );
35996
- vehicleValue.recNo = recNos.find((r) => r) ?? void 0;
35997
- })
36058
+ message += ` WARNING: the plate number was written to ${stranded.join(", ")} and could not be removed again - it WILL still open the barrier. Remove it on the camera by hand.`;
36059
+ }
36060
+ logger63.error(
36061
+ `bulkUpsertVehicles NOT saving plate ${JSON.stringify(entry.plateNumber)} (site ${entry.site}): ` + entry.failures.map((failure) => `${failure.camera} (${failure.reason})`).join(", ")
36062
+ );
36063
+ failedRows.push({
36064
+ plateNumber: String(entry.plateNumber ?? ""),
36065
+ message
36066
+ });
36067
+ }
36068
+ const savable = new Set(savableIds);
36069
+ const toSave = sanitizedValues.filter(
36070
+ (_, index) => savable.has(String(index))
35998
36071
  );
35999
- return await _bulkUpsertVehicles(sanitizedValues);
36072
+ const result = toSave.length ? await _bulkUpsertVehicles(toSave) : { matchedCount: 0, modifiedCount: 0, upsertedCount: 0 };
36073
+ return { ...result, savedCount: toSave.length, failedRows };
36000
36074
  } catch (error) {
36001
36075
  throw error;
36002
36076
  }
@@ -91591,6 +91665,7 @@ export {
91591
91665
  encodeHidPacsCard,
91592
91666
  events_namespace_collection,
91593
91667
  expiredBulletinSweepFilter,
91668
+ expiredVehicleSweepFilter,
91594
91669
  facility_bookings_namespace_collection,
91595
91670
  feedbackSchema,
91596
91671
  feedbacks2_namespace_collection,