@7365admin1/core 2.45.0 → 2.46.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/dist/index.js CHANGED
@@ -34,6 +34,7 @@ __export(src_exports, {
34
34
  AccessTypeProps: () => AccessTypeProps,
35
35
  AppServiceType: () => AppServiceType,
36
36
  BuildingStatus: () => BuildingStatus,
37
+ BulletinOrder: () => BulletinOrder,
37
38
  BulletinRecipient: () => BulletinRecipient,
38
39
  BulletinSort: () => BulletinSort,
39
40
  BulletinStatus: () => BulletinStatus,
@@ -5897,6 +5898,13 @@ var MRole = class {
5897
5898
  throw new import_node_server_utils22.BadRequestError("Invalid org ID format.");
5898
5899
  }
5899
5900
  }
5901
+ if (typeof value.site === "string" && value.site.length === 24) {
5902
+ try {
5903
+ value.site = new import_mongodb19.ObjectId(value.site);
5904
+ } catch (error) {
5905
+ throw new import_node_server_utils22.BadRequestError("Invalid site ID format.");
5906
+ }
5907
+ }
5900
5908
  if (value.createdBy) {
5901
5909
  try {
5902
5910
  value.createdBy = new import_mongodb19.ObjectId(value.createdBy);
@@ -5910,6 +5918,8 @@ var MRole = class {
5910
5918
  this.permissions = value.permissions ?? [];
5911
5919
  this.type = value.type ? value.type : "account";
5912
5920
  this.org = value.org ?? "";
5921
+ this.site = value.site ?? "";
5922
+ this.platform = value.platform ?? "website";
5913
5923
  this.default = value.default ?? false;
5914
5924
  this.status = value.status ?? "active";
5915
5925
  this.createdBy = value.createdBy ?? "";
@@ -7193,7 +7203,9 @@ function useRoleController() {
7193
7203
  name: import_joi14.default.string().required(),
7194
7204
  permissions: import_joi14.default.array().items(import_joi14.default.string()).required(),
7195
7205
  type: import_joi14.default.string().optional().allow("", null),
7196
- org: import_joi14.default.string().hex().optional().allow("", null)
7206
+ org: import_joi14.default.string().hex().optional().allow("", null),
7207
+ site: import_joi14.default.string().hex().optional().allow("", null),
7208
+ platform: import_joi14.default.string().valid("website", "mobile").optional().default("website")
7197
7209
  });
7198
7210
  const payload = { ...req.body };
7199
7211
  const { error } = validation.validate(payload);
@@ -13122,7 +13134,7 @@ function useSiteCameraRepo() {
13122
13134
  key: { type: 1 }
13123
13135
  },
13124
13136
  {
13125
- key: { host: 1, type: 1, status: 1 },
13137
+ key: { host: 1, type: 1, status: 1, site: 1 },
13126
13138
  unique: true,
13127
13139
  partialFilterExpression: { status: "active" }
13128
13140
  }
@@ -15023,7 +15035,7 @@ function useVehicleRepo() {
15023
15035
  try {
15024
15036
  const updateValue = {
15025
15037
  ...value,
15026
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
15038
+ updatedAt: /* @__PURE__ */ new Date()
15027
15039
  };
15028
15040
  const res = await collection.updateOne(
15029
15041
  { _id },
@@ -17000,11 +17012,14 @@ function useVehicleService() {
17000
17012
  endDate = new Date(startDate);
17001
17013
  endDate.setFullYear(endDate.getFullYear() + 10);
17002
17014
  } else {
17003
- startDate = hasStart ? new Date(vehicle.start) : null;
17004
- endDate = hasEnd ? new Date(vehicle.end) : null;
17015
+ startDate = hasStart ? new Date(vehicle.start) : /* @__PURE__ */ new Date();
17016
+ if (hasEnd) {
17017
+ endDate = new Date(vehicle.end);
17018
+ } else {
17019
+ endDate = new Date(startDate);
17020
+ endDate.setFullYear(endDate.getFullYear() + 10);
17021
+ }
17005
17022
  }
17006
- const startIso = startDate ? startDate.toISOString() : "";
17007
- const endIso = endDate ? endDate.toISOString() : "";
17008
17023
  const startDahua = startDate ? formatDahuaDate(startDate) : "";
17009
17024
  const endDahua = endDate ? formatDahuaDate(endDate) : "";
17010
17025
  try {
@@ -17061,8 +17076,8 @@ function useVehicleService() {
17061
17076
  }
17062
17077
  const formattedValue = {
17063
17078
  ...value,
17064
- start: startIso,
17065
- end: endIso
17079
+ start: startDate,
17080
+ end: endDate
17066
17081
  };
17067
17082
  await _updateVehicleById(id, formattedValue, session);
17068
17083
  await session.commitTransaction();
@@ -17442,6 +17457,40 @@ function useVehicleService() {
17442
17457
  };
17443
17458
  }
17444
17459
 
17460
+ // src/utils/logger-dahua.ts
17461
+ var winston = __toESM(require("winston"));
17462
+ var import_winston_daily_rotate_file = __toESM(require("winston-daily-rotate-file"));
17463
+ var loggerDahua = winston.createLogger({
17464
+ level: "info",
17465
+ format: winston.format.combine(
17466
+ winston.format.timestamp(),
17467
+ winston.format.json()
17468
+ ),
17469
+ transports: [
17470
+ // 1. Daily Error Logs - Using the class directly
17471
+ new import_winston_daily_rotate_file.default({
17472
+ filename: "logs/dahua/error-%DATE%.log",
17473
+ datePattern: "YYYY-MM-DD",
17474
+ level: "error",
17475
+ zippedArchive: true,
17476
+ maxSize: "20m",
17477
+ maxFiles: "14d"
17478
+ }),
17479
+ // 2. Daily Combined Logs - Using the class directly
17480
+ new import_winston_daily_rotate_file.default({
17481
+ filename: "logs/dahua/combined-%DATE%.log",
17482
+ datePattern: "YYYY-MM-DD",
17483
+ zippedArchive: true,
17484
+ maxSize: "20m",
17485
+ maxFiles: "14d"
17486
+ }),
17487
+ // 3. Console logging (Optional)
17488
+ new winston.transports.Console({
17489
+ format: winston.format.simple()
17490
+ })
17491
+ ]
17492
+ });
17493
+
17445
17494
  // src/services/dahua.service.ts
17446
17495
  function useDahuaDigest({
17447
17496
  host = "",
@@ -17499,14 +17548,14 @@ function useDahuaService() {
17499
17548
  function enqueue(buffer) {
17500
17549
  if (queue.length >= MAX_QUEUE_SIZE) {
17501
17550
  droppedChunks++;
17502
- import_node_server_utils76.logger.error(
17551
+ loggerDahua.error(
17503
17552
  `[${site}][${gate}] Queue overflow. Dropped: ${droppedChunks}`
17504
17553
  );
17505
17554
  return;
17506
17555
  }
17507
17556
  queue.push(buffer);
17508
17557
  if (queue.length >= BACKPRESSURE_THRESHOLD && streamRef && !streamRef.isPaused()) {
17509
- import_node_server_utils76.logger.warn(
17558
+ loggerDahua.warn(
17510
17559
  `[${site}][${gate}] Queue at ${queue.length}/${MAX_QUEUE_SIZE}, pausing stream`
17511
17560
  );
17512
17561
  streamRef.pause();
@@ -17523,7 +17572,7 @@ function useDahuaService() {
17523
17572
  if (streamRef && streamRef.isPaused()) {
17524
17573
  streamRef.resume();
17525
17574
  }
17526
- import_node_server_utils76.logger.info(
17575
+ loggerDahua.info(
17527
17576
  `[${site}][${gate}] BufferQueue destroyed. Processed=${processedChunks}, Dropped=${droppedChunks}`
17528
17577
  );
17529
17578
  }
@@ -17536,20 +17585,20 @@ function useDahuaService() {
17536
17585
  await handleBuffer(buffer);
17537
17586
  processedChunks++;
17538
17587
  if (queue.length <= RESUME_THRESHOLD && streamRef && streamRef.isPaused()) {
17539
- import_node_server_utils76.logger.info(
17588
+ loggerDahua.info(
17540
17589
  `[${site}][${gate}] Queue at ${queue.length}/${MAX_QUEUE_SIZE}, resuming stream`
17541
17590
  );
17542
17591
  streamRef.resume();
17543
17592
  }
17544
17593
  } catch (err) {
17545
- import_node_server_utils76.logger.error(`[${site}][${gate}] Error processing buffer:`, err);
17594
+ loggerDahua.error(`[${site}][${gate}] Error processing buffer:`, err);
17546
17595
  } finally {
17547
17596
  processing = false;
17548
17597
  processNext();
17549
17598
  }
17550
17599
  }
17551
17600
  async function processVehicleTransaction() {
17552
- import_node_server_utils76.logger.info(
17601
+ loggerDahua.info(
17553
17602
  `[${site}][${gate}] Vehicle transaction: Plate=${plateNumber}, UTC=${UTCData}, UTCMs=${UTCMs}`
17554
17603
  );
17555
17604
  let org = "";
@@ -17557,7 +17606,7 @@ function useDahuaService() {
17557
17606
  const theSite = await getSiteById(site);
17558
17607
  org = theSite?.orgId.toString() || "unknown";
17559
17608
  } catch (error) {
17560
- import_node_server_utils76.logger.error(
17609
+ loggerDahua.error(
17561
17610
  `[${site}][${gate}] Error fetching site for orgId:`,
17562
17611
  error
17563
17612
  );
@@ -17577,7 +17626,7 @@ function useDahuaService() {
17577
17626
  });
17578
17627
  }
17579
17628
  } catch (error) {
17580
- import_node_server_utils76.logger.error(
17629
+ loggerDahua.error(
17581
17630
  `[${site}][${gate}] Error closing existing open transaction:`,
17582
17631
  error
17583
17632
  );
@@ -17633,7 +17682,7 @@ function useDahuaService() {
17633
17682
  currentSnapshotField = "snapshotEntryImage";
17634
17683
  } catch (error) {
17635
17684
  console.log("failed to create visitor transaction", error);
17636
- import_node_server_utils76.logger.error(
17685
+ loggerDahua.error(
17637
17686
  `[${site}][${gate}] Error creating visitor transaction:`,
17638
17687
  error
17639
17688
  );
@@ -17717,7 +17766,7 @@ function useDahuaService() {
17717
17766
  try {
17718
17767
  await import_fs.promises.mkdir(dir, { recursive: true });
17719
17768
  await import_fs.promises.writeFile(snapFolder, accumulatedImageBuffer);
17720
- import_node_server_utils76.logger.debug(`[${site}][${gate}] Saved image locally: ${filename}`);
17769
+ loggerDahua.debug(`[${site}][${gate}] Saved image locally: ${filename}`);
17721
17770
  const fileId = await _createFile(
17722
17771
  {
17723
17772
  originalname: filename,
@@ -17726,7 +17775,7 @@ function useDahuaService() {
17726
17775
  },
17727
17776
  `anpr/${site}`
17728
17777
  );
17729
- import_node_server_utils76.logger.info(
17778
+ loggerDahua.info(
17730
17779
  `[${site}][${gate}] Created file record for image: ${fileId.toString()}`
17731
17780
  );
17732
17781
  if (currentTransactionId && currentSnapshotField) {
@@ -17734,23 +17783,23 @@ function useDahuaService() {
17734
17783
  [currentSnapshotField]: fileId.toString()
17735
17784
  });
17736
17785
  }
17737
- import_node_server_utils76.logger.info(
17786
+ loggerDahua.info(
17738
17787
  `[${site}][${gate}] Image stored with fileId: ${fileId.toString()}`
17739
17788
  );
17740
17789
  await import_fs.promises.unlink(snapFolder);
17741
- import_node_server_utils76.logger.debug(`[${site}][${gate}] Deleted local file: ${filename}`);
17790
+ loggerDahua.debug(`[${site}][${gate}] Deleted local file: ${filename}`);
17742
17791
  } catch (err) {
17743
- import_node_server_utils76.logger.error(
17792
+ loggerDahua.error(
17744
17793
  `[${site}][${gate}] Failed to process image ${filename}:`,
17745
17794
  err
17746
17795
  );
17747
17796
  try {
17748
17797
  await import_fs.promises.unlink(snapFolder);
17749
- import_node_server_utils76.logger.debug(
17798
+ loggerDahua.debug(
17750
17799
  `[${site}][${gate}] Cleaned up local file after error: ${filename}`
17751
17800
  );
17752
17801
  } catch (unlinkErr) {
17753
- import_node_server_utils76.logger.error(
17802
+ loggerDahua.error(
17754
17803
  `[${site}][${gate}] Failed to clean up local file: ${filename}`,
17755
17804
  unlinkErr
17756
17805
  );
@@ -17785,7 +17834,7 @@ function useDahuaService() {
17785
17834
  },
17786
17835
  "snapshots"
17787
17836
  );
17788
- import_node_server_utils76.logger.info(`Successfully saved snapshot fileId: ${fileId.toString()}`);
17837
+ loggerDahua.info(`Successfully saved snapshot fileId: ${fileId.toString()}`);
17789
17838
  return fileId;
17790
17839
  } catch (error) {
17791
17840
  throw error;
@@ -17804,7 +17853,7 @@ function useDahuaService() {
17804
17853
  const contentType = response.res.headers["content-type"];
17805
17854
  const boundaryMatch = contentType?.match(/boundary=(.*)$/i);
17806
17855
  const boundary = boundaryMatch ? `--${boundaryMatch[1]}` : "--myboundary";
17807
- import_node_server_utils76.logger.debug(`[${site}][${gate}] Using boundary: ${boundary}`);
17856
+ loggerDahua.debug(`[${site}][${gate}] Using boundary: ${boundary}`);
17808
17857
  const bufferQueue = useBufferQueue(
17809
17858
  boundary,
17810
17859
  site,
@@ -17816,7 +17865,7 @@ function useDahuaService() {
17816
17865
  );
17817
17866
  bufferQueue.setStream(response.res);
17818
17867
  if ([400, 401, 403, 500].includes(response.statusCode)) {
17819
- import_node_server_utils76.logger.error(
17868
+ loggerDahua.error(
17820
17869
  `[${site}][${gate}] Connection error:`,
17821
17870
  response.statusCode
17822
17871
  );
@@ -17825,14 +17874,14 @@ function useDahuaService() {
17825
17874
  );
17826
17875
  }
17827
17876
  if ([200, 201, 202].includes(response.statusCode)) {
17828
- import_node_server_utils76.logger.info(`[${site}][${gate}] Successfully connected to ANPR.`);
17877
+ loggerDahua.info(`[${site}][${gate}] Successfully connected to ANPR.`);
17829
17878
  console.log(`[${site}][${gate}] Successfully connected to ANPR.`);
17830
17879
  }
17831
17880
  response.res.on("data", (chunk) => {
17832
17881
  bufferQueue.enqueue(chunk);
17833
17882
  });
17834
17883
  const handleDisconnect = async (reason, err) => {
17835
- import_node_server_utils76.logger.error(
17884
+ loggerDahua.error(
17836
17885
  `[${site}][${gate}] ${reason}`,
17837
17886
  err ? err.code || err : ""
17838
17887
  );
@@ -17855,7 +17904,7 @@ function useDahuaService() {
17855
17904
  (err) => handleDisconnect("Connection error:", err)
17856
17905
  );
17857
17906
  } catch (error) {
17858
- import_node_server_utils76.logger.error(
17907
+ loggerDahua.error(
17859
17908
  `[${site}][${gate}] Initial connect error:`,
17860
17909
  error.code || error
17861
17910
  );
@@ -17892,7 +17941,7 @@ function useDahuaService() {
17892
17941
  });
17893
17942
  return response;
17894
17943
  } catch (error2) {
17895
- import_node_server_utils76.logger.error(`[${value.host}] Error adding plate number:`, error2);
17944
+ loggerDahua.error(`[${value.host}] Error adding plate number:`, error2);
17896
17945
  throw new import_node_server_utils76.BadRequestError(`Failed to add plate number: ${error2.message}`);
17897
17946
  }
17898
17947
  }
@@ -17929,7 +17978,7 @@ function useDahuaService() {
17929
17978
  });
17930
17979
  return response;
17931
17980
  } catch (error2) {
17932
- import_node_server_utils76.logger.error(`[${value.host}] Error updating plate number:`, error2);
17981
+ loggerDahua.error(`[${value.host}] Error updating plate number:`, error2);
17933
17982
  throw new import_node_server_utils76.BadRequestError(
17934
17983
  `Failed to update plate number: ${error2.message}`
17935
17984
  );
@@ -17956,7 +18005,7 @@ function useDahuaService() {
17956
18005
  });
17957
18006
  return response;
17958
18007
  } catch (error2) {
17959
- import_node_server_utils76.logger.error(`[${value.host}] Error removing plate number:`, error2);
18008
+ loggerDahua.error(`[${value.host}] Error removing plate number:`, error2);
17960
18009
  }
17961
18010
  }
17962
18011
  async function getPlateNumber(value) {
@@ -17981,7 +18030,7 @@ function useDahuaService() {
17981
18030
  const text = response?.data?.toString?.("utf-8");
17982
18031
  return text;
17983
18032
  } catch (error2) {
17984
- import_node_server_utils76.logger.error(`[${value.host}] Error finding plate number:`, error2);
18033
+ loggerDahua.error(`[${value.host}] Error finding plate number:`, error2);
17985
18034
  throw error2;
17986
18035
  }
17987
18036
  }
@@ -18018,7 +18067,7 @@ function useDahuaService() {
18018
18067
  });
18019
18068
  return response;
18020
18069
  } catch (error2) {
18021
- import_node_server_utils76.logger.error(`[${value.host}] Error bulk add plate number:`, error2);
18070
+ loggerDahua.error(`[${value.host}] Error bulk add plate number:`, error2);
18022
18071
  throw new import_node_server_utils76.BadRequestError(
18023
18072
  `Failed bulk adding plate number: ${error2.message}`
18024
18073
  );
@@ -19575,7 +19624,7 @@ function useVehicleController() {
19575
19624
  next(new import_node_server_utils87.BadRequestError("Spreadsheet file is required."));
19576
19625
  return;
19577
19626
  }
19578
- const { originalname, path: path4 } = req.file;
19627
+ const { originalname, path: path5 } = req.file;
19579
19628
  const lowerName = originalname.toLowerCase();
19580
19629
  const rowSchema = import_joi46.default.object({
19581
19630
  fullName: import_joi46.default.string().trim().required(),
@@ -19614,7 +19663,7 @@ function useVehicleController() {
19614
19663
  let rows = [];
19615
19664
  if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
19616
19665
  const workbook = new import_exceljs.default.Workbook();
19617
- await workbook.xlsx.readFile(path4);
19666
+ await workbook.xlsx.readFile(path5);
19618
19667
  const worksheet = workbook.worksheets[0];
19619
19668
  if (!worksheet) {
19620
19669
  next(
@@ -19640,7 +19689,7 @@ function useVehicleController() {
19640
19689
  } else if (lowerName.endsWith(".csv")) {
19641
19690
  rows = await new Promise((resolve, reject) => {
19642
19691
  const parsed = [];
19643
- import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
19692
+ import_fs2.default.createReadStream(path5).pipe((0, import_csv_parser.default)()).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
19644
19693
  });
19645
19694
  } else {
19646
19695
  next(
@@ -19679,7 +19728,7 @@ function useVehicleController() {
19679
19728
  validationErrors: invalidRows,
19680
19729
  data
19681
19730
  });
19682
- import_fs2.default.unlink(path4, () => {
19731
+ import_fs2.default.unlink(path5, () => {
19683
19732
  });
19684
19733
  } catch (error) {
19685
19734
  import_node_server_utils87.logger.log({ level: "error", message: error.message });
@@ -19877,26 +19926,27 @@ function useVehicleController() {
19877
19926
  }
19878
19927
  }
19879
19928
  async function approveVehicleById(req, res, next) {
19880
- const validation = import_joi46.default.object({
19881
- _id: import_joi46.default.string().hex().length(24).required(),
19882
- org: import_joi46.default.string().hex().length(24).required(),
19883
- site: import_joi46.default.string().hex().length(24).required()
19884
- });
19885
- const _id = req.params.id;
19886
- const payload = { ...req.body };
19887
- const { error, value } = validation.validate({ _id, ...payload });
19888
- if (error) {
19889
- import_node_server_utils87.logger.log({ level: "error", message: error.message });
19890
- next(new import_node_server_utils87.BadRequestError(error.message));
19891
- return;
19892
- }
19893
19929
  try {
19894
- await _approveVehicleById(value._id, value.org, value.site);
19930
+ const schema2 = import_joi46.default.object({
19931
+ _id: import_joi46.default.string().hex().length(24).required(),
19932
+ org: import_joi46.default.string().hex().length(24).required(),
19933
+ site: import_joi46.default.string().hex().length(24).required()
19934
+ });
19935
+ const payload = { _id: req.params.id, ...req.body };
19936
+ const { error, value } = schema2.validate(payload, { abortEarly: false });
19937
+ if (error) {
19938
+ const messages = error.details.map((d) => d.message).join(", ");
19939
+ import_node_server_utils87.logger.log({ level: "error", message: messages });
19940
+ next(new import_node_server_utils87.BadRequestError(messages));
19941
+ return;
19942
+ }
19943
+ const { _id, org, site } = value;
19944
+ await _approveVehicleById(_id, org, site);
19895
19945
  res.json({ message: "Successfully approved and updated vehicle." });
19896
19946
  return;
19897
- } catch (error2) {
19898
- import_node_server_utils87.logger.log({ level: "error", message: error2.message });
19899
- next(error2);
19947
+ } catch (error) {
19948
+ import_node_server_utils87.logger.log({ level: "error", message: error.message });
19949
+ next(error);
19900
19950
  return;
19901
19951
  }
19902
19952
  }
@@ -24078,7 +24128,16 @@ var import_node_server_utils108 = require("@7365admin1/node-server-utils");
24078
24128
 
24079
24129
  // src/services/person.service.ts
24080
24130
  var import_node_server_utils107 = require("@7365admin1/node-server-utils");
24131
+ var import_path = __toESM(require("path"));
24081
24132
  function usePersonService() {
24133
+ const MailerConfig = {
24134
+ host: MAILER_TRANSPORT_HOST,
24135
+ port: MAILER_TRANSPORT_PORT,
24136
+ secure: MAILER_TRANSPORT_SECURE,
24137
+ email: MAILER_EMAIL,
24138
+ password: MAILER_PASSWORD
24139
+ };
24140
+ const mailer = new import_node_server_utils107.useMailer(MailerConfig);
24082
24141
  const {
24083
24142
  add: _add,
24084
24143
  getById: _getById,
@@ -24284,24 +24343,73 @@ function usePersonService() {
24284
24343
  value.status = "active";
24285
24344
  }
24286
24345
  await _reviewResidentPerson(id, value, session);
24346
+ const logoPath = import_path.default.join(
24347
+ __dirname,
24348
+ "public",
24349
+ "images",
24350
+ "seven-365.svg"
24351
+ );
24352
+ const statusIconPath = import_path.default.join(__dirname, "public", "icons");
24353
+ let title = "";
24354
+ let message2 = "";
24355
+ let hideLogin = true;
24356
+ let logo = logoPath;
24357
+ let statusLogo = statusIconPath;
24287
24358
  if (person.user) {
24288
- let userStatus;
24359
+ let userStatus = "";
24289
24360
  switch (reviewStatus) {
24290
24361
  case "approved":
24291
24362
  userStatus = "active";
24292
24363
  if (person.plateNumber && person.plateNumber.trim() !== "") {
24293
24364
  await addVehicle(vehicle, session);
24294
24365
  }
24366
+ title = "Your account has been approved";
24367
+ hideLogin = false;
24368
+ statusLogo = `${statusIconPath}/approved-icon.png`;
24369
+ message2 = `Welcome, ${person.name}! Thank you for signing up; we're excited to have you join us!`;
24295
24370
  break;
24296
24371
  case "resubmit":
24297
24372
  userStatus = "resubmit";
24373
+ title = "We request resubmission for your application";
24374
+ hideLogin = false;
24375
+ statusLogo = `${statusIconPath}/resubmission-icon.png`;
24376
+ message2 = `Hi ${person.name}, please resubmit your application with the required updates.`;
24298
24377
  break;
24299
24378
  case "rejected":
24300
24379
  userStatus = "rejected";
24380
+ title = "Your account request for deletion has been rejected.";
24381
+ statusLogo = `${statusIconPath}/deleted-icon.png`;
24382
+ message2 = `Hi ${person.name}, unfortunately your application has been rejected. Please contact support for more information.`;
24301
24383
  break;
24302
24384
  default:
24303
24385
  throw new Error("Invalid review status");
24304
24386
  }
24387
+ const dir = __dirname;
24388
+ const filePath = (0, import_node_server_utils107.getDirectory)(
24389
+ dir,
24390
+ "./public/handlebars/resident-remarks-email"
24391
+ );
24392
+ const emailContent = (0, import_node_server_utils107.compileHandlebar)({
24393
+ context: {
24394
+ title,
24395
+ message2,
24396
+ hideLogin,
24397
+ logo,
24398
+ statusLogo
24399
+ },
24400
+ filePath
24401
+ });
24402
+ await mailer.sendMail({
24403
+ to: person.email,
24404
+ subject: title,
24405
+ html: emailContent,
24406
+ sender: "iService365"
24407
+ }).catch((error) => {
24408
+ import_node_server_utils107.logger.log({
24409
+ level: "error",
24410
+ message: `Error sending user ${reviewStatus} email: ${error}`
24411
+ });
24412
+ });
24305
24413
  await _updateUserFieldById(
24306
24414
  { _id: person.user.toString(), field: "status", value: userStatus },
24307
24415
  session
@@ -29363,6 +29471,11 @@ var BulletinSort = /* @__PURE__ */ ((BulletinSort2) => {
29363
29471
  BulletinSort2["ID"] = "_id";
29364
29472
  return BulletinSort2;
29365
29473
  })(BulletinSort || {});
29474
+ var BulletinOrder = /* @__PURE__ */ ((BulletinOrder2) => {
29475
+ BulletinOrder2["ASC"] = "asc";
29476
+ BulletinOrder2["DESC"] = "desc";
29477
+ return BulletinOrder2;
29478
+ })(BulletinOrder || {});
29366
29479
  var schemaBulletinBoard = import_joi75.default.object({
29367
29480
  _id: import_joi75.default.string().hex().optional().allow("", null),
29368
29481
  site: import_joi75.default.string().hex().optional().allow("", null),
@@ -29659,12 +29772,13 @@ function useBulletinBoardRepo() {
29659
29772
  }
29660
29773
  async function processExpiredBulletinBoards(session) {
29661
29774
  const today = (/* @__PURE__ */ new Date()).toISOString();
29775
+ const query = {
29776
+ noExpiration: false,
29777
+ endDate: { $lt: today }
29778
+ };
29662
29779
  try {
29663
29780
  const res = await collection.updateMany(
29664
- {
29665
- noExpiration: false,
29666
- endDate: { $lt: today }
29667
- },
29781
+ query,
29668
29782
  {
29669
29783
  $set: {
29670
29784
  status: "expired",
@@ -29822,9 +29936,9 @@ function useBulletinBoardController() {
29822
29936
  page: import_joi76.default.number().integer().min(1).allow("", null).default(1),
29823
29937
  limit: import_joi76.default.number().integer().min(1).max(100).allow("", null).default(10),
29824
29938
  sort: import_joi76.default.string().valid(...Object.values(BulletinSort)).default("_id" /* ID */),
29825
- order: import_joi76.default.string().valid(...Object.values(SortOrder)).default("desc" /* DESC */),
29939
+ order: import_joi76.default.string().valid(...Object.values(BulletinOrder)).default("desc" /* DESC */),
29826
29940
  site: import_joi76.default.string().hex().length(24).required(),
29827
- status: import_joi76.default.string().valid(...Object.values(BuildingStatus)).optional().default("active" /* ACTIVE */),
29941
+ status: import_joi76.default.string().valid(...Object.values(BulletinStatus)).optional().default("active" /* ACTIVE */),
29828
29942
  recipients: import_joi76.default.alternatives().try(
29829
29943
  import_joi76.default.array().items(
29830
29944
  import_joi76.default.string().valid(...Object.values(BulletinRecipient))
@@ -31344,7 +31458,7 @@ function useEventManagementRepo() {
31344
31458
  ...type && { type }
31345
31459
  };
31346
31460
  if (search) {
31347
- query.$text = { $search: search };
31461
+ query.$or = [{ title: { $regex: search, $options: "i" } }];
31348
31462
  cacheOptions.search = search;
31349
31463
  }
31350
31464
  const cacheKey = (0, import_node_server_utils146.makeCacheKey)(events_namespace_collection, cacheOptions);
@@ -33047,7 +33161,7 @@ var import_mongodb90 = require("mongodb");
33047
33161
 
33048
33162
  // src/utils/access-management.ts
33049
33163
  var import_fs3 = __toESM(require("fs"));
33050
- var import_path = __toESM(require("path"));
33164
+ var import_path2 = __toESM(require("path"));
33051
33165
  var import_axios = __toESM(require("axios"));
33052
33166
  var import_xml2js = require("xml2js");
33053
33167
  var import_crypto = __toESM(require("crypto"));
@@ -33077,7 +33191,7 @@ var minifyXml = (xml) => {
33077
33191
  };
33078
33192
  var readTemplate = (name, params) => {
33079
33193
  const template = import_fs3.default.readFileSync(
33080
- import_path.default.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
33194
+ import_path2.default.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
33081
33195
  "utf-8"
33082
33196
  );
33083
33197
  if (!params)
@@ -33189,9 +33303,9 @@ var import_xml2js2 = require("xml2js");
33189
33303
  // src/utils/rsa-encryption.ts
33190
33304
  var crypto2 = __toESM(require("crypto"));
33191
33305
  var import_fs4 = __toESM(require("fs"));
33192
- var import_path2 = __toESM(require("path"));
33193
- var pub = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
33194
- var priv = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
33306
+ var import_path3 = __toESM(require("path"));
33307
+ var pub = import_path3.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
33308
+ var priv = import_path3.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
33195
33309
  var EncryptionCredentials = class {
33196
33310
  };
33197
33311
  EncryptionCredentials.RAW_PUBLIC_KEY = import_fs4.default.readFileSync(pub, "utf8");
@@ -33308,6 +33422,19 @@ function UseAccessManagementRepo() {
33308
33422
  return Promise.reject("Failed to create Access cards indexes.");
33309
33423
  }
33310
33424
  }
33425
+ async function indexCombination() {
33426
+ try {
33427
+ await Promise.all([
33428
+ collection().createIndex({ isWinsland: 1 }),
33429
+ collection().createIndex({ doorName: 1 }),
33430
+ collection().createIndex({ liftName: 1 }),
33431
+ collection().createIndex({ liftName: 1, doorName: 1, isWinsland: 1 })
33432
+ ]);
33433
+ return Promise.resolve("Access cards indexes created.");
33434
+ } catch (error) {
33435
+ return Promise.reject("Failed to create Access cards indexes.");
33436
+ }
33437
+ }
33311
33438
  async function createIndexForEntrypass() {
33312
33439
  try {
33313
33440
  const entrypass = collectionName("entrypass-settings");
@@ -35185,7 +35312,8 @@ function UseAccessManagementRepo() {
35185
35312
  addVisitorAccessCardRepo,
35186
35313
  signQrCodeRepo,
35187
35314
  checkoutVisitorRepo,
35188
- getBlockLevelAndUnitListRepo
35315
+ getBlockLevelAndUnitListRepo,
35316
+ indexCombination
35189
35317
  };
35190
35318
  }
35191
35319
 
@@ -35258,8 +35386,8 @@ function useAccessManagementSvc() {
35258
35386
  const command = readTemplate("door-levels");
35259
35387
  const response = await sendCommand(command, params.acm_url);
35260
35388
  const res = await (0, import_xml2js3.parseStringPromise)(response, { explicitArray: false });
35261
- const format = await formatDoorAccessLevels(res);
35262
- return format;
35389
+ const format2 = await formatDoorAccessLevels(res);
35390
+ return format2;
35263
35391
  } catch (err) {
35264
35392
  throw new Error(err.message);
35265
35393
  }
@@ -35269,8 +35397,8 @@ function useAccessManagementSvc() {
35269
35397
  const command = readTemplate("lift-levels");
35270
35398
  const response = await sendCommand(command, params.acm_url);
35271
35399
  const res = await (0, import_xml2js3.parseStringPromise)(response, { explicitArray: false });
35272
- const format = await formatLiftAccessLevels(res);
35273
- return format;
35400
+ const format2 = await formatLiftAccessLevels(res);
35401
+ return format2;
35274
35402
  } catch (error) {
35275
35403
  throw new Error(error.message);
35276
35404
  }
@@ -35280,8 +35408,8 @@ function useAccessManagementSvc() {
35280
35408
  const command = readTemplate("access-group");
35281
35409
  const response = await sendCommand(command, params.acm_url);
35282
35410
  const res = await (0, import_xml2js3.parseStringPromise)(response, { explicitArray: false });
35283
- const format = await formatAccessGroup(res);
35284
- return format;
35411
+ const format2 = await formatAccessGroup(res);
35412
+ return format2;
35285
35413
  } catch (err) {
35286
35414
  throw new Error(err.message);
35287
35415
  }
@@ -37571,6 +37699,18 @@ function useBulletinVideoRepo() {
37571
37699
  );
37572
37700
  }
37573
37701
  }
37702
+ async function createTextIndex() {
37703
+ try {
37704
+ await collection.createIndex({
37705
+ title: "text",
37706
+ description: "text"
37707
+ });
37708
+ } catch (error) {
37709
+ throw new import_node_server_utils161.InternalServerError(
37710
+ "Failed to create text index on bulletin videos."
37711
+ );
37712
+ }
37713
+ }
37574
37714
  const namespace_collection = "bulletin-videos";
37575
37715
  const collection = db.collection(namespace_collection);
37576
37716
  const { delNamespace, getCache, setCache } = (0, import_node_server_utils161.useCache)(namespace_collection);
@@ -37610,7 +37750,8 @@ function useBulletinVideoRepo() {
37610
37750
  }
37611
37751
  const query = {
37612
37752
  site,
37613
- status: { $ne: "deleted" }
37753
+ status: { $ne: "deleted" },
37754
+ ...search && { $text: { $search: search } }
37614
37755
  };
37615
37756
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
37616
37757
  const cacheOptions = {
@@ -37618,10 +37759,14 @@ function useBulletinVideoRepo() {
37618
37759
  sort: JSON.stringify(sort),
37619
37760
  page,
37620
37761
  limit,
37621
- status: { $ne: "deleted" }
37762
+ status: { $ne: "deleted" },
37763
+ ...search && { search }
37622
37764
  };
37623
37765
  if (search) {
37624
- query.$text = { $search: search };
37766
+ query.$or = [
37767
+ { title: { $regex: search, $options: "i" } },
37768
+ { description: { $regex: search, $options: "i" } }
37769
+ ];
37625
37770
  cacheOptions.search = search;
37626
37771
  }
37627
37772
  const cacheKey = (0, import_node_server_utils161.makeCacheKey)(namespace_collection, cacheOptions);
@@ -37757,7 +37902,8 @@ function useBulletinVideoRepo() {
37757
37902
  getBulletinVideoById,
37758
37903
  updateBulletinVideoById,
37759
37904
  deleteBulletinVideoById,
37760
- createIndexes
37905
+ createIndexes,
37906
+ createTextIndex
37761
37907
  };
37762
37908
  }
37763
37909
 
@@ -44128,11 +44274,11 @@ async function fetchAttendanceData({
44128
44274
  };
44129
44275
  }
44130
44276
  }
44131
- function filterByShiftTime(attendance, shiftData, timezone, format) {
44277
+ function filterByShiftTime(attendance, shiftData, timezone, format2) {
44132
44278
  return attendance.filter((item) => {
44133
44279
  if (!item.checkIn)
44134
44280
  return false;
44135
- const checkInLocal = (0, import_moment_timezone.default)(item.checkIn, format);
44281
+ const checkInLocal = (0, import_moment_timezone.default)(item.checkIn, format2);
44136
44282
  if (!checkInLocal.isValid())
44137
44283
  return false;
44138
44284
  const [startHour, startMinute] = shiftData.checkIn.split(":").map(Number);
@@ -44207,7 +44353,7 @@ function designationCount(attendance, designationConfig, shiftName) {
44207
44353
  }
44208
44354
  return result;
44209
44355
  }
44210
- function totalCountPerShift(attendance, shiftData, timezone, format) {
44356
+ function totalCountPerShift(attendance, shiftData, timezone, format2) {
44211
44357
  let totalCountPerShift3 = [];
44212
44358
  const seen = /* @__PURE__ */ new Set();
44213
44359
  const uniqueAttendanceData = [];
@@ -44230,7 +44376,7 @@ function totalCountPerShift(attendance, shiftData, timezone, format) {
44230
44376
  data = uniqueAttendanceData.filter((item) => {
44231
44377
  if (!item.checkIn)
44232
44378
  return false;
44233
- const checkInLocal = (0, import_moment_timezone.default)(item.checkIn, format);
44379
+ const checkInLocal = (0, import_moment_timezone.default)(item.checkIn, format2);
44234
44380
  if (!checkInLocal.isValid())
44235
44381
  return false;
44236
44382
  const [startHour, startMinute] = shift.checkIn.split(":").map(Number);
@@ -44267,11 +44413,11 @@ function totalCountPerShift(attendance, shiftData, timezone, format) {
44267
44413
  }
44268
44414
  return totalCountPerShift3;
44269
44415
  }
44270
- function filterByStatus(attendance, shiftData, timezone, format, status) {
44416
+ function filterByStatus(attendance, shiftData, timezone, format2, status) {
44271
44417
  return attendance.filter((item) => {
44272
44418
  if (!item.checkIn)
44273
44419
  return false;
44274
- const checkInLocal = (0, import_moment_timezone.default)(item.checkIn, format);
44420
+ const checkInLocal = (0, import_moment_timezone.default)(item.checkIn, format2);
44275
44421
  if (!checkInLocal.isValid())
44276
44422
  return false;
44277
44423
  const [lateHour, lateMinute] = shiftData.lateCheckInAlert.split(":").map(Number);
@@ -44321,7 +44467,7 @@ async function fetchSites({ siteUrl, token }) {
44321
44467
  } while (attempt < maxRetries);
44322
44468
  throw lastError;
44323
44469
  }
44324
- async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, format, totalShifts) {
44470
+ async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, format2, totalShifts) {
44325
44471
  const totalCountPerStatus3 = {
44326
44472
  onTime: 0,
44327
44473
  late: 0,
@@ -44338,7 +44484,7 @@ async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, f
44338
44484
  const shiftStartTime = parseTime(shift.checkIn);
44339
44485
  const shiftEndTime = parseTime(shift.checkOut);
44340
44486
  const lateTime = parseTime(shift.lateCheckInAlert);
44341
- const uniqueAttendanceData = shiftName === "all" ? await filterByShiftTime(attendance, shift, timezone, format) : attendance;
44487
+ const uniqueAttendanceData = shiftName === "all" ? await filterByShiftTime(attendance, shift, timezone, format2) : attendance;
44342
44488
  for (const item of uniqueAttendanceData) {
44343
44489
  const {
44344
44490
  checkIn: checkInStr,
@@ -44347,9 +44493,9 @@ async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, f
44347
44493
  } = item;
44348
44494
  if (!checkInStr || seenGlobal.has(identificationNumber))
44349
44495
  continue;
44350
- const checkIn = (0, import_moment_timezone.default)(checkInStr, format);
44351
- const checkOut = checkOutStr ? (0, import_moment_timezone.default)(checkOutStr, format) : null;
44352
- const checkOutChecker = checkOut ? (0, import_moment_timezone.default)(checkOutStr, format) : checkIn;
44496
+ const checkIn = (0, import_moment_timezone.default)(checkInStr, format2);
44497
+ const checkOut = checkOutStr ? (0, import_moment_timezone.default)(checkOutStr, format2) : null;
44498
+ const checkOutChecker = checkOut ? (0, import_moment_timezone.default)(checkOutStr, format2) : checkIn;
44353
44499
  if (!checkIn.isValid())
44354
44500
  continue;
44355
44501
  const shiftStart = (0, import_moment_timezone.default)(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
@@ -44385,7 +44531,7 @@ async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, f
44385
44531
  totalCountPerStatus3.totalCount = shiftMap[shiftName];
44386
44532
  return totalCountPerStatus3;
44387
44533
  }
44388
- async function chartCountData(attendance, shiftData, timezone, format, totalShifts, startDateStr, endDateStr, status = "all") {
44534
+ async function chartCountData(attendance, shiftData, timezone, format2, totalShifts, startDateStr, endDateStr, status = "all") {
44389
44535
  const categorizedData = [];
44390
44536
  const seenPerDay = /* @__PURE__ */ new Set();
44391
44537
  const parseTime = (timeStr) => {
@@ -44408,7 +44554,7 @@ async function chartCountData(attendance, shiftData, timezone, format, totalShif
44408
44554
  dailyAttendance,
44409
44555
  shiftData,
44410
44556
  timezone,
44411
- format
44557
+ format2
44412
44558
  );
44413
44559
  if (status === "all" || status === "under" || status === "over") {
44414
44560
  const shifts = [
@@ -44454,7 +44600,7 @@ async function chartCountData(attendance, shiftData, timezone, format, totalShif
44454
44600
  dailyAttendance,
44455
44601
  shift,
44456
44602
  timezone,
44457
- format
44603
+ format2
44458
44604
  );
44459
44605
  for (const item of uniqueAttendanceData) {
44460
44606
  const {
@@ -44464,7 +44610,7 @@ async function chartCountData(attendance, shiftData, timezone, format, totalShif
44464
44610
  } = item;
44465
44611
  if (!checkInStr)
44466
44612
  continue;
44467
- const checkIn = (0, import_moment_timezone.default)(checkInStr, format);
44613
+ const checkIn = (0, import_moment_timezone.default)(checkInStr, format2);
44468
44614
  if (!checkIn.isValid())
44469
44615
  continue;
44470
44616
  const dayKey = `${identificationNumber}-${checkIn.format(
@@ -44473,7 +44619,7 @@ async function chartCountData(attendance, shiftData, timezone, format, totalShif
44473
44619
  if (seenPerDay.has(dayKey))
44474
44620
  continue;
44475
44621
  seenPerDay.add(dayKey);
44476
- const checkOut = checkOutStr ? (0, import_moment_timezone.default)(checkOutStr, format) : checkIn;
44622
+ const checkOut = checkOutStr ? (0, import_moment_timezone.default)(checkOutStr, format2) : checkIn;
44477
44623
  const shiftStart = (0, import_moment_timezone.default)(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
44478
44624
  const shiftEnd = (0, import_moment_timezone.default)(checkOut).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
44479
44625
  const lateCheckIn = (0, import_moment_timezone.default)(checkIn).set({
@@ -50167,6 +50313,7 @@ function useRoleControllerV2() {
50167
50313
  AccessTypeProps,
50168
50314
  AppServiceType,
50169
50315
  BuildingStatus,
50316
+ BulletinOrder,
50170
50317
  BulletinRecipient,
50171
50318
  BulletinSort,
50172
50319
  BulletinStatus,