@7365admin1/core 2.51.0 → 2.53.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @iservice365/core
2
2
 
3
+ ## 2.53.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 77eff04: release new/latest core package version (hot fix issue)
8
+
9
+ ## 2.52.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 8b9b973: get latest changes for today
14
+
3
15
  ## 2.51.0
4
16
 
5
17
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -1870,6 +1870,7 @@ declare function useBuildingController(): {
1870
1870
  updateById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1871
1871
  deleteById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1872
1872
  getBuildingLevel: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1873
+ uploadSpreadsheetBuilding: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1873
1874
  };
1874
1875
 
1875
1876
  declare function useBuildingUnitRepo(): {
@@ -1927,6 +1928,7 @@ type TCamera = {
1927
1928
  };
1928
1929
  type TSiteCamera = {
1929
1930
  _id?: ObjectId;
1931
+ name?: string;
1930
1932
  site: string | ObjectId;
1931
1933
  host: string;
1932
1934
  username: string;
@@ -1953,6 +1955,7 @@ declare function MSiteCamera(value: TSiteCamera): {
1953
1955
  guardPost: number;
1954
1956
  status: string;
1955
1957
  direction: string;
1958
+ name: string;
1956
1959
  createdAt: string | Date;
1957
1960
  updatedAt: string | Date;
1958
1961
  deletedAt: string | Date;
@@ -2285,7 +2288,7 @@ declare function useSiteCameraRepo(): {
2285
2288
  };
2286
2289
 
2287
2290
  declare function useSiteCameraService(): {
2288
- add: (value: TSiteCamera) => Promise<string>;
2291
+ add: (value: TSiteCamera) => Promise<"CCTV(s) added successfully." | "ANPR(s) added successfully.">;
2289
2292
  listenToCapturedPlateNumber: (onDetected?: ((data: any) => void) | undefined) => Promise<void>;
2290
2293
  };
2291
2294
 
@@ -2705,7 +2708,7 @@ declare function useVisitorTransactionRepo(): {
2705
2708
  pageRange: string;
2706
2709
  }>;
2707
2710
  getOpenByPlateNumber: (plateNumber: string, site: string | ObjectId) => Promise<TVisitorTransaction | null>;
2708
- updateById: (_id: string | ObjectId, value: Partial<TVisitorTransaction>, session?: ClientSession, isNotManualCheckOut?: boolean) => Promise<mongodb.UpdateResult<bson.Document>>;
2711
+ updateById: (_id: string | ObjectId, value: Partial<TVisitorTransaction>, session?: ClientSession, isManualCheckOut?: boolean) => Promise<mongodb.UpdateResult<bson.Document>>;
2709
2712
  deleteVisitorTransaction: (_id: string | ObjectId) => Promise<number>;
2710
2713
  createTextIndex: () => Promise<void>;
2711
2714
  getDeliveryPickupTransactions: () => Promise<mongodb.WithId<bson.Document>[]>;
package/dist/index.js CHANGED
@@ -13313,23 +13313,42 @@ var CameraType = /* @__PURE__ */ ((CameraType2) => {
13313
13313
  })(CameraType || {});
13314
13314
  var schemaUpdateSiteCamera = import_joi34.default.object({
13315
13315
  host: import_joi34.default.string().required(),
13316
- username: import_joi34.default.string().required(),
13317
- password: import_joi34.default.string().required(),
13316
+ username: import_joi34.default.string().when("type", {
13317
+ is: "anpr",
13318
+ then: import_joi34.default.required(),
13319
+ otherwise: import_joi34.default.optional().allow(null, "")
13320
+ }),
13321
+ password: import_joi34.default.string().when("type", {
13322
+ is: "anpr",
13323
+ then: import_joi34.default.required(),
13324
+ otherwise: import_joi34.default.optional().allow(null, "")
13325
+ }),
13318
13326
  category: import_joi34.default.string().allow("standard", "resident", "visitor").required(),
13319
13327
  guardPost: import_joi34.default.number().integer().optional(),
13320
- direction: import_joi34.default.string().optional().allow("entry", "exit", "both", "none")
13328
+ direction: import_joi34.default.string().optional().allow("entry", "exit", "both", "none"),
13329
+ status: import_joi34.default.string().optional().allow("active", "inactive", "deleted"),
13330
+ name: import_joi34.default.string().optional().allow(null, "")
13321
13331
  });
13322
13332
  var schemaSiteCamera = import_joi34.default.object({
13323
13333
  _id: import_joi34.default.string().hex().optional(),
13324
13334
  site: import_joi34.default.string().hex().required(),
13325
13335
  host: import_joi34.default.string().required(),
13326
- username: import_joi34.default.string().required(),
13327
- password: import_joi34.default.string().required(),
13336
+ username: import_joi34.default.string().when("type", {
13337
+ is: "anpr",
13338
+ then: import_joi34.default.required(),
13339
+ otherwise: import_joi34.default.optional().allow(null, "")
13340
+ }),
13341
+ password: import_joi34.default.string().when("type", {
13342
+ is: "anpr",
13343
+ then: import_joi34.default.required(),
13344
+ otherwise: import_joi34.default.optional().allow(null, "")
13345
+ }),
13328
13346
  type: import_joi34.default.string().allow("ip", "anpr").required(),
13329
13347
  category: import_joi34.default.string().allow("standard", "resident", "visitor").required(),
13330
13348
  direction: import_joi34.default.string().required().allow("entry", "exit", "both", "none"),
13331
13349
  guardPost: import_joi34.default.number().integer().optional(),
13332
13350
  status: import_joi34.default.string().optional().allow("active", "inactive", "deleted"),
13351
+ name: import_joi34.default.string().optional().allow(null, ""),
13333
13352
  createdAt: import_joi34.default.date().optional(),
13334
13353
  updatedAt: import_joi34.default.date().optional(),
13335
13354
  deletedAt: import_joi34.default.date().optional()
@@ -13358,6 +13377,7 @@ function MSiteCamera(value) {
13358
13377
  guardPost: value.guardPost ?? 0,
13359
13378
  status: value.status ?? "active",
13360
13379
  direction: value.direction ?? "",
13380
+ name: value.name ?? "",
13361
13381
  createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
13362
13382
  updatedAt: value.updatedAt ?? "",
13363
13383
  deletedAt: value.deletedAt ?? ""
@@ -13672,7 +13692,24 @@ var schemaUpdateVisTrans = import_joi36.default.object({
13672
13692
  checkInRemarks: import_joi36.default.string().optional().allow("", null),
13673
13693
  checkOutRemarks: import_joi36.default.string().optional().allow("", null),
13674
13694
  expectedCheckIn: import_joi36.default.string().isoDate().optional(),
13675
- purpose: import_joi36.default.string().optional().allow(null, "")
13695
+ purpose: import_joi36.default.string().optional().allow(null, ""),
13696
+ members: import_joi36.default.array().items(
13697
+ import_joi36.default.object({
13698
+ name: import_joi36.default.string().optional().allow(null, ""),
13699
+ nric: import_joi36.default.string().optional().allow(null, ""),
13700
+ visitorPass: import_joi36.default.array().items(
13701
+ import_joi36.default.object({
13702
+ keyId: import_joi36.default.string().hex().length(24).required()
13703
+ })
13704
+ ).optional().allow(null),
13705
+ passKeys: import_joi36.default.array().items(
13706
+ import_joi36.default.object({
13707
+ keyId: import_joi36.default.string().hex().length(24).required()
13708
+ })
13709
+ ).optional().allow(null),
13710
+ contact: import_joi36.default.string().optional().allow(null, "")
13711
+ })
13712
+ ).optional().allow(null)
13676
13713
  });
13677
13714
  function MVisitorTransaction(value) {
13678
13715
  const { error } = schemaVisitorTransaction.validate(value, {
@@ -14122,14 +14159,14 @@ function useVisitorTransactionRepo() {
14122
14159
  );
14123
14160
  }
14124
14161
  }
14125
- async function updateById(_id, value, session, isNotManualCheckOut = true) {
14162
+ async function updateById(_id, value, session, isManualCheckOut = true) {
14126
14163
  try {
14127
14164
  _id = new import_mongodb40.ObjectId(_id);
14128
14165
  } catch (error) {
14129
14166
  throw new import_node_server_utils68.BadRequestError("Invalid visitor transaction ID format.");
14130
14167
  }
14131
14168
  value.updatedAt = /* @__PURE__ */ new Date();
14132
- if (value.checkOut && isNotManualCheckOut) {
14169
+ if (value.checkOut && isManualCheckOut) {
14133
14170
  value.manualCheckout = true;
14134
14171
  }
14135
14172
  try {
@@ -17552,7 +17589,7 @@ function useDahuaService() {
17552
17589
  );
17553
17590
  }
17554
17591
  }
17555
- if (["entry", "both"].includes(designation) && direction.toLowerCase() === "approach" && plateNumber) {
17592
+ if (["entry"].includes(designation) && plateNumber) {
17556
17593
  await closeOpenTransaction(plateNumber);
17557
17594
  const vehicle = await getVehicleByPlateNumber(plateNumber);
17558
17595
  const visitorTransaction = {
@@ -17607,11 +17644,11 @@ function useDahuaService() {
17607
17644
  } catch (error) {
17608
17645
  console.log("failed to create visitor transaction", error);
17609
17646
  loggerDahua.error(
17610
- `[${site}][${gate}] Error creating visitor transaction:`,
17647
+ `[${site}][${host}] Error creating visitor transaction:`,
17611
17648
  error
17612
17649
  );
17613
17650
  }
17614
- } else if (["exit", "both"].includes(designation) && direction.toLowerCase() === "leave" && plateNumber) {
17651
+ } else if (["exit"].includes(designation) && plateNumber) {
17615
17652
  const vehicle = await getVehicleByPlateNumber(plateNumber);
17616
17653
  const existingOpenTransaction = await getOpenByPlateNumber(
17617
17654
  plateNumber,
@@ -17636,6 +17673,92 @@ function useDahuaService() {
17636
17673
  if (onDetected2) {
17637
17674
  onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
17638
17675
  }
17676
+ } else if (["both"].includes(designation) && plateNumber) {
17677
+ if (direction.toLowerCase() === "leave") {
17678
+ const vehicle = await getVehicleByPlateNumber(plateNumber);
17679
+ const existingOpenTransaction = await getOpenByPlateNumber(
17680
+ plateNumber,
17681
+ site
17682
+ );
17683
+ if (existingOpenTransaction?._id) {
17684
+ currentTransactionId = existingOpenTransaction._id.toString();
17685
+ currentSnapshotField = "snapshotExitImage";
17686
+ }
17687
+ if (vehicle?.recNo) {
17688
+ const dahuaPayload = {
17689
+ host,
17690
+ username,
17691
+ password,
17692
+ plateNumber,
17693
+ mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
17694
+ recno: vehicle?.recNo
17695
+ };
17696
+ await removePlateNumber(dahuaPayload);
17697
+ }
17698
+ await closeOpenTransaction(plateNumber);
17699
+ if (onDetected2 && existingOpenTransaction?.site) {
17700
+ onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
17701
+ }
17702
+ } else if (direction.toLowerCase() === "approach") {
17703
+ await closeOpenTransaction(plateNumber);
17704
+ const vehicle = await getVehicleByPlateNumber(plateNumber);
17705
+ const visitorTransaction = {
17706
+ site,
17707
+ plateNumber,
17708
+ org,
17709
+ status: "unregistered" /* UNREGISTERED */
17710
+ };
17711
+ const typesForAutoRegister = Object.values(PersonTypes);
17712
+ let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
17713
+ let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
17714
+ if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
17715
+ visitorTransaction.name = vehicle.name;
17716
+ visitorTransaction.nric = vehicle.nric;
17717
+ visitorTransaction.contact = vehicle.phoneNumber;
17718
+ visitorTransaction.block = Number(vehicle.block);
17719
+ visitorTransaction.level = vehicle.level;
17720
+ visitorTransaction.unit = vehicle.unit?.toString();
17721
+ visitorTransaction.unitName = vehicle.unitName;
17722
+ visitorTransaction.type = vehicle.category;
17723
+ visitorTransaction.status = "registered" /* REGISTERED */;
17724
+ visitorTransaction.recNo = vehicle.recNo;
17725
+ visitorTransaction.expiredAt = vehicle.end;
17726
+ }
17727
+ const dahuaPayload = {
17728
+ host,
17729
+ username,
17730
+ password,
17731
+ plateNumber,
17732
+ mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
17733
+ owner: vehicle?.name ?? ""
17734
+ };
17735
+ dahuaPayload.start = formatDahuaDate(startDate);
17736
+ dahuaPayload.end = formatDahuaDate(endDate);
17737
+ const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
17738
+ if (shouldHaveTimeLimit) {
17739
+ const startDate2 = /* @__PURE__ */ new Date();
17740
+ const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
17741
+ dahuaPayload.start = formatDahuaDate(startDate2);
17742
+ dahuaPayload.end = formatDahuaDate(endDate2);
17743
+ visitorTransaction.expiredAt = endDate2.toISOString();
17744
+ }
17745
+ try {
17746
+ await addPlateNumber(dahuaPayload);
17747
+ const result = await add(visitorTransaction, void 0, true);
17748
+ const transactionId = result?._id;
17749
+ currentTransactionId = transactionId?.toString();
17750
+ currentSnapshotField = "snapshotEntryImage";
17751
+ if (onDetected2) {
17752
+ onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber, host, direction });
17753
+ }
17754
+ } catch (error) {
17755
+ console.log("failed to create visitor transaction", error);
17756
+ loggerDahua.error(
17757
+ `[${site}][${host}] Error creating visitor transaction:`,
17758
+ error
17759
+ );
17760
+ }
17761
+ }
17639
17762
  }
17640
17763
  }
17641
17764
  }
@@ -17767,6 +17890,9 @@ function useDahuaService() {
17767
17890
  }
17768
17891
  }
17769
17892
  async function listenToCamera(camera, onDetected) {
17893
+ if (camera?.type != "anpr" && camera?.status != "deleted") {
17894
+ return;
17895
+ }
17770
17896
  if (onDetected) {
17771
17897
  _savedOnDetected = onDetected;
17772
17898
  }
@@ -17775,6 +17901,14 @@ function useDahuaService() {
17775
17901
  return;
17776
17902
  }
17777
17903
  const cameraId = camera._id.toString();
17904
+ if (camera.status !== "active") {
17905
+ if (cameraRegistry.has(cameraId)) {
17906
+ loggerDahua.info(`[${camera?.host ?? camera?._id}] Camera is ${camera.status}. Stopping connection.`);
17907
+ cameraRegistry.get(cameraId)?.abort();
17908
+ cameraRegistry.delete(cameraId);
17909
+ }
17910
+ return;
17911
+ }
17778
17912
  if (cameraRegistry.has(cameraId)) {
17779
17913
  loggerDahua.info(`[${camera.host}] Stopping existing connection for update.`);
17780
17914
  cameraRegistry.get(cameraId)?.abort();
@@ -17922,6 +18056,9 @@ function useDahuaService() {
17922
18056
  continue;
17923
18057
  } else if ([400, 401, 403, 500].includes(response.statusCode)) {
17924
18058
  loggerDahua.error(`[${host}] Connection error: ${response.statusCode}`);
18059
+ if (onDetected) {
18060
+ onDetected({ site, messagePermanent: `Camera with last 3 characters ${host?.slice(-3)} Connection Error. Check username and password.` });
18061
+ }
17925
18062
  return;
17926
18063
  }
17927
18064
  loggerDahua.info(`[${host}] Successfully connected to ANPR.`);
@@ -17974,8 +18111,15 @@ function useDahuaService() {
17974
18111
  break;
17975
18112
  }
17976
18113
  loggerDahua.error(
17977
- `[${host}] Connection lost or error: ${error.message || error}. Retrying in 5s...`
18114
+ `[${host}] Connection lost or error: ${error.message || error}. Retrying in 10 seconds...`
17978
18115
  );
18116
+ if (onDetected) {
18117
+ onDetected({
18118
+ site,
18119
+ host,
18120
+ message: `Camera in ${gate} Connection Lost. Retrying in 10 seconds. Check the camera if this issue persists, Or set the camera to Inactive to stop this notification.`
18121
+ });
18122
+ }
17979
18123
  } finally {
17980
18124
  if (bufferQueue?.destroy) {
17981
18125
  try {
@@ -17996,7 +18140,7 @@ function useDahuaService() {
17996
18140
  }
17997
18141
  }
17998
18142
  if (!signal.aborted) {
17999
- await new Promise((res) => setTimeout(res, 5e3));
18143
+ await new Promise((res) => setTimeout(res, 1e4));
18000
18144
  }
18001
18145
  }
18002
18146
  loggerDahua.info(`[${host}] ANPR Listener stopped.`);
@@ -18498,6 +18642,8 @@ function useSiteCameraRepo() {
18498
18642
  }
18499
18643
  try {
18500
18644
  await collection.deleteOne({ _id }, { session });
18645
+ const { listenToCamera } = useDahuaService();
18646
+ await listenToCamera({ _id, status: "deleted" });
18501
18647
  delCachedData();
18502
18648
  return "Successfully deleted site camera.";
18503
18649
  } catch (error) {
@@ -19544,6 +19690,9 @@ function useBuildingService() {
19544
19690
  // src/controllers/building.controller.ts
19545
19691
  var import_node_server_utils84 = require("@7365admin1/node-server-utils");
19546
19692
  var import_joi44 = __toESM(require("joi"));
19693
+ var import_exceljs = __toESM(require("exceljs"));
19694
+ var import_csv_parser = __toESM(require("csv-parser"));
19695
+ var import_fs2 = __toESM(require("fs"));
19547
19696
  function useBuildingController() {
19548
19697
  const {
19549
19698
  getAll: _getAll,
@@ -19565,7 +19714,10 @@ function useBuildingController() {
19565
19714
  serial: import_joi44.default.string().optional().allow("", null),
19566
19715
  status: import_joi44.default.string().optional().allow("", null),
19567
19716
  // buildingFloorPlan: Joi.array().items(Joi.string()).optional(),
19568
- buildingFiles: import_joi44.default.array().items({ id: import_joi44.default.string().hex().optional().allow("", null), name: import_joi44.default.string().optional().allow("", null) }).optional().allow("", null)
19717
+ buildingFiles: import_joi44.default.array().items({
19718
+ id: import_joi44.default.string().hex().optional().allow("", null),
19719
+ name: import_joi44.default.string().optional().allow("", null)
19720
+ }).optional().allow("", null)
19569
19721
  });
19570
19722
  const { error } = validation.validate(value);
19571
19723
  if (error) {
@@ -19703,13 +19855,125 @@ function useBuildingController() {
19703
19855
  next(error2);
19704
19856
  }
19705
19857
  }
19858
+ async function uploadSpreadsheetBuilding(req, res, next) {
19859
+ try {
19860
+ if (!req.file) {
19861
+ next(new import_node_server_utils84.BadRequestError("Spreadsheet file is required."));
19862
+ return;
19863
+ }
19864
+ const { originalname, path: path4 } = req.file;
19865
+ const lowerName = originalname.toLowerCase();
19866
+ const rowSchema = import_joi44.default.object({
19867
+ block: import_joi44.default.number().integer().min(0).required(),
19868
+ level: import_joi44.default.string().optional().allow(null, ""),
19869
+ unit: import_joi44.default.string().optional().allow(null, ""),
19870
+ category: import_joi44.default.string().trim().required(),
19871
+ name: import_joi44.default.string().trim().optional().allow(null, ""),
19872
+ email: import_joi44.default.string().email().lowercase().optional().allow(null, ""),
19873
+ phoneNumber: import_joi44.default.string().trim().optional().allow(null, "")
19874
+ });
19875
+ const querySchema = import_joi44.default.object({
19876
+ site: import_joi44.default.string().hex().length(24).required(),
19877
+ org: import_joi44.default.string().hex().length(24).optional().allow(null, "")
19878
+ });
19879
+ const { error: queryError, value: queryValue } = querySchema.validate(
19880
+ req.query,
19881
+ { abortEarly: false, convert: true }
19882
+ );
19883
+ if (queryError) {
19884
+ next(
19885
+ new import_node_server_utils84.BadRequestError(
19886
+ queryError.details.map((d) => d.message).join(", ")
19887
+ )
19888
+ );
19889
+ return;
19890
+ }
19891
+ const { site, org } = queryValue;
19892
+ let rows = [];
19893
+ if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
19894
+ const workbook = new import_exceljs.default.Workbook();
19895
+ await workbook.xlsx.readFile(path4);
19896
+ const worksheet = workbook.worksheets[0];
19897
+ if (!worksheet) {
19898
+ next(
19899
+ new import_node_server_utils84.BadRequestError("No worksheet found in uploaded Excel file.")
19900
+ );
19901
+ return;
19902
+ }
19903
+ const headerRow = worksheet.getRow(1);
19904
+ const headers = (headerRow.values || []).slice(1).map(
19905
+ (header) => String(header ?? "").trim().replace(/\(.*\)/, "").trim()
19906
+ );
19907
+ worksheet.eachRow((row, rowNumber) => {
19908
+ if (rowNumber === 1)
19909
+ return;
19910
+ const rowData = {};
19911
+ headers.forEach((header, index) => {
19912
+ rowData[header] = row.getCell(index + 1).value ?? "";
19913
+ });
19914
+ if (Object.values(rowData).some(
19915
+ (v) => v !== "" && v !== null && v !== void 0
19916
+ )) {
19917
+ rows.push(rowData);
19918
+ }
19919
+ });
19920
+ } else if (lowerName.endsWith(".csv")) {
19921
+ rows = await new Promise((resolve, reject) => {
19922
+ const parsed = [];
19923
+ import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("headers", (headers) => {
19924
+ headers = headers.map(
19925
+ (h) => h.trim().replace(/\(.*\)/, "").trim()
19926
+ );
19927
+ }).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
19928
+ });
19929
+ } else {
19930
+ next(
19931
+ new import_node_server_utils84.BadRequestError("Only .xlsx, .xls, or .csv files are allowed.")
19932
+ );
19933
+ return;
19934
+ }
19935
+ const validRows = [];
19936
+ const invalidRows = [];
19937
+ rows.forEach((row, index) => {
19938
+ const { error, value } = rowSchema.validate(row, {
19939
+ abortEarly: false,
19940
+ stripUnknown: true
19941
+ });
19942
+ if (error) {
19943
+ invalidRows.push({
19944
+ row: index + 2,
19945
+ data: row,
19946
+ errors: error.details.map((d) => d.message)
19947
+ });
19948
+ } else {
19949
+ validRows.push(value);
19950
+ }
19951
+ });
19952
+ res.status(200).json({
19953
+ message: "Spreadsheet import completed (buildings).",
19954
+ fileName: originalname,
19955
+ totalRows: rows.length,
19956
+ validRows: validRows.length,
19957
+ invalidRows: invalidRows.length,
19958
+ validationErrors: invalidRows,
19959
+ data: validRows
19960
+ // testing: return the validated building rows directly
19961
+ });
19962
+ import_fs2.default.unlink(path4, () => {
19963
+ });
19964
+ } catch (error) {
19965
+ import_node_server_utils84.logger.log({ level: "error", message: error.message });
19966
+ next(error);
19967
+ }
19968
+ }
19706
19969
  return {
19707
19970
  createBuilding,
19708
19971
  getAll,
19709
19972
  getById,
19710
19973
  updateById,
19711
19974
  deleteById,
19712
- getBuildingLevel
19975
+ getBuildingLevel,
19976
+ uploadSpreadsheetBuilding
19713
19977
  };
19714
19978
  }
19715
19979
 
@@ -20025,9 +20289,9 @@ function useBuildingUnitController() {
20025
20289
  // src/controllers/vehicle.controller.ts
20026
20290
  var import_node_server_utils87 = require("@7365admin1/node-server-utils");
20027
20291
  var import_joi46 = __toESM(require("joi"));
20028
- var import_exceljs = __toESM(require("exceljs"));
20029
- var import_csv_parser = __toESM(require("csv-parser"));
20030
- var import_fs2 = __toESM(require("fs"));
20292
+ var import_exceljs2 = __toESM(require("exceljs"));
20293
+ var import_csv_parser2 = __toESM(require("csv-parser"));
20294
+ var import_fs3 = __toESM(require("fs"));
20031
20295
  function useVehicleController() {
20032
20296
  const {
20033
20297
  add: _add,
@@ -20147,7 +20411,7 @@ function useVehicleController() {
20147
20411
  const { site, org } = queryValue;
20148
20412
  let rows = [];
20149
20413
  if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
20150
- const workbook = new import_exceljs.default.Workbook();
20414
+ const workbook = new import_exceljs2.default.Workbook();
20151
20415
  await workbook.xlsx.readFile(path4);
20152
20416
  const worksheet = workbook.worksheets[0];
20153
20417
  if (!worksheet) {
@@ -20176,7 +20440,7 @@ function useVehicleController() {
20176
20440
  } else if (lowerName.endsWith(".csv")) {
20177
20441
  rows = await new Promise((resolve, reject) => {
20178
20442
  const parsed = [];
20179
- import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("headers", (headers) => {
20443
+ import_fs3.default.createReadStream(path4).pipe((0, import_csv_parser2.default)()).on("headers", (headers) => {
20180
20444
  headers = headers.map(
20181
20445
  (h) => h.trim().replace(/\(.*\)/, "").trim()
20182
20446
  );
@@ -20219,7 +20483,7 @@ function useVehicleController() {
20219
20483
  validationErrors: invalidRows,
20220
20484
  data
20221
20485
  });
20222
- import_fs2.default.unlink(path4, () => {
20486
+ import_fs3.default.unlink(path4, () => {
20223
20487
  });
20224
20488
  } catch (error) {
20225
20489
  import_node_server_utils87.logger.log({ level: "error", message: error.message });
@@ -20387,7 +20651,8 @@ function useVehicleController() {
20387
20651
  recNo: import_joi46.default.string().optional().allow(null, ""),
20388
20652
  type: import_joi46.default.string().optional().valid(...Object.values(VehicleType)).allow(null, ""),
20389
20653
  peopleId: import_joi46.default.string().hex().length(24).optional().allow(null, ""),
20390
- seasonPassType: import_joi46.default.string().optional().allow("", null)
20654
+ seasonPassType: import_joi46.default.string().optional().allow("", null),
20655
+ remarks: import_joi46.default.string().optional().allow("", null)
20391
20656
  });
20392
20657
  const { error, value } = schema2.validate(
20393
20658
  {
@@ -20613,8 +20878,9 @@ function useSiteCameraService() {
20613
20878
  try {
20614
20879
  session.startTransaction();
20615
20880
  await _add(value, session);
20881
+ const message = value.type === "ip" ? "CCTV(s) added successfully." : "ANPR(s) added successfully.";
20616
20882
  await session.commitTransaction();
20617
- return "ANPR(s) added successfully.";
20883
+ return message;
20618
20884
  } catch (error2) {
20619
20885
  await session.abortTransaction();
20620
20886
  throw error2;
@@ -33748,7 +34014,7 @@ var import_node_server_utils153 = require("@7365admin1/node-server-utils");
33748
34014
  var import_mongodb90 = require("mongodb");
33749
34015
 
33750
34016
  // src/utils/access-management.ts
33751
- var import_fs3 = __toESM(require("fs"));
34017
+ var import_fs4 = __toESM(require("fs"));
33752
34018
  var import_path = __toESM(require("path"));
33753
34019
  var import_axios = __toESM(require("axios"));
33754
34020
  var import_xml2js = require("xml2js");
@@ -33778,7 +34044,7 @@ var minifyXml = (xml) => {
33778
34044
  return xml.replace(/>\s+</g, "><").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").trim();
33779
34045
  };
33780
34046
  var readTemplate = (name, params) => {
33781
- const template = import_fs3.default.readFileSync(
34047
+ const template = import_fs4.default.readFileSync(
33782
34048
  import_path.default.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
33783
34049
  "utf-8"
33784
34050
  );
@@ -33909,14 +34175,14 @@ var import_xml2js2 = require("xml2js");
33909
34175
 
33910
34176
  // src/utils/rsa-encryption.ts
33911
34177
  var crypto2 = __toESM(require("crypto"));
33912
- var import_fs4 = __toESM(require("fs"));
34178
+ var import_fs5 = __toESM(require("fs"));
33913
34179
  var import_path2 = __toESM(require("path"));
33914
34180
  var pub = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
33915
34181
  var priv = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
33916
34182
  var EncryptionCredentials = class {
33917
34183
  };
33918
- EncryptionCredentials.RAW_PUBLIC_KEY = import_fs4.default.readFileSync(pub, "utf8");
33919
- EncryptionCredentials.RAW_PRIVATE_KEY = import_fs4.default.readFileSync(priv, "utf8");
34184
+ EncryptionCredentials.RAW_PUBLIC_KEY = import_fs5.default.readFileSync(pub, "utf8");
34185
+ EncryptionCredentials.RAW_PRIVATE_KEY = import_fs5.default.readFileSync(priv, "utf8");
33920
34186
  var EntrypassRSAEncryption = class extends EncryptionCredentials {
33921
34187
  static hexToCardNumber(hex) {
33922
34188
  if (!/^[0-9A-Fa-f]{8}$/.test(hex)) {